예제 #1
0
class _MPLPlotWidget(PlotWidget):
    """
    Base class for matplotlib-based plot widgets.
    Per default, add a canvas and the matplotlib NavBar.
    """
    def __init__(self, parent: Optional[QtWidgets.QWidget] = None):
        super().__init__(parent=parent)

        setMplDefaults(self)
        scaling = np.rint(self.logicalDpiX() / 96.0)
        defaultIconSize = 16 * scaling

        self.plot = MPLPlot()
        self.mplBar = NavBar(self.plot, self)
        self.addMplBarOptions()
        self.mplBar.setIconSize(QtCore.QSize(defaultIconSize, defaultIconSize))

        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.plot)
        layout.addWidget(self.mplBar)
        self.setLayout(layout)

    def setMeta(self, data: DataDictBase) -> None:
        if data.has_meta('title'):
            self.plot.setFigureTitle(data.meta_val('title'))

        if data.has_meta('info'):
            self.plot.setFigureInfo(data.meta_val('info'))

        meta_info = {}
        for meta_key in ('qcodes_guid', 'qcodes_sample_name',
                         'qcodes_experiment_name', 'qcodes_dataset_name',
                         'qcodes_runId', 'qcodes_db', 'qcodes_completedTS',
                         'qcodes_runTS'):
            if data.has_meta(meta_key):
                key_without_prefix = (meta_key.replace("qcodes_", "")
                                      if meta_key.startswith("qcodes_") else
                                      meta_key)
                meta_info[key_without_prefix] = data.meta_val(meta_key)

        self.plot.setMetaInfo(meta_info=meta_info)

    def addMplBarOptions(self) -> None:
        tlCheck = QtWidgets.QCheckBox('Tight layout')
        tlCheck.toggled.connect(self.plot.setTightLayout)

        infoCheck = QtWidgets.QCheckBox('Info')
        infoCheck.toggled.connect(self.plot.setShowInfo)

        self.mplBar.addSeparator()
        self.mplBar.addWidget(tlCheck)
        self.mplBar.addSeparator()
        self.mplBar.addWidget(infoCheck)
        self.mplBar.addSeparator()
        self.mplBar.addAction('Copy plot', self.plot.toClipboard)
        self.mplBar.addAction('Copy metadata', self.plot.metaToClipboard)
예제 #2
0
파일: widgets.py 프로젝트: wpfff/plottr
class MPLPlotWidget(PlotWidget):
    """
    Base class for matplotlib-based plot widgets.
    Per default, add a canvas and the matplotlib NavBar.
    """
    def __init__(self, parent: Optional[QtWidgets.QWidget] = None):
        super().__init__(parent=parent)

        #: the plot widget
        self.plot = MPLPlot()

        #: the matplotlib toolbar
        self.mplBar = NavBar(self.plot, self)

        self.addMplBarOptions()
        defaultIconSize = int(16 * dpiScalingFactor(self))
        self.mplBar.setIconSize(QtCore.QSize(defaultIconSize, defaultIconSize))
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.plot)
        layout.addWidget(self.mplBar)
        self.setLayout(layout)

    def setMeta(self, data: DataDictBase) -> None:
        """Add meta info contained in the data to the figure.

        :param data: data object containing the meta information
            if meta field ``title`` or ``info`` are in the data object, then
            they will be added as text info to the figure.
        """
        if data.has_meta('title'):
            self.plot.setFigureTitle(data.meta_val('title'))

        if data.has_meta('info'):
            self.plot.setFigureInfo(data.meta_val('info'))

        all_meta = {}
        for k, v in sorted(data.meta_items()):
            this_meta = str(v)
            if len(this_meta) > 200:
                this_meta = this_meta[:200] + "..."
            all_meta[k] = this_meta
        self.plot.setMetaInfo(all_meta)

    def addMplBarOptions(self) -> None:
        """Add options for displaying ``info`` meta data and copying the figure to the clipboard to the
        plot toolbar."""
        self.mplBar.addSeparator()
        infoAction = self.mplBar.addAction('Show Info')
        infoAction.setCheckable(True)
        infoAction.toggled.connect(self.plot.setShowInfo)

        self.mplBar.addSeparator()
        self.mplBar.addAction('Copy Figure', self.plot.toClipboard)
        self.mplBar.addAction('Copy Meta', self.plot.metaToClipboard)
예제 #3
0
파일: mpl.py 프로젝트: neildick/plottr
class MPLPlotWidget(QtGui.QWidget):
    """
    Base class for matplotlib-based plot widgets.
    Per default, add a canvas and the matplotlib NavBar.
    """
    def __init__(self, parent=None):
        super().__init__(parent=parent)

        setMplDefaults()

        self.plot = MPLPlot()
        self.mplBar = NavBar(self.plot, self)
        self.addMplBarOptions()

        self.toolLayout = QtGui.QHBoxLayout()

        self.layout = QtGui.QVBoxLayout(self)
        self.layout.addLayout(self.toolLayout)
        self.layout.addWidget(self.plot)
        self.layout.addWidget(self.mplBar)

    def setData(self, data: DataDictBase):
        raise NotImplementedError

    def setMeta(self, data: DataDictBase):
        if data.has_meta('title'):
            self.plot.setFigureTitle(data.meta_val('title'))

        if data.has_meta('info'):
            self.plot.setFigureInfo(data.meta_val('info'))

    def addMplBarOptions(self):
        tlCheck = QtGui.QCheckBox('Tight layout')
        tlCheck.toggled.connect(self.plot.setTightLayout)

        infoCheck = QtGui.QCheckBox('Info')
        infoCheck.toggled.connect(self.plot.setShowInfo)

        self.mplBar.addSeparator()
        self.mplBar.addWidget(tlCheck)
        self.mplBar.addSeparator()
        self.mplBar.addWidget(infoCheck)
        self.mplBar.addSeparator()
        self.mplBar.addAction('Copy', self.plot.toClipboard)
예제 #4
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._molecule = nx.Graph()
        self._mapping = MappingModel(self._molecule)

        layout = QHBoxLayout()
        canvas_layout = QVBoxLayout()
        self.embeddings_box = QComboBox()
        self.embeddings_box.addItems(EMBEDDINGS.keys())
        self.embeddings_box.setEditable(False)
        self.embeddings_box.currentTextChanged.connect(self._set_embedding)

        canvas_layout.addWidget(self.embeddings_box)

        self.figure = Figure()
        self.canvas = MappingView(self.figure)
        canvas_layout.addWidget(self.canvas)

        canvas_toolbar = NavigationToolbar(self.canvas, self.canvas, False)
        canvas_toolbar.addSeparator()
        hide_mapping = QAction('Hide Mapping',
                               self,
                               icon=self.style().standardIcon(
                                   QStyle.SP_DesktopIcon))
        hide_mapping.triggered.connect(self.canvas.hide_mapping)
        canvas_toolbar.addAction(hide_mapping)

        remove_mapping = QAction('Remove Mapping',
                                 self,
                                 icon=self.style().standardIcon(
                                     QStyle.SP_DialogDiscardButton))
        remove_mapping.triggered.connect(self.canvas.remove_mapping)
        canvas_toolbar.addAction(remove_mapping)

        canvas_layout.addWidget(canvas_toolbar, alignment=Qt.AlignBottom)

        layout.addLayout(canvas_layout)

        self._table = QTableView()
        self._table.horizontalHeader().setStretchLastSection(True)
        layout.addWidget(self._table)

        self.setLayout(layout)
        self._set_embedding(self.embeddings_box.currentText())
예제 #5
0
파일: mpl.py 프로젝트: labist/plottr
class _MPLPlotWidget(PlotWidget):
    """
    Base class for matplotlib-based plot widgets.
    Per default, add a canvas and the matplotlib NavBar.
    """
    def __init__(self, parent: Optional[QtWidgets.QWidget] = None):
        super().__init__(parent=parent)

        setMplDefaults(self)
        scaling = np.rint(self.logicalDpiX() / 96.0)
        defaultIconSize = 16 * scaling

        self.plot = MPLPlot()
        self.mplBar = NavBar(self.plot, self)
        self.addMplBarOptions()
        self.mplBar.setIconSize(QtCore.QSize(defaultIconSize, defaultIconSize))

        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.plot)
        layout.addWidget(self.mplBar)
        self.setLayout(layout)

    def setMeta(self, data: DataDictBase) -> None:
        if data.has_meta('title'):
            self.plot.setFigureTitle(data.meta_val('title'))

        if data.has_meta('info'):
            self.plot.setFigureInfo(data.meta_val('info'))

    def addMplBarOptions(self) -> None:
        tlCheck = QtWidgets.QCheckBox('Tight layout')
        tlCheck.toggled.connect(self.plot.setTightLayout)

        infoCheck = QtWidgets.QCheckBox('Info')
        infoCheck.toggled.connect(self.plot.setShowInfo)

        self.mplBar.addSeparator()
        self.mplBar.addWidget(tlCheck)
        self.mplBar.addSeparator()
        self.mplBar.addWidget(infoCheck)
        self.mplBar.addSeparator()
        self.mplBar.addAction('Copy', self.plot.toClipboard)
예제 #6
0
class PlotWidget(QtWidgets.QWidget):
    """ Qt widget to hold the matplotlib canvas and the tools for interacting with the plots """
    def __init__(self, data, xlabel, ylabel):
        QtWidgets.QWidget.__init__(self)

        self.setLayout(QtWidgets.QVBoxLayout())
        self.canvas = PlotCanvas(data, xlabel, ylabel)        
        self.toolbar = NavigationToolbar(self.canvas, self)
        self.toolbar.addSeparator()
        
        self.ACshowselector = QtWidgets.QAction('Activate/Clear RangeSelector')
        self.ACshowselector.setIconText('RANGE SELECTOR')
        self.ACshowselector.setFont(QtGui.QFont("Times", 12, QtGui.QFont.Bold))
        self.ACshowselector.triggered.connect(self.toggle_showselector)

        self.toolbar.addAction(self.ACshowselector)
        self.toolbar.addSeparator()
        self.layout().addWidget(self.toolbar)
        self.layout().addWidget(self.canvas)

    def toggle_showselector(self):
        self.canvas.toggle_rangeselector()
예제 #7
0
    def __init__(self, title, shape=None, *args):
        super().__init__(*args)

        self.setWindowTitle(title)
        self.setWindowFlag(Qt.Window, True)
        self.setContentsMargins(0, 0, 0, 0)
        self._descriptor = ''
        self.setFocusPolicy(Qt.StrongFocus)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)

        self.title = title

        if shape is None:
            self.fig, self.axis = plt.subplots()
            self.axis.set_title(self.title)
        else:
            rows, columns = shape
            self.fig, self.axis = plt.subplots(rows, columns)
            self.fig.suptitle(title)

        self.fig.set_dpi(100)

        self.figure_widget = FigureCanvas(self.fig)
        self.figure_widget.setMinimumHeight(500)

        toolbar = NavigationToolbar(self.figure_widget, self)
        toolbar.addAction('Edit', self.show_editor)

        layout.addWidget(self.figure_widget)
        layout.addWidget(toolbar)

        self._command_box = None
        self._run_command_btn = None
        self._highlighter = None

        self.setLayout(layout)
예제 #8
0
    def initUI(self):
        self.setWindowTitle('NyqLab: Scope')

        # Figure
        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)
        toolbar = NavigationToolbar(self.canvas, self)

        # Eye diagram toolbar button
        action_eye = QtWidgets.QAction(QtGui.QIcon('media/eye'), 'Scope', self)
        action_eye.triggered.connect(self.onEyeClick)
        toolbar.addAction(action_eye)

        # Axis
        self.ax_t = self.figure.add_subplot(2, 1, 1)
        self.ax_t.grid(True, which='major', linestyle='--')
        self.ax_t.set_xlabel('$t / T_\mathrm{b}$')
        self.ax_t.axis(self.ax_t_lim_free)
        self.ax_t.xaxis.set_major_locator(ticker.MultipleLocator(1.0))
        self.ax_t.yaxis.set_major_locator(ticker.MultipleLocator(0.5))

        self.ax_f = self.figure.add_subplot(2, 1, 2)
        self.ax_f.axis(self.ax_f_lim)
        self.ax_f.grid(True, which='major', linestyle='--')
        self.ax_f.set_xlabel('$f / R_\mathrm{b}$')
        self.ax_f.xaxis.set_major_locator(ticker.MultipleLocator(0.5))
        self.ax_f.yaxis.set_major_locator(ticker.MultipleLocator(10.0))


        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(toolbar)
        layout.addWidget(self.canvas)

        widget = QtWidgets.QWidget(self)
        self.setCentralWidget(widget)
        widget.setLayout(layout)
        self.resize(800, 500)
예제 #9
0
class dae2DPlot(QtWidgets.QDialog):
    plotDefaults = [
        daePlot2dDefaults('black', 0.5, 'solid', 'o', 6, 'black', 'black'),
        daePlot2dDefaults('blue', 0.5, 'solid', 's', 6, 'blue', 'black'),
        daePlot2dDefaults('red', 0.5, 'solid', '^', 6, 'red', 'black'),
        daePlot2dDefaults('green', 0.5, 'solid', 'p', 6, 'green', 'black'),
        daePlot2dDefaults('c', 0.5, 'solid', 'h', 6, 'c', 'black'),
        daePlot2dDefaults('m', 0.5, 'solid', '*', 6, 'm', 'black'),
        daePlot2dDefaults('k', 0.5, 'solid', 'd', 6, 'k', 'black'),
        daePlot2dDefaults('y', 0.5, 'solid', 'x', 6, 'y', 'black'),
        daePlot2dDefaults('black', 0.5, 'dashed', 'o', 6, 'black', 'black'),
        daePlot2dDefaults('blue', 0.5, 'dashed', 's', 6, 'blue', 'black'),
        daePlot2dDefaults('red', 0.5, 'dashed', '^', 6, 'red', 'black'),
        daePlot2dDefaults('green', 0.5, 'dashed', 'p', 6, 'green', 'black'),
        daePlot2dDefaults('c', 0.5, 'dashed', 'h', 6, 'c', 'black'),
        daePlot2dDefaults('m', 0.5, 'dashed', '*', 6, 'm', 'black'),
        daePlot2dDefaults('k', 0.5, 'dashed', 'd', 6, 'k', 'black'),
        daePlot2dDefaults('y', 0.5, 'dashed', 'x', 6, 'y', 'black'),
        daePlot2dDefaults('black', 0.5, 'dotted', 'o', 6, 'black', 'black'),
        daePlot2dDefaults('blue', 0.5, 'dotted', 's', 6, 'blue', 'black'),
        daePlot2dDefaults('red', 0.5, 'dotted', '^', 6, 'red', 'black'),
        daePlot2dDefaults('green', 0.5, 'dotted', 'p', 6, 'green', 'black'),
        daePlot2dDefaults('c', 0.5, 'dotted', 'h', 6, 'c', 'black'),
        daePlot2dDefaults('m', 0.5, 'dotted', '*', 6, 'm', 'black'),
        daePlot2dDefaults('k', 0.5, 'dotted', 'd', 6, 'k', 'black'),
        daePlot2dDefaults('y', 0.5, 'dotted', 'x', 6, 'y', 'black')
    ]

    def __init__(self, parent, updateInterval=0, animated=False):
        QtWidgets.QDialog.__init__(self, parent, QtCore.Qt.Window)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

        self.plotter = parent

        self.legendOn = True
        self.gridOn = True
        self.curves = []
        self.funcAnimation = None
        self._isAnimating = False
        self._timer = None
        self._cv_dlg = None
        self.xmin_policy = 0
        self.xmax_policy = 0
        self.ymin_policy = 1
        self.ymax_policy = 1

        if animated == True:
            self.updateInterval = updateInterval
            self.plotType = daeChooseVariable.plot2DAnimated
        elif updateInterval == 0:
            self.updateInterval = 0
            self.plotType = daeChooseVariable.plot2D
        else:
            self.updateInterval = int(updateInterval)
            self.plotType = daeChooseVariable.plot2DAutoUpdated

        self.setWindowTitle("2D plot")
        self.setWindowIcon(QtGui.QIcon(join(images_dir, 'line-chart.png')))

        exit = QtWidgets.QAction(QtGui.QIcon(join(images_dir, 'close.png')),
                                 'Exit', self)
        exit.setShortcut('Ctrl+Q')
        exit.setStatusTip('Exit application')
        exit.triggered.connect(self.close)

        export = QtWidgets.QAction(
            QtGui.QIcon(join(images_dir, 'template.png')), 'Export template',
            self)
        export.setShortcut('Ctrl+X')
        export.setStatusTip('Export template')
        export.triggered.connect(self.slotExportTemplate)

        properties = QtWidgets.QAction(
            QtGui.QIcon(join(images_dir, 'preferences.png')), 'Options', self)
        properties.setShortcut('Ctrl+P')
        properties.setStatusTip('Options')
        properties.triggered.connect(self.slotProperties)

        grid = QtWidgets.QAction(QtGui.QIcon(join(images_dir, 'grid.png')),
                                 'Grid on/off', self)
        grid.setShortcut('Ctrl+G')
        grid.setStatusTip('Grid on/off')
        grid.triggered.connect(self.slotToggleGrid)

        legend = QtWidgets.QAction(QtGui.QIcon(join(images_dir, 'legend.png')),
                                   'Legend on/off', self)
        legend.setShortcut('Ctrl+L')
        legend.setStatusTip('Legend on/off')
        legend.triggered.connect(self.slotToggleLegend)

        viewdata = QtWidgets.QAction(QtGui.QIcon(join(images_dir, 'data.png')),
                                     'View tabular data', self)
        viewdata.setShortcut('Ctrl+T')
        viewdata.setStatusTip('View tabular data')
        viewdata.triggered.connect(self.slotViewTabularData)

        export_csv = QtWidgets.QAction(
            QtGui.QIcon(join(images_dir, 'csv.png')), 'Export CSV', self)
        export_csv.setShortcut('Ctrl+S')
        export_csv.setStatusTip('Export CSV')
        export_csv.triggered.connect(self.slotExportCSV)

        fromUserData = QtWidgets.QAction(
            QtGui.QIcon(join(images_dir, 'add-user-data.png')),
            'Add line from the user-provided data...', self)
        fromUserData.setShortcut('Ctrl+D')
        fromUserData.setStatusTip('Add line from the user-provided data')
        fromUserData.triggered.connect(self.slotFromUserData)

        remove_line = QtWidgets.QAction(
            QtGui.QIcon(join(images_dir, 'remove.png')), 'Remove line', self)
        remove_line.setShortcut('Ctrl+R')
        remove_line.setStatusTip('Remove line')
        remove_line.triggered.connect(self.slotRemoveLine)

        new_line = QtWidgets.QAction(QtGui.QIcon(join(images_dir, 'add.png')),
                                     'Add line', self)
        new_line.setShortcut('Ctrl+A')
        new_line.setStatusTip('Add line')
        if animated == True:
            new_line.triggered.connect(self.newAnimatedCurve)
        else:
            new_line.triggered.connect(self.newCurve)

        play_animation = QtWidgets.QAction(
            QtGui.QIcon(join(images_dir, 'media-playback-start.png')),
            'Start animation', self)
        play_animation.setShortcut('Ctrl+S')
        play_animation.setStatusTip('Start animation')
        play_animation.triggered.connect(self.playAnimation)
        self.play_animation = play_animation  # save it

        stop_animation = QtWidgets.QAction(
            QtGui.QIcon(join(images_dir, 'media-playback-stop.png')),
            'Stop animation', self)
        stop_animation.setShortcut('Ctrl+E')
        stop_animation.setStatusTip('Stop animation')
        stop_animation.triggered.connect(self.stopAnimation)
        self.stop_animation = stop_animation  # save it

        export_video = QtWidgets.QAction(
            QtGui.QIcon(join(images_dir, 'save-video.png')),
            'Export video/sequence of images', self)
        export_video.setShortcut('Ctrl+V')
        export_video.setStatusTip('Export video/sequence of images')
        export_video.triggered.connect(self.exportVideo)

        self.actions_to_disable = [
            export, viewdata, export_csv, grid, legend, properties
        ]
        self.actions_to_disable_permanently = [
            fromUserData
        ]  #[new_line, fromUserData, remove_line]

        self.toolbar_widget = QtWidgets.QWidget(self)
        layoutToolbar = QtWidgets.QVBoxLayout(self.toolbar_widget)
        layoutToolbar.setContentsMargins(0, 0, 0, 0)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
                                           QtWidgets.QSizePolicy.Fixed)
        self.toolbar_widget.setSizePolicy(sizePolicy)

        layoutPlot = QtWidgets.QVBoxLayout(self)
        layoutPlot.setContentsMargins(2, 2, 2, 2)
        self.figure = Figure((8, 6.5), dpi=100, facecolor='white')  #"#E5E5E5")
        self.canvas = FigureCanvas(self.figure)
        self.canvas.setParent(self)
        self.canvas.axes = self.figure.add_subplot(111)

        self.mpl_toolbar = NavigationToolbar(self.canvas, self.toolbar_widget,
                                             False)

        #self.mpl_toolbar.addSeparator()
        self.mpl_toolbar.addAction(export)
        self.mpl_toolbar.addAction(export_csv)
        self.mpl_toolbar.addAction(viewdata)
        self.mpl_toolbar.addSeparator()
        self.mpl_toolbar.addAction(grid)
        self.mpl_toolbar.addAction(legend)
        self.mpl_toolbar.addSeparator()
        self.mpl_toolbar.addAction(new_line)
        self.mpl_toolbar.addAction(fromUserData)
        self.mpl_toolbar.addAction(remove_line)
        self.mpl_toolbar.addSeparator()
        #self.mpl_toolbar.addAction(properties)
        #self.mpl_toolbar.addSeparator()
        #self.mpl_toolbar.addAction(exit)
        if self.plotType == daeChooseVariable.plot2DAnimated:
            self.mpl_toolbar.addSeparator()
            self.mpl_toolbar.addAction(play_animation)
            self.mpl_toolbar.addAction(stop_animation)
            self.mpl_toolbar.addAction(export_video)

        self.fp9 = matplotlib.font_manager.FontProperties(family='sans-serif',
                                                          style='normal',
                                                          variant='normal',
                                                          weight='normal',
                                                          size=9)
        self.fp10 = matplotlib.font_manager.FontProperties(family='sans-serif',
                                                           style='normal',
                                                           variant='normal',
                                                           weight='normal',
                                                           size=10)
        self.fp12 = matplotlib.font_manager.FontProperties(family='sans-serif',
                                                           style='normal',
                                                           variant='normal',
                                                           weight='normal',
                                                           size=12)

        self.textTime = self.figure.text(0.01,
                                         0.01,
                                         '',
                                         fontproperties=self.fp10)

        self.xtransform = 1.0
        self.ytransform = 1.0

        for xlabel in self.canvas.axes.get_xticklabels():
            xlabel.set_fontproperties(self.fp10)
        for ylabel in self.canvas.axes.get_yticklabels():
            ylabel.set_fontproperties(self.fp10)

        layoutToolbar.addWidget(self.mpl_toolbar)
        layoutPlot.addWidget(self.canvas)
        layoutPlot.addWidget(self.toolbar_widget)

        if animated == False and self.updateInterval > 0:
            self._timer = QtCore.QTimer()
            self._timer.timeout.connect(self.updateCurves)
            self._timer.start(self.updateInterval)

    def closeEvent(self, event):
        #print("dae2DPlot.closeEvent")
        if self.funcAnimation:
            self.funcAnimation.event_source.stop()

        if self._timer:
            self._timer.stop()

        return QtWidgets.QDialog.closeEvent(self, event)

    def updateCurves(self):
        try:
            #                                                      these three not used
            for (line, variable, domainIndexes, domainPoints, fun, times,
                 xPoints, yPoints_2D) in self.curves:
                results = fun(variable, domainIndexes, domainPoints)
                if self.xtransform != 1:
                    xPoints = numpy.array(results[5]) * self.xtransform
                else:
                    xPoints = results[5]

                if self.ytransform != 1:
                    yPoints = numpy.array(results[6]) * self.ytransform
                else:
                    yPoints = results[6]

                currentTime = results[7]

                line.set_xdata(xPoints)
                line.set_ydata(yPoints)

                if self.textTime:
                    t = 'Time = {0} s'.format(currentTime)
                    self.textTime.set_text(t)

            #self.reformatPlot()

        except Exception as e:
            print((str(e)))

    #@QtCore.pyqtSlot()
    def slotExportTemplate(self):
        try:
            curves = []
            template = {
                'curves': curves,
                'plotType': self.plotType,
                'updateInterval': self.updateInterval,
                'xlabel': self.canvas.axes.get_xlabel(),
                'xmin': self.canvas.axes.get_xlim()[0],
                'xmax': self.canvas.axes.get_xlim()[1],
                'xscale': self.canvas.axes.get_xscale(),
                'xtransform': 1.0,
                'ylabel': self.canvas.axes.get_ylabel(),
                'ymin': self.canvas.axes.get_ylim()[0],
                'ymax': self.canvas.axes.get_ylim()[1],
                'yscale': self.canvas.axes.get_yscale(),
                'ytransform': 1.0,
                'legendOn': self.legendOn,
                'gridOn': self.gridOn,
                'plotTitle': self.canvas.axes.get_title(),
                'windowTitle': str(self.windowTitle()),
                'xmin_policy': int(self.xmin_policy),
                'xmax_policy': int(self.xmax_policy),
                'ymin_policy': int(self.ymin_policy),
                'ymax_policy': int(self.ymax_policy)
            }

            for (line, variable, domainIndexes, domainPoints, fun, times,
                 xPoints, yPoints_2D) in self.curves:
                # variableName, indexes, points, linelabel, style = {linecolor, linewidth, linestyle, marker, markersize, markerfacecolor, markeredgecolor}
                style = daePlot2dDefaults(line.get_color(),
                                          line.get_linewidth(),
                                          line.get_linestyle(),
                                          line.get_marker(),
                                          line.get_markersize(),
                                          line.get_markerfacecolor(),
                                          line.get_markeredgecolor())
                curves.append((variable.Name, domainIndexes, domainPoints,
                               line.get_label(), style.to_dict()))

            s = json.dumps(template, indent=2, sort_keys=True)

            filename, ok = QtWidgets.QFileDialog.getSaveFileName(
                self, "Save 2D plot template", "template.pt",
                "Templates (*.pt)")
            if not ok:
                return

            f = open(filename, 'w')
            f.write(s)
            f.close()

        except Exception as e:
            print((str(e)))

    #@QtCore.pyqtSlot()
    def slotProperties(self):
        figure_edit(self.canvas, self)

    #@QtCore.pyqtSlot()
    def slotToggleLegend(self):
        self.legendOn = not self.legendOn
        self.updateLegend()

    #@QtCore.pyqtSlot()
    def slotToggleGrid(self):
        self.gridOn = not self.gridOn
        self.updateGrid()

    def updateLegend(self):
        if self.legendOn:
            self.canvas.axes.legend(loc=0,
                                    prop=self.fp9,
                                    numpoints=1,
                                    fancybox=True)
        else:
            self.canvas.axes.legend_ = None
        self.canvas.draw()
        #self.reformatPlot()

    def updateGrid(self):
        self.canvas.axes.grid(self.gridOn)
        self.canvas.draw()
        #self.reformatPlot()

    #@QtCore.pyqtSlot()
    def slotExportCSV(self):
        strInitialFilename = QtCore.QDir.current().path()
        strInitialFilename += "/untitled.csv"
        strExt = "Comma separated files (*.csv)"
        strCaption = "Save file"
        fileName, ok = QtWidgets.QFileDialog.getSaveFileName(
            self, strCaption, strInitialFilename, strExt)
        if not ok:
            return

        datafile = open(str(fileName), 'w')
        lines = self.canvas.axes.get_lines()

        for line in lines:
            xlabel = self.canvas.axes.get_xlabel()
            ylabel = line.get_label()
            x = line.get_xdata()
            y = line.get_ydata()
            datafile.write('\"' + xlabel + '\",\"' + ylabel + '\"\n')
            for i in range(0, len(x)):
                datafile.write('%.14e,%.14e\n' % (x[i], y[i]))
            datafile.write('\n')

    #@QtCore.pyqtSlot()
    def slotViewTabularData(self):
        lines = self.canvas.axes.get_lines()

        tableDialog = daeTableDialog(self)
        tableDialog.setWindowTitle('Raw data')
        table = tableDialog.ui.tableWidget
        nr = 0
        ncol = len(lines)
        for line in lines:
            n = len(line.get_xdata())
            if nr < n:
                nr = n

        xlabel = self.canvas.axes.get_xlabel()
        table.setRowCount(nr)
        table.setColumnCount(ncol)
        horHeader = []
        verHeader = []
        for i, line in enumerate(lines):
            xlabel = self.canvas.axes.get_xlabel()
            ylabel = line.get_label()
            x = line.get_xdata()
            y = line.get_ydata()
            horHeader.append(ylabel)
            for k in range(0, len(x)):
                newItem = QtWidgets.QTableWidgetItem('%.14f' % y[k])
                table.setItem(k, i, newItem)
            for k in range(0, len(x)):
                verHeader.append('%.14f' % x[k])

        table.setHorizontalHeaderLabels(horHeader)
        table.setVerticalHeaderLabels(verHeader)
        table.resizeRowsToContents()
        tableDialog.exec_()

    #@QtCore.pyqtSlot()
    def slotRemoveLine(self):
        lines = self.canvas.axes.get_lines()
        items = []
        for line in lines:
            label = line.get_label()
            items.append(label)

        nameToRemove, ok = QtWidgets.QInputDialog.getItem(
            self, "Choose line to remove", "Lines:", items, 0, False)
        if ok:
            for i, line in enumerate(lines):
                label = line.get_label()
                if label == str(nameToRemove):
                    self.canvas.axes.lines.pop(i)
                    #self.reformatPlot()
                    # updateLegend will also call canvas.draw()
                    self.updateLegend()
                    return

    def newFromTemplate(self, template):
        """
        template is a dictionary:

        .. code-block:: javascript

           {
            "curves": [
                [
                "variableName", 
                [
                    1, 
                    -1
                ], 
                [
                    "0.05", 
                    "*"
                ], 
                "variableName(0.05, *)", 
                {
                    "color": [
                    0.0, 
                    0.0, 
                    0.0, 
                    1.0
                    ], 
                    "linestyle": "-", 
                    "linewidth": 1.0, 
                    "marker": "o", 
                    "markeredgecolor": "#000000ff", 
                    "markerfacecolor": "#000000ff", 
                    "markersize": 0.0
                }
                ]
            ], 
            "gridOn": true, 
            "legendOn": true, 
            "plotTitle": "", 
            "plotType": 0, 
            "updateInterval": 0, 
            "windowTitle": "tutorial_dealii_8.ActiveSurface.cs(2.0, *)", 
            "xlabel": "y-cordinate", 
            "xmax": 31.45, 
            "xmax_policy": 0, 
            "xmin": -0.4500000000000002, 
            "xmin_policy": 0, 
            "xscale": "linear", 
            "xtransform": 1.0, 
            "ylabel": "cs (mol/m**2)", 
            "ymax": 0.34935417753491, 
            "ymax_policy": 1, 
            "ymin": -0.00938086024107475, 
            "ymin_policy": 1, 
            "yscale": "linear", 
            "ytransform": 1.0
           }
        """
        processes = {}
        for process in self.plotter.getProcesses():
            processes[process.Name] = process

        if len(processes) == 0:
            return

        if len(template) == 0:
            return False

        curves = template['curves']

        if 'plotType' in template:
            self.plotType = int(template['plotType'])

        if 'xtransform' in template:
            self.xtransform = template['xtransform']
        if 'ytransform' in template:
            self.ytransform = template['ytransform']

        for i, curve in enumerate(curves):
            variableName = curve[0]
            domainIndexes = curve[1]
            domainPoints = curve[2]
            label = None
            pd = None
            if len(curve) > 3:
                label = curve[3]
            if len(curve) > 4:
                pd = daePlot2dDefaults.from_dict(curve[4])

            windowTitle = "Select process for variable {0} (of {1})".format(
                i + 1, len(curves))
            var_to_look_for = "Variable: {0}({1})".format(
                variableName, ','.join(domainPoints))
            items = sorted(processes.keys())
            processName, ok = self.showSelectProcessDialog(
                windowTitle, var_to_look_for, items)
            if not ok:
                return False

            process = processes[str(processName)]
            for variable in process.Variables:
                if variableName == variable.Name:
                    if self.plotType == daeChooseVariable.plot2D or self.plotType == daeChooseVariable.plot2DAutoUpdated:
                        variable, domainIndexes, domainPoints, xAxisLabel, yAxisLabel, xPoints, yPoints, currentTime = daeChooseVariable.get2DData(
                            variable, domainIndexes, domainPoints)
                        self._addNewCurve(variable, domainIndexes,
                                          domainPoints, xAxisLabel, yAxisLabel,
                                          xPoints, yPoints, currentTime, label,
                                          pd)
                        break

                    elif self.plotType == daeChooseVariable.plot2DAnimated:
                        variable, domainIndexes, domainPoints, xAxisLabel, yAxisLabel, xPoints, yPoints, times = daeChooseVariable.get2DAnimatedData(
                            variable, domainIndexes, domainPoints)
                        self._addNewAnimatedCurve(variable, domainIndexes,
                                                  domainPoints, xAxisLabel,
                                                  yAxisLabel, xPoints, yPoints,
                                                  times, None, None)
                        for action in self.actions_to_disable_permanently:
                            action.setEnabled(False)
                        break

                    else:
                        raise RuntimeError('Invalid plot type')

        if 'xlabel' in template:
            self.canvas.axes.set_xlabel(template['xlabel'],
                                        fontproperties=self.fp12)
        if 'xmin' in template and 'xmax' in template:
            self.canvas.axes.set_xlim(float(template['xmin']),
                                      float(template['xmax']))
        if 'xscale' in template:
            self.canvas.axes.set_xscale(template['xscale'])

        if 'ylabel' in template:
            self.canvas.axes.set_ylabel(template['ylabel'],
                                        fontproperties=self.fp12)
        if 'ymin' in template and 'ymax' in template:
            self.canvas.axes.set_ylim(float(template['ymin']),
                                      float(template['ymax']))
        if 'yscale' in template:
            self.canvas.axes.set_yscale(template['yscale'])

        if 'gridOn' in template:
            self.gridOn = template['gridOn']
            self.canvas.axes.grid(self.gridOn)

        if 'legendOn' in template:
            self.legendOn = template['legendOn']
            if self.legendOn:
                self.canvas.axes.legend(loc=0,
                                        prop=self.fp9,
                                        numpoints=1,
                                        fancybox=True)
            else:
                self.canvas.axes.legend_ = None

        if 'plotTitle' in template:
            self.canvas.axes.set_title(template['plotTitle'])

        if 'windowTitle' in template:
            self.setWindowTitle(template['windowTitle'])

        if 'xmin_policy' in template:
            self.xmin_policy = int(template['xmin_policy'])
        if 'xmax_policy' in template:
            self.xmax_policy = int(template['xmax_policy'])
        if 'ymin_policy' in template:
            self.ymin_policy = int(template['ymin_policy'])
        if 'ymax_policy' in template:
            self.ymax_policy = int(template['ymax_policy'])

        #fmt = matplotlib.ticker.ScalarFormatter(useOffset = False)
        #fmt.set_scientific(False)
        #fmt.set_powerlimits((-3, 4))
        #self.canvas.axes.xaxis.set_major_formatter(fmt)
        #self.canvas.axes.yaxis.set_major_formatter(fmt)

        self.figure.tight_layout()
        self.canvas.draw()

        return True

    def showSelectProcessDialog(self, windowTitle, label, items):
        dlg = QtWidgets.QInputDialog(self)
        dlg.resize(500, 300)
        dlg.setWindowTitle(windowTitle)
        dlg.setLabelText(label)
        dlg.setComboBoxItems(items)

        dlg.setComboBoxEditable(False)
        dlg.setOption(QtWidgets.QInputDialog.UseListViewForComboBoxItems)

        if dlg.exec_() == QtWidgets.QDialog.Accepted:
            return str(dlg.textValue()), True
        else:
            return '', False

    def _updateFrame(self, frame):
        lines = []
        for curve in self.curves:
            line = curve[0]
            lines.append(line)

            times = curve[5]
            xPoints = curve[6]
            yPoints = curve[7]
            yData = yPoints[frame]
            line.set_ydata(yData)
            time = times[frame]

            if self.xmin_policy == 0:  # From 1st frame
                xmin = numpy.min(xPoints)
            elif self.xmin_policy == 1:  # Overall min value
                xmin = numpy.min(xPoints)
            elif self.xmin_policy == 2:  # Adaptive
                xmin = numpy.min(xPoints)
            else:  # Do not change it
                xmin = self.canvas.axes.get_xlim()[0]

            if self.xmax_policy == 0:  # From 1st frame
                xmax = numpy.max(xPoints)
                dx = 0.5 * (xmax - xmin) * 0.05
            elif self.xmax_policy == 1:  # Overall max value
                xmax = numpy.max(xPoints)
                dx = 0.5 * (xmax - xmin) * 0.05
            elif self.xmax_policy == 2:  # Adaptive
                xmax = numpy.max(xPoints)
                dx = 0.5 * (xmax - xmin) * 0.05
            else:  # Do not change it
                xmax = self.canvas.axes.get_xlim()[1]
                dx = 0.0

            if self.ymin_policy == 0:  # From 1st frame
                ymin = numpy.min(yPoints[0])
            elif self.ymin_policy == 1:  # Overall min value
                ymin = numpy.min(yPoints)
            elif self.ymin_policy == 2:  # Adaptive
                ymin = numpy.min(yPoints[frame])
            else:  # Do not change it
                ymin = self.canvas.axes.get_ylim()[0]

            if self.ymax_policy == 0:  # From 1st frame
                ymax = numpy.max(yPoints[0])
                dy = 0.5 * (ymax - ymin) * 0.05
            elif self.ymax_policy == 1:  # Overall max value
                ymax = numpy.max(yPoints)
                dy = 0.5 * (ymax - ymin) * 0.05
            elif self.ymax_policy == 2:  # Adaptive
                ymax = numpy.max(yPoints[frame])
                dy = 0.5 * (ymax - ymin) * 0.05
            else:  # Do not change it
                ymax = self.canvas.axes.get_ylim()[1]
                dy = 0.0

        self.canvas.axes.set_xlim(xmin - dx, xmax + dx)
        self.canvas.axes.set_ylim(ymin - dy, ymax + dy)

        self.canvas.axes.set_title('time = %f s' % time,
                                   fontproperties=self.fp10)

        if frame == len(times) - 1:  # the last frame
            for action in self.actions_to_disable:
                action.setEnabled(True)

            del self.funcAnimation
            self.funcAnimation = None

            self.play_animation.setIcon(
                QtGui.QIcon(join(images_dir, 'media-playback-start.png')))
            self.play_animation.setStatusTip('Start animation')
            self.play_animation.setText('Start animation')
            self._isAnimating = False

        return lines

    def _startAnimation(self):
        #if len(self.curves) != 1:
        #    return

        # Set properties for the frame 0
        curve = self.curves[0]
        times = curve[5]
        frames = numpy.arange(0, len(times))

        self.canvas.axes.set_title('time = %f s' % times[0],
                                   fontproperties=self.fp10)
        self.funcAnimation = animation.FuncAnimation(
            self.figure,
            self._updateFrame,
            frames,
            interval=self.updateInterval,
            blit=False,
            repeat=False)
        self.play_animation.setIcon(
            QtGui.QIcon(join(images_dir, 'media-playback-pause.png')))
        self.play_animation.setStatusTip('Pause animation')
        self.play_animation.setText('Pause animation')
        self._isAnimating = True
        #At the end do not call show() nor save(), they will be ran by a caller

    #@QtCore.pyqtSlot()
    def playAnimation(self):
        if self.funcAnimation:  # animation started - pause/resume it
            if self._isAnimating:  # pause it
                for action in self.actions_to_disable:
                    action.setEnabled(True)
                self.funcAnimation.event_source.stop()
                self.play_animation.setIcon(
                    QtGui.QIcon(join(images_dir, 'media-playback-start.png')))
                self.play_animation.setStatusTip('Start animation')
                self.play_animation.setText('Start animation')
                self._isAnimating = False
                self.canvas.draw()
            else:  # restart it
                for action in self.actions_to_disable:
                    action.setEnabled(False)
                self.funcAnimation.event_source.start()
                self.play_animation.setIcon(
                    QtGui.QIcon(join(images_dir, 'media-playback-pause.png')))
                self.play_animation.setStatusTip('Pause animation')
                self.play_animation.setText('Pause animation')
                self._isAnimating = True
                self.canvas.draw()

        else:  # start animation
            for action in self.actions_to_disable:
                action.setEnabled(False)
            self._startAnimation()
            self.canvas.draw()

    #@QtCore.pyqtSlot()
    def stopAnimation(self):
        if self.funcAnimation:  # animated started - stop it
            for action in self.actions_to_disable:
                action.setEnabled(True)

            self.funcAnimation.event_source.stop()
            del self.funcAnimation
            self.funcAnimation = None

            self.play_animation.setIcon(
                QtGui.QIcon(join(images_dir, 'media-playback-start.png')))
            self.play_animation.setStatusTip('Start animation')
            self.play_animation.setText('Start animation')
            self._isAnimating = False

        # Go back to frame 0
        self._updateFrame(0)
        self.canvas.draw()

    #@QtCore.pyqtSlot()
    def exportVideo(self):
        dlg = daeSavePlot2DVideo()
        for enc in sorted(animation.writers.list()):
            dlg.ui.comboEncoders.addItem(str(enc))
        dlg.ui.lineeditCodec.setText('')
        dlg.ui.lineeditFilename.setText(
            os.path.join(os.path.expanduser('~'), 'video.avi'))
        dlg.ui.spinFPS.setValue(10)
        dlg.ui.lineeditExtraArgs.setText(json.dumps(
            []))  # ['-pix_fmt', 'yuv420p']
        dlg.ui.spinBitrate.setValue(-1)

        if dlg.exec_() != QtWidgets.QDialog.Accepted:
            return False

        filename = str(dlg.ui.lineeditFilename.text())
        fps = int(dlg.ui.spinFPS.value())
        encoder = str(dlg.ui.comboEncoders.currentText())
        codec = str(dlg.ui.lineeditCodec.text())
        bitrate = int(dlg.ui.spinBitrate.value())
        extra_args = []
        try:
            extra_args = list(json.loads(str(dlg.ui.lineeditExtraArgs.text())))
        except:
            pass
        if bitrate == -1:
            bitrate = None
        if codec == '':
            codec = None
        if not extra_args:
            extra_args = None

        print('%s(fps = %s, codec = %s, bitrate = %s, extra_args = %s) -> %s' %
              (encoder, fps, codec, bitrate, extra_args, filename))

        # First stop the existing animation, if already started
        self.stopAnimation()
        Writer = animation.writers[encoder]
        writer = Writer(fps=fps,
                        codec=codec,
                        bitrate=bitrate,
                        extra_args=extra_args)
        self._startAnimation()
        self.funcAnimation.save(filename, writer=writer)

    def slotFromUserData(self):
        dlg = daeUserData()
        if dlg.exec_() != QtWidgets.QDialog.Accepted:
            return

        self.newCurveFromUserData(dlg.xLabel, dlg.yLabel, dlg.lineLabel,
                                  dlg.xPoints, dlg.yPoints)

    def newCurveFromUserData(self, xAxisLabel, yAxisLabel, lineLabel, xPoints,
                             yPoints):
        class dummyVariable(object):
            def __init__(self, name='', units=''):
                self.Name = name
                self.Units = units

        self._addNewCurve(dummyVariable(lineLabel), [], [], xAxisLabel,
                          yAxisLabel, xPoints, yPoints, None, lineLabel, None)
        return True

    #@QtCore.pyqtSlot()
    def newCurve(self):
        processes = self.plotter.getProcesses()

        if not self._cv_dlg:
            self._cv_dlg = daeChooseVariable(self.plotType)
        self._cv_dlg.updateProcessesList(processes)
        self._cv_dlg.setWindowTitle('Choose variable for 2D plot')
        if self._cv_dlg.exec_() != QtWidgets.QDialog.Accepted:
            return False

        variable, domainIndexes, domainPoints, xAxisLabel, yAxisLabel, xPoints, yPoints, currentTime = self._cv_dlg.getPlot2DData(
        )
        self._addNewCurve(variable, domainIndexes, domainPoints, xAxisLabel,
                          yAxisLabel, xPoints, yPoints, currentTime, None,
                          None)

        return True

    def newVar1_vs_Var2Curve(self):
        processes = self.plotter.getProcesses()

        if not self._cv_dlg:
            self._cv_dlg = daeChooseVariable(self.plotType)
        self._cv_dlg.updateProcessesList(processes)

        self._cv_dlg.setWindowTitle(
            'Choose the 1st variable (x axis) for 2D plot')
        if self._cv_dlg.exec_() != QtWidgets.QDialog.Accepted:
            return False

        variable1, domainIndexes1, domainPoints1, xAxisLabel1, yAxisLabel1, xPoints1, yPoints1, currentTime1 = self._cv_dlg.getPlot2DData(
        )

        self._cv_dlg.setWindowTitle(
            'Choose the 2nd variable (y axis) for 2D plot')
        if self._cv_dlg.exec_() != QtWidgets.QDialog.Accepted:
            return False

        variable2, domainIndexes2, domainPoints2, xAxisLabel2, yAxisLabel2, xPoints2, yPoints2, currentTime2 = self._cv_dlg.getPlot2DData(
        )

        if len(yPoints1) != len(yPoints2):
            QtWidgets.QMessageBox.warning(
                None, 'Variable1 vs. variable2 2D plot',
                'The number of points in variables do not match')
            return False

        self._addNewCurve(variable2, domainIndexes2, domainPoints2,
                          yAxisLabel1, yAxisLabel2, yPoints1, yPoints2,
                          currentTime2, None, None)

        return True

    #@QtCore.pyqtSlot()
    def newAnimatedCurve(self):
        processes = self.plotter.getProcesses()

        if not self._cv_dlg:
            self._cv_dlg = daeChooseVariable(self.plotType)
        self._cv_dlg.updateProcessesList(processes)
        self._cv_dlg.setWindowTitle('Choose variable for animated 2D plot')
        if self._cv_dlg.exec_() != QtWidgets.QDialog.Accepted:
            return False

        dlg = daeAnimationParameters()
        if dlg.exec_() != QtWidgets.QDialog.Accepted:
            return

        self.updateInterval = int(dlg.ui.spinUpdateInterval.value())
        self.xmin_policy = dlg.ui.comboXmin.currentIndex()
        self.xmax_policy = dlg.ui.comboXmax.currentIndex()
        self.ymin_policy = dlg.ui.comboYmin.currentIndex()
        self.ymax_policy = dlg.ui.comboYmax.currentIndex()

        variable, domainIndexes, domainPoints, xAxisLabel, yAxisLabel, xPoints, yPoints, times = self._cv_dlg.getPlot2DAnimatedData(
        )
        self._addNewAnimatedCurve(variable, domainIndexes, domainPoints,
                                  xAxisLabel, yAxisLabel, xPoints, yPoints,
                                  times, None, None)

        for action in self.actions_to_disable_permanently:
            action.setEnabled(False)

        self._updateFrame(0)

        return True

    def _addNewAnimatedCurve(self,
                             variable,
                             domainIndexes,
                             domainPoints,
                             xAxisLabel,
                             yAxisLabel,
                             xPoints,
                             yPoints_2D,
                             times,
                             label=None,
                             pd=None):
        domains = '(' + ', '.join(domainPoints) + ')'

        if not label:
            label = variable.Name.replace("&", "").replace(";", "") + domains

        line = self.addLine(xAxisLabel, yAxisLabel, xPoints, yPoints_2D[0],
                            label, pd)
        self.setWindowTitle(label)

        #                                                                 update fun is None
        self.curves.append((line, variable, domainIndexes, domainPoints, None,
                            times, xPoints, yPoints_2D))

    def _addNewCurve(self,
                     variable,
                     domainIndexes,
                     domainPoints,
                     xAxisLabel,
                     yAxisLabel,
                     xPoints,
                     yPoints,
                     currentTime,
                     label=None,
                     pd=None):
        domains = "("
        for i in range(0, len(domainPoints)):
            if i != 0:
                domains += ", "
            domains += domainPoints[i]
        domains += ")"

        if not label:
            label = variable.Name.replace("&", "").replace(";", "") + domains

        line = self.addLine(xAxisLabel, yAxisLabel, xPoints, yPoints, label,
                            pd)
        self.setWindowTitle(label)
        #                                                                                              everything after update fun is none
        self.curves.append((line, variable, domainIndexes, domainPoints,
                            daeChooseVariable.get2DData, None, None, None))

    def addLine(self, xAxisLabel, yAxisLabel, xPoints, yPoints, label, pd):
        no_lines = len(self.canvas.axes.get_lines())
        if not pd:
            n = no_lines % len(dae2DPlot.plotDefaults)
            pd = dae2DPlot.plotDefaults[n]

        xPoints_ = numpy.array(xPoints) * self.xtransform
        yPoints_ = numpy.array(yPoints) * self.ytransform

        line, = self.canvas.axes.plot(xPoints_, yPoints_, label=label, color=pd.color, linewidth=pd.linewidth, \
                                      linestyle=pd.linestyle, marker=pd.marker, markersize=pd.markersize, \
                                      markerfacecolor=pd.markerfacecolor, markeredgecolor=pd.markeredgecolor)

        if no_lines == 0:
            # Set labels, fonts, gridlines and limits only when adding the first line
            self.canvas.axes.set_xlabel(xAxisLabel, fontproperties=self.fp12)
            self.canvas.axes.set_ylabel(yAxisLabel, fontproperties=self.fp12)
            t = self.canvas.axes.xaxis.get_offset_text()
            t.set_fontproperties(self.fp10)
            t = self.canvas.axes.yaxis.get_offset_text()
            t.set_fontproperties(self.fp10)
            self.updateGrid()

        # Update the legend and (x,y) limits after every addition
        self.updateLegend()
        self.reformatPlot()

        return line

    def reformatPlot(self):
        lines = self.canvas.axes.get_lines()
        xmin = 1e20
        xmax = -1e20
        ymin = 1e20
        ymax = -1e20
        for line in lines:
            if numpy.min(line.get_xdata()) < xmin:
                xmin = numpy.min(line.get_xdata())
            if numpy.max(line.get_xdata()) > xmax:
                xmax = numpy.max(line.get_xdata())

            if numpy.min(line.get_ydata()) < ymin:
                ymin = numpy.min(line.get_ydata())
            if numpy.max(line.get_ydata()) > ymax:
                ymax = numpy.max(line.get_ydata())

        dx = (xmax - xmin) * 0.05
        dy = (ymax - ymin) * 0.05
        xmin -= dx
        xmax += dx
        ymin -= dy
        ymax += dy

        self.canvas.axes.set_xlim(xmin, xmax)
        self.canvas.axes.set_ylim(ymin, ymax)

        #self.canvas.axes.grid(self.gridOn)

        #if self.legendOn:
        #    self.canvas.axes.legend(loc = 0, prop=self.fp9, numpoints = 1, fancybox=True)
        #else:
        #    self.canvas.axes.legend_ = None

        self.figure.tight_layout()
        self.canvas.draw()
예제 #10
0
class PlotWindow(QtWidgets.QMainWindow):
    def __init__(self, nrows=1, ncols=1, **kwargs):
        matplotlib.use('Qt5Agg')

        qapp = QtWidgets.QApplication.instance()
        if qapp is None:
            qapp = QtWidgets.QApplication(sys.argv)

        self.qapp = qapp

        super().__init__()

        self._main = QtWidgets.QWidget()

        self.setStyle(QStyleFactory.create('Fusion'))

        self.setCentralWidget(self._main)
        self.layout = QGridLayout(self._main)

        marker_kw = {}
        for k in marker_default_params.keys():
            if k in kwargs.keys():
                marker_kw[k] = kwargs.pop(k)

        title = kwargs.pop('title', None)
        icon = kwargs.pop('icon', None)

        if icon != None:
            self.setWindowIcon(QtGui.QIcon(str(icon)))

        marker_kw['interactive'] = kwargs.pop('interactive', True)
        marker_kw['top_axes'] = kwargs.pop('top_axes', None)
        marker_kw['link_all'] = kwargs.pop('link_all', False)

        self.single_trace = kwargs.pop('single_trace', False)

        subplot_kw = kwargs.pop('subplot_kw', {})
        sharex = kwargs.pop('sharex', False)
        sharey = kwargs.pop('sharey', False)
        gridspec_kw = kwargs.pop('gridspec_kw', None)

        self.fig = plt.figure(**kwargs)

        self.axes_grid = self.fig.subplots(nrows,
                                           ncols,
                                           squeeze=False,
                                           sharex=False,
                                           sharey=False,
                                           subplot_kw=subplot_kw,
                                           gridspec_kw=gridspec_kw)

        self.axes = self.axes_grid.flatten()

        self.nrows = nrows
        self.ncols = ncols

        self.canvas = self.fig.canvas
        self.canvas.mpl_disconnect(self.canvas.manager.key_press_handler_id)

        self.canvas.manager.show = self._show
        self.layout.addWidget(self.canvas, 0, 0, (self.nrows * self.ncols) + 1,
                              1)

        self.toolbar = NavigationToolbar(self.canvas, self, coordinates=False)
        self.build_toolbar()

        self.addToolBar(self.toolbar)
        self.fig.canvas.toolbar = self.toolbar
        self.canvas.setFocusPolicy(QtCore.Qt.ClickFocus)
        self.canvas.setFocus()

        p = self.palette()
        p.setColor(self.backgroundRole(), Qt.white)
        self.setPalette(p)

        title = 'Figure {}'.format(
            self.fig.canvas.manager.num) if title == None else title
        self.setWindowTitle(title)
        self._drop_event_handler = None

        self.fig.marker_enable(**marker_kw)
        self.fig.qapp = self.qapp
        self.fig.app = self
        self.draw_updates = False
        self.axes_cb_group = []
        self.current_data_format = None

        self.data_format_options = None

        for i, ax in enumerate(self.axes):
            ax_cb = AxesCheckBoxGroup(
                self, ax, "Axes {},{}".format(i // self.nrows, i % self.nrows))
            self.axes_cb_group.append(ax_cb)

    def keyPressEvent(self, event):
        if event.key() in (QtCore.Qt.Key_F5, ):
            self.fig.canvas.draw()
        super().keyPressEvent(event)

    def set_draw_updates(self, state):
        prev = self.draw_updates
        self.draw_updates = state
        return prev

    def add_toolbar_actions(self, *widgets, end=True):
        for icon_path, name, tooltip, action in widgets:

            icon = QtGui.QPixmap(str(icon_path))
            icon.setDevicePixelRatio(self.canvas._dpi_ratio)
            a = self.toolbar.addAction(QtGui.QIcon(icon), name, action)
            a.setToolTip(tooltip)

        if end:
            locLabel = QLabel("", self.toolbar)
            locLabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTop)
            locLabel.setSizePolicy(
                QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                      QtWidgets.QSizePolicy.Ignored))
            self.toolbar.addWidget(locLabel)

    def build_toolbar(self):

        self.toolbar.removeAction(self.toolbar._actions['configure_subplots'])
        self.toolbar.removeAction(self.toolbar._actions['forward'])
        self.toolbar.removeAction(self.toolbar._actions['back'])

        widgets = [
            (str(dir_ / 'icons/layout_large.png'), 'Layout',
             'Apply Tight Layout', self.set_tight_layout),
            (str(dir_ / 'icons/copy_large.png'), 'Copy', 'Copy To Clipboard',
             self.copy_figure),
            (str(dir_ / 'icons/erase_large.png'), 'Delete',
             'Remove All Markers', self.remove_all),
            (str(dir_ / 'icons/autoscale_y.png'), 'Autoscale',
             'Autoscale Y-Axis', self.autoscale_y),
            (str(dir_ / 'icons/autoscale_x.png'), 'Autoscale',
             'Autoscale X-Axis', self.autoscale_x),
            (str(dir_ / 'icons/set_format_large.png'), 'Set Data Format',
             'Set Data Format', self.set_data_format),
        ]

        self.add_toolbar_actions(*widgets, end=False)
        self.toolbar.addSeparator()

    def add_drop_event_handler(self, handler):
        self._drop_event_handler = handler

        if self._drop_event_handler != None:
            self.setAcceptDrops(True)

    def dragEnterEvent(self, e):

        if e.mimeData().hasText():
            text = e.mimeData().text()
            m = re.search(r's\d+p$', text)
            if m != None:
                e.accept()
            else:
                e.ignore()
        else:
            e.ignore()

    def dropEvent(self, e):
        text = e.mimeData().text()
        self._drop_event_handler(text)
        self.change_data_format(self.current_data_format)
        self.update_axes_groups()
        self.autoscale_x()
        self.remove_all()
        self.fig.canvas.draw()

    def set_data_format(self):
        dialog = DataFormatDialog(self, self.change_data_format,
                                  self.data_format_options)
        dialog.show()

    def change_data_format(self, options):
        self.current_data_format = options
        for i, ax in enumerate(self.axes):
            self._data_format_handler(ax, options[i])
        self.autoscale_y()

    def add_data_format_handler(self, func, format_options, initial=None):
        self._data_format_handler = func
        self.data_format_options = format_options
        self.current_data_format = [initial] * len(self.axes)

    def autoscale_x(self):
        for ax_cb in self.axes_cb_group:
            ax_cb.scale_visible(yscale=False)
        self.fig.canvas.draw()

    def autoscale_y(self):
        for ax_cb in self.axes_cb_group:
            ax_cb.scale_visible(xscale=False)
        self.fig.canvas.draw()

    def remove_all(self):
        for ax in self.fig._top_axes:
            ax.marker_delete_all()
            ax.draw_lines_markers()
            for l_ax in ax.marker_linked_axes:
                l_ax.marker_delete_all()
                l_ax.draw_lines_markers()

    def set_tight_layout(self):
        self.fig.tight_layout()
        self.canvas.draw()

    def copy_figure(self):

        buf = io.BytesIO()
        self.fig.savefig(buf)

        image = Image.open(buf)
        output = io.BytesIO()
        image.convert("RGB").save(output, "BMP")
        data = output.getvalue()[14:]
        output.close()

        win32clipboard.OpenClipboard()
        win32clipboard.EmptyClipboard()
        win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
        win32clipboard.CloseClipboard()
        buf.close()

    def update_axes_groups(self):
        for i, ax_cb in enumerate(self.axes_cb_group):
            ax_cb.update_checkboxes()

    def create_axes_groups(self):
        for i, ax_cb in enumerate(self.axes_cb_group):
            ax_cb.add_to_layout(self.layout, i, 1)

        self.layout.addWidget(QGroupBox(), i + 1, 1)
        self.layout.setColumnStretch(0, 1)
        self.layout.setRowStretch(i + 1, 1)

    def _show(self):

        self.create_axes_groups()
        self.set_draw_updates(True)

        self.show()

        plt.close(self.fig)
class Plot(object):
    def __init__(self, figure, identifier, filepath):
        loader = UiLoader()
        self.ui = loader.load('plot_window.ui', PlotWindow())

        # Tell Windows how to handle our windows in the the taskbar, making pinning work properly and stuff:
        if os.name == 'nt':
            self.ui.newWindow.connect(set_win_appusermodel)

        self.set_window_title(identifier, filepath)

        # figure.tight_layout()
        self.figure = figure
        self.canvas = FigureCanvas(figure)
        self.navigation_toolbar = NavigationToolbar(self.canvas, self.ui)

        self.lock_action = self.navigation_toolbar.addAction(
            QtGui.QIcon(':qtutils/fugue/lock-unlock'), 'Lock axes',
            self.on_lock_axes_triggered)
        self.lock_action.setCheckable(True)
        self.lock_action.setToolTip('Lock axes')

        self.copy_to_clipboard_action = self.navigation_toolbar.addAction(
            QtGui.QIcon(':qtutils/fugue/clipboard--arrow'),
            'Copy to clipboard', self.on_copy_to_clipboard_triggered)
        self.copy_to_clipboard_action.setToolTip('Copy to clipboard')
        self.copy_to_clipboard_action.setShortcut(QtGui.QKeySequence.Copy)

        self.ui.verticalLayout_canvas.addWidget(self.canvas)
        self.ui.verticalLayout_navigation_toolbar.addWidget(
            self.navigation_toolbar)

        self.lock_axes = False
        self.axis_limits = None

        self.update_window_size()

        self.ui.show()

    def on_lock_axes_triggered(self):
        if self.lock_action.isChecked():
            self.lock_axes = True
            self.lock_action.setIcon(QtGui.QIcon(':qtutils/fugue/lock'))
        else:
            self.lock_axes = False
            self.lock_action.setIcon(QtGui.QIcon(':qtutils/fugue/lock-unlock'))

    def on_copy_to_clipboard_triggered(self):
        lyse.figure_to_clipboard(self.figure)

    @inmain_decorator()
    def save_axis_limits(self):
        axis_limits = {}
        for i, ax in enumerate(self.figure.axes):
            # Save the limits of the axes to restore them afterward:
            axis_limits[i] = ax.get_xlim(), ax.get_ylim()

        self.axis_limits = axis_limits

    @inmain_decorator()
    def clear(self):
        self.figure.clear()

    @inmain_decorator()
    def restore_axis_limits(self):
        for i, ax in enumerate(self.figure.axes):
            try:
                xlim, ylim = self.axis_limits[i]
                ax.set_xlim(xlim)
                ax.set_ylim(ylim)
            except KeyError:
                continue

    @inmain_decorator()
    def set_window_title(self, identifier, filepath):
        self.ui.setWindowTitle(
            str(identifier) + ' - ' + os.path.basename(filepath))

    @inmain_decorator()
    def update_window_size(self):
        l, w = self.figure.get_size_inches()
        dpi = self.figure.get_dpi()
        self.canvas.resize(int(l * dpi), int(w * dpi))
        self.ui.adjustSize()

    @inmain_decorator()
    def draw(self):
        self.canvas.draw()

    def show(self):
        self.ui.show()

    @property
    def is_shown(self):
        return self.ui.isVisible()
class Plot(object):
    def __init__(self, figure, identifier, filepath):
        self.identifier = identifier
        loader = UiLoader()
        self.ui = loader.load(os.path.join(LYSE_DIR, 'plot_window.ui'),
                              PlotWindow())

        # Tell Windows how to handle our windows in the the taskbar, making pinning work properly and stuff:
        if os.name == 'nt':
            self.ui.newWindow.connect(set_win_appusermodel)

        self.set_window_title(identifier, filepath)

        # figure.tight_layout()
        self.figure = figure
        self.canvas = figure.canvas
        self.navigation_toolbar = NavigationToolbar(self.canvas, self.ui)

        self.lock_action = self.navigation_toolbar.addAction(
            QtGui.QIcon(':qtutils/fugue/lock-unlock'), 'Lock axes',
            self.on_lock_axes_triggered)
        self.lock_action.setCheckable(True)
        self.lock_action.setToolTip('Lock axes')

        self.copy_to_clipboard_action = self.navigation_toolbar.addAction(
            QtGui.QIcon(':qtutils/fugue/clipboard--arrow'),
            'Copy to clipboard', self.on_copy_to_clipboard_triggered)
        self.copy_to_clipboard_action.setToolTip('Copy to clipboard')
        self.copy_to_clipboard_action.setShortcut(QtGui.QKeySequence.Copy)

        self.ui.verticalLayout_canvas.addWidget(self.canvas)
        self.ui.verticalLayout_navigation_toolbar.addWidget(
            self.navigation_toolbar)

        self.lock_axes = False
        self.axis_limits = None

        self.update_window_size()

        self.ui.show()

    def on_lock_axes_triggered(self):
        if self.lock_action.isChecked():
            self.lock_axes = True
            self.lock_action.setIcon(QtGui.QIcon(':qtutils/fugue/lock'))
        else:
            self.lock_axes = False
            self.lock_action.setIcon(QtGui.QIcon(':qtutils/fugue/lock-unlock'))

    def on_copy_to_clipboard_triggered(self):
        lyse.figure_to_clipboard(self.figure)

    @inmain_decorator()
    def save_axis_limits(self):
        axis_limits = {}
        for i, ax in enumerate(self.figure.axes):
            # Save the limits of the axes to restore them afterward:
            axis_limits[i] = ax.get_xlim(), ax.get_ylim()

        self.axis_limits = axis_limits

    @inmain_decorator()
    def clear(self):
        self.figure.clear()

    @inmain_decorator()
    def restore_axis_limits(self):
        for i, ax in enumerate(self.figure.axes):
            try:
                xlim, ylim = self.axis_limits[i]
                ax.set_xlim(xlim)
                ax.set_ylim(ylim)
            except KeyError:
                continue

    @inmain_decorator()
    def set_window_title(self, identifier, filepath):
        self.ui.setWindowTitle(
            str(identifier) + ' - ' + os.path.basename(filepath))

    @inmain_decorator()
    def update_window_size(self):
        l, w = self.figure.get_size_inches()
        dpi = self.figure.get_dpi()
        self.canvas.resize(int(l * dpi), int(w * dpi))
        self.ui.adjustSize()

    @inmain_decorator()
    def draw(self):
        self.canvas.draw()

    def show(self):
        self.ui.show()

    @property
    def is_shown(self):
        return self.ui.isVisible()

    def analysis_complete(self, figure_in_use):
        """To be overriden by subclasses. 
        Called as part of the post analysis plot actions"""
        pass

    def get_window_state(self):
        """Called when the Plot window is about to be closed due to a change in 
        registered Plot window class

        Can be overridden by subclasses if custom information should be saved
        (although bear in mind that you will passing the information from the previous 
        Plot subclass which might not be what you want unless the old and new classes
        have a common ancestor, or the change in Plot class is triggered by a reload
        of the module containing your Plot subclass). 

        Returns a dictionary of information on the window state.

        If you have overridden this method, please call the base method first and
        then update the returned dictionary with your additional information before 
        returning it from your method.
        """
        return {
            'window_geometry': self.ui.saveGeometry(),
            'axis_lock_state': self.lock_axes,
            'axis_limits': self.axis_limits,
        }

    def restore_window_state(self, state):
        """Called when the Plot window is recreated due to a change in registered
        Plot window class.

        Can be overridden by subclasses if custom information should be restored
        (although bear in mind that you will get the information from the previous 
        Plot subclass which might not be what you want unless the old and new classes
        have a common ancestor, or the change in Plot class is triggered by a reload
        of the module containing your Plot subclass). 

        If overriding, please call the parent method in addition to your new code

        Arguments:
            state: A dictionary of information to restore
        """
        geometry = state.get('window_geometry', None)
        if geometry is not None:
            self.ui.restoreGeometry(geometry)

        axis_limits = state.get('axis_limits', None)
        axis_lock_state = state.get('axis_lock_state', None)
        if axis_lock_state is not None:
            if axis_lock_state:
                # assumes the default state is False for new windows
                self.lock_action.trigger()

                if axis_limits is not None:
                    self.axis_limits = axis_limits
                    self.restore_axis_limits()

    def on_close(self):
        """Called when the window is closed.

        Note that this only happens if the Plot window class has changed. 
        Clicking the "X" button in the window title bar has been overridden to hide
        the window instead of closing it."""
        # release selected toolbar action as selecting an action acquires a lock
        # that is associated with the figure canvas (which is reused in the new
        # plot window) and this must be released before closing the window or else
        # it is held forever
        self.navigation_toolbar.pan()
        self.navigation_toolbar.zoom()
        self.navigation_toolbar.pan()
        self.navigation_toolbar.pan()
예제 #13
0
class Mpltab(QtWidgets.QWidget):
    """ Widget to keep track of mpl figure in tab"""
    def __init__(self,
                 MplCanvas,
                 plotId,
                 tabId,
                 mainWindow,
                 parent=None,
                 toolbar=True,
                 docked=True,
                 dockingIcon=None,
                 unDockingIcon=None):
        super().__init__(parent=parent)

        # Save both plotId and tabId
        self.plotId = plotId
        self.tabId = tabId

        # If docked, as standard the Mpltab is created as docked in a DetachableTabWidget
        self.docked = docked
        self.mainWindow = mainWindow

        self.layout = QtWidgets.QVBoxLayout()
        self.layout.setContentsMargins(0, 0, 0,
                                       0)  # Remove border around layout

        self.dockingIcon = dockingIcon
        self.unDockingIcon = unDockingIcon

        if toolbar:  # If a toolbar is wanted, create it, otherwise create menubar above figure
            self.menubar = NavigationToolbar(MplCanvas, None)
        else:
            self.menubar = QtWidgets.QMenuBar(self)
            self.menubar.setFixedHeight(25)

        # ad menubar and canvas to layout
        self.layout.addWidget(self.menubar)
        self.layout.addWidget(MplCanvas)
        if not self.dockingIcon is None and not self.unDockingIcon is None:
            self.dockAction = QtWidgets.QAction(self.unDockingIcon, 'Undock',
                                                self.menubar)
        else:
            self.dockAction = QtWidgets.QAction('Undock', self.menubar)

        if not self.docked:  # start undocked
            self.undock(parent=self.parent)

        self.setLayout(self.layout)

        # Add shortcut to dock
        self.dockAction.setShortcut("Ctrl+D")
        self.menubar.addAction(self.dockAction)
        self.dockAction.triggered.connect(self.toggleDocked)

    def toggleDocked(self):
        if self.docked:
            self.parent().parent().detachTab(index=self.tabId,
                                             point=QtGui.QCursor().pos())
        else:
            parent = self.parent()
            parent.dock(
            )  #attachTab(parent.contentWidget, parent.objectName(), parent.windowIcon())

    def undock(self, newParent):
        self.docked = False
        self.dockAction.setText('Dock')
        if not self.dockingIcon is None and not self.unDockingIcon is None:
            self.dockAction.setIcon(self.dockingIcon)
        self.setParent(newParent)

    def dock(self, newParent):
        self.docked = True
        self.dockAction.setText('Undock')
        if not self.dockingIcon is None and not self.unDockingIcon is None:
            self.dockAction.setIcon(self.unDockingIcon)
        self.setParent(newParent)
class CameraGui(QDialog):
    def set_vars(self):
        self.camera = 'vertical_mot'
        self.name = self.camera
        self.fluorescence_mode = True
        self.update_id = np.random.randint(0, 2**31 - 1)
        self.ROI = None
        self.no_lim = True

    def __init__(self):
        super(CameraGui, self).__init__(None)
        self.set_vars()
        self.connect_to_labrad()
        self.populate()
        self.Plotter = LivePlotter(self)

    def populate(self):
        self.setWindowTitle(self.name)
        self.canvas = MplCanvas()

        self.nav = NavigationToolbar(self.canvas, self)
        #select_cam = self.nav.addAction('&Select camera')
        #select_cam.addAction('horizontal mot')
        #select_cam.addAction('vertical mot (cavity)')
        self.nav.addAction('Launch live plotter', self.launch_plotter)

        self.layout = QGridLayout()
        self.layout.setSpacing(0)
        self.layout.setContentsMargins(0, 0, 0, 0)

        self.layout.addWidget(self.nav)
        self.layout.addWidget(self.canvas)

        self.setLayout(self.layout)
        width = self.canvas.width()
        height = self.nav.height() + self.canvas.height()
        self.setFixedSize(width, height)

    #Labrad connection:
    @inlineCallbacks
    def connect_to_labrad(self):
        #self.cxn = connect(name=self.name)
        self.cxn = connection()
        yield self.cxn.connect(name='camera viewer')
        server = yield self.cxn.get_server('camera')
        yield server.signal__update(self.update_id)
        yield server.addListener(listener=self.receive_update,
                                 source=None,
                                 ID=self.update_id)
        print('connected')

    def receive_update(self, c, update_json):
        update = json.loads(update_json)
        for key, value in update.items():
            if key == self.camera:
                if self.fluorescence_mode:
                    if not (('exc' in value[0]) or ('background' in value[0])):
                        print(value)
                        if 'gnd' in value[0]:
                            print(value[0])
                            str_end = '_fluorescence.png'
                            keyword = 'mot_cavity_'
                            split_str = value[0].partition(str_end)
                            parse_name = split_str[0].partition(keyword)
                            print(parse_name)
                            beginning = parse_name[0]
                            shot_num = int(parse_name[-1])
                            offset = 3
                            mod_shot = shot_num - offset
                            new_path = beginning + keyword + str(
                                mod_shot) + str_end
                            print(new_path)
                            self.file_to_show = new_path  #value[0]
                        else:
                            self.file_to_show = value[0]
                        print(self.file_to_show)

                        time.sleep(.1)
                        self.Plotter.show_window()
                        self.show_window()

    def show_window(self):
        try:
            if not self.no_lim:
                xlim = self.canvas.ax.get_xlim()
                ylim = self.canvas.ax.get_ylim()
            #self.canvas.ax.clear() #MOVED to after attempt to load fig
            it.fig_gui_window_ROI(self.file_to_show, self.canvas.ax, self.ROI)
            if not self.no_lim:
                self.canvas.ax.set_xlim(xlim)
                self.canvas.ax.set_ylim(ylim)
            else:
                self.no_lim = False
            print(self.canvas.ax.get_xlim())
            self.canvas.ax.set_title("{:.3e}".format(self.Plotter.title),
                                     color='w',
                                     y=.85,
                                     size=42)
            self.canvas.draw()
            print('redrawn')
        except:
            #self.no_lim = True
            print('Error loading file: not refreshed')

    def launch_plotter(self):
        self.Plotter.show()
예제 #15
0
class LivePlotter(QDialog):
    def set_class_vars(self):
        self.script = it.fig_plotter
        self.n_show = 30
        self.live_data = np.full(self.n_show, None)

    def __init__(self, parent):
        super(LivePlotter, self).__init__()
        self.parent = parent
        self.set_class_vars()
        self.populate()

    def populate(self):
        self.setWindowTitle('Live plotter')
        self.canvas = MplCanvas()
        self.nav = NavigationToolbar(self.canvas, self)
        '''Changed nav toolbar'''
        self.nav.addAction('Reset optimizer', self.reset_opt)

        self.layout = QGridLayout()
        self.layout.setSpacing(0)
        self.layout.setContentsMargins(0, 0, 0, 0)

        self.layout.addWidget(self.nav)
        self.layout.addWidget(self.canvas)

        self.setLayout(self.layout)
        #self.canvas.ax.set_ylim((0, 5e-5))
        #self.canvas.ax.set_xlim((0, .04))
        width = self.canvas.width()
        height = self.nav.height() + self.canvas.height() + 20
        self.setFixedSize(width, height)

    def reset_opt(self):
        self.live_data = np.full(self.n_show, None)

    def live_plot(self):
        #try:
        roi = self.get_ROI()
        this_shot = self.script(self.parent.file_to_show, roi)
        self.title = this_shot
        empty_data = np.where(self.live_data == None)
        if len(empty_data[0]) == 0:
            self.live_data[0:self.n_show - 1] = self.live_data[1:self.n_show]
            self.live_data[-1] = this_shot
        else:
            self.live_data[empty_data[0][0]] = this_shot

    #except AttributeError:
    #   print('Not loaded')

    def get_ROI(self):
        xlim = self.parent.canvas.ax.get_xlim()
        ylim = self.parent.canvas.ax.get_ylim()
        ROI_exact = [xlim[0], ylim[0], xlim[1] - xlim[0], ylim[1] - ylim[0]]
        return [int(x) for x in ROI_exact]

    def show_window(self):
        self.live_plot()
        self.canvas.ax.clear()
        self.canvas.ax.plot(self.live_data, 'o')
        #self.canvas.ax.title(np.std(self.live_data))
        self.canvas.draw()
예제 #16
0
class GraphWidget(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.x_label = "Eje X"
        self.y_label = "Eje Y"
        self.title = " "
        self.figure = Figure()
        self.canvas = FigureCanvas(self.figure)  # Canvas a agregar al widget
        self.toolbar = NavigationToolbar(
            self.canvas,
            self)  # cada gráfico tiene un toolbar con herramientos para
        # trabajar sobre él

        vertical_layout = QVBoxLayout()

        # Se le agregan nuevos botones al toolbar, además de los que vienen por defecto y se les asigna una función para
        # cuando son clickeados.
        self.toolbar.addAction(QIcon("Resources\saveall.png"),
                               "Guardar ambos gráficos", self.save_all_pressed)
        self.toolbar.addAction(QIcon("Resources\mark.png"), "Marcar puntos",
                               self.mark_points)
        self.toolbar.addAction(QIcon("Resources\log_lin_approx.jpg"),
                               "Cambiar escala", self.change_scale)
        self.toolbar.addAction(QIcon("Resources\scatter_or_lineal.png"),
                               "Lineal o Dispersión", self.change_format)

        self.cid = self.figure.canvas.mpl_connect(
            'button_press_event', self)  # Evento de cuando se aprieta un botón

        vertical_layout.addWidget(
            self.canvas)  # Se le agrega el canvas al widget
        vertical_layout.addWidget(
            self.toolbar)  # Se le agrega el toolbar al widget

        # Arreglos de los puntos marcados por el usuario.
        self.x_marked_points = []
        self.y_marked_points = []

        #
        self.canvas.axes = self.canvas.figure.add_subplot(
            111)  # Plotea el canvas. Si no se entiende que es el ploteo,
        # mirar
        # https://stackoverflow.com/questions/3584805/in-matplotlib-what-does-the-argument-mean-in-fig-add-subplot111

        self.setLayout(vertical_layout)

        # callbacks de los nuevos botones del toolbar. En None por defecto
        self.save_all_callback = None
        self.redraw_callback = None

        self.mark_points_flag = False  # Flag que indica si los puntos se deben mostrar o estar escondidos.
        self.log_flag = True  # Flag que indica si el grafico se encuentra en escala logaritmica.
        self.continuous_line_flag = False  # Flag que indica si el grafico de medicion se muestra como una curva continua o de
        # dispersion

    def __call__(self, event):  # Se llama con un evento de click en el widget.
        if self.mark_points_flag:  # Si el flag de mostrar puntos está activado se agregarán las coordenadas del
            # click a un nuevo punto
            self.x_marked_points.append(event.xdata)
            self.y_marked_points.append(event.ydata)
            self.redraw_callback()

    def save_all_pressed(
        self
    ):  # Funcion que se llama el tocar en el toolbar el boton de guardar todos los graficos.
        self.save_all_callback()  # Callback que exporte todos los graficos.

    def mark_points(
        self
    ):  # Funcion que se llama el tocar en el toolbar el boton de marcar puntos.
        self.mark_points_flag = not self.mark_points_flag  # Función que togglea el flag de marcar puntos.

    def clear_marked_points(self):  # Se limpian los puntos marcados
        self.x_marked_points = []
        self.y_marked_points = []

    def change_scale(self):
        self.log_flag = not self.log_flag
        self.redraw_callback()

    def change_format(self):
        self.continuous_line_flag = not self.continuous_line_flag
        self.redraw_callback()
예제 #17
0
class CavityClockGui(QDialog):
    def __init__(self):
        super(CavityClockGui, self).__init__(None)
        self.update_id = np.random.randint(0, 2**31 - 1)
        self.expt = "Waiting for updates"
        self.data_path = None
        self.update = None
        #Specify analysis frameworks
        self.analysis_script = fits.do_gaussian_fit
        self.mode = lambda update, preset: None
        self.connect_to_labrad_cav()
        self.connect_to_labrad_clock()
        self.populate()

        #self.Plotter = LivePlotter(self)

    def populate(self):
        self.setWindowTitle("Clock + cavity gui")
        self.canvas = MplCanvas()

        self.nav = NavigationToolbar(self.canvas, self)
        #self.nav.addAction('Select analysis method')
        #self.nav.addAction('Launch live plotter', self.launch_plotter)

        self.layout = QGridLayout()
        self.layout.setSpacing(0)
        self.layout.setContentsMargins(0, 0, 0, 0)

        self.layout.addWidget(self.nav)
        self.layout.addWidget(self.canvas)

        self.setLayout(self.layout)
        width = self.canvas.width()
        height = self.nav.height() + self.canvas.height()
        self.setFixedSize(width, height)

        self.add_subplot_buttons()

    # Labrad connection:
    @inlineCallbacks
    def connect_to_labrad_cav(self):
        #self.cxn = connect(name=self.name)
        self.cxn = connection()
        yield self.cxn.connect(name='cavity viewer')
        server = yield self.cxn.get_server('cavity_probe_pico')
        yield server.signal__update(self.update_id)
        yield server.addListener(listener=self.receive_update,
                                 source=None,
                                 ID=self.update_id)
        print('connected to cavity probe pico server')

    @inlineCallbacks
    def connect_to_labrad_clock(self):
        #self.cxn = connect(name=self.name)
        self.cxn = connection()
        yield self.cxn.connect(name='clock viewer')
        server = yield self.cxn.get_server('clock_pico')
        yield server.signal__update(self.update_id)
        yield server.addListener(listener=self.receive_update,
                                 source=None,
                                 ID=self.update_id)
        print('connected to clock pico server')

    def preserve_lim(self):
        all_ax = self.canvas.trace_axes + self.canvas.data_axes
        lims = np.zeros((len(all_ax), 4))
        for i in np.arange(len(all_ax)):
            lims[i, 0:2] = all_ax[i].get_xlim()
            lims[i, 2:4] = all_ax[i].get_ylim()
        return lims

    def enforce_lim(self, lims, preset):
        all_ax = self.canvas.trace_axes + self.canvas.data_axes
        for i in np.arange(len(all_ax)):
            if preset[i]:
                all_ax[i].set_xlim(lims[i, 0:2])
                current_y = all_ax[i].get_ylim()
                if current_y[1] > lims[i, 3]:
                    lims[i, 3] = current_y[1]
                if current_y[0] < lims[i, 2]:
                    lims[i, 2] = current_y[0]
                all_ax[i].set_ylim(lims[i, 2:4])

    def save_fig(self, ax, fig, title):
        #https://stackoverflow.com/questions/4325733/save-a-subplot-in-matplotlib
        extent = ax.get_window_extent().transformed(
            fig.dpi_scale_trans.inverted())
        extent_expanded = extent.expanded(1.5, 2)
        fig.savefig(title, bbox_inches=extent_expanded)

    def receive_update(self, c, update_json):
        update = json.loads(update_json)
        self.update = update
        this_expt, this_path = listeners.get_expt(update)
        if this_expt is not None and self.expt != this_expt:
            if (not self.expt.isnumeric()) and (self.data_path is not None):
                #Save data traces when expt ends
                folder_path = os.path.join(self.data_path, self.expt)
                np.save(os.path.join(folder_path, "processed_data_x"),
                        self.canvas.data_x)
                np.save(os.path.join(folder_path, "processed_data_y"),
                        self.canvas.data_y)
                self.save_fig(self.canvas.data_axes[0], self.canvas.fig,
                              os.path.join(folder_path, 'fig_0.png'))
                self.save_fig(self.canvas.data_axes[1], self.canvas.fig,
                              os.path.join(folder_path, 'fig_1.png'))
                print('Saved data in folder: ' + folder_path)
            if this_expt.isnumeric():
                self.canvas.fig.suptitle(self.expt + " ended")
                self.expt = this_expt
            else:
                print(this_expt)
                self.canvas.reset_data()
                self.expt = this_expt
                self.data_path = this_path
                self.canvas.fig.suptitle(self.expt)
                self.canvas.lim_set = self.canvas.lim_default

        #Get current lims to prevent re-scaling
        lims = self.preserve_lim()
        preset = self.canvas.lim_set.copy()

        #!!Specify listeners for diff axes:

        #Comment/uncomment next lines to turn off/on pmt listeners:
        self.mode(update, preset)
        listeners.atom_number(update,
                              self.canvas.data_axes[1],
                              self.canvas.data_x[1],
                              self.canvas.data_y[1],
                              bad_points=self.canvas.bad_data,
                              freq_domain=False)

        #Cavity single-tone traces:
        listeners.bare_cavity_single_tone(update, self.canvas.trace_axes[1],
                                          'gnd')
        listeners.bare_cavity_single_tone(update, self.canvas.trace_axes[2],
                                          'exc')

        #Cavity 2-tone probing clock operation:
        '''
        try:
            returned, vrs_gnd = listeners.cavity_probe_two_tone(update, self.canvas.trace_axes[1]) 
            self.canvas.lim_set[1] = returned or preset[1]
            print('fit one')
            returned, vrs_exc = listeners.cavity_probe_two_tone(update, self.canvas.trace_axes[2], 'exc') 
            self.canvas.lim_set[2] = returned or preset[2]
            
            listeners.exc_frac_cavity(update, self.canvas.data_axes[1], self.canvas.data_x[1], self.canvas.data_y[1], vrs_gnd, vrs_exc, 'sequencer.clock_phase')
            
        except:
            print('cannot extract tones')
        '''

        #Add back past lims to prevent rescaling
        self.enforce_lim(lims, preset)
        self.canvas.draw()

#Different potential plotter configs

    def set_freq(self):
        def freq_update(update, preset):
            self.canvas.lim_set[0] = listeners.pmt_trace(
                update, self.canvas.trace_axes[0]) or preset[0]
            exc_called = listeners.exc_frac(update, self.canvas.data_axes[0],
                                            self.canvas.data_x[0],
                                            self.canvas.data_y[0])

        return freq_update

    def set_time(self, time_name):
        def time_update(update, preset):
            self.canvas.lim_set[0] = listeners.pmt_trace(
                update, self.canvas.trace_axes[0]) or preset[0]
            exc_called = listeners.exc_frac(update,
                                            self.canvas.data_axes[0],
                                            self.canvas.data_x[0],
                                            self.canvas.data_y[0],
                                            time_domain=True,
                                            time_name=time_name)

        return time_update

    def set_phase(self):
        def phase_update(update, preset):
            self.canvas.lim_set[0] = listeners.pmt_trace(
                update, self.canvas.trace_axes[0]) or preset[0]
            exc_called = listeners.exc_frac(update,
                                            self.canvas.data_axes[0],
                                            self.canvas.data_x[0],
                                            self.canvas.data_y[0],
                                            time_domain=True,
                                            time_name='sequencer.clock_phase')

        return phase_update

    def set_shot(self):
        def shot_update(update, preset):
            bad_shot = self.canvas.bad_data[-1]
            self.canvas.lim_set[0] = listeners.pmt_trace(
                update, self.canvas.trace_axes[0]) or preset[0]
            exc_called = listeners.exc_frac(update,
                                            self.canvas.data_axes[0],
                                            self.canvas.data_x[0],
                                            self.canvas.data_y[0],
                                            freq_domain=False,
                                            n_avg=1,
                                            bad_shot=bad_shot)

        return shot_update

#Add buttons to select config, fit methods

    def add_subplot_buttons(self):
        self.nav.addAction('Fit', self.do_fit)

        #Add fft client option to left cavity trace
        self.fft_left = QPushButton(self)
        self.fft_left.setText('FFT on click')
        self.fft_left.move(500, 380)
        self.fft_left.clicked.connect(self.show_fft)

        #Add dropdown for setting data x axis
        self.dropdown = QComboBox(self)
        self.labels = [
            "Frequency", "Phase", "Dark time", "Pi time", "Shot num"
        ]
        self.fxns = [
            self.set_freq(),
            self.set_phase(),
            self.set_time('sequencer.t_dark'),
            self.set_time('sequencer.t_pi'),
            self.set_shot()
        ]
        self.dropdown.addItems(self.labels)
        self.dropdown.currentIndexChanged.connect(self.select_mode)
        self.dropdown.move(870, 4)
        self.mode = self.fxns[0]

        #Add dropdown for setting analysis fxn
        self.fxn_drop = QComboBox(self)
        self.fit_labels = [
            "Gaussian", "Inv. Gauss", "Phase fringe", "Local max", "Local min"
        ]
        self.fit_fxns = [
            fits.do_gaussian_fit, fits.do_inverted_gaussian_fit,
            fits.do_phase_fit, fits.do_local_max, fits.do_local_min
        ]
        self.fxn_drop.addItems(self.fit_labels)
        self.analysis_script = self.fit_fxns[0]
        self.fxn_drop.move(1000, 4)
        self.fxn_drop.currentIndexChanged.connect(self.select_script)

    def select_mode(self):
        txt = self.dropdown.currentText()
        ix = self.dropdown.currentIndex()
        self.mode = self.fxns[ix]
        self.canvas.reset_data()
        print(txt)

    def select_script(self):
        ix = self.fxn_drop.currentIndex()
        self.analysis_script = self.fit_fxns[ix]

    def do_fit(self):
        self.analysis_script(self.canvas.data_axes[0], self.canvas.data_x[0],
                             self.canvas.data_y[0])

    def show_fft(self):
        self.mouse_listener = self.canvas.mpl_connect('button_press_event',
                                                      self.process_click)

    def process_click(self, event):
        t_click = event.xdata
        self.canvas.mpl_disconnect(self.mouse_listener)
        self.FFTPlot = FFTPlotter(self.update, t_click)
        self.FFTPlot.show()

    def show_fft(self):
        self.mouse_listener = self.canvas.mpl_connect('button_press_event',
                                                      self.process_click)
예제 #18
0
class QmyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)  #调用父类构造函数,创建窗体
        self.ui = Ui_MainWindow()  #创建UI对象
        self.ui.setupUi(self)  #构造UI界面

        self.setWindowTitle("Demo14_3, 交互操作")
        self.__labMove = QLabel("Mouse Move:")
        self.__labMove.setMinimumWidth(200)
        self.ui.statusBar.addWidget(self.__labMove)

        self.__labPick = QLabel("Mouse Pick:")
        self.__labPick.setMinimumWidth(200)
        self.ui.statusBar.addWidget(self.__labPick)

        mpl.rcParams['font.sans-serif'] = ['SimHei']  #显示汉字为 楷体, 汉字不支持 粗体,斜体等设置
        mpl.rcParams['font.size'] = 11
        ##  Windows自带的一些字体
        ##  黑体:SimHei 宋体:SimSun 新宋体:NSimSun 仿宋:FangSong  楷体:KaiTi
        mpl.rcParams['axes.unicode_minus'] = False  #减号unicode编码

        self.__fig = None  #Figue对象
        self.__createFigure()  #创建Figure和FigureCanvas对象,初始化界面
        self.__drawFig1X2()

##  ==============自定义功能函数========================

    def __createFigure(self):  ##创建绘图系统
        self.__fig = mpl.figure.Figure(figsize=(8, 5))  #单位英寸
        figCanvas = FigureCanvas(self.__fig)  #创建FigureCanvas对象,必须传递一个Figure对象
        self.__naviBar = NavigationToolbar(figCanvas,
                                           self)  #创建NavigationToolbar工具栏

        actList = self.__naviBar.actions()  #关联的Action列表
        for act in actList:  #获得每个Action的标题和tooltip,可注释掉
            print("text=%s,\ttoolTip=%s" % (act.text(), act.toolTip()))
        self.__changeActionLanguage()  #改工具栏的语言为汉语
        ##工具栏改造
        actList[6].setVisible(False)  #隐藏Subplots 按钮
        actList[7].setVisible(False)  #隐藏Customize按钮
        act8 = actList[8]  #分隔条
        self.__naviBar.insertAction(act8, self.ui.actTightLayout)  #"紧凑布局"按钮
        self.__naviBar.insertAction(act8, self.ui.actSetCursor)  #"十字光标"按钮

        count = len(actList)  #Action的个数
        lastAction = actList[count - 1]  #最后一个Action
        self.__naviBar.insertAction(lastAction,
                                    self.ui.actScatterAgain)  #"重绘散点"按钮

        lastAction.setVisible(False)  #隐藏其原有的坐标提示
        self.__naviBar.addSeparator()
        self.__naviBar.addAction(self.ui.actQuit)  #"退出"按钮
        self.__naviBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)  #显示方式

        self.addToolBar(self.__naviBar)  #添加作为主窗口工具栏
        self.setCentralWidget(figCanvas)

        figCanvas.setCursor(Qt.CrossCursor)
        ## 必须保留变量cid,否则可能被垃圾回收
        self._cid1 = figCanvas.mpl_connect("motion_notify_event",
                                           self.do_canvas_mouseMove)
        self._cid2 = figCanvas.mpl_connect("axes_enter_event",
                                           self.do_axes_mouseEnter)
        self._cid3 = figCanvas.mpl_connect("axes_leave_event",
                                           self.do_axes_mouseLeave)
        self._cid4 = figCanvas.mpl_connect("pick_event", self.do_series_pick)
        self._cid5 = figCanvas.mpl_connect("scroll_event", self.do_scrollZoom)

    def __changeActionLanguage(self):
        actList = self.__naviBar.actions()  #关联的Action列表
        actList[0].setText("复位")  #Home
        actList[0].setToolTip("复位到原始视图")  #Reset original view

        actList[1].setText("回退")  #Back
        actList[1].setToolTip("回到前一视图")  #Back to previous view

        actList[2].setText("前进")  #Forward
        actList[2].setToolTip("前进到下一视图")  #Forward to next view

        actList[4].setText("平动")  #Pan
        actList[4].setToolTip(
            "左键平移坐标轴,右键缩放坐标轴")  #Pan axes with left mouse, zoom with right

        actList[5].setText("缩放")  #Zoom
        actList[5].setToolTip("框选矩形框缩放")  #Zoom to rectangle

        actList[6].setText("子图")  #Subplots
        actList[6].setToolTip("设置子图")  #Configure subplots

        actList[7].setText("定制")  #Customize
        actList[7].setToolTip("定制图表参数")  #Edit axis, curve and image parameters

        actList[9].setText("保存")  #Save
        actList[9].setToolTip("保存图表")  #Save the figure

    def __drawScatters(self, N=15):
        x = range(N)  #序列0,1,....N-1
        ##      x=np.random.rand(N)
        y = np.random.rand(N)
        colors = np.random.rand(N)  #0~1之间随机数
        self.__markerSize = (
            40 * (0.2 + np.random.rand(N)))**2  #0 to 15 point radius
        self.__axScatter.scatter(x,
                                 y,
                                 s=self.__markerSize,
                                 c=colors,
                                 marker='*',
                                 alpha=0.5,
                                 label="scatter series",
                                 picker=True)  #允许被拾取pick
        #s=The marker size in points**2
        #c=color, sequence, or sequence of color, optional, default: 'b'
        ## marker : `~matplotlib.markers.MarkerStyle`, optional, default: 'o'
        self.__axScatter.set_title("散点图")
        self.__axScatter.set_xlabel('序号')  # X轴标题

    def __drawFig1X2(self):  #初始化绘图
        gs = self.__fig.add_gridspec(1, 2)  #1行,2列
        ##      ax1=self.__fig.add_subplot(1,1,1) #添加一个Axes对象,并返回此对象,不支持constrained_layout
        ax1 = self.__fig.add_subplot(gs[0, 0], label="Line2D plot")

        t = np.linspace(0, 10, 40)
        y1 = np.sin(t)
        y2 = np.cos(2 * t)
        ax1.plot(t,
                 y1,
                 'r-o',
                 label="sin series",
                 linewidth=1,
                 markersize=5,
                 picker=True)  #绘制一条曲线
        ax1.plot(t, y2, 'b:', label="cos series", linewidth=2)  #绘制一条曲线
        ax1.set_xlabel('X 轴')
        ax1.set_ylabel('Y 轴')
        ax1.set_xlim([0, 10])
        ax1.set_ylim([-1.5, 1.5])
        ax1.set_title("曲线")
        ax1.legend()  #自动创建Axes的图例

        self.__axScatter = self.__fig.add_subplot(gs[0, 1],
                                                  label="scatter plot")  #创建子图
        self.__drawScatters(N=15)  #绘制散点图

##  ==============event处理函数==========================

##  ==========由connectSlotsByName()自动连接的槽函数============

    @pyqtSlot()  ## 紧凑布局
    def on_actTightLayout_triggered(self):
        self.__fig.tight_layout()  # 对所有子图 进行一次tight_layout
        self.__fig.canvas.draw()

    @pyqtSlot()  ## 设置鼠标光标
    def on_actSetCursor_triggered(self):
        self.__fig.canvas.setCursor(Qt.CrossCursor)

    @pyqtSlot()  ## 重新绘制散点图
    def on_actScatterAgain_triggered(self):
        self.__axScatter.clear()  #清除子图
        self.__drawScatters(N=15)
        self.__fig.canvas.draw()  #刷新

##  =================自定义槽函数==========
#event类型 matplotlib.backend_bases.MouseEvent

    def do_canvas_mouseMove(self, event):
        if event.inaxes == None:
            return
        info = "%s: xdata=%.2f,ydata=%.2f  " % (event.inaxes.get_label(),
                                                event.xdata, event.ydata)
        self.__labMove.setText(info)

## event类型:matplotlib.backend_bases.LocationEvent

    def do_axes_mouseEnter(self, event):
        event.inaxes.patch.set_facecolor('g')  #设置背景颜色
        event.inaxes.patch.set_alpha(0.2)  #透明度
        event.canvas.draw()

    def do_axes_mouseLeave(self, event):
        event.inaxes.patch.set_facecolor('w')  #设置背景颜色
        event.canvas.draw()

##event 类型: matplotlib.backend_bases.PickEvent

    def do_series_pick(self, event):
        series = event.artist  # 产生事件的对象
        index = event.ind[0]  #索引号,是array([int32])类型,可能有多个对象被pick,只取第1个
        #是否有ind属性与具体的对象有关

        if isinstance(series, mpl.collections.PathCollection):  #scatter()生成的序列
            markerSize = self.__markerSize[index]
            info = "%s: index=%d, marker size=%d " % (
                event.mouseevent.inaxes.get_label(), index, markerSize)
        elif isinstance(series, mpl.lines.Line2D):  #plot()生成的序列
            ##         xdata=series.get_xdata() #两种方法都可以
            ##         x=xdata[index]
            ##         ydata=series.get_ydata()
            ##         y=ydata[index]
            x = event.mouseevent.xdata  #标量数据点
            y = event.mouseevent.ydata  #标量数据点
            info = "%s: index=%d, data_xy=(%.2f, %.2f) " % (series.get_label(),
                                                            index, x, y)

        self.__labPick.setText(info)

#event类型 matplotlib.backend_bases.MouseEvent

    def do_scrollZoom(self, event):  #通过鼠标滚轮缩放
        ax = event.inaxes  # 产生事件的axes对象
        if ax == None:
            return

        self.__naviBar.push_current(
        )  #Push the current view limits and position onto the stack,这样才可以还原
        xmin, xmax = ax.get_xbound()  #获取范围
        xlen = xmax - xmin

        ymin, ymax = ax.get_ybound()  #获取范围
        ylen = ymax - ymin

        xchg = event.step * xlen / 20  #step [scalar],positive = ’up’, negative ='down'
        xmin = xmin + xchg
        xmax = xmax - xchg

        ychg = event.step * ylen / 20
        ymin = ymin + ychg
        ymax = ymax - ychg

        ax.set_xbound(xmin, xmax)
        ax.set_ybound(ymin, ymax)

        event.canvas.draw()
예제 #19
0
class Ui_MainWindow(QMainWindow):
    def __init__(self):
        super(Ui_MainWindow, self).__init__()

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1900, 980)
        MainWindow.setMaximumSize(1900, 980)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        ######################################        Creating Table Widget       ######################################
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget.setGeometry(QtCore.QRect(50, 540, 850, 300))
        font = QtGui.QFont()
        font.setBold(True)
        font.setItalic(True)
        font.setWeight(75)
        self.tableWidget.setFont(font)
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(4)
        # self.tableWidget.setRowCount(0)
        self.tableWidget.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.tableWidget.setHorizontalHeaderLabels(
            ("PW", " PA ", " PRI ", " Classification "))
        self.tableWidget.setStatusTip("Table widget")
        #self.tableWidget.setRowCount(0)
        #######################################       Creating Pushbutton   ############################################
        self.pushButton_Start = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_Start.setGeometry(QtCore.QRect(400, 870, 180, 51))
        font = QtGui.QFont()
        font.setPointSize(14)
        font.setBold(True)
        font.setItalic(False)
        font.setUnderline(False)
        font.setWeight(75)
        self.pushButton_Start.setFont(font)
        self.pushButton_Start.setStyleSheet(
            "border-top-color: rgb(144, 255, 248);\n"
            "border-bottom-color: rgb(157, 255, 121);")
        self.pushButton_Start.setObjectName("pushButton_Start")
        ######################################## Creating Widgets(Plotting Graphs) ####################################
        self.Graph1 = pg.PlotWidget(self.centralwidget)
        self.Graph1.setGeometry(QtCore.QRect(50, 80, 850, 410))
        self.Graph1.setLabel('left', 'PRI')
        self.Graph1.setLabel('bottom', 'Pulse Count')

        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)

        self.Graph2 = pg.LayoutWidget(self.centralwidget)
        self.Graph2.setGeometry(QtCore.QRect(1000, 80, 850, 410))
        self.Graph2.addWidget(self.canvas)
        self.Graph2.addWidget(self.toolbar)

        self.Dialer = QtWidgets.QDial(self.centralwidget)
        self.Dialer.setGeometry(QtCore.QRect(1640, 300, 150, 150))
        self.Dialer.setNotchesVisible(True)
        # self.Dialer.setWrapping(True)
        self.Dialer.setMinimum(1)
        self.Dialer.setMaximum(100)

        self.Graph3 = pg.PlotWidget(self.centralwidget)
        self.Graph3.setGeometry(QtCore.QRect(1000, 520, 850, 410))
        self.Graph3.setObjectName("Graph3")
        self.Graph3.setLabel('left', 'Count')
        self.Graph3.setLabel('bottom', 'TOA')

        ## Set Graph background colour ( White-'w',Black-'k',Green-'g',Red-'r',Yellow-'y',Blue-'b',cyan (bright blue-green)-'c',magenta (bright pink)-'m' ) ###########
        self.Graph1.setBackground('k')
        #self.Graph2.setBackground('k')
        self.Graph3.setBackground('k')

        MainWindow.setCentralWidget(self.centralwidget)
        ############################################## Status Bar  ####################################################
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        ##############################################   Tool Bar  ####################################################
        self.toolbar = QtWidgets.QToolBar(MainWindow)
        self.toolbar.setObjectName("toolbar")
        self.toolbar.setMovable(False)
        self.toolbar.setGeometry(QtCore.QRect(0, 0, 1900, 50))
        self.toolbar.setIconSize(QtCore.QSize(60, 60))
        self.toolbar.addSeparator()
        ######################################    Creating Tool Bar Icons #################################################
        self.btn1 = QtWidgets.QAction(MainWindow)
        self.btn1.setIcon(QtGui.QIcon("IP.png"))
        self.btn1.setObjectName("btn1")
        self.toolbar.addAction(self.btn1)

        self.btn2 = QtWidgets.QAction(MainWindow)
        self.btn2.setIcon(QtGui.QIcon("pulse1.png"))
        self.btn2.setObjectName("btn2")
        self.toolbar.addAction(self.btn2)

        self.btn3 = QtWidgets.QAction(MainWindow)
        self.btn3.setIcon(QtGui.QIcon(""))
        self.btn3.setObjectName("btn3")
        self.toolbar.addAction(self.btn3)

        self.btn4 = QtWidgets.QAction(MainWindow)
        self.btn4.setIcon(QtGui.QIcon(""))
        self.btn4.setObjectName("btn4")
        self.toolbar.addAction(self.btn4)

        self.pushButton_Start.clicked.connect(self.StartPA)
        self.Dialer.valueChanged.connect(self.Plot_DTOA)
        self.btn1.triggered.connect(self.Window1)
        self.btn2.triggered.connect(self.Window2)
        self.tableWidget.rowCount()
        self.df = pd.read_csv("pdw.csv")

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        self.thread = MyThread()
        # self.thread.change_value.connect(self.setProgressVal)
        self.thread.StopFlag = False
        self.thread.start()
        self.thread.StartPulseAnalysis = False
        self.thread.pd_PDW_Update.connect(self.updateGraphs)
        self.thread.Track_Update.connect(self.updateTrackTable)

    # Track_Update = pyqtSignal(bytearray)

    def StartPA(self):
        if self.thread.StartPulseAnalysis == False:
            self.pushButton_Start.setText("Stop PA")
            self.thread.StartPulseAnalysis = True

        elif self.thread.StartPulseAnalysis == True:
            self.pushButton_Start.setText("Start PA")
            self.thread.StartPulseAnalysis = False

    def updateGraphs(self, df_Pdw):
        print('Update Graphs')
        print(df_Pdw.head())
#Munny write here for Graphs updation

    def updateTrackTable(self, TrackData):
        print('Update Table')
        print(TrackData)
        #Munny Write here for Tbale updation

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton_Start.setText(_translate("MainWindow", "Start PA"))

    def Window1(self):
        self.Wd1 = Tool1_Window()
        self.Wd1.show()

    def Window2(self):
        self.Wd2 = Tool2_Window()
        self.Wd2.show()

    def Plot_DTOA(self):
        pen1 = pg.mkPen(color=(0, 150, 0), width=3, style=QtCore.Qt.SolidLine)
        TOA = self.df['TOA']
        PW = self.df['PW']
        PA = self.df['PA']
        PC = self.df['PC']
        DTOA = self.df['DTOA']
        #print(PA)
        self.Graph1.plot(PC, DTOA, pen=pen1)
        #self.Graph1.setYRange()

        x_lim = self.Dialer.value() * 1000
        #print("count", x_lim)
        y = []
        #for index in range(10):
        cur_TOA = 0
        index = 0
        while cur_TOA < x_lim:
            for t in range(TOA[index], TOA[index] + PW[index]):
                y.append(1)
            for t in range(TOA[index] + PW[index], TOA[index + 1]):
                y.append(0)
            cur_TOA = TOA[index + 1]
            index = index + 1
        x = [*range(0, len(y), 1)]
        plt.plot(x, y, "g")
        plt.title('DTOA vs Pulse Count')
        plt.ylabel('DTOA (micro sec)')
        plt.xlabel('Pulse Count->')
        plt.xlim(0, x_lim)
        plt.ylim(-1, +5)
        # plt.hlines(y=0, xmin=0, xmax=4000, linewidth=1, color='k', linestyles="--")
        self.canvas.draw()

    def Exit(self):
        reply = QMessageBox.question(
            self, 'Confirm Exit',
            'Are you sure you want to exit Hub Configuration?',
            QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            quit()
예제 #20
0
class MplWidget(QtWidgets.QWidget):
    """
    Widget defined in Qt Designer.
    """

    zoom_to_full_view = pyqtSignal()
    map_press = pyqtSignal(float, float)

    def __init__(self, parent = None):

        # initialization of Qt MainWindow widget
        QtWidgets.QWidget.__init__(self, parent)
        
        # set the canvas to the Matplotlib widget
        self.canvas = MplCanvas()

        self.ntb = NavigationToolbar(self.canvas, self)
        
        #self.ntb.removeAction(self.ntb.buttons[0])
        self.ntb.clear()
        
        program_folder = os.path.join(os.path.dirname(__file__), "ims")

        a = self.ntb.addAction(self.ntb._icon(os.path.join(program_folder, "world.png")), 'Home', self.zoom2fullextent)
        a.setToolTip('Reset original view')
        a = self.ntb.addAction(self.ntb._icon(os.path.join(program_folder, "arrow_left.png")), 'Back', self.ntb.back)
        a.setToolTip('Back to previous view')
        a = self.ntb.addAction(self.ntb._icon(os.path.join(program_folder, "arrow_right.png")), 'Forward', self.ntb.forward)
        a.setToolTip('Forward to next view')

        a = self.ntb.addAction(self.ntb._icon(os.path.join(program_folder, "arrow_out.png")), 'Pan', self.ntb.pan)
        a.setToolTip('Pan axes with left mouse, zoom with right')
        a = self.ntb.addAction(self.ntb._icon(os.path.join(program_folder, "zoom.png")), 'Zoom', self.ntb.zoom)
        a.setToolTip('Zoom to rectangle')

        action_SetSrcPt = self.ntb.addAction(self.ntb._icon(os.path.join(program_folder, "bullet_red.png")), 'Source point', self.pt_map)
        action_SetSrcPt.setToolTip('Set source point in map') 

        a = self.ntb.addAction(self.ntb._icon(os.path.join(program_folder, "camera.png")), 'Save',
                self.ntb.save_figure)
        a.setToolTip('Save map as image')

        a = self.ntb.addAction(self.ntb._icon(os.path.join(program_folder, "help.png")), 'Help',
                self.openHelp)
        a.setToolTip('Help')
        
        a = self.ntb.addAction(self.ntb._icon(os.path.join(program_folder, "information.png")), 'About',
                self.helpAbout)
        a.setToolTip('About')        
                                            
        # create a vertical box layout
        self.vbl = QtWidgets.QVBoxLayout()
        
        # add widgets to the vertical box
        self.vbl.addWidget(self.canvas)
        self.vbl.addWidget(self.ntb)
                                                             
        # set the layout to the vertical box
        self.setLayout(self.vbl)        
        
    def onclick(self, event): 
        """
        Emit a signal to induce the update of source point location.
        
        @param event: press event.
        @type event: Matplotlib event.
        """          
        global set_srcpt_count, cid
        
        set_srcpt_count += 1
        
        if set_srcpt_count == 1:
            self.map_press.emit(event.xdata, event.ydata)

        self.canvas.fig.canvas.mpl_disconnect(cid)
                
    def pt_map(self):
        """
        Connect the press event with the function for updating the source point location.
        
        """        
        global set_srcpt_count, cid
            
        set_srcpt_count = 0
        
        cid = self.canvas.fig.canvas.mpl_connect('button_press_event', self.onclick)    
                
    def zoom2fullextent(self):
        """
        Emit the signal for updating the map view to the extent of the DEM, in alternative of
        the shapefile, or at the standard extent.
        
        """
        self.zoom_to_full_view.emit()

    def openHelp(self):
        """
        Open an Help HTML file

        after CADTOOLS module in QG
        """
        help_path = os.path.join(os.path.dirname(__file__), 'help', 'help.html')         
        webbrowser.open(help_path)
            
    def helpAbout(self):
        """
        Visualize an About window.
        """
        QtWidgets.QMessageBox.about(self, "About gSurf",
        """
            <p>gSurf<br />License: GPL v. 3</p>
            <p>This application calculates the intersection between a plane and a DEM in an interactive way.
            The result is a set of points/lines that can be saved as shapefiles.            
            </p>
             <p>Report any bug to <a href="mailto:[email protected]">[email protected]</a></p>
        """)              
예제 #21
0
파일: GeoUI.py 프로젝트: arthurHamel/GeoUI
class MyApp(QMainWindow, Ui_MainWindow):
	def __init__(self):
		QMainWindow.__init__(self)
		Ui_MainWindow.__init__(self)
		self.setupUi(self)
		
		self.setWindowTitle('GeoProcessing') 
		
		self.dirSelect_main.clicked.connect(self.select_output)
		self.process_main.clicked.connect(self.process)
		self.exportGeoTiff_main.clicked.connect(self.exportGeo)
		self.actionImport_main.triggered.connect(self.importDialog)
		self.actionSettings.triggered.connect(self.settingsDialog)
		self.actionAssemble_main.triggered.connect(self.assembleDialog)
		self.getStats_main.triggered.connect(self.makeStatistics)
		self.exportGeoTiff_main.setEnabled(False)
		self.loadParam()
		
		#Create the toolbar
		
		actionRotateR = QAction(QIcon(os.path.join(os.path.dirname(__file__), 'ressources/rotateR.png')), 'Rotate clockwise', self)
		actionRotateL = QAction(QIcon(os.path.join(os.path.dirname(__file__), 'ressources/rotateL.png')), 'Rotate counter clockwise', self)
		actionFlipUD = QAction(QIcon(os.path.join(os.path.dirname(__file__), 'ressources/flipud.png')), 'Flip vertical', self)
		actionFlipLR = QAction(QIcon(os.path.join(os.path.dirname(__file__), 'ressources/fliplr.png')), 'Flip horiziontal', self)
		#Icon from https://www.iconfinder.com/icons/281321/adjust_align_control_editor_manage_move_operate_rotate_icon#size=128
	
	
		actionRotateR.triggered.connect(self.rotateR)
		actionRotateL.triggered.connect(self.rotateL)
		actionFlipUD.triggered.connect(self.flipud)
		actionFlipLR.triggered.connect(self.fliplr)
		
		
		self.figure = plt.figure()
		self.canvas = FigureCanvas(self.figure)
		 # set button context menu policy
		self.canvas.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
		self.canvas.customContextMenuRequested.connect(self.on_context_menu)

		# create context menu
		self.popMenu = QMenu(self)
		self.actionOpenEditor=QAction('Open grid in editor', self)
		self.actionEditPoint=QAction('Edit point', self)
		self.popMenu.addAction(self.actionOpenEditor)
		self.popMenu.addAction(self.actionEditPoint)
		self.actionOpenEditor.triggered.connect(self.openEditor)
		self.actionEditPoint.triggered.connect(self.editPoint)
	 

		   


		self.toolbar = NavigationToolbar(self.canvas, self)
		self.toolbar.addAction(actionRotateL)
		self.toolbar.addAction(actionRotateR)
		self.toolbar.addAction(actionFlipUD)
		self.toolbar.addAction(actionFlipLR)
		
		self.canvasLayout.addWidget(self.toolbar)
		self.canvasLayout.addWidget(self.canvas)
		self.sizeTiles_lbl.setText("x:%s y:%s" %(self.tileSize[0], self.tileSize[0]))
		self.epsg_txt.setText("EPSG: %s" %(self.epsg))

		self.stdClip_val.setText(str(self.stdClip_slider.value()/float(100)))
		self.stdClip_slider.valueChanged.connect(self.changeClipValue)
		
		self.stdClip_check.toggled.connect(self.clipChecked)
		self.survey=Survey(self.foldername, self.siteName)
		
		
		self.statusBar().showMessage('Ready')
		self.gridSize=(20,20)
		
	def clipChecked(self):
		if self.stdClip_check.isChecked():
			self.stdClip_slider.setEnabled(True)
			self.stdClip_val.setEnabled(True)
			#Update view
		else:
			self.stdClip_slider.setEnabled(False)
			self.stdClip_val.setEnabled(False)
		
	def changeClipValue(self):
		self.stdClip_val.setText(str(self.stdClip_slider.value()/float(100)))
		
	def addInfo(self,l):
		self.infotxt+=l
		self.infoTxt_main.setText(self.infotxt)
		app.processEvents()
		
	def clearInfo(self):
		self.infotxt=""
		self.infoTxt_main.setText(self.infotxt)
		app.processEvents()
		

	def select_output(self):

		foldername = QFileDialog.getExistingDirectory(self, "Select output directory ",self.foldername)
		self.foldername=foldername
		#Here check that the directory is valid
		self.pathRaw=foldername +"/raw/"
		self.pathOutput=foldername +"/output/"
		infotxt=""
		if (os.path.isdir(self.pathRaw)==0):
			infotxt+="Raw folder not found\n"
		if (os.path.isdir(self.pathOutput)==0):
			infotxt+="Output folder not found\n"		

		if (infotxt!=""):
			QMessageBox.about(self, "Invalid directory", infotxt)
			self.actionImport_main.setEnabled(False)
			self.actionAssemble_main.setEnabled(False)
			self.dir_main.setText("")
		else:
			self.dir_main.setText(foldername)
			self.actionImport_main.setEnabled(True)
			self.actionAssemble_main.setEnabled(True)
			self.siteName=foldername.split("/")[-1]
			self.siteName_main.setText(self.siteName)
			self.saveParam()
			

	def scanLastGridId(self):
		listCsv=os.listdir(self.pathRaw)
		last=0
		for i in range (0,len(listCsv)):
			str=listCsv[i].split(".")
			if (str[1]=="csv"):
				a=str[0].split("_")
				gridId=a[1]
				if ("v" not in gridId) and ("n" not in gridId):
					if (int(gridId)>last):
						last=int(gridId)+1
		return last
		
	def importDialog(self):
		self.dlgImport = ImportDialog()	
		self.siteName=self.siteName_main.text()
		self.dlgImport.exportDir.setText(str(self.siteName))
		self.init=self.scanLastGridId()

		self.dlgImport.firstGrid.setValue(self.init)
		self.dlgImport.go.clicked.connect(self.downloadRM85)
		
		self.dlgImport.show()
		
	def settingsDialog(self):
		self.dlgSettings = SettingsDialog()
		index = self.dlgSettings.epsg.findText(str(self.epsg), QtCore.Qt.MatchFixedString)
		if index >= 0:
			self.dlgSettings.epsg.setCurrentIndex(index)
		# self.dlgSettings.epsg.value(self.epsg)
		self.dlgSettings.go.clicked.connect(self.saveSettingsChanges)
		self.dlgSettings.show()
		
	def saveSettingsChanges(self):
		self.epsg=int(self.dlgSettings.epsg.currentText())
		self.saveParam()
		self.epsg_txt.setText("EPSG: %s" %(self.epsg))
		del self.dlgSettings
		
	def assembleDialog(self):
		self.siteName=str(self.siteName_main.text())
		print (self.siteName)
		self.geoFile="0\t0\t0\t0\t0\n0\t0\t0\t0\t0\n0\t0\t0\t0\t0\n0\t0\t0\t0\t0\n"
		if os.path.isfile(self.foldername+"/output/geometry.txt"):
			f=open(self.foldername+"/output/geometry.txt", "r+")
			self.geoFile=f.read()
			f.close()
		
		else: 
			print ("The geometry file was not found. A new one was initiated.")
			f=open(self.foldername+"/output/geometry.txt", "w+")
			f.write(self.geoFile)
			f.close()

		self.dlgAss = Assemble()
		self.dlgAss.buttonBox.accepted.connect(self.assembleSave)
		self.dlgAss.text.setLineWrapMode(0)
		self.dlgAss.text.appendPlainText(self.geoFile)
		self.dlgAss.show()
			
	def assembleSave(self):
		self.geoFile=self.dlgAss.text.toPlainText()
		f=open(self.foldername+"/output/geometry.txt", "w+")
		f.write(self.geoFile)
		f.close()

	def makeStatistics(self):
		import matplotlib.pyplot as plt
		first=1
		files=os.listdir(self.pathRaw)
		for file in files:
			if ".csv" in file:
				grid=np.genfromtxt(self.pathRaw+file, delimiter=",")
				print (grid.shape)
				if first:
					all=grid
					first=0
				else:
					all=np.concatenate((grid,all))
		
		print (all.shape)
		self.min=all.min()
		self.max=all.max()
		self.std=all.std()
		self.mean=all.mean()
		
		hist, bin_edges = np.histogram(all)
		plt.hist(all, bins=100)
		plt.show()
		
		report=("Statistics\nmin=%.3f\nmax=%.3f\nStd=%.3f\nMean=%.3f" %(self.min,self.max,self.std,self.mean))
		
		self.infoTxt_main.setText(report)
		
	def drawSelection(self):
		
		x,y=self.currentSelection
		if (x!=-1):
			self.select=self.ax.add_patch(
				patches.Rectangle(
					(x*self.tileSize[0], y*self.tileSize[1]),   # (x,y)
					self.tileSize[0],		  # width
					self.tileSize[1],		  # height
					fill=False,
					edgecolor="red",
					linewidth=1
				)
			)
			gridID=self.getGeometry()[y][x]
			print (x,y,gridID)
			self.select_gridID= plt.text(x*self.tileSize[0], y*self.tileSize[1]+self.tileSize[1],gridID)
			self.canvas.draw()
	
	def clearSelection(self):
		x,y=self.currentSelection
		if (x!=-1):
			try:
				self.select.remove()
				self.select_gridID.remove()
				self.canvas.draw()
			except:
				print ("No selection to clear")
	
	def onclickFig(self,event):
		print('button=%d, x=%d, y=%d, xdata=%f, ydata=%f' %
			  (event.button, event.x, event.y, event.xdata, event.ydata))
		selection=True
		if event.button==1:
			if selection:
				x=int(event.xdata/self.tileSize[0])
				y=int(event.ydata/self.tileSize[1])
				print("right Click at %s %s" %(x,y))
				self.clearSelection()
				if self.index[y][x]!="0":
					self.currentSelection=(x,y)
					self.drawSelection()
		
		elif event.button==2:
			self.drag_view(event)
			
		elif event.button==3:
			x=int(event.xdata/self.tileSize[0])
			y=int(event.ydata/self.tileSize[1])
			self.clearSelection()
			if self.index[y][x]!="0":
				self.currentSelection=(x,y)
				self.drawSelection()
				
				point=QPoint(event.x, self.canvas.height()-event.y)
				self.popMenu.exec_(self.canvas.mapToGlobal(point))
			
			
	def drag_view(self, event):
		print ("pan")
		'on button press we will see if the mouse is over us and store some data'
		if event.inaxes != self.ax.axes: return
		cur_xlim = self.ax.get_xlim()
		cur_ylim = self.ax.get_ylim()
		self.press = cur_xlim, cur_ylim, event.xdata, event.ydata

	def on_motion(self, event):
		'on motion we will move the rect if the mouse is over us'
		if self.press is None: return
		if event.inaxes != self.ax.axes: return
		cur_xlim, cur_ylim, xpress, ypress = self.press
		dx = event.xdata - xpress
		dy = event.ydata - ypress
		
		#print('x0=%f, xpress=%f, event.xdata=%f, dx=%f, x0+dx=%f' %
		#	  (x0, xpress, event.xdata, dx, x0+dx))
		self.ax.set_xlim([cur_xlim[0]-dx,cur_xlim[1]-dx])
		self.ax.set_ylim([cur_ylim[0]-dy,cur_ylim[1]-dy])
		app.processEvents()

		self.canvas.draw()

	def on_context_menu(self, point):
		# # show context menu
		# self.popMenu.exec_(self.canvas.mapToGlobal(point)) 
		pass

	def on_release(self, event):
		if event.button==2:
			'on release we reset the press data'
			self.press = None
			print ("realese button")

	def zoom_fun(self,event,base_scale = 1.5):
		dataXmax=self.survey.getGeometry().shape[1]*self.gridSize[1]
		dataYmax=self.survey.getGeometry().shape[0]*self.gridSize[0]

		# get the current x and y limits
		curr_xlim = self.ax.get_xlim()
		curr_ylim = self.ax.get_ylim()
		xdata = event.xdata # get event x location
		ydata = event.ydata # get event y location
		if event.button == 'up':
			# deal with zoom in

			scale_factor = 1/base_scale
		elif event.button == 'down':

			# deal with zoom out
			scale_factor = base_scale
		else:
			# deal with something that should never happen
			scale_factor = 1
			print (event.button)
		# set new limits
		


		new_width = (curr_xlim[1]-curr_xlim[0])*scale_factor
		new_height= (curr_ylim[1]-curr_ylim[0])*scale_factor

		relx = (curr_xlim[1]-event.xdata)/(curr_xlim[1]-curr_xlim[0])
		rely = (curr_ylim[1]-event.ydata)/(curr_ylim[1]-curr_ylim[0])

		new_xlim=[event.xdata-new_width*(1-relx),event.xdata+new_width*(relx)]
		if new_xlim[0]<0:
			new_xlim[0]=0
		if  new_xlim[1]>dataXmax:
			new_xlim[1]=dataXmax
			
		self.ax.set_xlim(new_xlim)
		new_ylim=[event.ydata+new_width*(1-rely),event.ydata-new_width*(rely)]
		if new_ylim[0]<0:
			new_ylim[0]=0
		if  new_ylim[1]>dataYmax:
			new_ylim[1]=dataYmax
		self.ax.set_ylim(new_ylim)
		
		app.processEvents()

		self.canvas.draw()

	
	def rotateL(self):
		ii,i=self.currentSelection
		csv=np.genfromtxt(str(self.pathRaw+self.siteName+'_'+self.index[i][ii]+'.csv'), delimiter=",")
		csv=np.rot90(csv)
		
		np.savetxt(str(self.pathRaw+self.siteName+'_'+self.index[i][ii]+'.csv'), csv, delimiter=",", fmt='%.2f')

		self.process()
		
		self.currentSelection=(ii,i)
		
		self.drawSelection()
	
	def rotateR(self):
		ii,i=self.currentSelection
		csv=np.genfromtxt(str(self.pathRaw+self.siteName+'_'+self.index[i][ii]+'.csv'), delimiter=",")
		csv=np.rot90(csv,3)
		
		np.savetxt(str(self.pathRaw+self.siteName+'_'+self.index[i][ii]+'.csv'), csv, delimiter=",", fmt='%.2f')

		self.process()
		self.currentSelection=(ii,i)
		self.drawSelection()
		
		
	def fliplr(self):
		ii,i=self.currentSelection
		csv=np.genfromtxt(str(self.pathRaw+self.siteName+'_'+self.index[i][ii]+'.csv'), delimiter=",")
		csv=np.fliplr(csv)
		
		np.savetxt(str(self.pathRaw+self.siteName+'_'+self.index[i][ii]+'.csv'), csv, delimiter=",", fmt='%.2f')
		
		self.process()
		self.currentSelection=(ii,i)
		self.drawSelection()
		
	def flipud(self):
		ii,i=self.currentSelection
		csv=np.genfromtxt(str(self.pathRaw+self.siteName+'_'+self.index[i][ii]+'.csv'), delimiter=",")
		csv=np.flipud(csv)
		
		np.savetxt(str(self.pathRaw+self.siteName+'_'+self.index[i][ii]+'.csv'), csv, delimiter=",", fmt='%.2f')
		
		self.process()
		self.currentSelection=(ii,i)
		self.drawSelection()
		
	def openEditor(self):
		ii,i=self.currentSelection
		file=str(self.pathRaw+self.siteName+'_'+self.index[i][ii]+'.csv')
		import subprocess
		print (file)
		subprocess.call(['notepad',file])
		
	def editPoint(self):
		print ("the point")
	
	def downloadRM85(self):
		import serial
		
		rows=self.dlgImport.YSize.value()
		cols=self.dlgImport.XSize.value()
		
		
		try:
			ser = serial.Serial(str(self.dlgImport.com.currentText()), int(self.dlgImport.baud.currentText()), timeout=1) #Tried with and without the last 3 parameters, and also at 1Mbps, same happens.
			ser.flushInput()
			ser.flushOutput()
		except:
			connected=0
			self.dlgImport.status.setText("No device detected. Check connection.")
			app.processEvents()
		else:
			self.dlgImport.status.setText("Ready. Press <<Dump>> on device.")
			connected=1
			
		app.processEvents()
		if connected:
			started = 0
			ii=int(self.dlgImport.firstGrid.value())-1
			data_raw=""
			mode= self.dlgImport.mode.currentIndex()
			siteNameID=self.siteName
			while True:

				bytesToRead = ser.readline()
				if (bytesToRead!=""):
					self.dlgImport.status.setText("Loading...")
					app.processEvents()
					started=1
					ii+=1
					if (ii<10):
						countStr=str("0%s" %ii)
					else: 
						countStr=ii
					
					matrix1=np.empty([rows,cols])
					if mode==1:
						matrix50=np.empty([rows,2*cols])
						samplesPerPoints=3
					if mode ==0:
						samplesPerPoints=1
					self.dlgImport.progressBar.setValue(0)
					
					for x in range (0,cols):
						line=""
						self.dlgImport.status.setText("Loading... Grid %s - Line %s" %(ii, x+1))
						for y in range (0,rows):
							for pt in range (0,samplesPerPoints):
								while True:
									if (x==0 and y==0 and pt==0):
										line=str(bytesToRead)
									else:
										line=str(ser.readline())

									reading=str(ser.readline())
									if "01" in reading:
										gain=1
									elif "11" in reading:
										gain=10
									elif "21" in reading:
										gain=100
									break
								if ("4095" in line):  
									value="0"
								elif ("4094" in line):
									value="0.01"
								else:
									value=int(line.strip())
									value=value/(2*float(gain))
									value= round(value, 3)#convert to resistance values
								if (x%2!=0):#Zigzag mode
									if (pt==0):
										matrix1[19-y][x]=value
									elif(pt==1):
										matrix50[19-y][2*x+1]=value
									elif(pt==2):
										matrix50[19-y][2*x]=value
								else:
									if (pt==0):
										matrix1[y][x]=value
									elif(pt==1):
										matrix50[y][2*x]=value
									elif(pt==2):
										matrix50[y][2*x+1]=value
							self.dlgImport.progressBar.setValue((100/cols)*(x+1))
							app.processEvents()
				
				### Rotate 
				
					if self.dlgImport.SWV.isChecked():
						matrix1=np.flipud(matrix1)
					elif self.dlgImport.SWH.isChecked():
						matrix1=np.rot90(matrix1)
						
					elif self.dlgImport.SEV.isChecked():
						matrix1=np.rot90(matrix1,2)

					elif self.dlgImport.SEH.isChecked():
						matrix1=np.rot90(matrix1,3)
						matrix1=np.flipud(matrix1)
						
					elif self.dlgImport.NWV.isChecked():
						pass
					elif self.dlgImport.NWH.isChecked():
						matrix1=np.rot90(matrix1)
						matrix1=np.flipud(matrix1)
						
					elif self.dlgImport.NEH.isChecked():
						matrix1=np.rot90(matrix1,3)
					elif self.dlgImport.NEV.isChecked():
						matrix1=np.fliplr(matrix1)

				#### Writing file. Checking whether the file already exists ####
					
					fname1='%s\%s_%s.csv' %(self.pathRaw,siteNameID,countStr)
					if (os.path.isfile(fname1)):
						msg=QMessageBox.about(self, "Error", "Error: Grid %s Already exists. Erase it first." %ii)
						break
					else:
						np.savetxt(fname1, matrix1, delimiter=",", fmt='%.2f')
					if mode==1:
						fname50='%s\grid50_%s.csv' %(self.pathRaw,countStr)
						if (os.path.isfile(fname1)):
							msg=QMessageBox.about(self, "Error", "Error: Grid %s Already exists. Erase it first." %ii)
							break
						else:
							matrix50=np.rot90(matrix50)
							np.savetxt(fname50, matrix50, delimiter=",", fmt='%.2f')
					app.processEvents()

				if (started==1 and bytesToRead==""):
					ser.flushInput()
					ser.flushOutput()
					ser.close()
					del ser
					self.dlgImport.status.setText("Done")
					self.dlgImport.go.setText("Done")
					self.dlgImport.close()
					
					break

			
			
	def saveParam(self):
		try:
			confFile=open(os.path.join(os.path.dirname(__file__), 'conf.txt'),'w')
		except:
			print ("Error opening the config file. Check you have the rights to write in the directory.")
		
		conftxt="SITEDIR="+ self.foldername + "\n"
		conftxt+="SITENAME="+ self.siteName + "\n"
		conftxt+="TILESIZEX=%s\n" %self.tileSize[0]
		conftxt+="TILESIZEY=%s\n" %self.tileSize[1]
		conftxt+="EPSG= %s\n" %self.epsg
		
		confFile.write(conftxt)
		
	def loadParam(self):
		confFile=open(os.path.join(os.path.dirname(__file__), 'conf.txt'),'r')

		# print "Error loading the config file. Default values will be used."
		##Set some default values
		X=20
		Y=20
		self.foldername=""
		for line in confFile:
			if "SITEDIR" in line:
				foldername=line.split('=')[1].strip()
				self.foldername=foldername
				self.pathRaw=foldername +"/raw/"
				self.pathOutput=foldername +"/output/"
				
				if (os.path.isdir(self.pathRaw)==0 or os.path.isdir(self.pathOutput)==0):
					self.actionImport_main.setEnabled(False)
					self.actionAssemble_main.setEnabled(False)
					self.dir_main.setText("")
					print("no dir found")
					self.foldername=""
				else:
					self.dir_main.setText(foldername)
					self.actionImport_main.setEnabled(True)
					self.actionAssemble_main.setEnabled(True)
					self.dir_main.setText(self.foldername)
					
			if "TILESIZEX" in line:
				X=int(line.split('=')[1])
			if "TILESIZEY" in line:
				Y=int(line.split('=')[1])
			if "SITENAME" in line:
				self.siteName=line.split('=')[1].strip()
				self.siteName_main.setText(self.siteName)
			if "EPSG" in line:
				self.epsg=line.split('=')[1].strip()
			
		self.tileSize=(X,Y)
		
				
	def process(self):
		self.clearInfo()
		self.index=self.getGeometry()
		self.mainMatrix=self.makeMosaic()
		self.exportGeoTiff_main.setEnabled(True)
		

	
	def matrix2figure(self, matrix):

		self.figure.clear()
		 
		if self.stdClip_check.isChecked():
			matrix=self.stdClip(matrix, self.stdClip_slider.value()/float(100))

		self.ax = self.figure.add_subplot(111)
		# discards the old graph
		#self.ax.hold(False)
		
		noData=0
		masked_data = np.ma.masked_where(matrix == noData, matrix)
		print (self.vis_palette.currentText())
		array = plt.imshow(masked_data, interpolation='none', cmap=str(self.vis_palette.currentText()))
		# cbar = plt.colorbar(mappable=array, orientation = 'horizontal', fraction=0.030, pad=0.07)
		# cbar.set_label('Resisitivity (Ohm/m)')
		plt.tight_layout()
		self.ax.grid(True)
		index=self.getGeometry()
		y=(index.shape[0])
		x=(index.shape[1])
		xmax=x*self.tileSize[0]
		ymax=y*self.tileSize[1]
		print(xmax,ymax)
		self.ax.xaxis.set_ticks(np.arange(0, xmax, 20))
		self.ax.yaxis.set_ticks(np.arange(0, ymax, 20))

		app.processEvents()

		self.canvas.draw()
		cid = self.canvas.mpl_connect('button_press_event', self.onclickFig)
		zo=self.canvas.mpl_connect('scroll_event',self.zoom_fun)
		cidMove=self.canvas.mpl_connect('motion_notify_event', self.on_motion)
		self.press=None
		cidRelease= self.canvas.mpl_connect('button_release_event', self.on_release)
		self.currentSelection=(-1,-1)
		
	def exportGeoTiff(self, filename, mat):
		import os.path
		import gdal, osr
		
		mat=np.int16(mat)
		
		xSize=mat.shape[1]
		ySize=mat.shape[0]
		step=1
		output_file=str(self.pathOutput+filename+'.tif')

		xCoord=0
		yCoord=0
		rotX=0
		rotY=0
		epsg=int(self.epsg)
		#epsg=32633 UTM nord 33
		#epsg=3004 Monte Mario 2
		print('Output coordintate system: %s' % epsg)
		geoTrans=[ xCoord, step , 0,  yCoord , 0, step ]
		srs = osr.SpatialReference()
		srs.ImportFromEPSG(epsg)
		# Create gtif (uncomment when using gdal)
		# 
		DataType= gdal.GDT_UInt16
		driver = gdal.GetDriverByName("GTiff")
		dst_ds = driver.Create(output_file, xSize, ySize, 1, DataType)
		#top left x, w-e pixel resolution, rotation, top left y, rotation, n-s pixel resolution
		print (geoTrans)
		#leavev the geotransform to use worldfile
		##dst_ds.SetGeoTransform( geoTrans )

		
		dst_ds.SetProjection( srs.ExportToWkt() )
		


		# write the band
		dst_ds.GetRasterBand(1).WriteArray(mat)
		band = dst_ds.GetRasterBand(1)
		band.SetNoDataValue(0)
		band.FlushCache()
	
	def exportTiff(self, filename, mat):
		import os.path
		import gdal, osr
		from libtiff import TIFF
		import arcpy
	
		
		mat=np.uint16(mat)
		
		xSize=mat.shape[1]
		ySize=mat.shape[0]
		step=1
		output_file=str(self.pathOutput+filename+'.tif')
		
		tiff = TIFF.open(output_file, mode='w')
		tiff.write_image(mat)
		tiff.close()
		
		arcpy.SetRasterProperties_management(output_file, "GENERIC","#" , "0" , "#")
	
	def georeferencing(self):
		import arcpy
		if os.path.isfile(self.pathOutput+"gcp.txt"):
			print ("Georeferencing output from GCPs")
			files=os.listdir(self.pathOutput)
			for file in files:
				if ".tif" in file:	
					try:
						arcpy.WarpFromFile_management(
						self.pathOutput+file, self.pathOutput+"georef_"+file,
						self.pathOutput+"gcp.txt", "POLYORDER1", "BILINEAR")
					except:
						print ("Error georeferencing "+file)
		else:
			print ("No GCP file found.")
	
	def normalize(self,mat):
		min=999999
		max=0
		for i in range (0,mat.shape[0]):
			for ii in range (0,mat.shape[1]):
				if (mat[i][ii]!=0 and mat[i][ii]<min):
					min=mat[i][ii]
				if (mat[i][ii]!=0 and mat[i][ii]>max):
					max=mat[i][ii]
		print(min, max)
		mat=((mat-min)/(max-min))
		return mat
		
	def normalizeClip(self,mat,clip):
		dev=mat.std()
		mean=mat.mean()
		min=mean-clip*dev
		max=mean+clip*dev
		
		mat=((mat-min)/(max-min))
		return mat
	
	def stdClip(self,mat,clip):
		dev=mat.std()
		mean=mat.mean()
		min=mean-clip*dev
		max=mean+clip*dev
		
		for i in range (0, mat.shape[0]):
			for ii in range (0,mat.shape [1]):
				if mat[i][ii]>max:	
					mat[i][ii]=max
				if mat[i][ii]<min:
					mat[i][ii]=min
				
		return mat
		
		
	def getGeometry(self):
		#print (str(self.pathOutput)+'geometry.txt')
		index=np.genfromtxt(str(self.pathOutput)+'geometry.txt',dtype='str', delimiter="\t");
		return index;
	
	def excludeOdds(self,mat):			#Exclude weird values and 0's from the mean calculation
		mat=np.array(mat)
		mat=mat.flatten()
		mat=mat[np.nonzero(mat)]
		std=np.std(mat)
		mean=np.mean(mat)
		indexOdds=list()
		limMin=mean-2.5*std
		limMax=mean+2.5*std
		for i in range (0, len(mat)):
			if(mat[i] <limMin or mat[i]>limMax):
				indexOdds.append(i)
		mat=np.delete(mat,indexOdds)
		return mat;


	def delta_extrap(self,grid_2,adj_2):	#determine the difference between adajcent edges of two grids
		grid_extrap=np.zeros(grid_2.shape[0])
		adj_extrap=np.zeros(grid_2.shape[0])
		grid_lin=grid_2[:,0]
		adj_lin=adj_2[:,1]
		delete=[]
		good=0
		bad=0
		for i in range (0,len(grid_extrap)):
			grid_extrap[i]=((grid_2[i][0]-grid_2[i][1])*0.5)+grid_2[i][0]
			adj_extrap[i]=((adj_2[i][1]-adj_2[i][0])*0.5)+adj_2[i][1]
			
		diff=np.zeros(len(grid_extrap))
		
		for i in range (0,len(grid_extrap)):
			diff[i]=((grid_extrap[i]-adj_extrap[i])+(grid_lin[i]-adj_lin[i]))/2
			
		mean_diff=np.mean(diff)
		std_diff=np.std(diff)
		for i in range (0,len(diff)):
			if (grid_2[i][0]==0 or grid_2[i][1]==0 or adj_2[i][0]==0 or adj_2[i][1]==0):
				delete=np.append(delete,i)
			if (diff[i]>mean_diff+2*std_diff or diff[i]<mean_diff-2*std_diff):
				delete=np.append(delete,i)
				
		diff=np.delete(diff,delete)		
		if (len(diff)>2):#if the edge is not too small....
			d=np.round(np.mean(diff),3)			#the difference between the grids
			if (d!=0):
				w=np.power(len(diff),2)/(np.std(diff))	#The weighting factor
				good+=1
			else:
				w=0
				bad+=1
		else:
			w=0
			d=0
			bad+=1

		return d,w

	def edgeMatch2(self,matrix,sizeEdge):
		print ('edge matching...')
		edgeSize=sizeEdge
		
		#Split the whole matrix in tiles (grids of 20x20 in our case)
		xGrids=int(matrix.shape[1]/edgeSize)	
		yGrids=int(matrix.shape[0]/edgeSize)
		n=int(xGrids*yGrids)
		print (n)
		print (int(n))
		A=np.zeros([n,n])
		x=np.zeros([n])
		b=np.zeros([n])
		
		minInit=np.min(matrix)
		if minInit<0:
			print ("warning: Negative values in the data. This may cause errors later.\n Consider despiking or correct these data.")
			matSorted=np.sort(matrix, axis=None)
			pos=1
			for i in range (0,len(matSorted)):
				if matSorted[i]==0 and pos:
					print ("%s negative values" %(i))
					print (matSorted[0:i])
					pos=0
				if matSorted[i]>0.01:
					minInit=matSorted[i]
					break
		i=0
		maxInit=np.max(matrix)
		print (minInit,maxInit)
		range_init=maxInit-minInit
		bestW=0
		reference=0
		print ('%s rows x %s cols' %(yGrids,xGrids))
		for x in range(0,xGrids):
			for y in range (0,yGrids):	#for each grid we compute the mismatch d and the weight coefficient w with the four neighbours 1:W, 2:N, 3,E, 4S 
				ymin=y*edgeSize
				ymax=(y+1)*edgeSize
				xmin=x*edgeSize
				xmax=(x+1)*edgeSize
				#Adjacent edge
				if (x>0):
					gridW=(matrix[ymin:ymax,xmin:xmin+2])
					edgeW=(matrix[ymin:ymax,xmin-2:xmin])
					di1,wi1=self.delta_extrap(gridW,edgeW)
					

				else:
					di1=0
					wi1=0

				if (y<yGrids-1):	
					
					gridN=np.fliplr(np.rot90((matrix[ymax-2:ymax,xmin:xmax])))
					edgeN=np.fliplr(np.rot90((matrix[ymax:ymax+2,xmin:xmax])))
					di2,wi2=self.delta_extrap(gridN,edgeN)
				
				else:
					di2=0
					wi2=0
				
				if (x<xGrids-1):	
					gridE=np.fliplr((matrix[ymin:ymax,xmax-2:xmax]))
					edgeE=np.fliplr((matrix[ymin:ymax,xmax:xmax+2]))
					di3,wi3=self.delta_extrap(gridE,edgeE)
						
				else:
					di3=0
					wi3=0
					
				if (y>0):
					gridS=np.flipud(np.rot90((matrix[ymin:ymin+2,xmin:xmax])))
					edgeS=np.flipud(np.rot90((matrix[ymin-2:ymin,xmin:xmax])))
					di4,wi4=self.delta_extrap(gridS,edgeS)
					

				else:
					di4=0
					wi4=0
					
				if (wi1!=0 and wi2!=0 and wi3!=0 and wi4!=0):
					fitness=wi1+wi2+wi3+wi4
					if fitness>bestW:
						bestW=fitness
						bestGrid=(x,y)
						reference=1
				
				#following the equation of Haigh 1995
				A[i,i]=(wi1+wi2+wi3+wi4)				#factor of xi
				
				if (x>0):						#the left line has no W side
					A[i,i-yGrids]=-wi1				#factor of xi1
				if (y<yGrids-1):					#the top line has no N side
					A[i,i+1]=-wi2				#factor of xi2
				if (x<xGrids-1):					#the right line has no E side
					A[i,i+yGrids]=-wi3				#factor of xi3
				if (y>0):					#the bottom line has no S side
					A[i,i-1]=-wi4				#factor of xi4
				
				b[i]=((di1*wi1)+(di2*wi2)+(di3*wi3)+(di4*wi4))

				i+=1

		print ('Resolving the equation of the meaning of life...')
		try:
			U,s,V = np.linalg.svd(A) # SVD decomposition of A

			# computing the inverse using pinv
			pinv = np.linalg.pinv(A)
			# computing the inverse using the SVD decomposition
			pinv_svd = np.dot(np.dot(V.T,np.linalg.inv(np.diag(s))),U.T)
			
			c = np.dot(U.T,b) # c = U^t*b
			w = np.linalg.solve(np.diag(s),c) # w = V^t*c
			xSVD = np.dot(V.T,w) # x = V*w
			
			#the function is described here: http://students.mimuw.edu.pl/~pbechler/numpy_doc/reference/generated/numpy.linalg.lstsq.html
			corr=np.flipud(np.rot90(np.reshape(xSVD,(xGrids,yGrids)),1))	#We reshape the coefficient to the size of the initial matrix
		except: 
			errorMessage= 'Singular Matrix, edge matching equation could not be solved. Survey area is possibly too small.'
			print (errorMessage)
			QMessageBox.about(self, "Edge matching Error", errorMessage)
			return matrix
		else: 	
			#rescale to the reference grid:
			if reference:
				delta=corr[bestGrid[1]][bestGrid[0]]
				print ("reference grid at x:%s y:%s  delta:%s" % (bestGrid[0],bestGrid[1],delta))
				corr=corr-delta
			#apply the correction:
			matrix_out=np.zeros((matrix.shape[0],matrix.shape[1]))
			mask=np.zeros((matrix.shape[0],matrix.shape[1]))
			mask[matrix.nonzero()]=1
			for x in range(0,xGrids):
				for y in range (0,yGrids):
					ymin=y*edgeSize
					ymax=(y+1)*edgeSize
					xmin=x*edgeSize
					xmax=(x+1)*edgeSize
					
					b=corr[y,x]
					matrix_out[ymin:ymax,xmin:xmax]=matrix[ymin:ymax,xmin:xmax]-b
			
			matrix_out= matrix_out * mask
			min=np.nanmin(matrix_out)
			max=np.nanmax(matrix_out)
			range_output=max-min
			print (range_output)
			print (min)
			print (max)
			if (min<0):
				matrix_out=matrix_out-min

			print("minimum:%s"%(np.nanmin(matrix_out[matrix_out>0.0])))
			matrix_out=((matrix_out+minInit)/range_output)*maxInit
			matrix_mask= matrix_out * mask
			print("minimum:%s"%(np.nanmin(matrix_mask[matrix_out>0.0])))
			print("maximum:%s"%(np.nanmax(matrix_mask)))
			
			return matrix_mask
			
		
	def deslope(self,matrix,sizeEdge):
	
		print ("deloping...")
		edgeSize=sizeEdge
		
		#Split the whole matrix in tiles (grids of 20x20 in our case)
		xGrids=int(matrix.shape[1]/edgeSize)		
		yGrids=int(matrix.shape[0]/edgeSize)
		n=int(xGrids*yGrids)
		for x in range(0,xGrids):
			for y in range (0,yGrids):	#for each grid we compute the mismatch d and the weight coefficient w with the four neighbours 1:W, 2:N, 3,E, 4S 
				for a in range (0,(edgeSize-1)):
					xmin=x*edgeSize
					xmax=(x+1)*edgeSize
					yline=y*edgeSize+a
					
					lineBottom=matrix[yline,xmin:xmax]
					lineTop=matrix[yline+1,xmin:xmax]
					
					delta=np.mean(lineTop)-np.mean(lineBottom)
					matrix[yline+1,xmin:xmax]=lineTop-delta
					
					
		
		return matrix 
	
	def gaussian_blur1d(self, in_array, size):
		#check validity
		try:
			if 0 in in_array.shape:
				raise Exception("Null array can't be processed!")
		except TypeError:
			raise Exception("Null array can't be processed!")
		# expand in_array to fit edge of kernel
		padded_array = np.pad(in_array, size, 'symmetric').astype(float)
		# build kernel
		x, y = np.mgrid[-size:size + 1, -size:size + 1]
		g = np.exp(-(x**2 / float(size) + y**2 / float(size)))
		g = (g / g.sum()).astype(float)
		# do the Gaussian blur
		out_array = fftconvolve(padded_array, g, mode='valid')
		return out_array.astype(in_array.dtype)
	
	def sharpening(self, in_array, alpha):
		try:
			if 0 in in_array.shape:
				raise Exception("Null array can't be processed!")
		except TypeError:
			raise Exception("Null array can't be processed!")
		f=in_array
		blurred_f = ndimage.gaussian_filter(f, 3)

		filter_blurred_f = ndimage.gaussian_filter(blurred_f, 1)

		alpha = 30
		sharpened = blurred_f + alpha * (blurred_f - filter_blurred_f)
		
		return sharpened.astype(in_array.dtype)
		
	def makeMosaic(self):
		from PIL import Image
		self.addInfo("Load parameters\n")
		self.siteName=self.siteName_main.text()
		gridSize=self.gridSize
		index=self.getGeometry()
		zero=np.zeros(gridSize)
		x=index.shape[0]
		y=index.shape[1]
		self.addInfo("Assembling tiles\n")
		for i in range (0,x):
			for ii in range (0,y):
				
				if (index[i][ii]=='0'):
					A=zero
				else:
					try:
						A = np.genfromtxt(str(self.pathRaw+self.siteName+'_'+index[i][ii]+'.csv'), delimiter=",")
					except:
						print ('Warning: Grid '+index[i][ii]+'  not found.\n'+str(self.pathRaw+self.siteName+'_'+index[i][ii]+'.csv'))
						A=zero
					if A.shape!=(20,20):
						print ("grid of odd dimensions: " + index[i][ii] )
						print (A.shape)
				if (ii==0):
					line=A
				else:
					#print('--------Grid: %s - %s -------' %(i, ii))
					grid=A
					#grid=edgeMatch(line,A,'horizontal')
					line=np.concatenate((line,grid),axis=1)
					
			if (i==0):
				mos=line
			else:
				#line=edgeMatch(mos,line,'vertical')
				mos=np.concatenate((mos,line),axis=0)
				
		if (self.despike_main.isChecked()):
			self.addInfo("Despiking...")
			mos=p.despike(mos)
			self.addInfo("Done\n")
			
		if (self.deslope_main.isChecked()):
			self.addInfo("Desloping...")
			mos= self.deslope(mos,20)
			self.addInfo("Done\n")
		
		if (self.edgeMatching_main.isChecked()):
			self.addInfo("Edge matching...")
			mos=self.edgeMatch2(mos,20)
			self.addInfo("Done\n")
		
			
		#mos=localVariation(mos)
		step=1
		xtif=y*gridSize[0]
		ytif=x*gridSize[1]
		self.addInfo("Creating preview...")
		#mos,cdf = histeq(mos)
		print(np.min(mos),np.max(mos))
		print('%s x %s' %(x,y))
		hs_array = p.hillshade(mos,45, 315, 0.0025)
		self.makePreview(mos, hs_array, str(self.siteName))
		self.addInfo("Finished\n")
		self.matrix2figure(mos)
		return mos
		
	def makePreview(self,array, hillshade_mat, filename):
		import matplotlib
		import matplotlib.mlab as mlab
		import matplotlib.pyplot as plt
		import matplotlib.cm as cm
		from PIL import Image
		import cv2
		#import scipy.ndimage
		x=array.shape[0]
		y=array.shape[1]
		min= 99999
		max=0
		if self.stdClip_check.isChecked():
				array=self.stdClip(array, self.stdClip_slider.value()/float(100))
		for i in range (0,x):
			for ii in range (0,y):
				if (array[i][ii]!=0 and array[i][ii]<min):
					min=array[i][ii]
				if (array[i][ii]!=0 and array[i][ii]>max):
					max=array[i][ii]
		print('min: %.2f max: %.2f \nsize: %s x %s' %(min,max, x, y))
	

		mask=np.empty([x, y], dtype='float64')
		for i in range (0,x):
			for ii in range (0,y):
				if (array[i][ii]!=0):
					mask[i][ii]=255
				if (array[i][ii]==0):
					mask[i][ii]=0

		if (min!=max and max!=0):
			
			array=(1-(array-min)/(max-min))
			array = cv2.resize(array, (0,0), fx=5, fy=5) 
			hillshade_mat = cv2.resize(hillshade_mat, (0,0), fx=5, fy=5) 
			mask = cv2.resize(mask, (0,0), fx=5, fy=5,  interpolation=cv2.INTER_NEAREST) 
			#array= scipy.ndimage.median_filter(array, 4)	
			values = Image.fromarray(np.uint8(cm.jet_r(array)*255)).convert('RGB')
			 
			
			
				
			hs_array = Image.fromarray(np.uint8(hillshade_mat)).convert('RGB')
			new_img = Image.blend(values, hs_array, 0.3).convert('RGBA')
			mask = Image.fromarray(np.uint8(mask)).convert('L')
			new_img.putalpha(mask)
			new_img.save(str(self.pathOutput+filename)+'preview.png')
			# self.displayPreview()
		else:
			print('error in reading image')

	
	def exportGeo(self):

		print('Export image...')
		self.statusBar().showMessage('Export image...')
		self.exportGeoTiff(self.siteName, self.mainMatrix*100)
		print('Export hillshade...')
		self.statusBar().showMessage('Export hillshade...')
		hs_array = p.hillshade(self.mainMatrix*100,45, 315, 0.0025)
		self.exportGeoTiff(self.siteName+"_hs", hs_array)
		self.statusBar().showMessage('GeoTIFF exported')
class MplWindow(UI_MainWindow, MainWindow):
    def __init__(self):
        super(MplWindow, self).__init__()
        self.verbose = 1
        self.setupUi(self)

        self.showMaximized()

        self.fig = Figure()

        self.graph_sequence = []
        self.graph_sequence_comments = []

        self._V6fromPHC = []
        #        self._log = ''
        #        self.setRequiresRecomputing()
        self.setActiveGraph(GraphCouplerCurve(window=self))
        self.init_widgets()
        self.init_mpl()
        #        self.init_data()
        self.init_plot()
        #self.init_pick()
        self.dockLog.resize(self.dockLog.minimumWidth() * 2, 300)
        self.dockLog.updateGeometry()

    def setActiveGraph(self, G):
        self.graph = G
        self.updateParameter()
        if self.graph.isComputed():
            self.setComputed()
        else:
            self.setRequiresRecomputing()

    def init_widgets(self):
        """Initialize the widgets, mainly connecting the relevant signals"""
        self.plainTextEdit.setReadOnly(True)
        #        self.plainTextEdit.setCenterOnScroll(True)
        #        self.plainTextEdit.setMaximumBlockCount(40)

        self.doubleSpinBoxLengths = {
            '12': self.doubleSpinBoxL12,
            '13': self.doubleSpinBoxL13,
            '14': self.doubleSpinBoxL14,
            '15': self.doubleSpinBoxL15,
            '16': self.doubleSpinBoxL16,
            '27': self.doubleSpinBoxL27,
            '37': self.doubleSpinBoxL37,
            '47': self.doubleSpinBoxL47,
            '57': self.doubleSpinBoxL57,
            '67': self.doubleSpinBoxL67,
            '23': self.doubleSpinBoxL23,
            '34': self.doubleSpinBoxL34,
            '45': self.doubleSpinBoxL45,
            '56': self.doubleSpinBoxL56,
        }

        self.update_graph2tabLengths()
        self.update_graph2phi()

        for e in self.doubleSpinBoxLengths:
            self.doubleSpinBoxLengths[e].valueChanged.connect(
                self.update_tabLengths2graph)

        self.update_graph2R26()
        self.doubleSpinBoxR26.valueChanged.connect(self.update_R26toGraph)
        self.doubleSpinBoxY2.valueChanged.connect(self.update_yV2toGraph)

        self.doubleSpinBoxPhi.valueChanged.connect(self.update_phi2graph)
        self.doubleSpinBoxTheta.valueChanged.connect(self.update_theta2graph)

        self.pushButtonPlot.clicked.connect(self.computeCouplerCurves)
        self.pushButtonPlot.setShortcut(QKeySequence("Ctrl+P"))

        self.checkBoxBranches = {
            'orange': self.checkBoxOrange,
            'red': self.checkBoxRed,
            'green': self.checkBoxGreen,
            'blue': self.checkBoxBlue
        }
        for c in self.checkBoxBranches:
            self.checkBoxBranches[c].stateChanged.connect(self.plotScene)

        self.checkBoxMirror.stateChanged.connect(self.plotScene)

        #        self.spinBoxSamples.valueChanged.connect(self.updateSamples)

        self.comboBoxGraphFor.currentTextChanged.connect(
            self.updateDisplayedGraph)
        self.spinBoxParameter.valueChanged.connect(self.updateDisplayedGraph)
        self.spinBoxParameter.setWrapping(True)

        self.spinBoxParameterStep.valueChanged.connect(
            self.update_parameterStep)

        self.doc_tb = self.addToolBar("File")

        self.loadLengthsButton = QAction(QIcon.fromTheme("document-open"),
                                         "Load lengths", self)
        self.doc_tb.addAction(self.loadLengthsButton)
        self.loadLengthsButton.triggered.connect(self.loadLengths)
        action = self.menuFile.addAction('Load lengths')
        action.triggered.connect(self.loadLengths)

        self.saveLengthsButton = QAction(QIcon.fromTheme("document-save"),
                                         "Save lengths", self)
        self.doc_tb.addAction(self.saveLengthsButton)
        self.saveLengthsButton.triggered.connect(self.saveLengths)
        action = self.menuFile.addAction('Save lengths')
        action.triggered.connect(self.saveLengths)

        self.inOut_tb = self.addToolBar("Input/Output")

        self.insertLengthsButton = QAction(QIcon.fromTheme("insert-text"),
                                           "Insert lengths", self)
        self.inOut_tb.addAction(self.insertLengthsButton)
        self.insertLengthsButton.triggered.connect(self.insertLengths)
        action = self.menuInputOutput.addAction('Insert lengths')
        action.triggered.connect(self.insertLengths)

        self.insertLengthsByEmbeddingsButton = QAction(
            "Insert lengths by embedding", self)
        self.inOut_tb.addAction(self.insertLengthsByEmbeddingsButton)
        self.insertLengthsByEmbeddingsButton.triggered.connect(
            self.insertLengthsByEmbeddings)
        action = self.menuInputOutput.addAction('Insert lengths by embedding')
        action.triggered.connect(self.insertLengthsByEmbeddings)

        self.exportLengthsButton = QAction("Export lengths", self)
        self.inOut_tb.addAction(self.exportLengthsButton)
        self.exportLengthsButton.triggered.connect(self.exportLengths)
        action = self.menuInputOutput.addAction('Export lengths')
        action.triggered.connect(self.exportLengths)

        self.actionFullscreen.toggled.connect(self.fullScreen)

        self.updateParameter()

        self.buttonLoadSequence.clicked.connect(self.loadSequence)

        self.spinBoxImgInSeq.setMinimum(1)
        self.spinBoxImgInSeq.setMaximum(1)
        self.spinBoxImgInSeq.valueChanged.connect(self.plotGraphFromSequence)

        self.spinBoxSeqLength.setReadOnly(True)
        self.spinBoxSeqLength.setButtonSymbols(QAbstractSpinBox.NoButtons)

        self.noteToImgInSeq.setReadOnly(True)
        self.boxInfoImgInSeq.setVisible(False)

        self.buttonRunPHC.clicked.connect(self.runPHC)
        self.spinBoxNumberReal.setReadOnly(True)
        self.spinBoxNumberReal.setButtonSymbols(QAbstractSpinBox.NoButtons)

        self.buttonRotateVertices.clicked.connect(self.rotateVertices)

        #        self.exportButton.clicked.connect(self.exportLengths)

        self.doubleSpinBox_x.valueChanged.connect(self.plotScene)
        self.doubleSpinBox_y.valueChanged.connect(self.plotScene)
        self.doubleSpinBox_z.valueChanged.connect(self.plotScene)

        dockWidgets = self.findChildren(QDockWidget)
        for dockWidget in dockWidgets:
            action = self.menuView.addAction(dockWidget.windowTitle())
            action.setCheckable(True)
            action.setChecked(True)
            action.triggered.connect(dockWidget.setVisible)
            dockWidget.visibilityChanged.connect(action.setChecked)
#            dockWidget.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
#            dockWidget.updateGeometry()
#        self.dockLog.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
#        self.dockLog.updateGeometry()

        self.buttonSamplingPhiTheta.clicked.connect(self.runSamplingPhiTheta)

        self._possibleParametrizedVertices = {
            '[2, 1, 6, 3, 7]': [2, 1, 6, 3, 7],
            '[2, 3, 1, 7, 6]': [2, 3, 1, 7, 6],
            '[2, 6, 1, 7, 3]': [2, 6, 1, 7, 3],
            '[2, 7, 6, 3, 1]': [2, 7, 6, 3, 1],
            '[3, 1, 2, 4, 7]': [3, 1, 2, 4, 7],
            '[3, 2, 1, 7, 4]': [3, 2, 1, 7, 4],
            '[3, 4, 1, 7, 2]': [3, 4, 1, 7, 2],
            '[3, 7, 2, 4, 1]': [3, 7, 2, 4, 1],
            '[4, 1, 3, 5, 7]': [4, 1, 3, 5, 7],
            '[4, 3, 1, 7, 5]': [4, 3, 1, 7, 5],
            '[4, 5, 1, 7, 3]': [4, 5, 1, 7, 3],
            '[4, 7, 3, 5, 1]': [4, 7, 3, 5, 1],
            '[5, 1, 4, 6, 7]': [5, 1, 4, 6, 7],
            '[5, 4, 1, 7, 6]': [5, 4, 1, 7, 6],
            '[5, 6, 1, 7, 4]': [5, 6, 1, 7, 4],
            '[5, 7, 4, 6, 1]': [5, 7, 4, 6, 1],
            '[6, 1, 5, 2, 7]': [6, 1, 5, 2, 7],
            '[6, 2, 1, 7, 5]': [6, 2, 1, 7, 5],
            '[6, 5, 1, 7, 2]': [6, 5, 1, 7, 2],
            '[6, 7, 5, 2, 1]': [6, 7, 5, 2, 1]
        }
        self.comboBoxParamVert.setInsertPolicy(6)
        for comb in self._possibleParametrizedVertices:
            self.comboBoxParamVert.addItem(comb)

        self.buttonFindMore.clicked.connect(self.findMoreEmbeddings)

        self.tabifyDockWidget(self.dockBranches, self.dockSceneShift)
        self.tabifyDockWidget(self.dockSceneShift, self.dockSequenceNavigation)

    def fullScreen(self, bool):
        if bool:
            self.showFullScreen()
        else:
            self.showMaximized()

    def loadLengths(self):
        options = QFileDialog.Options()
        #        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getOpenFileName(
            self,
            "Load lengths",
            "./examples",
            "Python Objects (*.p);;All Files (*)",
            options=options)
        if fileName:
            try:
                self.printLog('Lengths loaded from: ' + fileName)
                lengths, R26 = pickle.load(open(fileName, 'rb'))
                lengths['26'] = R26
                self.graph.setLengthsAndUpdateFixedTriangle(lengths)
                #                self.graph.setR26(R26)
                blocked = self.doubleSpinBoxR26.blockSignals(True)
                self.update_graph2R26()
                self.update_graph2tabLengths()
                self.update_graph2phi()
                self.doubleSpinBoxR26.blockSignals(blocked)

                self.computeCouplerCurves()
            except Exception as e:
                self.showError('Some problem with loading: \n' + str(e))

    def saveLengths(self):
        options = QFileDialog.Options()
        #        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getSaveFileName(
            self,
            "Save lengths",
            "./examples",
            "Python Objects (*.p);;All Files (*)",
            options=options)
        if fileName:
            self.printLog('Lengths saved to: ' + fileName)
            pickle.dump(
                [self.graph._lengths, self.graph.getR26()],
                open(fileName, 'wb'))

    def insertLengths(self):
        text, ok = QInputDialog.getMultiLineText(
            self, 'Insert lengths',
            'Insert lengths as dictionary or list of squares of lengths:')
        if ok:
            try:
                evaluated_expr = ast.literal_eval(str(text))
                if not type(evaluated_expr) is dict:
                    g = evaluated_expr
                    lengths = {
                        '12': np.sqrt(g[0]),
                        '13': np.sqrt(g[1]),
                        '14': np.sqrt(g[2]),
                        '15': np.sqrt(g[3]),
                        '16': np.sqrt(g[4]),
                        '27': np.sqrt(g[5]),
                        '37': np.sqrt(g[6]),
                        '47': np.sqrt(g[7]),
                        '57': np.sqrt(g[8]),
                        '67': np.sqrt(g[9]),
                        '23': np.sqrt(g[10]),
                        '34': np.sqrt(g[11]),
                        '45': np.sqrt(g[12]),
                        '56': np.sqrt(g[13]),
                        '26': np.sqrt(g[14])
                    }
                else:
                    lengths = evaluated_expr

                if type(lengths) == dict:
                    self.printLog('Inserted lengths: ')
                    self.graph.setLengthsAndUpdateFixedTriangle(lengths)
                    self.update_graph2R26()
                    self.update_graph2tabLengths()
                    self.update_graph2phi()
                    self.computeCouplerCurves()
                else:
                    self.showError(
                        'Input must be list containing dictionary of lengths and float R26 or list of squares of lengths'
                    )
            except Exception as e:
                self.showError('Problem with input: \n' + str(e))

    def insertLengthsByEmbeddings(self):
        text, ok = QInputDialog.getMultiLineText(
            self, 'Insert embedding',
            'Insert list of coordinates of v1,..., v7:')
        if ok:
            try:
                evaluated_expr = ast.literal_eval(str(text))
                v1, v2, v3, v4, v5, v6, v7 = evaluated_expr
                lengths = {
                    '12': self.graph.dist(v1, v2),
                    '13': self.graph.dist(v1, v3),
                    '14': self.graph.dist(v1, v4),
                    '15': self.graph.dist(v1, v5),
                    '16': self.graph.dist(v1, v6),
                    '27': self.graph.dist(v2, v7),
                    '37': self.graph.dist(v3, v7),
                    '47': self.graph.dist(v4, v7),
                    '57': self.graph.dist(v5, v7),
                    '67': self.graph.dist(v6, v7),
                    '23': self.graph.dist(v2, v3),
                    '34': self.graph.dist(v3, v4),
                    '45': self.graph.dist(v4, v5),
                    '56': self.graph.dist(v5, v6),
                    '26': self.graph.dist(v2, v6)
                }

                self.printLog('Inserted lengths: ')
                self.graph.setLengthsAndUpdateFixedTriangle(lengths)
                self.update_graph2R26()
                self.update_graph2tabLengths()
                self.update_graph2phi()
                self.computeCouplerCurves()
            except Exception as e:
                self.showError('Problem with input: \n' + str(e))

    def showError(self, s):
        msg = QErrorMessage(self)
        msg.showMessage(s)
        self.printLog(s)

    def init_plot(self):
        """Initialize the plot of the axes"""

        self.fig.subplots_adjust(left=0.0, top=1, right=1, bottom=0.0)

        self._branches_plot = self.fig.add_subplot(111, projection='3d')
        self._branches_plot.axis(aspect='equal')
        self._branches_plot.auto_scale_xyz([-1, 1], [-1, 1], [-1, 1])
        self._firstPlot = True

    def init_mpl(self):
        """Initialize the mpl canvas and connect the relevant parts"""

        self.canvas = FigureCanvas(self.fig)
        self.canvas.draw()
        self.figLayout.addWidget(self.canvas)

        NavigationToolbar.toolitems = [
            t for t in NavigationToolbar.toolitems if t[0] in ("Save", )
        ]  #,"Pan","Zoom","Subplots")]
        self.img_tb = NavigationToolbar(self.canvas, self, coordinates=False)
        actions = self.img_tb.findChildren(QAction)
        for a in actions:
            if a.text() == 'Customize':
                self.img_tb.removeAction(a)
                break

        self.addToolBar(self.img_tb)
        self.buttonAxelVisualisation = QAction('Axel visualisation', self)
        self.img_tb.addAction(self.buttonAxelVisualisation)
        self.buttonAxelVisualisation.triggered.connect(self.axelVisualisation)
        action = self.menuInputOutput.addAction('Axel visualisation')
        action.triggered.connect(self.axelVisualisation)

    def updateParameter(self):
        N = self.graph.getSamples()

        self.spinBoxParameter.setMaximum(N)

        blocked = self.spinBoxParameter.blockSignals(True)
        self.spinBoxParameter.setValue(N / 2)
        self.spinBoxParameter.blockSignals(blocked)

        self.spinBoxParameterStep.setValue(N / 20)

    def update_parameterStep(self):
        self.spinBoxParameter.setSingleStep(self.spinBoxParameterStep.value())

    def updateDisplayedGraph(self):
        if self.isComputed():
            self.plotScene()
        else:
            self.showError('Recomputation of coupler curve needed!')

    def update_graph2tabLengths(self):
        self.printLog('Tab Lengths updated from graph', verbose=1)
        for e in self.doubleSpinBoxLengths:
            blocked = self.doubleSpinBoxLengths[e].blockSignals(True)
            self.doubleSpinBoxLengths[e].setValue(self.graph.getEdgeLength(e))
            self.doubleSpinBoxLengths[e].blockSignals(blocked)
            self.printLog(e + ': ' + str(self.doubleSpinBoxLengths[e].value()),
                          verbose=2)

    def update_tabLengths2graph(self):
        self.printLog('Graph updated from tab Lengths', verbose=1)
        lengths = {
            '12': self.doubleSpinBoxL12.value(),
            '13': self.doubleSpinBoxL13.value(),
            '14': self.doubleSpinBoxL14.value(),
            '15': self.doubleSpinBoxL15.value(),
            '16': self.doubleSpinBoxL16.value(),
            '27': self.doubleSpinBoxL27.value(),
            '37': self.doubleSpinBoxL37.value(),
            '47': self.doubleSpinBoxL47.value(),
            '57': self.doubleSpinBoxL57.value(),
            '67': self.doubleSpinBoxL67.value(),
            '23': self.doubleSpinBoxL23.value(),
            '34': self.doubleSpinBoxL34.value(),
            '45': self.doubleSpinBoxL45.value(),
            '56': self.doubleSpinBoxL56.value(),
            '26': self.doubleSpinBoxR26.value()
        }
        try:
            self.graph.setLengthsAndUpdateFixedTriangle(lengths)
        except TriangleInequalityError as e:
            self.showError(
                'Please, change the lengths, triangle inequality is violated!!!\n'
                + str(e))
        self.update_graph2yV2()
        self.update_graph2phi()
        self.setRequiresRecomputing()

    def update_phi2graph(self):
        self.graph.setPhiDegree(self.doubleSpinBoxPhi.value())

        blocked = self.doubleSpinBoxY2.blockSignals(True)
        self.doubleSpinBoxY2.setValue(self.graph.getyV2())
        self.doubleSpinBoxY2.blockSignals(blocked)

        self.update_yV2toGraph()

    def update_theta2graph(self):
        self.graph.setThetaDegree(self.doubleSpinBoxTheta.value())
        blocked = self.doubleSpinBoxR26.blockSignals(True)
        self.doubleSpinBoxR26.setValue(self.graph.getR26())
        self.doubleSpinBoxR26.blockSignals(blocked)
        self.update_R26toGraph()

    def update_R26toGraph(self):
        self.printLog('Graph updated from R26')
        self.graph.setR26(self.doubleSpinBoxR26.value())
        self.labelRecomputePHC.setText(
            '<html><head/><body><p><span style=" color:#ff0000;">Recomputation needed</span></p></body></html>'
        )
        self.update_graph2theta()
        if self.isComputed():
            self.graph.computeIntersections()
            self.plotScene()
        else:
            self.showError('Recomputation of coupler curve needed!')

    def update_yV2toGraph(self):
        self.printLog('v2 changed')
        self.labelRecomputePHC.setText(
            '<html><head/><body><p><span style=" color:#ff0000;">Recomputation needed</span></p></body></html>'
        )
        self.graph.setyV2(self.doubleSpinBoxY2.value())
        self.update_graph2tabLengths()
        self.update_graph2phi()
        if self.isComputed():
            self.graph.computeIntersections()
            self.plotScene()
        else:
            self.showError('Recomputation of coupler curve needed!')

    def update_graph2R26(self):
        blocked = self.doubleSpinBoxR26.blockSignals(True)
        self.doubleSpinBoxR26.setValue(self.graph.getR26())
        self.doubleSpinBoxR26.blockSignals(blocked)
        self.update_graph2yV2()
        self.update_graph2theta()

    def update_graph2yV2(self):
        blocked = self.doubleSpinBoxY2.blockSignals(True)
        self.doubleSpinBoxY2.setValue(self.graph.getyV2())
        self.doubleSpinBoxY2.blockSignals(blocked)

        self.update_graph2phi()

    def update_graph2phi(self):
        self.update_graph2theta()
        blocked = self.doubleSpinBoxPhi.blockSignals(True)
        self.doubleSpinBoxPhi.setValue(self.graph.getPhiDegree())
        self.doubleSpinBoxPhi.blockSignals(blocked)

    def update_graph2theta(self):
        blocked = self.doubleSpinBoxTheta.blockSignals(True)
        self.doubleSpinBoxTheta.setValue(self.graph.getThetaDegree())
        self.doubleSpinBoxTheta.blockSignals(blocked)

    def setRequiresRecomputing(self):
        self.graph.setRequiresRecomputing(propagate=False)
        self.labelComputed.setText(
            '<html><head/><body><p><span style=" color:#ff0000;">Recomputation needed</span></p></body></html>'
        )
        self._V6fromPHC = []
        self.labelRecomputePHC.setText(
            '<html><head/><body><p><span style=" color:#ff0000;">Recomputation needed</span></p></body></html>'
        )

    def setComputed(self):
        self.graph.setComputed(propagate=False)
        self.labelComputed.setText('Ready')
        c_x, c_y, c_z = self.graph.getCenterOfGravity()
        self.doubleSpinBox_x.setValue(-c_x)
        self.doubleSpinBox_y.setValue(-c_y)
        self.doubleSpinBox_z.setValue(-c_z)

    def isComputed(self):
        return self.graph.isComputed()

    def computeCouplerCurves(self):
        N = self.spinBoxSamples.value()

        self.printLog('Computing coupler curve')
        self.pushButtonPlot.setEnabled(False)

        self.graph.computeCouplerCurve(N)
        self.updateParameter()
        self.updateDisplayedGraph()
        self.pushButtonPlot.setEnabled(True)

    def plotScene(self):
        c_x, c_y, c_z = self.doubleSpinBox_x.value(
        ), self.doubleSpinBox_y.value(), self.doubleSpinBox_z.value()

        def draw(points, style='black', line_width=2):
            self._branches_plot.plot([x + c_x for x, y, z in points],
                                     [y + c_y for x, y, z in points],
                                     [z + c_z for x, y, z in points],
                                     style,
                                     linewidth=line_width)

        if self.isComputed():
            if not self._firstPlot:
                xlim = self._branches_plot.get_xlim()
                ylim = self._branches_plot.get_ylim()
                zlim = self._branches_plot.get_zlim()
                minbound = min([xlim[0], ylim[0], zlim[0]])
                maxbound = max([xlim[1], ylim[1], zlim[1]])
            else:
                minbound = self.graph.minbound
                maxbound = self.graph.maxbound
                self._firstPlot = False

            self._branches_plot.cla()

            if self.comboBoxGraphFor.currentText() == 'orange':
                pos = self.graph.getPositionsOfVertices(
                    self.spinBoxParameter.value() - 1, 0, 0, 0)
            elif self.comboBoxGraphFor.currentText() == 'red':
                pos = self.graph.getPositionsOfVertices(
                    self.spinBoxParameter.value() - 1, 0, 1, 0)
            elif self.comboBoxGraphFor.currentText() == 'green':
                pos = self.graph.getPositionsOfVertices(
                    self.spinBoxParameter.value() - 1, 0, 0, 1)
            elif self.comboBoxGraphFor.currentText() == 'blue':
                pos = self.graph.getPositionsOfVertices(
                    self.spinBoxParameter.value() - 1, 0, 1, 1)
            else:
                pos = None

            allOrange = True
            for c in self.checkBoxBranches:
                if self.checkBoxBranches[c].checkState():
                    for part in self.graph.getBranch(c):
                        if allOrange:
                            draw(part, 'darkorange', line_width=2)
                        else:
                            draw(part, c, line_width=2)
            if self.checkBoxMirror.checkState():
                for c in self.checkBoxBranches:
                    if self.checkBoxBranches[c].checkState():
                        for part in self.graph.getMirrorBranch(c):
                            if allOrange:
                                draw(part, 'darkorange', line_width=2)
                            else:
                                draw(part, 'dark' + c, line_width=2)
                draw(self.graph.intersections_mirror, 'ro')
            draw(self.graph.intersections, 'ro')

            if pos:
                v1, v2, v3, v4, v5, v6, v7 = pos
                draw([v2, v3, v7, v2, v1, v3, v4, v5, v1, v4, v7, v6, v5, v7])
                draw([v1, v6])
                #                draw([v1, v2, v3], 'ko')
                draw(pos, 'ko')
                draw([v6, v6], 'y^')
                for i, v in enumerate(pos):
                    self._branches_plot.text(v[0] + 0.1 + c_x,
                                             v[1] + c_y,
                                             v[2] + c_z,
                                             'v' + str(i + 1),
                                             size=20)

            self._branches_plot.set_xlim3d(minbound, maxbound)
            self._branches_plot.set_ylim3d(minbound, maxbound)
            self._branches_plot.set_zlim3d(minbound, maxbound)
            self._branches_plot.get_proj()
        else:
            self.showError('Recomputation of coupler curve needed!')
        if self._V6fromPHC:
            draw(self._V6fromPHC, 'go')
#        self._branches_plot.auto_scale_xyz([minbound, maxbound], [minbound, maxbound], [minbound, maxbound])

#        x, y, z = self.graph.getSphere(100)
#        self._branches_plot.plot_surface(x, y, z, alpha=0.2, color='grey',  shade=True, linewidth=0)

        self._branches_plot.set_axis_off()

        self.canvas.draw()

    def printLog(self, s, verbose=0, newLine=True):
        #        self._log += s +'\n'
        #        self.plainTextEdit.setPlainText(self._log)
        if verbose <= self.verbose:
            if newLine:
                print s
                self.plainTextEdit.appendPlainText(str(s))
            else:
                print s,
                self.plainTextEdit.insertPlainText(str(s))
        self.plainTextEdit.moveCursor(QTextCursor.End)
        self.plainTextEdit.ensureCursorVisible()
        QApplication.processEvents()

    def setGraphSequence(self, seq, seq_comments):
        self.graph_sequence = seq
        self.graph_sequence_comments = seq_comments

        self.spinBoxSeqLength.setValue(len(seq))

        self.spinBoxImgInSeq.setMinimum(1)
        self.spinBoxImgInSeq.setMaximum(len(self.graph_sequence))
        self.noteToImgInSeq.setPlainText(
            self.graph_sequence_comments[self.spinBoxImgInSeq.value() - 1])

        self.boxInfoImgInSeq.setVisible(True)

        self.pushButtonPlot.setEnabled(False)
        N = self.spinBoxSamples.value()
        for graph in self.graph_sequence:
            graph.computeCouplerCurve(N)
        self.plotGraphFromSequence()
        self.pushButtonPlot.setEnabled(True)

    def loadSequence(self):
        options = QFileDialog.Options()
        fileName, _ = QFileDialog.getOpenFileName(
            self,
            "Load sequence",
            "./sequences",
            "Python Objects (*.p);;All Files (*)",
            options=options)
        if fileName:
            try:
                self.printLog('Sequence loaded from: ' + fileName)
                seq = pickle.load(open(fileName, 'rb'))
                graph_sequence = []
                graph_sequence_comments = []
                if type(seq[0]) == list:
                    for g in seq:
                        lengths = {
                            '12': np.sqrt(g[0]),
                            '13': np.sqrt(g[1]),
                            '14': np.sqrt(g[2]),
                            '15': np.sqrt(g[3]),
                            '16': np.sqrt(g[4]),
                            '27': np.sqrt(g[7]),
                            '37': np.sqrt(g[9]),
                            '47': np.sqrt(g[11]),
                            '57': np.sqrt(g[13]),
                            '67': np.sqrt(g[14]),
                            '23': np.sqrt(g[5]),
                            '34': np.sqrt(g[8]),
                            '45': np.sqrt(g[10]),
                            '56': np.sqrt(g[12]),
                            '26': np.sqrt(g[6])
                        }
                    graph_sequence.append(
                        GraphCouplerCurve(lengths=lengths, window=self))
                    try:
                        graph_sequence_comments.append(str(g[15]))
                    except:
                        graph_sequence_comments.append(str(' '))
                else:
                    self.printLog(seq)
                    for len_seq in seq[1]:
                        for lengths in len_seq[1]:
                            graph_sequence.append(
                                GraphCouplerCurve(lengths=lengths,
                                                  window=self))
                            graph_sequence_comments.append(str(' '))

                self.setGraphSequence(graph_sequence, graph_sequence_comments)
            except Exception as e:
                self.showError('Some problem with loading: \n' + str(e))

    def plotGraphFromSequence(self):
        if self.graph_sequence:
            self.setActiveGraph(
                self.graph_sequence[self.spinBoxImgInSeq.value() - 1])
            self._V6fromPHC = []
            self.noteToImgInSeq.setPlainText(
                self.graph_sequence_comments[self.spinBoxImgInSeq.value() - 1])
            self.update_graph2tabLengths()
            self.update_graph2R26()
            self.updateParameter()
            self.updateDisplayedGraph()
            self.labelRecomputePHC.setText(
                '<html><head/><body><p><span style=" color:#ff0000;">Recomputation needed</span></p></body></html>'
            )

    def runPHC(self):
        self.buttonRunPHC.setEnabled(False)
        self._V6fromPHC = self.graph.getSolutionsForV6(usePrev=False)
        num_sol = len(self._V6fromPHC)
        self.printLog('Number of real solutions by PHC:')
        self.printLog(str(num_sol))
        self.spinBoxNumberReal.setValue(num_sol)
        self.plotScene()
        self.labelRecomputePHC.setText('Green points OK')
        self.buttonRunPHC.setEnabled(True)
        return num_sol

    def rotateVertices(self):
        self.buttonRotateVertices.setEnabled(False)
        self.printLog('Rotating labeling of vertices:')
        rotated_lengths = {
            '12': self.graph.getEdgeLength('13'),
            '13': self.graph.getEdgeLength('14'),
            '14': self.graph.getEdgeLength('15'),
            '15': self.graph.getEdgeLength('16'),
            '16': self.graph.getEdgeLength('12'),
            '27': self.graph.getEdgeLength('37'),
            '37': self.graph.getEdgeLength('47'),
            '47': self.graph.getEdgeLength('57'),
            '57': self.graph.getEdgeLength('67'),
            '67': self.graph.getEdgeLength('27'),
            '23': self.graph.getEdgeLength('34'),
            '34': self.graph.getEdgeLength('45'),
            '45': self.graph.getEdgeLength('56'),
            '56': self.graph.getEdgeLength('26'),
            '26': self.graph.getEdgeLength('23')
        }
        self.graph.setLengthsAndUpdateFixedTriangle(rotated_lengths)

        blocked = self.doubleSpinBoxR26.blockSignals(True)
        self.update_graph2R26()
        self.update_graph2tabLengths()
        self.doubleSpinBoxR26.blockSignals(blocked)

        self.computeCouplerCurves()
        self.buttonRotateVertices.setEnabled(True)

    def showDialog(self, texts):
        dialog = QDialog(self)

        dialog.textBrowser = QPlainTextEdit(dialog)
        dialog.verticalLayout = QVBoxLayout(dialog)
        dialog.verticalLayout.addWidget(dialog.textBrowser)
        dialog.setMinimumSize(600, 300)

        for s in texts:
            dialog.textBrowser.appendPlainText(str(s))

        dialog.show()

    def exportLengths(self):
        len_vect = []
        for e in ['12', '13', '14', '15', '16', '23']:
            len_vect.append(self.graph.getEdgeLength(e))
        len_vect.append(self.graph.getR26())
        for e in ['27', '34', '37', '45', '47', '56', '57', '67']:
            len_vect.append(self.graph.getEdgeLength(e))
        squared = True
        if squared:
            tmp = copy.copy(len_vect)
            len_vect = []
            for r in tmp:
                len_vect.append(r**2)

        dialog = QDialog(self)

        dialog.textBrowser = QPlainTextEdit(dialog)
        dialog.textBrowser.appendPlainText(str(len_vect))
        len_dict = copy.deepcopy(self.graph._lengths)
        len_dict[(2, 6)] = self.graph.getR26()
        dialog.textBrowser.appendPlainText(str(len_dict))

        dialog.verticalLayout = QVBoxLayout(dialog)
        dialog.verticalLayout.addWidget(dialog.textBrowser)
        dialog.setMinimumSize(600, 300)

        dialog.exec_()

    def axelVisualisation(self):
        #        #colors
        blue = [0, 0, 255]
        cyan = [0, 255, 255]
        green = [0, 255, 0]
        magenta = [255, 0, 255]
        dark_yellow = [100, 100, 0]
        yellow = [255, 255, 0]
        dark_green = [0, 190, 0]
        red = [255, 0, 0]
        black = [0, 0, 0]

        colors = {
            'orange': yellow,
            'red': red,
            'green': green,
            'blue': blue,
            'darkorange': dark_yellow,
            'darkred': cyan,
            'darkgreen': dark_green,
            'darkblue': magenta
        }

        if self.isComputed():
            v = VisualizationAxel("/home/jan/Programs/miniconda3/bin/axel-s")
            if self.comboBoxGraphFor.currentText() == 'orange':
                pos = self.graph.getPositionsOfVertices(
                    self.spinBoxParameter.value() - 1, 0, 0, 0)
            elif self.comboBoxGraphFor.currentText() == 'red':
                pos = self.graph.getPositionsOfVertices(
                    self.spinBoxParameter.value() - 1, 0, 1, 0)
            elif self.comboBoxGraphFor.currentText() == 'green':
                pos = self.graph.getPositionsOfVertices(
                    self.spinBoxParameter.value() - 1, 0, 0, 1)
            elif self.comboBoxGraphFor.currentText() == 'blue':
                pos = self.graph.getPositionsOfVertices(
                    self.spinBoxParameter.value() - 1, 0, 1, 1)
            else:
                pos = None
            if pos:
                v1, v2, v3, v4, v5, v6, v7 = pos
                v.add_polyline(
                    [v2, v3, v7, v2, v1, v3, v4, v5, v1, v4, v7, v6, v5, v7],
                    color=black)
                v.add_polyline([v1, v6], color=black)
                v.add_points([v1, v2, v3], color=black, size=1.5)

            v.add_points(self.graph.intersections, color=red, size=1.0)
            for c in self.checkBoxBranches:
                if self.checkBoxBranches[c].checkState():
                    for part in self.graph.getBranch(c):
                        v.add_polyline(part, color=colors[c])

            if self.checkBoxMirror.checkState():
                v.add_points(self.graph.intersections_mirror,
                             color=red,
                             size=1.0)
                for c in self.checkBoxBranches:
                    if self.checkBoxBranches[c].checkState():
                        for part in self.graph.getMirrorBranch(c):
                            v.add_polyline(part, color=colors['dark' + c])

            if self._V6fromPHC:
                v.add_points(self._V6fromPHC, color=dark_green, size=1.0)
            v.show()
        else:
            self.showError('Recomputation of coupler curve needed!')

    def runSamplingPhiTheta(self):
        self.computeCouplerCurves()
        n = 0
        first = True
        while n < 48 and (not self.interrupt.checkState() or first):
            first = False
            self.printLog('Sampling phi and theta')
            alg = AlgRealEmbeddings(
                'Max7vertices',
                num_phi=self.spinBoxSamplesPhi.value(),
                num_theta=self.spinBoxSamplesTheta.value(),
                choice_from_clusters='closestToAverageLength',
                window=self)
            alg.runSamplingPhiTheta(
                self.graph.getLengths(), self._possibleParametrizedVertices[
                    self.comboBoxParamVert.currentText()])
            self.printLog('Sampling finished, see sequence')

            if not self.interrupt.checkState():
                self.printLog('Rotating:')
                self.rotateVertices()

    def findMoreEmbeddings(self):
        self.computeCouplerCurves()
        self.printLog('Searching more embeddings:')
        alg = AlgRealEmbeddings('Max7vertices',
                                window=self,
                                num_phi=self.spinBoxSamplesPhi.value(),
                                num_theta=self.spinBoxSamplesTheta.value(),
                                name=self.lineEditName.text())
        alg.findMoreEmbeddings(self.graph.getLengths())

        if not self.interrupt.checkState():
            self.printLog('Rotating:')
            self.rotateVertices()

    def showClusters(self, clusters, centers):
        pass
        newDialog = QDialog(self)
        newDialog.figure = Figure()
        newDialog.canvas = FigureCanvas(newDialog.figure)

        layout = QVBoxLayout()
        layout.addWidget(newDialog.canvas)
        newDialog.setLayout(layout)

        ax = newDialog.figure.add_subplot(111)
        for cluster in clusters:
            ax.plot([x for x, y in cluster], [y for x, y in cluster], 'o')
        ax.plot([x for x, y in centers], [y for x, y in centers], 'ro')

        newDialog.canvas.draw()

        newDialog.show()