Esempio n. 1
0
class LiteBoxView(QGraphicsView):

    ALPHA = QColor(0, 0, 0, 192)

    closed_signal = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(LiteBoxView, self).__init__(parent)
        self.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
        #self.setAttribute(Qt.WA_DeleteOnClose)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
        QtGui.QShortcut(Qt.Key_Escape, self, self.close)
        self.desktopshot = None

        # will propagate to children
        self.setRenderHint(QPainter.Antialiasing)
        self.setRenderHint(QPainter.TextAntialiasing)

        self.scene = QGraphicsScene()
        self.setScene(self.scene)

    def close(self):
        self.closed_signal.emit()
        super(LiteBoxView, self).close()

    def drawBackground(self, painter, rect):
        if self.desktopshot is None:
            self.desktopshot = get_desktop_pixmap()

        painter.drawPixmap(self.mapToScene(0, 0), self.desktopshot)
        painter.setBrush(LiteBoxView.ALPHA)
        painter.drawRect(rect)

    def show_fullscreen_svg(self, path):
        """:param path: path to an svg file"""
        from PyQt4 import QtSvg
        item = QtSvg.QGraphicsSvgItem(path)
        self.show_fullscreen_item(item)

    def show_fullscreen_pixmap(self, pixmap):
        """:param pixmap: a QPixmap"""
        item = QGraphicsPixmapItem(pixmap)
        self.show_fullscreen_item(item)

    def show_fullscreen_image(self, image):
        """:param image: a QImage"""
        pixmap = QPixmap.fromImage(image)
        self.show_fullscreen_pixmap(pixmap)

    def show_fullscreen_item(self, item):
        """:param item: a QGraphicsItem to be shown fullscreen"""
        item.setFlag(QtGui.QGraphicsItem.ItemIsFocusable, True)
        self.scene.clear()
        self.scene.addItem(item)
        CloseMark(parent=item)
        self.showFullScreen()
        self.setFocus()
Esempio n. 2
0
class LiteBoxView(QGraphicsView):

    ALPHA = QColor(0, 0, 0, 192)

    closed_signal = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(LiteBoxView, self).__init__(parent)
        self.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
        #self.setAttribute(Qt.WA_DeleteOnClose)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
        QtGui.QShortcut( Qt.Key_Escape, self, self.close )
        self.desktopshot = None

        # will propagate to children
        self.setRenderHint(QPainter.Antialiasing)
        self.setRenderHint(QPainter.TextAntialiasing)

        self.scene = QGraphicsScene()
        self.setScene(self.scene)

    def close(self):
        self.closed_signal.emit()
        super(LiteBoxView, self).close()

    def drawBackground(self, painter, rect):
        if self.desktopshot is None:
            self.desktopshot = get_desktop_pixmap()

        painter.drawPixmap(self.mapToScene(0, 0), self.desktopshot)
        painter.setBrush(LiteBoxView.ALPHA)
        painter.drawRect(rect)

    def show_fullscreen_svg(self, path):
        """:param path: path to an svg file"""
        from PyQt4 import QtSvg
        item = QtSvg.QGraphicsSvgItem(path)
        self.show_fullscreen_item(item)

    def show_fullscreen_pixmap(self, pixmap):
        """:param pixmap: a QPixmap"""
        item = QGraphicsPixmapItem(pixmap)
        self.show_fullscreen_item(item)
        
    def show_fullscreen_image(self, image):
        """:param image: a QImage"""
        pixmap = QPixmap.fromImage(image)
        self.show_fullscreen_pixmap( pixmap )

    def show_fullscreen_item(self, item):
        """:param item: a QGraphicsItem to be shown fullscreen"""
        item.setFlag(QtGui.QGraphicsItem.ItemIsFocusable, True)
        self.scene.clear()
        self.scene.addItem(item)
        CloseMark(parent=item)
        self.showFullScreen()
        self.setFocus()
Esempio n. 3
0
class Canvas(QGraphicsView):
    def __init__(self):
        self._scene = QGraphicsScene()
        QGraphicsView.__init__(self, self._scene)
        self._document = Document()
        self._document.changed.connect(self._update_scene)
        self.use_tool(PenTool)
        self.setMouseTracking(True)

    def use_tool(self, tool_class):
        """Instantiates tool_class and uses it as the current tool."""
        self._tool = tool_class(self._document)
        self._tool.needs_repaint.connect(self._update)

    def new_shape(self):
        self._document.new_shape()

    def delete_selection(self):
        self._document.delete_selection()
        if not self._document.current_shape:
            self._document.delete_current_shape()

    def _update(self):
        self.update()

    def _update_scene(self):
        self._scene.clear()
        for shape in self._document.shapes:
            self._scene.addPath(shape.make_painter_path())

    def _call_tool(self, method_name, *args):
        method = getattr(self._tool, method_name, None)
        if method:
            method(*args)

    def _map_event(self, qt_event):
        """Take a QMouseEvent and return a MouseEvent in scene space."""
        point = self.mapToScene(qt_event.x(), qt_event.y())
        return MouseEvent((_round_to_half(point.x()), _round_to_half(point.y())))

    def mouseMoveEvent(self, event):
        self._call_tool("mouse_move_event", self._map_event(event))

    def mousePressEvent(self, event):
        self._call_tool("mouse_press_event", self._map_event(event))

    def mouseReleaseEvent(self, event):
        self._call_tool("mouse_release_event", self._map_event(event))

    def paintEvent(self, event):
        QGraphicsView.paintEvent(self, event)
        self._call_tool("paint_event", self)
Esempio n. 4
0
def render_drop_shadow_frame(pixmap, shadow_rect, shadow_color,
                             offset, radius, rect_fill_color):
    pixmap.fill(QColor(0, 0, 0, 0))
    scene = QGraphicsScene()
    rect = QGraphicsRectItem(shadow_rect)
    rect.setBrush(QColor(rect_fill_color))
    rect.setPen(QPen(Qt.NoPen))
    scene.addItem(rect)
    effect = QGraphicsDropShadowEffect(color=shadow_color,
                                       blurRadius=radius,
                                       offset=offset)

    rect.setGraphicsEffect(effect)
    scene.setSceneRect(QRectF(QPointF(0, 0), QSizeF(pixmap.size())))
    painter = QPainter(pixmap)
    scene.render(painter)
    painter.end()
    scene.clear()
    scene.deleteLater()
    return pixmap
Esempio n. 5
0
class TestItems(unittest.TestCase):
    def setUp(self):
        import logging

        from PyQt4.QtGui import QApplication, QGraphicsScene, QGraphicsView, \
                                QPainter

        from PyQt4.QtCore import QTimer

        logging.basicConfig()

        self.app = QApplication([])
        self.scene = QGraphicsScene()
        self.view = QGraphicsView(self.scene)
        self.view.setRenderHints(
            QPainter.Antialiasing | \
            QPainter.SmoothPixmapTransform | \
            QPainter.TextAntialiasing
            )
        self.view.resize(500, 300)
        self.view.show()
        QTimer.singleShot(10000, self.app.exit)

        def my_excepthook(*args):
            sys.setrecursionlimit(1010)
            traceback.print_exc(limit=4)

        self._orig_excepthook = sys.excepthook
        sys.excepthook = my_excepthook
        self.singleShot = QTimer.singleShot

    def tearDown(self):
        self.scene.clear()
        self.scene.deleteLater()
        self.view.deleteLater()
        del self.scene
        del self.view
        self.app.processEvents()
        del self.app
        sys.excepthook = self._orig_excepthook
Esempio n. 6
0
class TestItems(unittest.TestCase):
    def setUp(self):
        import logging

        from PyQt4.QtGui import QApplication, QGraphicsScene, QGraphicsView, \
                                QPainter

        from PyQt4.QtCore import QTimer

        logging.basicConfig()

        self.app = QApplication([])
        self.scene = QGraphicsScene()
        self.view = QGraphicsView(self.scene)
        self.view.setRenderHints(
            QPainter.Antialiasing | \
            QPainter.SmoothPixmapTransform | \
            QPainter.TextAntialiasing
            )
        self.view.resize(500, 300)
        self.view.show()
        QTimer.singleShot(10000, self.app.exit)

        def my_excepthook(etype, value, tb):
            sys.setrecursionlimit(1010)
            traceback.print_exception(etype, value, tb)

        self._orig_excepthook = sys.excepthook
        sys.excepthook = my_excepthook
        self.singleShot = QTimer.singleShot

    def tearDown(self):
        self.scene.clear()
        self.scene.deleteLater()
        self.view.deleteLater()
        del self.scene
        del self.view
        self.app.processEvents()
        del self.app
        sys.excepthook = self._orig_excepthook
Esempio n. 7
0
class OWQualityControl(widget.OWWidget):
    name = "Quality Control"
    description = "Experiment quality control"
    icon = "../widgets/icons/QualityControl.svg"
    priority = 5000

    inputs = [("Experiment Data", Orange.data.Table, "set_data")]
    outputs = []

    DISTANCE_FUNCTIONS = [("Distance from Pearson correlation", dist_pcorr),
                          ("Euclidean distance", dist_eucl),
                          ("Distance from Spearman correlation", dist_spearman)
                          ]

    settingsHandler = SetContextHandler()

    split_by_labels = settings.ContextSetting({})
    sort_by_labels = settings.ContextSetting({})

    selected_distance_index = settings.Setting(0)

    def __init__(self, parent=None):
        super().__init__(parent)

        ## Attributes
        self.data = None
        self.distances = None
        self.groups = None
        self.unique_pos = None
        self.base_group_index = 0

        ## GUI
        box = gui.widgetBox(self.controlArea, "Info")
        self.info_box = gui.widgetLabel(box, "\n")

        ## Separate By box
        box = gui.widgetBox(self.controlArea, "Separate By")
        self.split_by_model = itemmodels.PyListModel(parent=self)
        self.split_by_view = QListView()
        self.split_by_view.setSelectionMode(QListView.ExtendedSelection)
        self.split_by_view.setModel(self.split_by_model)
        box.layout().addWidget(self.split_by_view)

        self.split_by_view.selectionModel().selectionChanged.connect(
            self.on_split_key_changed)

        ## Sort By box
        box = gui.widgetBox(self.controlArea, "Sort By")
        self.sort_by_model = itemmodels.PyListModel(parent=self)
        self.sort_by_view = QListView()
        self.sort_by_view.setSelectionMode(QListView.ExtendedSelection)
        self.sort_by_view.setModel(self.sort_by_model)
        box.layout().addWidget(self.sort_by_view)

        self.sort_by_view.selectionModel().selectionChanged.connect(
            self.on_sort_key_changed)

        ## Distance box
        box = gui.widgetBox(self.controlArea, "Distance Measure")
        gui.comboBox(box,
                     self,
                     "selected_distance_index",
                     items=[name for name, _ in self.DISTANCE_FUNCTIONS],
                     callback=self.on_distance_measure_changed)

        self.scene = QGraphicsScene()
        self.scene_view = QGraphicsView(self.scene)
        self.scene_view.setRenderHints(QPainter.Antialiasing)
        self.scene_view.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.mainArea.layout().addWidget(self.scene_view)

        self.scene_view.installEventFilter(self)

        self._disable_updates = False
        self._cached_distances = {}
        self._base_index_hints = {}
        self.main_widget = None

        self.resize(800, 600)

    def clear(self):
        """Clear the widget state."""
        self.data = None
        self.distances = None
        self.groups = None
        self.unique_pos = None

        with disable_updates(self):
            self.split_by_model[:] = []
            self.sort_by_model[:] = []

        self.main_widget = None
        self.scene.clear()
        self.info_box.setText("\n")
        self._cached_distances = {}

    def set_data(self, data=None):
        """Set input experiment data."""
        self.closeContext()
        self.clear()

        self.error(0)
        self.warning(0)

        if data is not None:
            keys = self.get_suitable_keys(data)
            if not keys:
                self.error(0, "Data has no suitable feature labels.")
                data = None

        self.data = data
        if data is not None:
            self.on_new_data()

    def update_label_candidates(self):
        """Update the label candidates selection GUI 
        (Group/Sort By views).

        """
        keys = self.get_suitable_keys(self.data)
        with disable_updates(self):
            self.split_by_model[:] = keys
            self.sort_by_model[:] = keys

    def get_suitable_keys(self, data):
        """ Return suitable attr label keys from the data where
        the key has at least two unique values in the data.

        """
        attrs = [attr.attributes.items() for attr in data.domain.attributes]
        attrs = reduce(operator.iadd, attrs, [])
        # in case someone put non string values in attributes dict
        attrs = [(str(key), str(value)) for key, value in attrs]
        attrs = set(attrs)
        values = defaultdict(set)
        for key, value in attrs:
            values[key].add(value)
        keys = [key for key in values if len(values[key]) > 1]
        return keys

    def selected_split_by_labels(self):
        """Return the current selected split labels.
        """
        sel_m = self.split_by_view.selectionModel()
        indices = [r.row() for r in sel_m.selectedRows()]
        return [self.sort_by_model[i] for i in indices]

    def selected_sort_by_labels(self):
        """Return the current selected sort labels
        """
        sel_m = self.sort_by_view.selectionModel()
        indices = [r.row() for r in sel_m.selectedRows()]
        return [self.sort_by_model[i] for i in indices]

    def selected_distance(self):
        """Return the selected distance function.
        """
        return self.DISTANCE_FUNCTIONS[self.selected_distance_index][1]

    def selected_base_group_index(self):
        """Return the selected base group index
        """
        return self.base_group_index

    def selected_base_indices(self, base_group_index=None):
        indices = []
        for g, ind in self.groups:
            if base_group_index is None:
                label = group_label(self.selected_split_by_labels(), g)
                ind = [i for i in ind if i is not None]
                i = self._base_index_hints.get(label, ind[0] if ind else None)
            else:
                i = ind[base_group_index]
            indices.append(i)
        return indices

    def on_new_data(self):
        """We have new data and need to recompute all.
        """
        self.closeContext()

        self.update_label_candidates()
        self.info_box.setText(
            "%s genes \n%s experiments" %
            (len(self.data), len(self.data.domain.attributes)))

        self.base_group_index = 0

        keys = self.get_suitable_keys(self.data)
        self.openContext(keys)

        ## Restore saved context settings (split/sort selection)
        split_by_labels = self.split_by_labels
        sort_by_labels = self.sort_by_labels

        def select(model, selection_model, selected_items):
            """Select items in a Qt item model view
            """
            all_items = list(model)
            try:
                indices = [all_items.index(item) for item in selected_items]
            except:
                indices = []
            for ind in indices:
                selection_model.select(model.index(ind),
                                       QItemSelectionModel.Select)

        with disable_updates(self):
            select(self.split_by_view.model(),
                   self.split_by_view.selectionModel(), split_by_labels)

            select(self.sort_by_view.model(),
                   self.sort_by_view.selectionModel(), sort_by_labels)

        with widget_disable(self):
            self.split_and_update()

    def on_split_key_changed(self, *args):
        """Split key has changed
        """
        with widget_disable(self):
            if not self._disable_updates:
                self.base_group_index = 0
                self.split_by_labels = self.selected_split_by_labels()
                self.split_and_update()

    def on_sort_key_changed(self, *args):
        """Sort key has changed
        """
        with widget_disable(self):
            if not self._disable_updates:
                self.base_group_index = 0
                self.sort_by_labels = self.selected_sort_by_labels()
                self.split_and_update()

    def on_distance_measure_changed(self):
        """Distance measure has changed
        """
        if self.data is not None:
            with widget_disable(self):
                self.update_distances()
                self.replot_experiments()

    def on_view_resize(self, size):
        """The view with the quality plot has changed
        """
        if self.main_widget:
            current = self.main_widget.size()
            self.main_widget.resize(size.width() - 6, current.height())

            self.scene.setSceneRect(self.scene.itemsBoundingRect())

    def on_rug_item_clicked(self, item):
        """An ``item`` in the quality plot has been clicked.
        """
        update = False
        sort_by_labels = self.selected_sort_by_labels()
        if sort_by_labels and item.in_group:
            ## The item is part of the group
            if item.group_index != self.base_group_index:
                self.base_group_index = item.group_index
                update = True

        else:
            if sort_by_labels:
                # If the user clicked on an background item it
                # invalidates the sorted labels selection
                with disable_updates(self):
                    self.sort_by_view.selectionModel().clear()
                    update = True

            index = item.index
            group = item.group
            label = group_label(self.selected_split_by_labels(), group)

            if self._base_index_hints.get(label, 0) != index:
                self._base_index_hints[label] = index
                update = True

        if update:
            with widget_disable(self):
                self.split_and_update()

    def eventFilter(self, obj, event):
        if obj is self.scene_view and event.type() == QEvent.Resize:
            self.on_view_resize(event.size())
        return super().eventFilter(obj, event)

    def split_and_update(self):
        """
        Split the data based on the selected sort/split labels
        and update the quality plot.

        """
        split_labels = self.selected_split_by_labels()
        sort_labels = self.selected_sort_by_labels()

        self.warning(0)
        if not split_labels:
            self.warning(0, "No separate by label selected.")

        self.groups, self.unique_pos = \
                exp.separate_by(self.data, split_labels,
                                consider=sort_labels,
                                add_empty=True)

        self.groups = sorted(self.groups.items(),
                             key=lambda t: list(map(float_if_posible, t[0])))
        self.unique_pos = sorted(
            self.unique_pos.items(),
            key=lambda t: list(map(float_if_posible, t[0])))

        if self.groups:
            if sort_labels:
                group_base = self.selected_base_group_index()
                base_indices = self.selected_base_indices(group_base)
            else:
                base_indices = self.selected_base_indices()
            self.update_distances(base_indices)
            self.replot_experiments()

    def get_cached_distances(self, measure):
        if measure not in self._cached_distances:
            attrs = self.data.domain.attributes
            mat = numpy.zeros((len(attrs), len(attrs)))

            self._cached_distances[measure] = \
                (mat, set(zip(range(len(attrs)), range(len(attrs)))))

        return self._cached_distances[measure]

    def get_cached_distance(self, measure, i, j):
        matrix, computed = self.get_cached_distances(measure)
        key = (i, j) if i < j else (j, i)
        if key in computed:
            return matrix[i, j]
        else:
            return None

    def get_distance(self, measure, i, j):
        d = self.get_cached_distance(measure, i, j)
        if d is None:
            vec_i = take_columns(self.data, [i])
            vec_j = take_columns(self.data, [j])
            d = measure(vec_i, vec_j)

            mat, computed = self.get_cached_distances(measure)
            mat[i, j] = d
            key = key = (i, j) if i < j else (j, i)
            computed.add(key)
        return d

    def store_distance(self, measure, i, j, dist):
        matrix, computed = self.get_cached_distances(measure)
        key = (i, j) if i < j else (j, i)
        matrix[j, i] = matrix[i, j] = dist
        computed.add(key)

    def update_distances(self, base_indices=()):
        """Recompute the experiment distances.
        """
        distance = self.selected_distance()
        if base_indices == ():
            base_group_index = self.selected_base_group_index()
            base_indices = [ind[base_group_index] \
                            for _, ind in self.groups]

        assert (len(base_indices) == len(self.groups))

        base_distances = []
        attributes = self.data.domain.attributes
        pb = gui.ProgressBar(self, len(self.groups) * len(attributes))

        for (group, indices), base_index in zip(self.groups, base_indices):
            # Base column of the group
            if base_index is not None:
                base_vec = take_columns(self.data, [base_index])
                distances = []
                # Compute the distances between base column
                # and all the rest data columns.
                for i in range(len(attributes)):
                    if i == base_index:
                        distances.append(0.0)
                    elif self.get_cached_distance(distance, i,
                                                  base_index) is not None:
                        distances.append(
                            self.get_cached_distance(distance, i, base_index))
                    else:
                        vec_i = take_columns(self.data, [i])
                        dist = distance(base_vec, vec_i)
                        self.store_distance(distance, i, base_index, dist)
                        distances.append(dist)
                    pb.advance()

                base_distances.append(distances)
            else:
                base_distances.append(None)

        pb.finish()
        self.distances = base_distances

    def replot_experiments(self):
        """Replot the whole quality plot.
        """
        self.scene.clear()
        labels = []

        max_dist = numpy.nanmax(list(filter(None, self.distances)))
        rug_widgets = []

        group_pen = QPen(Qt.black)
        group_pen.setWidth(2)
        group_pen.setCapStyle(Qt.RoundCap)
        background_pen = QPen(QColor(0, 0, 250, 150))
        background_pen.setWidth(1)
        background_pen.setCapStyle(Qt.RoundCap)

        main_widget = QGraphicsWidget()
        layout = QGraphicsGridLayout()
        attributes = self.data.domain.attributes
        if self.data is not None:
            for (group, indices), dist_vec in zip(self.groups, self.distances):
                indices_set = set(indices)
                rug_items = []
                if dist_vec is not None:
                    for i, attr in enumerate(attributes):
                        # Is this a within group distance or background
                        in_group = i in indices_set
                        if in_group:
                            rug_item = ClickableRugItem(
                                dist_vec[i] / max_dist, 1.0,
                                self.on_rug_item_clicked)
                            rug_item.setPen(group_pen)
                            tooltip = experiment_description(attr)
                            rug_item.setToolTip(tooltip)
                            rug_item.group_index = indices.index(i)
                            rug_item.setZValue(rug_item.zValue() + 1)
                        else:
                            rug_item = ClickableRugItem(
                                dist_vec[i] / max_dist, 0.85,
                                self.on_rug_item_clicked)
                            rug_item.setPen(background_pen)
                            tooltip = experiment_description(attr)
                            rug_item.setToolTip(tooltip)

                        rug_item.group = group
                        rug_item.index = i
                        rug_item.in_group = in_group

                        rug_items.append(rug_item)

                rug_widget = RugGraphicsWidget(parent=main_widget)
                rug_widget.set_rug(rug_items)

                rug_widgets.append(rug_widget)

                label = group_label(self.selected_split_by_labels(), group)
                label_item = QGraphicsSimpleTextItem(label, main_widget)
                label_item = GraphicsSimpleTextLayoutItem(label_item,
                                                          parent=layout)
                label_item.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
                labels.append(label_item)

        for i, (label, rug_w) in enumerate(zip(labels, rug_widgets)):
            layout.addItem(label, i, 0, Qt.AlignVCenter)
            layout.addItem(rug_w, i, 1)
            layout.setRowMaximumHeight(i, 30)

        main_widget.setLayout(layout)
        self.scene.addItem(main_widget)
        self.main_widget = main_widget
        self.rug_widgets = rug_widgets
        self.labels = labels
        self.on_view_resize(self.scene_view.size())
class CoLocation(QMainWindow, Ui_MainWindow):
    flag = True
    categories = {}
    valid_images = ["jpg", "png", "tga", "pgm", "jpeg"]
    valid_videos = ["mp4", "avi"]
    edge_threshold = 100
    to_disp = []
    stop = False
    framerate = 20
    export_name = ''

    def __init__(self, ):
        super(
            CoLocation,
            self).__init__()  #initialise from the ui designed by Designer App
        self.setupUi(self)
        self.setupUi_custom()
        Help = QtGui.QAction(QtGui.QIcon('images/info.png'), 'Help', self)
        Help.triggered.connect(self.show_help)

        Settings = QtGui.QAction(QtGui.QIcon('images/settings.png'),
                                 'Settings', self)
        Settings.triggered.connect(self.show_settings)

        Export = QtGui.QAction(QtGui.QIcon('images/export.png'), 'Export',
                               self)
        Export.triggered.connect(self.show_export)

        ##To set up the toolbar
        self.toolbar = self.addToolBar('Help')
        self.toolbar.addAction(Help)
        self.toolbar = self.addToolBar('Settings')
        self.toolbar.addAction(Settings)
        self.toolbar = self.addToolBar('Export')
        self.toolbar.addAction(Export)

    def show_help(self):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Information)
        msg.setText("Co-Location Visualisation")
        f = open('How-To/how-to-Co-Location.txt', 'r')
        msg.setInformativeText(
            "Developed by Yash Chandak, under supervision of Prof. Babiga Birregah, University of Technology, Troyes"
        )
        msg.setWindowTitle("About Us")
        msg.setDetailedText(f.read())
        msg.setStandardButtons(QMessageBox.Ok)
        msg.exec_()

    def show_settings(self):
        framerate, ok = QtGui.QInputDialog.getInt(
            self, 'Settings', 'Enter Frame Rate for Videos:')
        self.framerate = framerate

    def show_export(self):
        name, ok = QtGui.QInputDialog.getText(self, 'Export to Gephi format',
                                              'Enter file name :')
        self.export_name = name + '.gefx'

    def update_categories(self):
        #update selected categories
        for radiobox in self.findChildren(QtGui.QRadioButton):
            self.categories[radiobox.text()] = radiobox.isChecked()

    def setupUi_custom(self, ):
        self.scene = QGraphicsScene()
        self.scene2 = QGraphicsScene()
        self.pushButton.clicked.connect(self.selectFile)
        self.horizontalSlider.valueChanged.connect(self.updateLCD)
        self.pushButton_2.clicked.connect(self.disp_graph)
        self.pushButton_3.clicked.connect(self.selectFile_from_folder)
        self.stop_button.clicked.connect(self.set_stop)
        #TODO [WEIRD PROBLEM] QPixmap needs to be called at least once with JPG image before tensorFlow, otherwise program crashes
        self.scene.addPixmap(
            QPixmap(os.getcwd() + "/images/demo.jpg").scaled(
                self.graphicsView.size(), QtCore.Qt.KeepAspectRatio))
        self.graphicsView.setScene(self.scene)

        #Add blank canvas initially
        fig1 = Figure()
        self.addmpl(fig1)

    def set_stop(self):
        self.stop = True

    def updateLCD(self):
        #update edge_threshold variable based on slider
        self.edge_threshold = self.horizontalSlider.value()
        self.lcdNumber.display(self.edge_threshold)

    def tag_image(self, filename=None, batch=False, image=None):
        #importing TensorFlow on top causes segmentation fault (official bug #2034)
        #importing here helps in working around the problem
        #Python modules could be con)sidered as singletons... so no matter how many times they are imported, they get initialized only once
        import Yolo_module as yolo

        if (self.flag):
            #initialise the model, only once
            self.classifier = yolo.YOLO_TF()
            self.flag = False

        self.classifier.batch = batch

        if not image == None:
            self.classifier.detect_from_cvmat(image)
        else:
            self.classifier.detect_from_file(
                filename)  #execute Yolo on the image

        return self.classifier.tagged_image

    def disp_img(self, filename=None, img=None):
        if not img == None:
            img_rgb = img.copy()
            cv2.cvtColor(img, cv2.COLOR_BGR2RGB, img_rgb)
            img_rgb = QtGui.QImage(img_rgb, img_rgb.shape[1], img_rgb.shape[0],
                                   img_rgb.shape[1] * 3,
                                   QtGui.QImage.Format_RGB888)
            self.scene.addPixmap(
                QPixmap(img_rgb).scaled(self.graphicsView.size(),
                                        QtCore.Qt.KeepAspectRatio))
            image = self.tag_image(image=img)

        else:
            #DO this step before calling tensorflow
            self.scene.addPixmap(
                QPixmap(filename).scaled(self.graphicsView.size(),
                                         QtCore.Qt.KeepAspectRatio))

            #Dislplay tagged image
            image = self.tag_image(filename=filename)

        image = QtGui.QImage(
            image, image.shape[1], image.shape[0], image.shape[1] * 3,
            QtGui.QImage.Format_RGB888)  #convert to Qt image format
        self.scene2.addPixmap(
            QPixmap(image).scaled(self.graphicsView_3.size(),
                                  QtCore.Qt.KeepAspectRatio))

        self.graphicsView.setScene(self.scene)
        self.graphicsView_3.setScene(self.scene2)

    def disp_graph(self, result=[], graph_name=''):
        import graph_module as gm

        self.update_categories()
        self.rmmpl()  #remove previous graph
        if result != [] and result != False:
            self.to_disp = result

        #Display graph
        fig = Figure()
        fig.set_facecolor('w')
        axf = fig.add_subplot(111)
        axf.set_axis_off()
        gm.co_location(self.to_disp, axf, self.edge_threshold, self.categories,
                       graph_name)  #get updated graph
        self.addmpl(fig)
        print("graph added")

    def disp_video(self, filename, skip=20):

        cap = cv2.VideoCapture(filename)
        count = 0
        self.stop = False
        while True:
            #TODO: Better method - https://nikolak.com/pyqt-threading-tutorial/
            QtCore.QCoreApplication.processEvents()

            ret, img = cap.read()
            if (not ret) or self.stop:
                print("Ending video...")  #+ str(ret) + str(self.stop))
                break
            if count % skip == 0:
                img = cv2.resize(img, (640, 480))
                self.disp_img(img=img)
                self.disp_graph([self.classifier.result
                                 ])  #list of 1 resultant list
                count = 0
            count += 1

    def selectFile(self):
        #Clear previous image displays
        self.scene.clear()
        self.scene2.clear()
        self.update_categories()

        filename = QFileDialog.getOpenFileName(
            directory='/home/yash/Downloads/Pascal VOC 2012/samples')
        self.lineEdit.setText(filename)

        #check if file is valid video
        if filename.split('.')[1] in self.valid_videos:
            self.disp_video(filename, self.framerate)

        #check if the file is valid
        elif filename.split('.')[1] in self.valid_images:
            self.disp_img(filename=filename)
            self.disp_graph([self.classifier.result
                             ])  #list of 1 resultant list

        else:
            print("Invalid file format")

    def selectFile_from_folder(self):
        #Read all the images in the folder
        path = QFileDialog.getExistingDirectory(
            None, 'Select a folder:', '/home/yash/Downloads/Pascal VOC 2012',
            QtGui.QFileDialog.ShowDirsOnly)
        self.lineEdit_2.setText(path)

        self.batch_results = []
        for f in os.listdir(path):  #list all the files in the folder
            ext = f.split('.')[1]  #get the file extension
            if ext.lower(
            ) not in self.valid_images:  #check if the extension is valid for the image
                continue
            filename = path + '/' + f  #create the path of the image
            print(filename)

            self.tag_image(filename, batch=True)
            self.batch_results.append(
                self.classifier.result)  #list of all resultant lists

        #clear the image regions during batch upload
        self.scene.clear()
        self.scene2.clear()

        self.disp_graph(self.batch_results, self.export_name)

    def addmpl(self, fig):
        #Add figure to canvas and widget
        self.canvas = FigureCanvas(fig)
        self.mplvl.addWidget(self.canvas)
        self.canvas.draw()

    def rmmpl(self, ):
        #remove the canvas and widget
        self.mplvl.removeWidget(self.canvas)
        self.canvas.close()
Esempio n. 9
0
class ProfileGraphViewer(QWidget):
    " Profiling results as a graph "

    escapePressed = pyqtSignal()

    def __init__(self,
                 scriptName,
                 params,
                 reportTime,
                 dataFile,
                 stats,
                 parent=None):
        QWidget.__init__(self, parent)

        self.__dataFile = dataFile
        self.__script = scriptName
        self.__reportTime = reportTime
        self.__params = params
        self.__stats = stats

        project = GlobalData().project
        if project.isLoaded():
            self.__projectPrefix = os.path.dirname(project.fileName)
        else:
            self.__projectPrefix = os.path.dirname(scriptName)
        if not self.__projectPrefix.endswith(os.path.sep):
            self.__projectPrefix += os.path.sep

        self.__createLayout()
        self.__getDiagramLayout()

        self.__viewer.setScene(self.__scene)
        return

    def setFocus(self):
        " Sets the focus properly "
        self.__viewer.setFocus()
        return

    def __isOutsideItem(self, fileName):
        " Detects if the record should be shown as an outside one "
        return not fileName.startswith(self.__projectPrefix)

    def __createLayout(self):
        " Creates the widget layout "
        totalCalls = self.__stats.total_calls
        totalPrimitiveCalls = self.__stats.prim_calls  # The calls were not induced via recursion
        totalTime = self.__stats.total_tt

        txt = "<b>Script:</b> " + self.__script + " " + self.__params.arguments + "<br>" \
              "<b>Run at:</b> " + self.__reportTime + "<br>" + \
              str( totalCalls ) + " function calls (" + \
              str( totalPrimitiveCalls ) + " primitive calls) in " + \
              FLOAT_FORMAT % totalTime + " CPU seconds"
        summary = QLabel(txt)
        summary.setToolTip(txt)
        summary.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
        summary.setFrameStyle(QFrame.StyledPanel)
        summary.setAutoFillBackground(True)
        summaryPalette = summary.palette()
        summaryBackground = summaryPalette.color(QPalette.Background)
        summaryBackground.setRgb(min(summaryBackground.red() + 30, 255),
                                 min(summaryBackground.green() + 30, 255),
                                 min(summaryBackground.blue() + 30, 255))
        summaryPalette.setColor(QPalette.Background, summaryBackground)
        summary.setPalette(summaryPalette)

        self.__scene = QGraphicsScene()
        self.__viewer = DiagramWidget()
        self.__viewer.escapePressed.connect(self.__onESC)

        vLayout = QVBoxLayout()
        vLayout.setContentsMargins(0, 0, 0, 0)
        vLayout.setSpacing(0)
        vLayout.addWidget(summary)
        vLayout.addWidget(self.__viewer)

        self.setLayout(vLayout)
        return

    def __getDiagramLayout(self):
        " Runs external tools to get the diagram layout "

        # Preparation: build a map of func ID -> fileName + line
        funcMap = {}
        index = 0
        for func, props in self.__stats.stats.items():
            funcMap[index] = (func[0], func[1])
            index += 1

        # First step is to run grpof2dot
        gprof2dot = thirdpartyDir + "gprof2dot" + os.path.sep + "gprof2dot.py"
        outputFile = self.__dataFile + ".dot"
        nodeLimit = Settings().profileNodeLimit
        edgeLimit = Settings().profileEdgeLimit
        dotSpec = safeRun([
            gprof2dot, '-n',
            str(nodeLimit), '-e',
            str(edgeLimit), '-f', 'pstats', '-o', outputFile, self.__dataFile
        ])
        graphDescr = safeRun(["dot", "-Tplain", outputFile])
        graph = getGraphFromPlainDotData(graphDescr)
        graph.normalize(self.physicalDpiX(), self.physicalDpiY())

        self.__scene.clear()
        self.__scene.setSceneRect(0, 0, graph.width, graph.height)

        for edge in graph.edges:
            self.__scene.addItem(FuncConnection(edge))
            if edge.label != "":
                self.__scene.addItem(FuncConnectionLabel(edge))

        for node in graph.nodes:
            fileName = ""
            lineNumber = 0
            isOutside = True
            nodeID, newLabel = extractNodeID(node.label)
            if nodeID != -1:
                node.label = newLabel

                # Now, detect the file name/line number and
                # if it belongs to the project
                (fileName, lineNumber) = funcMap[nodeID]
            self.__scene.addItem(
                Function(node, fileName, lineNumber,
                         self.__isOutsideItem(fileName)))

        return

    def __onESC(self):
        " Triggered when ESC is clicked "
        self.escapePressed.emit()
        return

    def onCopy(self):
        " Copies the diagram to the exchange buffer "
        self.__viewer.onCopy()
        return

    def onSaveAs(self, fileName):
        " Saves the diagram to a file "
        self.__viewer.onSaveAs(fileName)
        return

    def zoomIn(self):
        " Triggered on the 'zoom in' button "
        self.__viewer.zoomIn()
        return

    def zoomOut(self):
        " Triggered on the 'zoom out' button "
        self.__viewer.zoomOut()
        return

    def resetZoom(self):
        " Triggered on the 'zoom reset' button "
        self.__viewer.resetZoom()
        return
Esempio n. 10
0
class Ui_MRMainWindow(Ui_MainWindow):
    def __init__(self, moviemodel, worker):
        self._moviemodel = moviemodel
        self.worker = worker
        self.job_canceled = False

    def setupUi(self, MainWindow):
        super(Ui_MRMainWindow, self).setupUi(MainWindow)
        self._main_window = MainWindow
        self.listView.set_model(self._moviemodel)
        self._graphic_scene = QGraphicsScene()
        self.movieCoverView.setScene(self._graphic_scene)

        self.draw_toolbar()

        QtCore.QObject.connect(self.actionQuit,
                               QtCore.SIGNAL("triggered()"),
                               QtCore.QCoreApplication.instance().quit)

        QtCore.QObject.connect(self.listView,
                                QtCore.SIGNAL("itemClicked(QListWidgetItem *)"),
                                self.candidates_proposition_menu)

        QtCore.QObject.connect(self.listView,
                               QtCore.SIGNAL("currentItemChanged(\
                               QListWidgetItem *,QListWidgetItem *)"),
                               self.load_movie_infos_in_view)

        QtCore.QObject.connect(self.actionAddFiles,
                               QtCore.SIGNAL("triggered()"),
                               self.add_files)

        QtCore.QObject.connect(self.actionAddDirectory,
                               QtCore.SIGNAL("triggered()"),
                                self.add_directory)

        QtCore.QObject.connect(self.actionLaunchRenameAssistant,
                               QtCore.SIGNAL("triggered()"),
                               self.do_compute)

        QtCore.QObject.connect(self.actionLaunchFromSelection,
                               QtCore.SIGNAL("triggered()"),
                               self.do_compute_from_selection)

        QtCore.QObject.connect(self.actionSave,
                               QtCore.SIGNAL("triggered()"),
                               self.do_batch_save)

        QtCore.QObject.connect(self.cancelJobButton,
                               QtCore.SIGNAL("clicked()"),
                               self.canceljob)

        self.listView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)

        self.listView.connect(self.listView,
                        QtCore.SIGNAL("customContextMenuRequested(QPoint)"),
                        self.onContext)

        QtCore.QObject.connect(self._main_window,
                                QtCore.SIGNAL("progress(int)"),
                                self.update_progress_bar)

        QtCore.QObject.connect(self._main_window,
                                QtCore.SIGNAL("statusmessage(QString)"),
                                self.update_status_bar)

        QtCore.QObject.connect(self.listView,
                               QtCore.SIGNAL("dropped"),
                               self.file_dropped)
    def draw_toolbar(self):
        actions = [self.actionAddFiles,
                   self.actionAddDirectory,
                   self.actionLaunchRenameAssistant,
                   self.actionLaunchFromSelection,
                   self.actionSave,
                   self.actionQuit]
        for action in actions:
            button = QtGui.QToolButton()
            button.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
            button.addAction(action)
            button.setDefaultAction(action)
            self.toolBar.addWidget(button)
        self.toolBar.show()

    def file_dropped(self, links):
            self.build_model_from_files(links)

    def load_movie_infos_in_view(self, item, previous):
        if len(self._moviemodel.data()) == 0:
            print 'modele vide'
            self.filenamEdit.setText("")
            self.titleEdit.setText("")
            self.imdbLinkEdit.setText("")
            self.descriptionEdit.setText("")
            self._graphic_scene.clear()
            return

        if item == None:
            return

        movie = self.listView.item_to_movie[item]
        self.filenamEdit.setText(movie.get_filename())
        self.titleEdit.setText(movie.get_title())
        self.imdbLinkEdit.setText(movie.get_imdb_link())
        self.descriptionEdit.setText(movie.get_desc())

        self._graphic_scene.clear()
        if movie.get_cover() != "":
            pixmap = QtGui.QPixmap(movie.get_cover())
            pixmap = pixmap.scaled(self.movieCoverView.size())
            qitem = QDraggableGraphicsPixmapItem(movie.get_cover(), pixmap)
            self._graphic_scene.addItem(qitem)

    def add_files(self):
        file_extensions = " ".join(map((lambda x: "*." + x),
                                       EXTENSIONS))
        files = QFileDialog.getOpenFileNames(
            None,
            "Select one or more files to open",
            "/home",
            "Video Files (" + file_extensions + ")")
        self.build_model_from_files([unicode(x) for x in files])

    def add_directory(self):
        direct = QFileDialog.getExistingDirectory(None,
                        "Open Directory", "/home",
                         QFileDialog.ShowDirsOnly)
        self.build_model_from_files([unicode(direct)])

    def build_model_from_files(self, files=[]):
        files = FileTools.recurse_files(files)
        for movie in xrange(len(files)):
            m = Movie(files[movie])
            self._moviemodel.add_movie(m)

    def onContext(self, point):
        if (len(self._moviemodel.data()) == 0) or (self.worker.job != None):
            return
        menu = QtGui.QMenu("Context Menu", self._main_window)
        assist = QtGui.QAction("Rename assistant", None)
        ignore = QtGui.QAction("Ignore", None)
        remove = QtGui.QAction("Remove", None)
        reset = QtGui.QAction("Undo modifications", None)
        save = QtGui.QAction("Save", None)
        rmall = QtGui.QAction("Remove all", None)

        menu.addAction(assist)
        menu.addAction(reset)
        menu.addAction(save)
        #menu.addAction(ignore)
        menu.addAction(remove)
        menu.addAction(rmall)

        res = menu.exec_(self.listView.mapToGlobal(point))
        item = self.listView.currentItem()
        movie = self.listView.item_to_movie[item]

        if res == save:
            self._moviemodel.save_movie(movie)

        if res == remove:
            self._moviemodel.remove_movie(movie)

        if res == reset:
            self._moviemodel.reset_movie_informations(movie)
            self.load_movie_infos_in_view(item, None)

        if res == assist:
            self.worker.do(self.do_compute_sub, movie)

        if res == ignore:
            pass

        if res == rmall:
            movies = list(self._moviemodel.data())
            for movie in movies:
                self._moviemodel.remove_movie(movie)

    def candidates_proposition_menu(self, item):
        movie = self.listView.item_to_movie[item]
        menu = QtGui.QMenu("Propositions", self._main_window)

        candidates = self._moviemodel.get_candidates(movie)
        if(len(candidates) == 0):
            return
        tmp = {}
        if candidates != []:
            for j in candidates:
                i = unicode(j)
                proposition = i[0:min(len(i), 100)]
                a = QtGui.QAction(proposition, None)
                tmp[a] = j
                menu.addAction(a)
        else:
            pass

        res = menu.exec_(QtGui.QCursor.pos())
        if res != None:
            self._moviemodel.affect_candidate(movie, tmp[res])
            self.load_movie_infos_in_view(item, None)

    def do_compute(self):
        self.worker.do(self.do_compute_sub)

    def do_compute_from_selection(self):
        self.worker.do(self.do_compute_sub, selection=True)

    def update_progress_bar(self, val):
        self.progressBar.setProperty("value", val)

    def update_status_bar(self, val):
        self.statusbar.showMessage(val)

    def do_compute_sub(self, movie=(), selection=False):
        self.job_canceled = False
        self._set_enable_toolbar(False)
        self._main_window.emit(QtCore.SIGNAL("statusmessage(QString)"),
                               "Querying Google. This may take some time ....")
        self._main_window.emit(QtCore.SIGNAL("progress(int)"), 0)
        #allocine_engine = GoogleQuery()
        allocine_engine = AllocineQuery()
        google_engine = GoogleQuery()
        movies = self._moviemodel.data()

        if movie != ():
            movies = [movie[0]]

        if selection:
            indexes = self.listView.selectedIndexes()
            if len(indexes) > 0:
                firstindex = indexes[0]
                movies = movies[firstindex.row():]

        for i in xrange(len(movies)):
            if self.job_canceled:
                self._main_window.emit(QtCore.SIGNAL("statusmessage(QString)"),
                                       "Job cancelled.")
                break
            current_movie = movies[i]
            self._main_window.emit(QtCore.SIGNAL("statusmessage(QString)"),
                                   "Processing: %s"%(current_movie.get_title()))

            query = FileTools.preprocess_query(current_movie.get_title())
            propositions = allocine_engine.extract_results(allocine_engine.query(query))
            if len(propositions) == 0:
                propositions = google_engine.extract_results(google_engine.query(query))
            def sorter(x,y):
                if "title" in x.get_imdb_link():
                    if "title" in y.get_imdb_link():
                        return 0
                    return -1
                return 1
            propositions.sort(sorter)
            self._moviemodel.set_candidates(current_movie, propositions)
            if(len(propositions) > 0):
                self._moviemodel.affect_candidate(current_movie,
                                                  propositions[0])
            self._main_window.emit(QtCore.SIGNAL("progress(int)"),
                                   (i + 1) * 100 / len(movies))
            time.sleep(SLEEP)
        self._main_window.emit(QtCore.SIGNAL("progress(int)"), 0)
        self._main_window.emit(QtCore.SIGNAL("statusmessage(QString)"),
                               "Finished.")
        self._set_enable_toolbar(True)

    def do_batch_save(self):
        self.worker.do(self.do_batch_save_sub)

    def do_batch_save_sub(self, args, kwargs):
        data = self._moviemodel.data()
        for movie in data:
            if movie.has_changed():
                self._moviemodel.save_movie(movie)

    def canceljob(self):
        self.job_canceled = True
        self._main_window.emit(QtCore.SIGNAL("statusmessage(QString)"),
                               "Abording current job. Please wait...")

    def _set_enable_toolbar(self, enabled):
        for action in self.toolBar.actions():
            action.setEnabled(enabled)
Esempio n. 11
0
File: printer.py Progetto: Ja-vi/pnp
class Printer(object):
	"""For printing in diferent card formats and sizes the associated deck, be it to the screen or pdfs or image files"""

	card_sizes = {"Jumbo":(3.5,5.5), "Tarot":(2.75,4.75), "Square":(3.5,3.5), "Poker":(2.5,3.5),
			 	  "Bridge":(2.25,3.5), "Biz":(2,3.5), "Mini":(1.75,2.5), "Micro":(1.25,1.75)}
	paper_sizes = {"A0":(33.1,46.8), "A1":(23.4,33.1), "A2":(16.5,23.4), "A3":(11.7,16.5),
				   "A4":(8.3,11.7), "A5":(5.8,8.3), "A6":(4.1,5.8)}
	#TODO paper margins when printing and centering the images

	def __init__(self, deck=None):
		self.deck = deck
		self.scene = QGraphicsScene()
		self.orientation = getattr(QPrinter, "Portrait")
		self.path = "output.pdf"
		self.paper = getattr(QPrinter, "A4")
		self.card_size = Printer.card_sizes["Poker"]

	def config(self, *args, **kwargs):
		"""kwargs: deck, card_size, paper_size, orientation, print_path
		if card_size is present I have to join the elements of the deck following the premises"""
		if "orientation" in kwargs:
			self.orientation = kwargs["orientation"]
		if "card_size" in kwargs:
			self.card_size = Printer.card_sizes[kwargs["card_size"][:kwargs["card_size"].find(" ")]]
		if "print_path" in kwargs:
			self.path = kwargs["print_path"]
		if "paper_size" in kwargs:
			self.paper = kwargs["paper_size"]
		if "deck" in kwargs:
			self.deck = kwargs["deck"]

	def print_grid(self):
		if self.deck is not None:
			#Setting the printer
			printer = QPrinter(QPrinter.HighResolution)
			printer.setOutputFormat(QPrinter.PdfFormat)
			printer.setOrientation(getattr(QPrinter, self.orientation))
			printer.setOutputFileName(self.path)
			printer.setPaperSize(getattr(QPrinter, self.paper))
			#Start printing
			with QPainter(printer) as paint:
				first = True
				for c in self.deck:
					if not first:
						printer.newPage()
					first = False
					self.preview_card(c)
					self.scene.render(paint)

	def max_cards(self):
		"""Taking in count the card_size, paper_size returns the max number of cards per page, horientation and margins"""
		port = {}
		port["orientation"] = "Portrait"
		pw = self.paper_sizes[self.paper][0]
		ph = self.paper_sizes[self.paper][1]
		port["horizontal"] = int(pw//self.card_size[0])
		port["vertical"] = int(ph//self.card_size[1])
		port["max"] = port["horizontal"] * port["vertical"]
		port["margin_horizontal"] = (pw % self.card_size[0]) / 2.0
		port["margin_vertical"] = (ph % self.card_size[1]) / 2.0
		land = {}
		land["orientation"] = "Landscape"
		pw = self.paper_sizes[self.paper][1]
		ph = self.paper_sizes[self.paper][0]
		land["horizontal"] = int(pw//self.card_size[0])
		land["vertical"] = int(ph//self.card_size[1])
		land["max"] = land["horizontal"] * land["vertical"]
		land["margin_horizontal"] = (pw % self.card_size[0]) / 2.0
		land["margin_vertical"] = (ph % self.card_size[1]) / 2.0
		if land["max"] > port["max"]:
			return land
		else:
			return port

	def print_pdf(self):
		if self.deck is not None:
			#Setting the printer
			printer = QPrinter(QPrinter.HighResolution)
			printer.setOutputFormat(QPrinter.PdfFormat)
			printer.setOrientation(getattr(QPrinter, "Portrait"))
			printer.setOutputFileName(self.path)
			printer.setPaperSize(getattr(QPrinter, self.paper))
			printer.setFullPage(True)
			guide = self.max_cards()
			printer.setOrientation(getattr(QPrinter, guide["orientation"]))
			print guide, self.card_size
			#Start printing
			with QPainter(printer) as paint:
				ind = 0
				resol = printer.resolution()
				for c in self.deck:
						c.resize(self.card_size[0], self.card_size[1])
						if ind == guide["max"]:
							printer.newPage()
							ind = 0

						col = ind % guide["horizontal"]
						fil = ind // guide["horizontal"]
						print ind, fil, col
						target = QRectF((col)*self.card_size[0]*resol, (fil)*self.card_size[1]*resol,
									self.card_size[0]*resol, self.card_size[1]*resol)

						self.preview_card(c)
						self.scene.render(paint, target=target, source=QRectF(0,0,c.width(),c.height()))
						ind += 1

	def save_images(self):
		if self.deck is not None:
			num = 1
			for c in self.deck:
				c.save_as("".join([str(self.path),str(num),".",c.format()]))
				num += 1

	def preview_card(self, card):
		try:
			self.scene.clear()
			ret = self.scene.addPixmap(card.pixmap())
		except:
			self.scene.clear()
			ret = self.scene.addText("Image not available")
		return ret
Esempio n. 12
0
class OWMosaicDisplay(OWWidget):
    name = "Mosaic Display"
    description = "Display data in a mosaic plot."
    icon = "icons/MosaicDisplay.svg"
    priority = 220

    inputs = [("Data", Table, "set_data", Default),
              ("Data Subset", Table, "set_subset_data")]
    outputs = [("Selected Data", Table)]

    settingsHandler = DomainContextHandler()
    use_boxes = Setting(True)
    variable1 = ContextSetting("", exclude_metas=False)
    variable2 = ContextSetting("", exclude_metas=False)
    variable3 = ContextSetting("", exclude_metas=False)
    variable4 = ContextSetting("", exclude_metas=False)
    selection = ContextSetting(set())
    # interior_coloring is context setting to properly reset it
    # if the widget switches to regression and back (set setData)
    interior_coloring = ContextSetting(1)

    PEARSON, CLASS_DISTRIBUTION = 0, 1
    interior_coloring_opts = ["Pearson residuals",
                              "Class distribution"]
    BAR_WIDTH = 5
    SPACING = 4
    ATTR_NAME_OFFSET = 20
    ATTR_VAL_OFFSET = 3
    BLUE_COLORS = [QColor(255, 255, 255), QColor(210, 210, 255),
                   QColor(110, 110, 255), QColor(0, 0, 255)]
    RED_COLORS = [QColor(255, 255, 255), QColor(255, 200, 200),
                  QColor(255, 100, 100), QColor(255, 0, 0)]

    graph_name = "canvas"

    class Warning(OWWidget.Warning):
        incompatible_subset = Msg("Data subset is incompatible with Data")
        no_valid_data = Msg("No valid data")
        no_cont_selection_sql = \
            Msg("Selection of continuous variables on SQL is not supported")

    def __init__(self):
        super().__init__()

        self.data = None
        self.discrete_data = None
        self.unprocessed_subset_data = None
        self.subset_data = None

        self.areas = []

        self.canvas = QGraphicsScene()
        self.canvas_view = ViewWithPress(self.canvas,
                                         handler=self.clear_selection)
        self.mainArea.layout().addWidget(self.canvas_view)
        self.canvas_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.canvas_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.canvas_view.setRenderHint(QPainter.Antialiasing)

        box = gui.vBox(self.controlArea, box=True)
        self.attr_combos = [
            gui.comboBox(
                    box, self, value="variable{}".format(i),
                    orientation=Qt.Horizontal, contentsLength=12,
                    callback=self.reset_graph,
                    sendSelectedValue=True, valueType=str)
            for i in range(1, 5)]
        self.rb_colors = gui.radioButtonsInBox(
                self.controlArea, self, "interior_coloring",
                self.interior_coloring_opts, box="Interior Coloring",
                callback=self.update_graph)
        self.bar_button = gui.checkBox(
                gui.indentedBox(self.rb_colors),
                self, 'use_boxes', label='Compare with total',
                callback=self._compare_with_total)
        gui.rubber(self.controlArea)

    def sizeHint(self):
        return QSize(530, 720)

    def _compare_with_total(self):
        if self.data and self.data.domain.has_discrete_class:
            self.interior_coloring = 1
            self.update_graph()

    def init_combos(self, data):
        for combo in self.attr_combos:
            combo.clear()
        if data is None:
            return
        for combo in self.attr_combos[1:]:
            combo.addItem("(None)")

        icons = gui.attributeIconDict
        for attr in chain(data.domain, data.domain.metas):
            if attr.is_discrete or attr.is_continuous:
                for combo in self.attr_combos:
                    combo.addItem(icons[attr], attr.name)

        if self.attr_combos[0].count() > 0:
            self.variable1 = self.attr_combos[0].itemText(0)
            self.variable2 = self.attr_combos[1].itemText(
                    2 * (self.attr_combos[1].count() > 2))
        self.variable3 = self.attr_combos[2].itemText(0)
        self.variable4 = self.attr_combos[3].itemText(0)

    def get_attr_list(self):
        return [
            a for a in [self.variable1, self.variable2,
                        self.variable3, self.variable4]
            if a and a != "(None)"]

    def resizeEvent(self, e):
        OWWidget.resizeEvent(self, e)
        self.update_graph()

    def showEvent(self, ev):
        OWWidget.showEvent(self, ev)
        self.update_graph()

    def set_data(self, data):
        if type(data) == SqlTable and data.approx_len() > LARGE_TABLE:
            data = data.sample_time(DEFAULT_SAMPLE_TIME)

        self.closeContext()
        self.data = data
        self.init_combos(self.data)
        if not self.data:
            self.discrete_data = None
            return
        if any(attr.is_continuous for attr in data.domain):
            self.discrete_data = Discretize(method=EqualFreq(n=4))(data)
        else:
            self.discrete_data = self.data

        if self.data.domain.class_var is None:
            self.rb_colors.setDisabled(True)
            disc_class = False
        else:
            self.rb_colors.setDisabled(False)
            disc_class = self.data.domain.has_discrete_class
            self.rb_colors.group.button(2).setDisabled(not disc_class)
            self.bar_button.setDisabled(not disc_class)
        self.interior_coloring = bool(disc_class)
        self.openContext(self.data)

        # if we first received subset we now call setSubsetData to process it
        if self.unprocessed_subset_data:
            self.set_subset_data(self.unprocessed_subset_data)
            self.unprocessed_subset_data = None

    def set_subset_data(self, data):
        self.Warning.incompatible_subset.clear()
        if self.data is None:
            self.unprocessed_subset_data = data
            return
        try:
            self.subset_data = data.from_table(self.data.domain, data)
        except:
            self.subset_data = None
            self.Warning.incompatible_subset(shown=data is not None)

    # this is called by widget after setData and setSubsetData are called.
    # this way the graph is updated only once
    def handleNewSignals(self):
        self.reset_graph()

    def clear_selection(self):
        self.selection = set()
        self.update_selection_rects()
        self.send_selection()

    def reset_graph(self):
        self.clear_selection()
        self.update_graph()

    def update_selection_rects(self):
        for i, (attr, vals, area) in enumerate(self.areas):
            if i in self.selection:
                area.setPen(QPen(Qt.black, 3, Qt.DotLine))
            else:
                area.setPen(QPen())

    def select_area(self, index, ev):
        if ev.button() != Qt.LeftButton:
            return
        if ev.modifiers() & Qt.ControlModifier:
            self.selection ^= {index}
        else:
            self.selection = {index}
        self.update_selection_rects()
        self.send_selection()

    def send_selection(self):
        if not self.selection or self.data is None:
            self.send("Selected Data", None)
            return
        filters = []
        self.Warning.no_cont_selection_sql.clear()
        if self.discrete_data is not self.data:
            if isinstance(self.data, SqlTable):
                self.Warning.no_cont_selection_sql()
        for i in self.selection:
            cols, vals, area = self.areas[i]
            filters.append(
                filter.Values(
                    filter.FilterDiscrete(col, [val])
                    for col, val in zip(cols, vals)))
        if len(filters) > 1:
            filters = filter.Values(filters, conjunction=False)
        else:
            filters = filters[0]
        selection = filters(self.discrete_data)
        if self.discrete_data is not self.data:
            idset = set(selection.ids)
            sel_idx = [i for i, id in enumerate(self.data.ids) if id in idset]
            selection = self.data[sel_idx]
        self.send("Selected Data", selection)


    def send_report(self):
        self.report_plot(self.canvas)

    def update_graph(self):
        spacing = self.SPACING
        bar_width = self.BAR_WIDTH

        def draw_data(attr_list, x0_x1, y0_y1, side, condition,
                      total_attrs, used_attrs=[], used_vals=[],
                      attr_vals=""):
            x0, x1 = x0_x1
            y0, y1 = y0_y1
            if conditionaldict[attr_vals] == 0:
                add_rect(x0, x1, y0, y1, "",
                         used_attrs, used_vals, attr_vals=attr_vals)
                # store coordinates for later drawing of labels
                draw_text(side, attr_list[0], (x0, x1), (y0, y1), total_attrs,
                          used_attrs, used_vals, attr_vals)
                return

            attr = attr_list[0]
            # how much smaller rectangles do we draw
            edge = len(attr_list) * spacing
            values = get_variable_values_sorted(data.domain[attr])
            if side % 2:
                values = values[::-1]  # reverse names if necessary

            if side % 2 == 0:  # we are drawing on the x axis
                # remove the space needed for separating different attr. values
                whole = max(0, (x1 - x0) - edge * (
                    len(values) - 1))
                if whole == 0:
                    edge = (x1 - x0) / float(len(values) - 1)
            else:  # we are drawing on the y axis
                whole = max(0, (y1 - y0) - edge * (len(values) - 1))
                if whole == 0:
                    edge = (y1 - y0) / float(len(values) - 1)

            if attr_vals == "":
                counts = [conditionaldict[val] for val in values]
            else:
                counts = [conditionaldict[attr_vals + "-" + val]
                          for val in values]
            total = sum(counts)

            # if we are visualizing the third attribute and the first attribute
            # has the last value, we have to reverse the order in which the
            # boxes will be drawn otherwise, if the last cell, nearest to the
            # labels of the fourth attribute, is empty, we wouldn't be able to
            # position the labels
            valrange = list(range(len(values)))
            if len(attr_list + used_attrs) == 4 and len(used_attrs) == 2:
                attr1values = get_variable_values_sorted(
                        data.domain[used_attrs[0]])
                if used_vals[0] == attr1values[-1]:
                    valrange = valrange[::-1]

            for i in valrange:
                start = i * edge + whole * float(sum(counts[:i]) / total)
                end = i * edge + whole * float(sum(counts[:i + 1]) / total)
                val = values[i]
                htmlval = to_html(val)
                if attr_vals != "":
                    newattrvals = attr_vals + "-" + val
                else:
                    newattrvals = val

                tooltip = condition + 4 * "&nbsp;" + attr + \
                    ": <b>" + htmlval + "</b><br>"
                attrs = used_attrs + [attr]
                vals = used_vals + [val]
                common_args = attrs, vals, newattrvals
                if side % 2 == 0:  # if we are moving horizontally
                    if len(attr_list) == 1:
                        add_rect(x0 + start, x0 + end, y0, y1,
                                 tooltip, *common_args)
                    else:
                        draw_data(attr_list[1:], (x0 + start, x0 + end),
                                  (y0, y1), side + 1,
                                  tooltip, total_attrs, *common_args)
                else:
                    if len(attr_list) == 1:
                        add_rect(x0, x1, y0 + start, y0 + end,
                                 tooltip, *common_args)
                    else:
                        draw_data(attr_list[1:], (x0, x1),
                                  (y0 + start, y0 + end), side + 1,
                                  tooltip, total_attrs, *common_args)

            draw_text(side, attr_list[0], (x0, x1), (y0, y1),
                      total_attrs, used_attrs, used_vals, attr_vals)

        def draw_text(side, attr, x0_x1, y0_y1,
                      total_attrs, used_attrs, used_vals, attr_vals):
            x0, x1 = x0_x1
            y0, y1 = y0_y1
            if side in drawn_sides:
                return

            # the text on the right will be drawn when we are processing
            # visualization of the last value of the first attribute
            if side == 3:
                attr1values = \
                    get_variable_values_sorted(data.domain[used_attrs[0]])
                if used_vals[0] != attr1values[-1]:
                    return

            if not conditionaldict[attr_vals]:
                if side not in draw_positions:
                    draw_positions[side] = (x0, x1, y0, y1)
                return
            else:
                if side in draw_positions:
                    # restore the positions of attribute values and name
                    (x0, x1, y0, y1) = draw_positions[side]

            drawn_sides.add(side)

            values = get_variable_values_sorted(data.domain[attr])
            if side % 2:
                values = values[::-1]

            spaces = spacing * (total_attrs - side) * (len(values) - 1)
            width = x1 - x0 - spaces * (side % 2 == 0)
            height = y1 - y0 - spaces * (side % 2 == 1)

            # calculate position of first attribute
            currpos = 0

            if attr_vals == "":
                counts = [conditionaldict.get(val, 1) for val in values]
            else:
                counts = [conditionaldict.get(attr_vals + "-" + val, 1)
                          for val in values]
            total = sum(counts)
            if total == 0:
                counts = [1] * len(values)
                total = sum(counts)

            aligns = [Qt.AlignTop | Qt.AlignHCenter,
                      Qt.AlignRight | Qt.AlignVCenter,
                      Qt.AlignBottom | Qt.AlignHCenter,
                      Qt.AlignLeft | Qt.AlignVCenter]
            align = aligns[side]
            for i in range(len(values)):
                val = values[i]
                perc = counts[i] / float(total)
                if distributiondict[val] != 0:
                    if side == 0:
                        CanvasText(self.canvas, str(val),
                                   x0 + currpos + width * 0.5 * perc,
                                   y1 + self.ATTR_VAL_OFFSET, align)
                    elif side == 1:
                        CanvasText(self.canvas, str(val),
                                   x0 - self.ATTR_VAL_OFFSET,
                                   y0 + currpos + height * 0.5 * perc, align)
                    elif side == 2:
                        CanvasText(self.canvas, str(val),
                                   x0 + currpos + width * perc * 0.5,
                                   y0 - self.ATTR_VAL_OFFSET, align)
                    else:
                        CanvasText(self.canvas, str(val),
                                   x1 + self.ATTR_VAL_OFFSET,
                                   y0 + currpos + height * 0.5 * perc, align)

                if side % 2 == 0:
                    currpos += perc * width + spacing * (total_attrs - side)
                else:
                    currpos += perc * height + spacing * (total_attrs - side)

            if side == 0:
                CanvasText(
                        self.canvas, attr,
                        x0 + (x1 - x0) / 2,
                        y1 + self.ATTR_VAL_OFFSET +
                        self.ATTR_NAME_OFFSET,
                        align, bold=1)
            elif side == 1:
                CanvasText(
                        self.canvas, attr,
                        x0 - max_ylabel_w1 - self.ATTR_VAL_OFFSET,
                        y0 + (y1 - y0) / 2,
                        align, bold=1, vertical=True)
            elif side == 2:
                CanvasText(
                        self.canvas, attr,
                        x0 + (x1 - x0) / 2,
                        y0 - self.ATTR_VAL_OFFSET -
                        self.ATTR_NAME_OFFSET,
                        align, bold=1)
            else:
                CanvasText(
                        self.canvas, attr,
                        x1 + max_ylabel_w2 + self.ATTR_VAL_OFFSET,
                        y0 + (y1 - y0) / 2,
                        align, bold=1, vertical=True)

        def add_rect(x0, x1, y0, y1, condition="",
                     used_attrs=[], used_vals=[], attr_vals=""):
            area_index = len(self.areas)
            if x0 == x1:
                x1 += 1
            if y0 == y1:
                y1 += 1

            # rectangles of width and height 1 are not shown - increase
            if x1 - x0 + y1 - y0 == 2:
                y1 += 1

            if class_var and class_var.is_discrete:
                colors = [QColor(*col) for col in class_var.colors]
            else:
                colors = None

            def select_area(_, ev):
                self.select_area(area_index, ev)

            def rect(x, y, w, h, z, pen_color=None, brush_color=None, **args):
                if pen_color is None:
                    return CanvasRectangle(
                            self.canvas, x, y, w, h, z=z, onclick=select_area,
                            **args)
                if brush_color is None:
                    brush_color = pen_color
                return CanvasRectangle(
                        self.canvas, x, y, w, h, pen_color, brush_color, z=z,
                        onclick=select_area, **args)

            def line(x1, y1, x2, y2):
                r = QGraphicsLineItem(x1, y1, x2, y2, None)
                self.canvas.addItem(r)
                r.setPen(QPen(Qt.white, 2))
                r.setZValue(30)

            outer_rect = rect(x0, y0, x1 - x0, y1 - y0, 30)
            self.areas.append((used_attrs, used_vals, outer_rect))
            if not conditionaldict[attr_vals]:
                return

            if self.interior_coloring == self.PEARSON:
                s = sum(apriori_dists[0])
                expected = s * reduce(
                        mul,
                        (apriori_dists[i][used_vals[i]] / float(s)
                         for i in range(len(used_vals))))
                actual = conditionaldict[attr_vals]
                pearson = (actual - expected) / sqrt(expected)
                if pearson == 0:
                    ind = 0
                else:
                    ind = max(0, min(int(log(abs(pearson), 2)), 3))
                color = [self.RED_COLORS, self.BLUE_COLORS][pearson > 0][ind]
                rect(x0, y0, x1 - x0, y1 - y0, -20, color)
                outer_rect.setToolTip(
                        condition + "<hr/>" +
                        "Expected instances: %.1f<br>"
                        "Actual instances: %d<br>"
                        "Standardized (Pearson) residual: %.1f" %
                        (expected, conditionaldict[attr_vals], pearson))
            else:
                cls_values = get_variable_values_sorted(class_var)
                prior = get_distribution(data, class_var.name)
                total = 0
                for i, value in enumerate(cls_values):
                    val = conditionaldict[attr_vals + "-" + value]
                    if val == 0:
                        continue
                    if i == len(cls_values) - 1:
                        v = y1 - y0 - total
                    else:
                        v = ((y1 - y0) * val) / conditionaldict[attr_vals]
                    rect(x0, y0 + total, x1 - x0, v, -20, colors[i])
                    total += v

                if self.use_boxes and \
                        abs(x1 - x0) > bar_width and \
                        abs(y1 - y0) > bar_width:
                    total = 0
                    line(x0 + bar_width, y0, x0 + bar_width, y1)
                    n = sum(prior)
                    for i, (val, color) in enumerate(zip(prior, colors)):
                        if i == len(prior) - 1:
                            h = y1 - y0 - total
                        else:
                            h = (y1 - y0) * val / n
                        rect(x0, y0 + total, bar_width, h, 20, color)
                        total += h

                if conditionalsubsetdict:
                    if conditionalsubsetdict[attr_vals]:
                        counts = [conditionalsubsetdict[attr_vals + "-" + val]
                                  for val in cls_values]
                        if sum(counts) == 1:
                            rect(x0 - 2, y0 - 2, x1 - x0 + 5, y1 - y0 + 5, -550,
                                 colors[counts.index(1)], Qt.white,
                                 penWidth=2, penStyle=Qt.DashLine)
                        if self.subset_data is not None:
                            line(x1 - bar_width, y0, x1 - bar_width, y1)
                            total = 0
                            n = conditionalsubsetdict[attr_vals]
                            if n:
                                for i, (cls, color) in \
                                        enumerate(zip(cls_values, colors)):
                                    val = conditionalsubsetdict[
                                        attr_vals + "-" + cls]
                                    if val == 0:
                                        continue
                                    if i == len(prior) - 1:
                                        v = y1 - y0 - total
                                    else:
                                        v = ((y1 - y0) * val) / n
                                    rect(x1 - bar_width, y0 + total,
                                         bar_width, v, 15, color)
                                    total += v

                actual = [conditionaldict[attr_vals + "-" + cls_values[i]]
                          for i in range(len(prior))]
                n_actual = sum(actual)
                if n_actual > 0:
                    apriori = [prior[key] for key in cls_values]
                    n_apriori = sum(apriori)
                    text = "<br/>".join(
                            "<b>%s</b>: %d / %.1f%% (Expected %.1f / %.1f%%)" %
                            (cls, act, 100.0 * act / n_actual,
                             apr / n_apriori * n_actual, 100.0 * apr / n_apriori
                             )
                            for cls, act, apr in zip(cls_values, actual, apriori
                                                     ))
                else:
                    text = ""
                outer_rect.setToolTip(
                        "{}<hr>Instances: {}<br><br>{}".format(
                                condition, n_actual, text[:-4]))

        def draw_legend(x0_x1, y0_y1):
            x0, x1 = x0_x1
            y0, y1 = y0_y1
            if self.interior_coloring == self.PEARSON:
                names = ["<-8", "-8:-4", "-4:-2", "-2:2", "2:4", "4:8", ">8",
                         "Residuals:"]
                colors = self.RED_COLORS[::-1] + self.BLUE_COLORS[1:]
            else:
                names = get_variable_values_sorted(class_var) + \
                        [class_var.name + ":"]
                colors = [QColor(*col) for col in class_var.colors]

            names = [CanvasText(self.canvas, name, alignment=Qt.AlignVCenter)
                     for name in names]
            totalwidth = sum(text.boundingRect().width() for text in names)

            # compute the x position of the center of the legend
            y = y1 + self.ATTR_NAME_OFFSET + self.ATTR_VAL_OFFSET + 35
            distance = 30
            startx = (x0 + x1) / 2 - (totalwidth + (len(names)) * distance) / 2

            names[-1].setPos(startx + 15, y)
            names[-1].show()
            xoffset = names[-1].boundingRect().width() + distance

            size = 8

            for i in range(len(names) - 1):
                if self.interior_coloring == self.PEARSON:
                    edgecolor = Qt.black
                else:
                    edgecolor = colors[i]

                CanvasRectangle(self.canvas, startx + xoffset, y - size / 2,
                                size, size, edgecolor, colors[i])
                names[i].setPos(startx + xoffset + 10, y)
                xoffset += distance + names[i].boundingRect().width()

        self.canvas.clear()
        self.areas = []

        data = self.discrete_data
        if data is None:
            return
        subset = self.subset_data
        attr_list = self.get_attr_list()
        class_var = data.domain.class_var
        if class_var:
            sql = type(data) == SqlTable
            name = not sql and data.name
            # save class_var because it is removed in the next line
            data = data[:, attr_list + [class_var]]
            data.domain.class_var = class_var
            if not sql:
                data.name = name
        else:
            data = data[:, attr_list]
        # TODO: check this
        # data = Preprocessor_dropMissing(data)
        if len(data) == 0:
            self.Warning.no_valid_data()
            return
        else:
            self.Warning.no_valid_data.clear()

        if self.interior_coloring == self.PEARSON:
            apriori_dists = [get_distribution(data, attr) for attr in attr_list]
        else:
            apriori_dists = []

        def get_max_label_width(attr):
            values = get_variable_values_sorted(data.domain[attr])
            maxw = 0
            for val in values:
                t = CanvasText(self.canvas, val, 0, 0, bold=0, show=False)
                maxw = max(int(t.boundingRect().width()), maxw)
            return maxw

        # get the maximum width of rectangle
        xoff = 20
        width = 20
        if len(attr_list) > 1:
            text = CanvasText(self.canvas, attr_list[1], bold=1, show=0)
            max_ylabel_w1 = min(get_max_label_width(attr_list[1]), 150)
            width = 5 + text.boundingRect().height() + \
                self.ATTR_VAL_OFFSET + max_ylabel_w1
            xoff = width
            if len(attr_list) == 4:
                text = CanvasText(self.canvas, attr_list[3], bold=1, show=0)
                max_ylabel_w2 = min(get_max_label_width(attr_list[3]), 150)
                width += text.boundingRect().height() + \
                    self.ATTR_VAL_OFFSET + max_ylabel_w2 - 10

        # get the maximum height of rectangle
        height = 100
        yoff = 45
        square_size = min(self.canvas_view.width() - width - 20,
                          self.canvas_view.height() - height - 20)

        if square_size < 0:
            return  # canvas is too small to draw rectangles
        self.canvas_view.setSceneRect(
                0, 0, self.canvas_view.width(), self.canvas_view.height())

        drawn_sides = set()
        draw_positions = {}

        conditionaldict, distributiondict = \
            get_conditional_distribution(data, attr_list)
        conditionalsubsetdict = None
        if subset:
            conditionalsubsetdict, _ = \
                get_conditional_distribution(subset, attr_list)

        # draw rectangles
        draw_data(
            attr_list, (xoff, xoff + square_size), (yoff, yoff + square_size),
            0, "", len(attr_list))
        draw_legend((xoff, xoff + square_size), (yoff, yoff + square_size))
        self.update_selection_rects()
Esempio n. 13
0
class ImageGrabber(object):
    '''
    classdocs
    '''
    _config = mrConfigParser()
    _gui = GuiLoader()
    _img = None
    __sources = []
    __grabTimer = QTimer()

    __scene = None
    __gview = None

    def __init__(self, gui=None, config=None):
        '''
        Constructor
        '''
        self._gui = GuiLoader()
        self._config = config

        if gui != None:
            self._gui = gui
            self.__initGui()

    def __initGui(self):
        '''
        Initiates gui listeners
        '''
        # initiate scene
        self.__gview = self._gui.getObj("imgVideo")
        self.__scene = QGraphicsScene()
        self.__gview.setScene(self.__scene)

        # add image size combobox items
        cmb = self._gui.getObj("cmbImgSize")
        cmb.addItem("320x240")
        cmb.addItem("640x480")
        cmb.addItem("800x600")
        cmb.addItem("1024x768")
        #cmb.addItem("1280x960")        # not working with libdc1394 and avt stringray 125c

        # add conversion combobox items
        cmb = self._gui.getObj("cmbConversion")
        cmb.addItem("None")
        cmb.addItem("COLOR_BGR2RGB")
        cmb.addItem("COLOR_GRAY2RGB")
        cmb.addItem("COLOR_YUV2RGB")
        cmb.addItem("COLOR_HLS2RGB")

        # add listeners
        self._gui.connect("cmdStartVideo", "clicked()", self.startVideo)
        self._gui.connect("cmdStopVideo", "clicked()", self.stopVideo)
        self._gui.connect("cmdAddSource", "clicked()", self.__addCamSource)
        self._gui.connect("cmdAddFile", "clicked()", self.__addFileSource)
        self._gui.connect("cmdDelSource", "clicked()",
                          self.__removeSourceFromList)
        self._gui.connect("cmbImgSize", "currentIndexChanged(QString)",
                          self.__imageSizeChanged)
        self._gui.connect("cmdSaveImg", "clicked()", self.saveImg)

    def isActive(self):
        '''
        @return: True if image grabbing is active
        '''
        return self.__grabTimer.isActive()

    def startVideo(self):
        '''
        Starts grabbing images
        '''
        if self.__grabTimer.isActive():
            self.__grabTimer.stop()

        self.__grabTimer = QTimer()
        self.__grabTimer.timeout.connect(self.__grabImage)
        self.__grabTimer.start(0)
        self._gui.status("Video started")

    def stopVideo(self):
        '''
        Stops grabbing video
        '''
        if self.__grabTimer.isActive():
            self.__grabTimer.stop()
            self.__scene.clear()
            self.__gview.show()
            self._gui.status("Video stopped")
            sleep(1)

    def getImage(self):
        '''
        Returns the last grabbed image
        @return: Image
        '''
        return self._img

    def saveImg(self):
        '''
        Saves image
        '''
        if self._img != None:
            img = self._img

            # stop video
            active = self.isActive()
            self.stopVideo()

            # open file dialog
            options = copy(self._gui.dialogOptionsDef)
            options['type'] = self._gui.dialogTypes['FileSave']
            options['filetypes'] = "JPG (*.jpg)"
            options['title'] = "Save current frame as"
            src = str(self._gui.dialog(options))

            # check filepath and save
            if len(src) > 0:
                if not src.endswith(".jpg"):
                    src = src + ".jpg"
                self._gui.status("write to " + src)
                cvtColor(img, COLOR_BGR2RGB)
                imwrite(src, img)

            # reset video streaming
            if active:
                self.startVideo()

    def __showImage(self):
        '''
        Shows image on graphics view
        '''
        if self._img != None:
            self.__scene.clear()
            self.__scene.addPixmap(imageToPixmap(self._img))
            self.__gview.fitInView(self.__scene.sceneRect(),
                                   Qt.KeepAspectRatio)
            self.__gview.show()

    def __grabImage(self):
        '''
        Graps image from sources
        '''
        images = []

        # grab all images
        for src in self.__sources:
            assert isinstance(src, AbstractSourceGrabber)
            images.append(src.getImg())

        # join and convert images
        img = self.__joinImages(images)

        # convert image
        convert = eval(str(self._gui.getObj("cmbConversion").currentText()))
        if convert != None:
            try:
                img = cvtColor(img, convert)
            except:
                img = None

        # show results
        if type(img) == ndarray:
            # add image as new image
            self._img = img
            self.__showImage()

        else:
            # show message
            self.__scene.clear()
            self.__scene.addText("NO VIDEO")

    def __joinImages(self, images=[]):
        '''
        Joins images
        '''
        # TO-DO: Joining images
        if len(images) > 0:
            return images[0]
        return False

    def __imageSizeChanged(self, size="640x480"):
        '''
        Changes image size
        '''
        size = str(size).split("x")
        w = int(size[0])
        h = int(size[1])

        # set size
        for cam in self.__sources:
            if type(cam) == CamGrabber:
                assert isinstance(cam, CamGrabber)
                cam.setImgSize(w, h)

    def __addSourceToList(self, grabber=None):
        '''
        Adds source to source list
        '''
        assert isinstance(grabber, AbstractSourceGrabber)

        if grabber != None:
            # add grabber to list
            self.__sources.append(grabber)
            txt = None

            # get type of grabber
            if type(grabber) == CamGrabber:
                txt = "cam [" + str(grabber.getSource()) + "]"
            elif type(grabber) == FileGrabber:
                txt = "file [" + str(grabber.getSource()) + "]"

            # add text string to gui list
            if txt != None:
                self._gui.getObj("lstSources").addItem(txt)

    def __removeSourceFromList(self):
        '''
        Removes selected source from list
        '''
        for item in self._gui.getObj("lstSources").selectedItems():
            # get item informationen
            txt = str(item.text())
            if "[" in txt and "]" in txt:
                data = txt.split("[")
                iType = data[0].strip()
                iSource = data[1].replace(']', '')

                # search for grabber
                for grabber in self.__sources:
                    assert isinstance(grabber, AbstractSourceGrabber)

                    if str(grabber.getSource()) == iSource:
                        if type(grabber) == CamGrabber and iType == "cam":
                            self.__sources.remove(grabber)
                            break
                        elif type(grabber) == FileGrabber and iType == "file":
                            self.__sources.remove(grabber)
                            break

                # remove source from gui list
                item = self._gui.getObj("lstSources").takeItem(
                    self._gui.getObj("lstSources").currentRow())
                item = None

    def __addCamSource(self):
        '''
        Adds camera as source
        '''
        obj = self._gui.getObj("txtSource")
        source = int(obj.text())

        grabber = CamGrabber(source)
        if grabber.isOpened():
            self.__addSourceToList(grabber)
            self._gui.status("Added camera source [" + str(source) + "]")
        else:
            self._gui.status(
                "Could not add camera source [" + str(source) + "]",
                self._gui.msgTypes['ERROR'])

    def __addFileSource(self):
        '''
        Adds file as source
        '''
        self.stopVideo()
        options = copy(self._gui.dialogOptionsDef)
        options['filetypes'] = "Images (*.jpg *jpeg *gif *png *bmp *tif)"
        source = str(self._gui.dialog(options))

        if len(source) > 0:
            grabber = FileGrabber(source)
            self.__addSourceToList(grabber)

            self._gui.status("Added file source [" + str(source) + "]")
Esempio n. 14
0
class BrushingModel(QObject):
    brushSizeChanged     = pyqtSignal(int)
    brushColorChanged    = pyqtSignal(QColor)
    brushStrokeAvailable = pyqtSignal(QPointF, object)
    drawnNumberChanged   = pyqtSignal(int)
    
    minBrushSize       = 1
    maxBrushSize       = 61
    defaultBrushSize   = 3
    defaultDrawnNumber = 1
    defaultColor       = Qt.white
    erasingColor       = Qt.black
    erasingNumber      = 100
    
    def __init__(self):
        QObject.__init__(self)
        self.sliceRect = None
        self.bb    = QRect() #bounding box enclosing the drawing
        self.brushSize = self.defaultBrushSize
        self.drawColor = self.defaultColor
        self._temp_color = None
        self._temp_number = None
        self.drawnNumber = self.defaultDrawnNumber

        self.pos = None
        self.erasing = False
        
        self.drawOnto = None
        
        #an empty scene, where we add all drawn line segments
        #a QGraphicsLineItem, and which we can use to then
        #render to an image
        self.scene = QGraphicsScene()

    def toggleErase(self):
        self.erasing = not(self.erasing)
        if self.erasing:
            self.setErasing()
        else:
            self.disableErasing()

    def setErasing(self):
        self.erasing = True
        self._temp_color = self.drawColor
        self._temp_number = self.drawnNumber
        self.setBrushColor(self.erasingColor)
        self.brushColorChanged.emit(self.erasingColor)
        self.setDrawnNumber(self.erasingNumber)
    
    def disableErasing(self):
        self.erasing = False
        self.setBrushColor(self._temp_color)
        self.brushColorChanged.emit(self.drawColor)
        self.setDrawnNumber(self._temp_number)

    def setBrushSize(self, size):
        self.brushSize = size
        self.brushSizeChanged.emit(self.brushSize)
    
    def setDrawnNumber(self, num):
        print "Setting Drawnnumer", num
        self.drawnNumber = num
        self.drawnNumberChanged.emit(num)
        
    def getBrushSize(self):
        return self.brushSize
    
    def brushSmaller(self):
        b = self.brushSize
        if b > self.minBrushSize:
            self.setBrushSize(b-1)
        
    def brushBigger(self):
        b = self.brushSize
        if self.brushSize < self.maxBrushSize:
            self.setBrushSize(b+1)
        
    def setBrushColor(self, color):
        self.drawColor = color
        self.brushColorChanged.emit(self.drawColor)
    
    def beginDrawing(self, pos, sliceRect):
        self.sliceRect = sliceRect
        self.scene.clear()
        self.bb = QRect()
        self.pos = QPointF(pos.x()+0.0001, pos.y()+0.0001)
        line = self.moveTo(pos)
        return line

    def endDrawing(self, pos):
        self.moveTo(pos)

        tempi = QImage(QSize(self.bb.width(), self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format
        tempi.fill(0)
        painter = QPainter(tempi)
        self.scene.render(painter, target=QRectF(), source=QRectF(QPointF(self.bb.x(), self.bb.y()), QSizeF(self.bb.width(), self.bb.height())))
        painter.end()
        
        ndarr = qimage2ndarray.rgb_view(tempi)[:,:,0]
        labels = numpy.where(ndarr>0,numpy.uint8(self.drawnNumber),numpy.uint8(0))
        labels = labels.swapaxes(0,1)
        assert labels.shape[0] == self.bb.width()
        assert labels.shape[1] == self.bb.height()

        self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels)

    def dumpDraw(self, pos):
        res = self.endDrawing(pos)
        self.beginDrawing(pos, self.sliceRect)
        return res

    def moveTo(self, pos):
        oldX, oldY = self.pos.x(), self.pos.y()
        x,y = pos.x(), pos.y()
        
        #print "BrushingModel.moveTo(pos=%r)" % (pos) 
        line = QGraphicsLineItem(oldX, oldY, x, y)
        line.setPen(QPen( QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        self.scene.addItem(line)

        #update bounding Box 
        if not self.bb.isValid():
            self.bb = QRect(QPoint(x,y), QSize(1,1))
        #grow bounding box
        self.bb.setLeft(  min(self.bb.left(),   max(0,                   x-self.brushSize/2-1) ) )
        self.bb.setRight( max(self.bb.right(),  min(self.sliceRect[0]-1, x+self.brushSize/2+1) ) )
        self.bb.setTop(   min(self.bb.top(),    max(0,                   y-self.brushSize/2-1) ) )
        self.bb.setBottom(max(self.bb.bottom(), min(self.sliceRect[1]-1, y+self.brushSize/2+1) ) )
        
        #update/move position
        self.pos = pos
Esempio n. 15
0
 def clear(self):
     QGraphicsScene.clear(self)
     self.G.clear()
     del self.nodes[:]
     del self.edges[:]
Esempio n. 16
0
class BrushingModel(QObject):
    brushSizeChanged = pyqtSignal(int)
    brushColorChanged = pyqtSignal(QColor)
    brushStrokeAvailable = pyqtSignal(QPointF, object)
    drawnNumberChanged = pyqtSignal(int)

    minBrushSize = 1
    maxBrushSize = 61
    defaultBrushSize = 3
    defaultDrawnNumber = 1
    defaultColor = Qt.white
    erasingColor = Qt.black
    erasingNumber = 100

    def __init__(self, parent=None):
        QObject.__init__(self, parent=parent)
        self.sliceRect = None
        self.bb = QRect()  #bounding box enclosing the drawing
        self.brushSize = self.defaultBrushSize
        self.drawColor = self.defaultColor
        self._temp_color = None
        self._temp_number = None
        self.drawnNumber = self.defaultDrawnNumber

        self.pos = None
        self.erasing = False
        self._hasMoved = False

        self.drawOnto = None

        #an empty scene, where we add all drawn line segments
        #a QGraphicsLineItem, and which we can use to then
        #render to an image
        self.scene = QGraphicsScene()

    def toggleErase(self):
        self.erasing = not (self.erasing)
        if self.erasing:
            self.setErasing()
        else:
            self.disableErasing()

    def setErasing(self):
        self.erasing = True
        self._temp_color = self.drawColor
        self._temp_number = self.drawnNumber
        self.setBrushColor(self.erasingColor)
        self.brushColorChanged.emit(self.erasingColor)
        self.setDrawnNumber(self.erasingNumber)

    def disableErasing(self):
        self.erasing = False
        self.setBrushColor(self._temp_color)
        self.brushColorChanged.emit(self.drawColor)
        self.setDrawnNumber(self._temp_number)

    def setBrushSize(self, size):
        self.brushSize = size
        self.brushSizeChanged.emit(self.brushSize)

    def setDrawnNumber(self, num):
        self.drawnNumber = num
        self.drawnNumberChanged.emit(num)

    def getBrushSize(self):
        return self.brushSize

    def brushSmaller(self):
        b = self.brushSize
        if b > self.minBrushSize:
            self.setBrushSize(b - 1)

    def brushBigger(self):
        b = self.brushSize
        if self.brushSize < self.maxBrushSize:
            self.setBrushSize(b + 1)

    def setBrushColor(self, color):
        self.drawColor = color
        self.brushColorChanged.emit(self.drawColor)

    def beginDrawing(self, pos, sliceRect):
        '''

        pos -- QPointF-like
        '''
        self.sliceRect = sliceRect
        self.scene.clear()
        self.bb = QRect()
        self.pos = QPointF(pos.x(), pos.y())
        self._hasMoved = False

    def endDrawing(self, pos):
        has_moved = self._hasMoved  # _hasMoved will change after calling moveTo
        if has_moved:
            self.moveTo(pos)
        else:
            assert (self.pos == pos)
            self.moveTo(QPointF(pos.x() + 0.0001,
                                pos.y() + 0.0001))  # move a little

        tempi = QImage(QSize(self.bb.width(), self.bb.height()),
                       QImage.Format_ARGB32_Premultiplied)  #TODO: format
        tempi.fill(0)
        painter = QPainter(tempi)
        self.scene.render(painter,
                          target=QRectF(),
                          source=QRectF(
                              QPointF(self.bb.x(), self.bb.y()),
                              QSizeF(self.bb.width(), self.bb.height())))
        painter.end()

        ndarr = qimage2ndarray.rgb_view(tempi)[:, :, 0]
        labels = numpy.where(ndarr > 0, numpy.uint8(self.drawnNumber),
                             numpy.uint8(0))
        labels = labels.swapaxes(0, 1)
        assert labels.shape[0] == self.bb.width()
        assert labels.shape[1] == self.bb.height()

        ##
        ## ensure that at least one pixel is label when the brush size is 1
        ##
        ## this happens when the user just clicked without moving
        ## in that case the lineitem will be so tiny, that it won't be rendered
        ## into a single pixel by the code above
        if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(
                labels) == 0:
            labels[labels.shape[0] // 2,
                   labels.shape[1] // 2] = self.drawnNumber

        self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()),
                                       labels)

    def dumpDraw(self, pos):
        res = self.endDrawing(pos)
        self.beginDrawing(pos, self.sliceRect)
        return res

    def moveTo(self, pos):
        #data coordinates
        oldX, oldY = self.pos.x(), self.pos.y()
        x, y = pos.x(), pos.y()

        line = QGraphicsLineItem(oldX, oldY, x, y)
        line.setPen(
            QPen(QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap,
                 Qt.RoundJoin))
        self.scene.addItem(line)
        self._hasMoved = True

        #update bounding Box
        if not self.bb.isValid():
            self.bb = QRect(QPoint(oldX, oldY), QSize(1, 1))
        #grow bounding box
        self.bb.setLeft(min(self.bb.left(), max(0,
                                                x - self.brushSize / 2 - 1)))
        self.bb.setRight(
            max(self.bb.right(),
                min(self.sliceRect[0] - 1, x + self.brushSize / 2 + 1)))
        self.bb.setTop(min(self.bb.top(), max(0, y - self.brushSize / 2 - 1)))
        self.bb.setBottom(
            max(self.bb.bottom(),
                min(self.sliceRect[1] - 1, y + self.brushSize / 2 + 1)))

        #update/move position
        self.pos = pos
Esempio n. 17
0
class CVViewModel(object):
    """docstring for View"""

    def __init__(self, ):
        super(CVViewModel, self).__init__()
        self.scence = QGraphicsScene()
        self.graphicsView.setScene(self.scence)
        self.beginTestCV.clicked.connect(
            partial(self.beginTestCV.setEnabled, False))
        self.reporterCV.clicked.connect(self.writeReporterCV)
        self.updateCVData.clicked.connect(self.write_cv_result_to_db)
        # if hasattr(self,"updateOPData"):
        # self.updateOPData.clicked.connect(self.write_cv_result_to_db)

        self.updata_CV_method = update_cv_data
        self.db_parameters,self.pdf_parameters = config.DB_PARAMETER,config.PDF_PARAMETER
        self.insert_widgets()
        self.emit_fibertype_in_items = PyTypeSignal()
        self.last_save = {}
        self._last_data_init()
        self.emit_close_event = PyTypeSignal()
        self.to_report = ReporterPdfs

    def insert_widgets(self):
        self.relative_index_canvas = RefractCanvas(QWidget(self.extendwidget), width=5, height=2, dpi=100)
        self.cvOperatorLayout.insertWidget(2, self.relative_index_canvas)

    def _last_data_init(self):
        load = load_pickle_nor_json("setting\\userdata")
        types = load.get("fiberTypes")
        self.fiberTypeBox.addItems(types)
        # now = self.fiberTypeBox.currentText()
        self.emit_fibertype_in_items.emit()

        try:
            self.olddata = WriteReadJson('setting\\old.json')
            self.last_save = self.olddata.load()
        except ValueError:
            return
        if self.last_save:
            self.fiberLength.setText(self.last_save['fiberLength'])
            self.Worker.setText(self.last_save['worker'])
            self.factory.setText(self.last_save['producer'])
            self.fiberNumber.setText(self.last_save['fiberNo'])

    def updatePixmap(self, arr, sharp, light):
        height, width, bytesPerComponent = arr.shape
        bytesPerLine = bytesPerComponent * width
        img = QImage(arr.data, width, height, bytesPerLine, QImage.Format_RGB888)
        pximapimg = QPixmap.fromImage(img)

        self.scence.clear()
        self.scence.addPixmap(pximapimg)

        self.dynamicSharp.setText(sharp)
        self.light.setText(light)

    def enable_move_button(self, is_move=True):
        collections = ("move_down", "move_up", "next_state",
                       "move_right", "move_left", "reset")
        moves = {getattr(self, c) for c in collections}
        for move in moves:
            move.setEnabled(is_move)

    def closeEvent(self, event, *args, **kwargs):
        # if 'olddata' in SETTING().keys():
        #     self.olddata.save(SETTING()['olddata'])
        logger.info('get last save\n' + str(self.last_save))
        # print(self.last_save)
        self.olddata.save(self.last_save)
        self.emit_close_event.emit()
        super(CVViewModel, self).closeEvent(event)

    def updateCVShow(self, str_, ):
        if str_:
            self.resultShowCV.setText(str_)
            # self.resultShowCV.setStyleSheet("QTextBrowser{font-family: \"Microsoft YaHei\";}")
        self.beginTestCV.setEnabled(True)

    def writeReporterCV(self):
        para = {}
        para['fiberLength'] = str(self.fiberLength.text())
        para['worker'] = str(self.Worker.text())
        para['producer'] = str(self.factory.text())
        para['fiberNo'] = str(self.fiberNumber.text())
        para['fibertype'] = str(self.fiberTypeBox.currentText())
        para['fibertypeindex'] = str(self.fiberTypeBox.currentIndex())
        para['date'] = datetime.strftime(datetime.now(), '%Y-%m-%d %H:%M:%S')
        para['title'] = para['fibertype'] + '光纤端面几何测试报告'
        self.pdf_parameters.update(para)
        # PDF_PARAMETER.update(para)
        self.last_save.update(para)
        self.to_report(self)
        # print 'get in session'
        self.db_parameters.update(para)
        # dbpara = SETTING()['dbpara']

    def write_cv_result_to_db(self):
        para = {}
        para['fiberLength'] = str(self.fiberLength.text())
        para['worker'] = str(self.Worker.text())
        para['producer'] = str(self.factory.text())
        para['fiberNo'] = str(self.fiberNumber.text())
        para['fibertype'] = str(self.fiberTypeBox.currentText())
        para['fibertypeindex'] = str(self.fiberTypeBox.currentIndex())
        para['date'] = datetime.strftime(datetime.now(), '%Y-%m-%d %H:%M:%S')
        para['sharpindex'] = float(self.dynamicSharp.text())
        self.db_parameters.update(para)

        # session_add_by_account(DB_PARAMETER)
        self.updata_CV_method(self.db_parameters)

        # def getCoreLight(self, coreLight, cladLight):
        #     if hasattr(self, "coreLight"):
        #         self.coreLight.setText(coreLight)
        #     if hasattr(self, "cladLight"):
        #         self.cladLight.setText(cladLight)


    def relative_index_show(self, plots):
        self.relative_index_canvas.update_figure(*plots)
Esempio n. 18
0
class DrawManager(QObject):
    """
    DEPRECATED.
    Will be replaced with BrushingModel, BrushingControler, BrushStroke.
    """
     
    brushSizeChanged  = pyqtSignal(int)
    brushColorChanged = pyqtSignal(QColor)
    
    minBrushSize       = 1
    maxBrushSize       = 61
    defaultBrushSize   = 3
    defaultDrawnNumber = 1
    defaultColor       = Qt.white
    erasingColor       = Qt.black
    
    def __init__(self):
        QObject.__init__(self)
        self.shape = None
        self.bb    = QRect() #bounding box enclosing the drawing
        self.brushSize = self.defaultBrushSize
        self.drawColor = self.defaultColor
        self.drawnNumber = self.defaultDrawnNumber

        self.penVis  = QPen(self.drawColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
        self.penDraw = QPen(self.drawColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
        self.pos = None
        self.erasing = False
        
        #on which layer do we want to draw when self.drawingEnabled?
        self.drawOnto = None
        
        #an empty scene, where we add all drawn line segments
        #a QGraphicsLineItem, and which we can use to then
        #render to an image
        self.scene = QGraphicsScene()

    def growBoundingBox(self):
        self.bb.setLeft(  max(0, self.bb.left()-self.brushSize-1))
        self.bb.setTop(   max(0, self.bb.top()-self.brushSize-1 ))
        self.bb.setRight( min(self.shape[0], self.bb.right()+self.brushSize+1))
        self.bb.setBottom(min(self.shape[1], self.bb.bottom()+self.brushSize+1))

    def toggleErase(self):
        self.erasing = not(self.erasing)

    def setErasing(self):
        self.erasing = True
        self.brushColorChanged.emit(self.erasingColor)
    
    def disableErasing(self):
        self.erasing = False
        self.brushColorChanged.emit(self.drawColor)

    def setBrushSize(self, size):
        self.brushSize = size
        self.penVis.setWidth(size)
        self.penDraw.setWidth(size)
        self.brushSizeChanged.emit(self.brushSize)
    
    def setDrawnNumber(self, num):
        self.drawnNumber = num
        self.drawnNumberChanged.emit(num)
        
    def getBrushSize(self):
        return self.brushSize
    
    def brushSmaller(self):
        b = self.brushSize
        if b > self.minBrushSize:
            self.setBrushSize(b-1)
        
    def brushBigger(self):
        b = self.brushSize
        if self.brushSize < self.maxBrushSize:
            self.setBrushSize(b+1)
        
    def setBrushColor(self, color):
        self.drawColor = color
        self.penVis.setColor(color)
        self.emit.brushColorChanged(self.drawColor)
        
    def beginDrawing(self, pos, shape):
        self.shape = shape
        self.bb = QRectF(0, 0, self.shape[0], self.shape[1])
        self.scene.clear()
        if self.erasing:
            self.penVis.setColor(self.erasingColor)
        else:
            self.penVis.setColor(self.drawColor)
        self.pos = QPointF(pos.x()+0.0001, pos.y()+0.0001)
        line = self.moveTo(pos)
        return line

    def endDrawing(self, pos):
        self.moveTo(pos)
        self.growBoundingBox()

        tempi = QImage(QSize(self.bb.width(), self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format
        tempi.fill(0)
        painter = QPainter(tempi)
        
        self.scene.render(painter, QRectF(QPointF(0,0), self.bb.size()), self.bb)
        
        return (self.bb.left(), self.bb.top(), tempi) #TODO: hackish, probably return a class ??

    def dumpDraw(self, pos):
        res = self.endDrawing(pos)
        self.beginDrawing(pos, self.shape)
        return res

    def moveTo(self, pos):    
        lineVis = QGraphicsLineItem(self.pos.x(), self.pos.y(), pos.x(), pos.y())
        lineVis.setPen(self.penVis)
        
        line = QGraphicsLineItem(self.pos.x(), self.pos.y(), pos.x(), pos.y())
        line.setPen(self.penDraw)
        self.scene.addItem(line)

        self.pos = pos
        x = pos.x()
        y = pos.y()
        #update bounding Box :
        if x > self.bb.right():
            self.bb.setRight(x)
        if x < self.bb.left():
            self.bb.setLeft(x)
        if y > self.bb.bottom():
            self.bb.setBottom(y)
        if y < self.bb.top():
            self.bb.setTop(y)
        return lineVis
Esempio n. 19
0
class CBIR(QMainWindow, Ui_MainWindow):
    #class variables
    flag = True
    categories = {}
    classes = [
        "Aeroplane", "Bicycle", "Bird", "Boat", "Bottle", "Bus", "Car", "Cat",
        "Chair", "Cow", "Dining Table", "Dog", "Horse", "Motorbike", "Person",
        "Potted plant", "Sheep", "Sofa", "Train", "Tv"
    ]
    mask = np.zeros(len(classes))
    class2idx = {item: i for i, item in enumerate(classes)}
    valid_images = ["jpg", "png", "tga", "pgm", "jpeg"]
    valid_videos = ["mp4", "avi"]
    edge_threshold = 100
    topk = 10
    to_disp = []
    stop = False
    database_path = ''
    thumbnail_size = 256
    spacing = 40
    images_per_row = 2
    cached_db = {}
    cached_db_path = ''
    alpha = 16
    beta = 0.8

    def __init__(self, ):
        super(
            CBIR,
            self).__init__()  #initialise from the ui designed by Designer App
        self.setupUi(self)
        self.setupUi_custom()

    def setupUi_custom(self, ):
        self.setWindowTitle('CBIR')

        #setup space to display selected image and it's tagged version
        self.scene = QGraphicsScene()
        self.scene2 = QGraphicsScene()

        #connect the buttons to their respective functions
        self.pushButton.clicked.connect(self.select_image)
        self.pushButton_2.clicked.connect(self.find_similar)
        self.pushButton_3.clicked.connect(self.select_database)
        self.horizontalSlider.valueChanged.connect(self.update_LCD)

        #TODO [WEIRD PROBLEM] QPixmap needs to be called at least once with JPG image before tensorFlow, otherwise program crashes
        self.scene.addPixmap(
            QPixmap(os.getcwd() + "/images/demo.jpg").scaled(
                self.graphicsView.size(), QtCore.Qt.KeepAspectRatio))
        self.graphicsView.setScene(self.scene)

        #set-up toolbar items and link them to respective functions
        Help = QtGui.QAction(QtGui.QIcon('images/info.png'), 'Help', self)
        Help.triggered.connect(self.show_help)

        Settings = QtGui.QAction(QtGui.QIcon('images/settings.png'),
                                 'Settings', self)
        Settings.triggered.connect(self.show_settings)

        Export = QtGui.QAction(QtGui.QIcon('images/export.png'), 'Export',
                               self)
        Export.triggered.connect(self.show_export)

        ##To set up the toolbar
        self.toolbar = self.addToolBar('Help')
        self.toolbar.addAction(Help)
        self.toolbar = self.addToolBar('Settings')
        self.toolbar.addAction(Settings)
        self.toolbar = self.addToolBar('Export')
        self.toolbar.addAction(Export)

    def show_help(self):
        msg = QMessageBox()
        #setup title, main heading, about us info
        msg.setIcon(QMessageBox.Information)
        msg.setWindowTitle("About Us")
        msg.setText("Semantic Graph based Image matching")
        msg.setInformativeText(
            "Developed by Yash Chandak, under supervision of Prof. Babiga Birregah, University of Technology, Troyes"
        )
        #Section for further details on how to use the software
        f = open('How-To/how-to-SGBIR.txt', 'r')
        msg.setDetailedText(f.read())

        #setup return buttons
        msg.setStandardButtons(QMessageBox.Ok)
        msg.exec_()

    def show_settings(self):
        topk, ok = QtGui.QInputDialog.getInt(self, 'Settings',
                                             'Number of results to display')
        self.topk = topk

    def show_export(self):
        #TODO gephi export
        name, ok = QtGui.QInputDialog.getText(self, 'Export to Gephi format',
                                              'Enter file name :')
        self.exportname = name

    def select_database(self):
        #Read all the images in the folder
        path = QFileDialog.getExistingDirectory(
            None, 'Select a folder:',
            '/home/yash/Project/dataset/Pascal VOC 2012/',
            QtGui.QFileDialog.ShowDirsOnly)
        self.lineEdit_2.setText(path)
        self.database_path = path

    def update_categories(self):
        #update selected categories
        self.mask.fill(0)
        for radiobox in self.findChildren(QtGui.QRadioButton):
            self.categories[radiobox.text()] = radiobox.isChecked()
            if not radiobox.text() == 'All':
                self.mask[self.class2idx[
                    radiobox.text()]] = radiobox.isChecked()

        if self.categories.get('All', 0) == 1: self.mask.fill(1)

    def update_LCD(self):
        #update edge_threshold variable based on slider
        self.edge_threshold = self.horizontalSlider.value()
        self.lcdNumber.display(self.edge_threshold)

    def show_similar(self, pictures, base_dir=''):
        #set the table layout spacing
        self.tableWidget.setMinimumWidth((self.thumbnail_size + self.spacing) *
                                         self.images_per_row +
                                         (self.spacing * 2))
        #set table row and column count based on similar images received
        rowCount = len(pictures) // self.images_per_row
        if len(pictures) % self.images_per_row: rowCount += 1
        self.tableWidget.setRowCount(rowCount)

        row = -1
        #set the pictures in the table cells
        for i, picture in enumerate(pictures):
            col = i % self.images_per_row
            if not col: row += 1
            #self.tableWidget.setCellWidget(row, col,  ImgWidget(imagePath = self.cached_db[picture][0], size=self.thumbnail_size))
            self.tableWidget.setCellWidget(
                row, col,
                ImgWidget(imagePath=base_dir + '/' + picture,
                          size=self.thumbnail_size))

    def read_database(self):
        #Option to select database
        if self.database_path == '':
            print("Database file not selected")
            self.select_database()

        found = False
        if self.cached_db_path == self.database_path:
            #No need to re-read from cPickle if it's re-run on the same db
            found = True

        #Search for any pre-existing db file
        else:
            self.cached_db_path = self.database_path
            for file in os.listdir(
                    self.database_path):  #list all the files in the folder
                extension = file.split('.')[1]  #get the file extension
                if extension.lower(
                ) == 'db':  #check for pickled cached_db file
                    self.cached_db = pickle.load(
                        open(self.database_path + '/' + file, 'rb'))
                    print("Cached database found!")
                    found = True
                    break

        #Create a new db if no exiting db is found
        if not found: self.cached_db = self.make_db(self.database_path)

    def count_diff(self, v1, v2):
        #alpha acts as a hyper-parameter that penalizes count differneces of
        #classes present only in one as compared to count differneces for classes
        #present in both.
        w = [self.alpha if i == 0 else 1 for i in v1]
        return np.sum(self.mask * w * np.power(
            (v1 - v2),
            2))  #sum of weighted Squared error, masked by selected classes

    def loc_diff(self, query_edges, db_edges):

        total = 0
        for e1 in query_edges:
            best = 99999
            for e2 in db_edges:
                if e1[0] == e2[0]:
                    diff = abs(e1[1] - e2[1])
                    best = diff if diff < best else best

            total += best
        #TODO: add the details
        return np.log(total)

    def score(self, edges, vec, db_img):
        #weighted score of location deifference and count difference
        #higher the score, higher is the difference, lesser the similarity
        return self.beta*self.count_diff(vec, self.cached_db['vec'][db_img]) \
                + (1-self.beta)*self.loc_diff(edges, self.cached_db['edges'][db_img])

    def get_vec_and_classes(self, results):
        #returns vector and all unique classes for the given image result.
        vec = np.zeros(len(self.classifier.classes))
        classes_present = []
        for result in results:
            vec[self.class2idx[result[0]]] += 1
            classes_present.append(result[0])
        return vec, set(classes_present)

    def order(self, c1, c2):
        #edge nodes concatenated in alphabetical order to create edge name
        if self.class2idx[c1] < self.class2idx[c2]: return c1 + c2
        else: return c2 + c1

    def get_edges_with_weights(self, results):
        #returns a list of (edge, weight)
        return [(self.order(results[i][0], results[j][0]), apx_distance(results[i], results[j])) \
                for i in range(len(results)) for j in range(i, len(results))]

    def make_db(self, path):
        print("caching database..")
        inv_map = {c: [] for c in self.classes}
        edges = {}
        vec = {}
        for file in os.listdir(path):  #list all the fileiles in the folder
            ext = file.split('.')[1]  #get the file extension
            if ext.lower() in self.valid_images:
                print(file)
                full_path = path + '/' + file
                self.tag_image(filename=full_path)

                #store the all the edges and weights for the image
                edges[file] = self.get_edges_with_weights(
                    self.classifier.result)

                #create the inverse map( class -> images )
                v, classes_present = self.get_vec_and_classes(
                    self.classifier.result)
                vec[file] = v
                for c in classes_present:
                    inv_map[c].append(file)

        #Storage format = {dir, inv_map[class]->images, vectors[image]->vec, edges[image]->edges}
        cached_db = {
            'dir': path,
            'inv_map': inv_map,
            'vec': vec,
            'edges': edges
        }
        pickle.dump(cached_db, open(path + '/cache.db', 'wb'))
        return cached_db

    def find_similar(self, results):
        #do pattern matching on the images in retrieved cached_db
        #keep top 10 and display on right
        self.read_database()

        #get the edges, vector, classes_present in the query image
        edges = self.get_edges_with_weights(results)
        vec, classes_present = self.get_vec_and_classes(results)

        #get all the images having at least one occurence of the class present in query image
        imgs = set([
            img for c in classes_present
            for img in self.cached_db['inv_map'][c]
        ])

        #choose the topK similar images from the images retrieved from database
        best_matches = nsmallest(self.topk,
                                 imgs,
                                 key=lambda e: self.score(edges, vec, e))

        self.show_similar(best_matches, self.cached_db['dir'])
        return best_matches[:5]

    def tag_image(self, filename=None, batch=False, image=None):
        #importing TensorFlow on top causes segmentation fault (official bug #2034)
        #importing here helps in working around the problem
        #Python modules could be con)sidered as singletons... so no matter how many times they are imported, they get initialized only once
        import Yolo_module as yolo

        if (self.flag):
            #initialise the model, only once
            self.classifier = yolo.YOLO_TF()
            self.flag = False

        self.classifier.batch = batch

        if not image == None:
            self.classifier.detect_from_cvmat(image)
        else:
            self.classifier.detect_from_file(
                filename)  #execute Yolo on the image

        return self.classifier.tagged_image

    def disp_img(self, filename=None, img=None):
        if not img == None:
            img_rgb = img.copy()
            #convert image to PyQt display format
            cv2.cvtColor(img, cv2.COLOR_BGR2RGB, img_rgb)
            img_rgb = QtGui.QImage(img_rgb, img_rgb.shape[1], img_rgb.shape[0],
                                   img_rgb.shape[1] * 3,
                                   QtGui.QImage.Format_RGB888)
            self.scene.addPixmap(
                QPixmap(img_rgb).scaled(self.graphicsView.size(),
                                        QtCore.Qt.KeepAspectRatio))
            image = self.tag_image(image=img)

        else:
            #DO this step before calling tensorflow
            self.scene.addPixmap(
                QPixmap(filename).scaled(self.graphicsView.size(),
                                         QtCore.Qt.KeepAspectRatio))

            #Dislplay tagged image
            image = self.tag_image(filename=filename)

        image = QtGui.QImage(
            image, image.shape[1], image.shape[0], image.shape[1] * 3,
            QtGui.QImage.Format_RGB888)  #convert to Qt image format
        self.scene2.addPixmap(
            QPixmap(image).scaled(self.graphicsView_3.size(),
                                  QtCore.Qt.KeepAspectRatio))

        self.graphicsView.setScene(self.scene)
        self.graphicsView_3.setScene(self.scene2)

    def select_image(self):
        #Clear previous image displays
        self.scene.clear()
        self.scene2.clear()
        self.tableWidget.clearContents()
        self.update_categories(
        )  #update categories to incorporate any changes made

        #Change the file path to any default directory, as per need.
        filename = QFileDialog.getOpenFileName(
            directory='/home/yash/Project/dataset/Pascal VOC 2012/')
        self.lineEdit.setText(filename)

        if filename.split('.')[1] in self.valid_images:
            self.disp_img(filename=filename)
            self.file_tag = '/home/yash/Project/dataset/Pascal VOC 2012/report/' + (
                filename.split('/')[-1]).split('.')[0] + "_"
            best_matches = self.find_similar(self.classifier.result)

            cv2.imwrite(self.file_tag + '.jpg', cv2.imread(filename, 1))
            cv2.imwrite(self.file_tag + 'tagged.jpg',
                        self.classifier.tagged_image_original)
            for idx, im in enumerate(best_matches):
                cv2.imwrite(self.file_tag + str(idx) + '.jpg',
                            cv2.imread(self.cached_db['dir'] + '/' + im, 1))
            #self.find_similar_using_vector(self.classifier.result)
        else:
            print("Invalid file format")
Esempio n. 20
0
class ToastWidget(QGraphicsView):
    """
    A widget to create toast messages to the user
    A friendly interface messages. (include image, and visual effects as blinking, fade etc)
    """
    def __init__(self, parent=None, back_image=None, width=100, heigth=100):
        super(ToastWidget, self).__init__(parent)
        self.setWindowFlags(Qt.SplashScreen)
        self.scene = QGraphicsScene(self)

        self.timer = QTimer(self)

        self.setScene(self.scene)
        self.set_image(back_image)
        self.setGeometry(QRect(self.x(), self.y(), width, heigth))
        self.show()

    def set_image(self, image):
        if image is None:
            return

        if not isinstance(image, QPixmap):
            raise Exception("Image must be of type QPixmap")
        self.scene.clear()
        self.scene.addPixmap(image.scaled(95, 95))

    def move_random(self, x1=0, x2=1300, y1=0, y2=768):
        x, y = random.randrange(x1, x2), random.randrange(y1, y2)
        self.setGeometry(QRect(x, y, 100, 100))
        return self

    def blink(self, time_limit=1000, time_interval=500):
        def _blink():
            self.setWindowOpacity(1 - self.windowOpacity())

        # self.timer.stop()
        # self.timer.setInterval(time_interval)
        # self.timer.timeout.connect(_blink)
        # self.timer.start_limited(time_interval, time_limit / time_interval)
        return self

    def fade(self, time=1500):
        """
        :param time:  the time to  completely execute the fade in ms
        :param out: fade out or in. out by default
       """
        steps = 100
        self.timer.stop()
        self.setWindowOpacity(1)
        self.timer.timeout.connect(
            lambda: self.setWindowOpacity(self.windowOpacity() - 1.0 / steps))
        self.timer.start(time * 1.0 / steps)
        # QTimer.singleShot(time, lambda: self.timer.stop())
        return self

    def disappear(self, time=1000):
        """
        """
        self.timer.stop()
        self.setWindowOpacity(1)
        self.timer.singleShot(time, lambda: self.setWindowOpacity(0))
        return self

    def vibrate(self, time_limit=1000):
        geometry = self.geometry()
        x, y = geometry.x(), geometry.y()

        def _move():
            self.setGeometry(
                QRect(x + random.randrange(-3, 3), y + random.randrange(-3, 3),
                      geometry.width(), geometry.height()))

        return self
Esempio n. 21
0
class AnalogClock(QGraphicsView):
    """
    Analog Clock Widget.
    It shows a analog svg clock
    """
    AUTO = 0
    QUARTZ = 1
    ECO = 2
    
    
    def __init__(self, parent=None, path=None, static = False):
        """
        Constructor
        """
        QGraphicsView.__init__(self, parent)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        #self.setAutoFillBackground(True)
        #pal = self.palette();
        #br = QBrush(Qt.NoBrush)
        #pal.setBrush(QPalette.Background, br);
        #self.setPalette(pal);
        #self.setBackgroundBrush(br)
        # is the only thing seems to work to get the background transparent
        self.setStyleSheet("background-color: rgba(0, 0, 0, 0%);")
        self.setFrameShape(QFrame.NoFrame)

        #   self.setBackgroundOrigin( BackgroundOrigin background )
        self._static = static
        self.setDefaults()
        
        self.loadTheme(path)

        self.startTimers()
        self.resetEcoTimer()
        #self.setClockType()

    def setDefaults(self):    
        self.sysThemeDir=os.path.join(os.path.dirname(__file__), os.path.pardir, "theme")
        self.themeDir=""
        self.themeName=""
        self.ecoTimeout = 0
        self.clockMode = self.AUTO
        self.drop="clock-drop-shadow.svg"
        self.face="clock-face.svg"
        self.shadow="clock-face-shadow.svg"
        self.marks= "clock-marks.svg" 
        self.frame="clock-frame.svg"
        self.hourHand="clock-hour-hand.svg"
        self.minuteHand="clock-minute-hand.svg"
        self.secondsHand="clock-second-hand.svg"
        self.glass="clock-glass.svg"
   
     #Variables that keep track of the angle of the hands, and  Time
        self.secTimer = QBasicTimer()
        self.minTimer=QTimer()
        self.calibrateTimer=QTimer()
        self.ecoTimer=QTimer()
        self.syncTimer=QTimer()
        self.secs=0
    #The second hand counter  166=6 beats per second, 1000 =1 beat per sec
        self.secTimerType=166.9
        self.secTimerBeat=1
     #The Minute update counter every 10secs for Quartz, once per minute for Eco   
        self.minTimerType=1000
    #Variables that keep track of scene
        self.scene = QGraphicsScene()
        self.sceneWidth=0
        self.sceneHeight=0
        self.centerx=0
        self.centery=0
        self.xoffset=-15
        self.yoffset=-5
        self.ixoffset=self.xoffset*-1
        self.iyoffset=self.yoffset*-1
        self.svgRect=QRect()
        self.svgRect.setX(self.xoffset)
        self.svgRect.setY(self.yoffset)


    def loadTheme(self, path):
        self.secTimer.stop()
        self.minTimer.stop()
        self.calibrateTimer.stop()
        self.syncTimer.stop()
        self.scene.clear()
 
        #Check to see if files in directory stored in QConfig exists
        self.themeDir=path or self.sysThemeDir
        try:
            f=open(os.path.join(self.themeDir, unicode(self.face)))
        except (OSError, IOError), e:
            print "can't load theme, loading default"

        #Initialize the Graphics Scene, Graphicsview is setup in QtDesigner UI,do not convert to a loop
        def path(suffix):
            return os.path.join(self.themeDir, self.themeName ,suffix)

        self.svgDrop=QGraphicsSvgItem(path(self.drop))
        renderer=self.svgDrop.renderer()
        self.svgDrop.setZValue(1)
        self.scene.addItem(self.svgDrop)
        
        self.svgFace=QGraphicsSvgItem(path(self.face))
        renderer=self.svgFace.renderer()
        self.svgFace.setZValue(2)
        self.scene.addItem(self.svgFace)
        
        self.svgShadow=QGraphicsSvgItem(path(self.shadow))
        renderer=self.svgShadow.renderer()
        self.svgShadow.setZValue(4)
        self.scene.addItem(self.svgShadow)
        
        self.svgMarks=QGraphicsSvgItem(path(self.marks))
        renderer=self.svgMarks.renderer()
        self.svgMarks.setZValue(5)
        self.scene.addItem(self.svgMarks)
        
        self.svgFrame=QGraphicsSvgItem(path(self.frame))
        renderer=self.svgFrame.renderer()
        self.svgFrame.setZValue(6)
        self.scene.addItem(self.svgFrame)
        
    #get the bounding box for the scene now filled with the clock theme
        self.sceneWidth=self.scene.itemsBoundingRect().width()
        self.sceneHeight=self.scene.itemsBoundingRect().height()
        self.centerx=self.sceneWidth/2
        self.centery=self.sceneHeight/2
        self.centerOn(self.centerx, self.centery)
        self.scene.setSceneRect(0, 0,self.sceneWidth, self.sceneHeight)
 
    #===Load the Hour hand and scale the viewport to its size===========
        self.svgHour=QGraphicsSvgItem(path(self.hourHand))
        self.renderer=self.svgHour.renderer()
        self.rect=self.svgHour.boundingRect()
        self.svgRect.setWidth(self.rect.width())
        self.svgRect.setHeight(self.rect.height())
        #setup the Viewbox
        self.renderer.setViewBox(self.svgRect)
        self.svgHour.setPos(self.centerx+self.xoffset, self.centery+self.yoffset)
        self.svgHour.setZValue(7)
        self.scene.addItem(self.svgHour)
        
        #===Load the Minute hand and scale the viewport to its size===========
        self.svgMinute=QGraphicsSvgItem(path(self.minuteHand))
        self.renderer=self.svgMinute.renderer()
        self.rect=self.svgMinute.boundingRect()
        self.svgRect.setWidth(self.rect.width())
        self.svgRect.setHeight(self.rect.height())
        #setup the Viewbox
        self.renderer.setViewBox(self.svgRect)
        self.svgMinute.setPos(self.centerx+self.xoffset, self.centery+self.yoffset)
        self.svgMinute.setZValue(8)
        self.scene.addItem(self.svgMinute)
        
        #===Load the Seconds Hand and scale the viewport to its size===========
        self.svgSecond=QGraphicsSvgItem(path(self.secondsHand))
        self.renderer=self.svgSecond.renderer()
        self.rect=self.svgSecond.boundingRect()
        self.svgRect.setWidth(self.rect.width())
        self.svgRect.setHeight(self.rect.height())
        #setup the Viewbox
        self.renderer.setViewBox(self.svgRect)
        self.svgSecond.setPos(self.centerx+self.xoffset, self.centery+self.yoffset)
        self.svgSecond.setZValue(9) 
        self.scene.addItem(self.svgSecond)

         #Add the Glass as the top layer
        self.fileExist=1
        try:
                f=open (path("clock-glass.svg"))
        except :
                self.fileExist=0
        if self.fileExist==1:
                self.svgItem=QGraphicsSvgItem(path(self.glass))
                renderer=self.svgItem.renderer()
                self.svgItem.setZValue(10)
                self.scene.addItem(self.svgItem)
             
                
         #setup the  hands against the current time  
        self.showTime()
        self.calibrateTime()
       
        #Scale the Clock to full screen and show whole clock
        self.resetTransform()
        self.setZoom(None)
        self.setScene(self.scene)
Esempio n. 22
0
class Distortion(visionModule):
    '''
    classdocs
    '''
    __imgScene = None  
    
    __scene = None
    __gview = None
    __sceneImgTimer = None
    
    __camera_matrix = None
    __dist_coefs = None
    __corners = None
    
    __calibrated = False
    __calibrating = False


    def __init__(self, gui=None, imageGrabber=None, config=None):
        '''
        Constructor
        '''        
        super(Distortion, self).__init__(gui=gui, imageGrabber=imageGrabber, config=config)
        self.__calibrated = False
        self.__calibrating = False
        
        if gui != None:
            self.__initGui()
            
        if self._config != None:
            cfgFile = self._config.getConfigValue("CONFIGURATION", "cfgCalibration")
            if cfgFile != None and self.__loadConfigData(cfgFile):
                self._gui.status( "Loaded distortion config." )
                mrLogger.logInfo( "Loaded distortion config file " + str(cfgFile) )
        
        
    def __initGui(self):
        '''
        Initiates gui
        '''
        # initiate scene
        self.__gview = self._gui.getObj("imgDistortion")
        self.__scene = QGraphicsScene()
        self.__gview.setScene(self.__scene)
        
        # create listeners
        self._gui.connect( "cmdFindPattern", "clicked()", self.findChessBoardPattern )
        self._gui.connect( "cmdCalibrateDistortion", "clicked()", self.calibrateCamera )
        self._gui.connect( "cmdSaveDistortion", "clicked()", self.__saveConfiguration )
        self._gui.connect( "cmdLoadDistortion", "clicked()", self.__loadConfiguration )
        self._gui.connect( "chkCropImg", "toggled(bool)", self.__borderSelectionChanged )
        self._gui.connect( "chkCropImgManual", "toggled(bool)", self.__borderSelectionChanged )
        self._gui.connect( "cmdSaveImgDistortion", "clicked()", self.__saveImg )
        
        # start timer
        self.__sceneImgTimer = QTimer()
        self.__sceneImgTimer.timeout.connect( self._showImage )
        self.__sceneImgTimer.start(200)        
     


    def isCalibrated(self):
        '''
        @return: True if image is calibrated
        '''
        return self.__calibrated
    
    def isCalibrating(self):
        '''
        @return: True if calibration is in progress
        '''
        return self.__calibrating
        
        
    def setImg(self, img=None):
        '''
        Sets current image
        '''
        super(Distortion, self).setImg(img)
        
        if not self.isCalibrating() and self._imageGrabber != None:
            self.__imgScene = self.cropImage( self.undistortImage(self._img) )
        
    def __borderSelectionChanged(self):
        '''
        Checks selection of manual/auto
        border settings gui group
        '''
        if self._gui.getObj("chkCropImgManual").isChecked():
            self._gui.getObj("chkCropImg").setChecked(False)
            self._gui.getObj("chkCropImg").setEnabled(False)
        else:
            self._gui.getObj("chkCropImg").setEnabled(True)
            
        if self._gui.getObj("chkCropImg").isChecked():
            self._gui.getObj("chkCropImgManual").setChecked(False)
            self._gui.getObj("chkCropImgManual").setEnabled(False)
        else:
            self._gui.getObj("chkCropImgManual").setEnabled(True)
    
    def findChessBoardPattern(self):
        '''
        Finds maximum chessboard pattern
        '''        
        # show message
        self.__imgScene = None
        self.__scene.clear()
        self.__scene.addSimpleText("Searching pattern...\nThis will take a while")
        self.__gview.show()
        
        # start search
        start_new_thread( self.__searchChessBoardPattern, () )
        
    def __searchChessBoardPattern(self):
        '''
        Searches for chessboard pattern
        (start in background)
        '''
        
        # get start and max values
        xStart = int( str( self._gui.getObj("txtPatternXMin").text() ) )
        yStart =  int( str( self._gui.getObj("txtPatternYMin").text() ) )
        xMax =  int( str( self._gui.getObj("txtPatternXMax").text() ) )
        yMax =  int( str( self._gui.getObj("txtPatternYMax").text() ) )
        
        # find pattern
        if self._img != None:
            pattern = findChessBoardPatternSize(self._img, xMax, yMax, xStart, yStart)
        
            if pattern != None and len(pattern) > 0:                
                # set pattern
                if len(pattern) == 2:
                    self._gui.getObj("txtPatternX").setText( str(pattern[0]) )
                    self._gui.getObj("txtPatternY").setText( str(pattern[1]) )
    
    def calibrateCamera(self):
        '''
        Calibrates camera
        '''
        start_new_thread(self.__calibrate, ())
        
        
    def __calibrate(self):
        '''
        Calibrates camera
        (run in background)
        '''
        # check for correct image        
        if self._img != None:
            self.__calibrating = True
            self._gui.status("Calibrating ...")
                  
            # get values
            x = int(str( self._gui.getObj("txtPatternX").text() ))
            y = int(str( self._gui.getObj("txtPatternY").text() ))
            n = int(str( self._gui.getObj("txtCalibrationFrames").text() ))
            square_size = float(str( self._gui.getObj("txtCalibrationSquareSize").text() ))
            
            # calculate distortion
            pattern_size = (x, y)
            ret = self.__calibrateCorners(pattern_size, n, square_size)
            
            if ret != None:
                camera_matrix, dist_coefs = ret
                self.__camera_matrix, self.__dist_coefs = camera_matrix, dist_coefs
            
            # undistort image
            img = self.undistortImage(self._img)
            self.__imgScene = img
            
            self._gui.status("Searching for boders to crop image ...")
            
            # get corners
            if ret != None:
                found = False
                frames = 0;
                tries = 0;
                while not found and frames < n and tries < 10:
                    img = self.undistortImage(self._img)
                    found, corners = getChessBoardCorners( img, pattern_size )
                    if found:
                        frames += 1
                    tries += 1
                
                if found:
                    self.__corners = getImageSizeFromCorners(corners)        
                
            # crop image
            self.__imgScene = self.cropImage(img)                    
            self.__calibrated = True    
            
        # set calibration flag
        self._gui.status("Calibration finished.")
                   
        
        self.__calibrating = False 
        
        
    def __calibrateCorners(self, pattern_size, n, square_size):
        '''
        Calibrates corners of chessboard
        @return: camera_matrix, dist_coefs
        '''
        pattern_points = zeros( (prod(pattern_size), 3), float32 )
        pattern_points[:,:2] = indices(pattern_size).T.reshape(-1, 2)
        pattern_points *= square_size

        obj_points = []
        img_points = []        
        frames = 0;
        tries = 0
        lastCount = self._imgCounter;
        
        # detect pattern
        while frames < n and tries < 10:
            img = self._img
            
            img = cvtColor(img, COLOR_RGB2GRAY)
            img = threshold(img, 40, 255, THRESH_BINARY)[1]
            img = cvtColor(img, COLOR_GRAY2RGB)
            self.__imgScene = img
            
            from time import sleep
            sleep(1)
            
            if lastCount != self._imgCounter:
                # get corners   
                print "getchessboardcorners"             
                found, corners = getChessBoardCorners( img, pattern_size )
                print "found", found
                
                # check if corners found
                if found:
                    frames += 1
                    
                    # get more detailed points and add them to list
                    img_points.append( corners.reshape(-1, 2) )
                    obj_points.append( pattern_points )
                    
                    # draw corners
                    drawChessboardCorners( img, pattern_size, corners, found )
                    self.__imgScene = img
                    tries = 0
                tries += 1
                    
        # get cmera values
        if img != None and len(obj_points) > 0 and len(img_points) > 0:
            return getCalibrationData(img, obj_points, img_points )
    
    def cropImage(self, img=None):
        '''
        Crops image if corners available
        @return: croped Image
        '''
        
        
        if self.__corners != None and img != None and ( self._gui.getObj("chkCropImg").isChecked() or self._gui.getObj("chkCropImgManual").isChecked() ) :            
            
            # default settings for manual crop
            try:
                borderX = int( str(self._gui.getObj("txtBorderLR").text()) ) 
                borderY = int( str(self._gui.getObj("txtBorderTB").text()) )
            except:
                borderX = 0
                borderY = 0
            
            xmin = (img.shape[1]-1)/2 - borderX
            xmax = (img.shape[1]-1)/2 + borderX
            ymin = (img.shape[0]-1)/2 - borderY
            ymax = (img.shape[0]-1)/2 + borderY
            
            
            # settings for automatic crop
            if self._gui.getObj("chkCropImg").isChecked():
                border = str( self._gui.getObj("txtCalibrationBorders").text() ).replace(",", ".")
                try:
                    borders = int( float(border)/100.0 )
                except:
                    borders = 0        
                borderX = int(img.shape[1] * borders)
                borderY = int(img.shape[0] * borders)
                
                xmin = int(self.__corners[0][0])
                xmax = int(self.__corners[0][1])
                ymin = int(self.__corners[1][0])
                ymax = int(self.__corners[1][1])
            
            # check new borders
            if xmin-borderX > 0:
                xmin = xmin-borderX
            else:
                xmin = 0    
                             
            if ymin-borderY > 0:
                ymin = ymin-borderY
            else:
                ymin = 0    
                             
            if xmax+borderX <= img.shape[1]:
                xmax = xmax+borderX
            else:
                xmax = img.shape[1]-1 
                                
            if ymax+borderY <= img.shape[0]:
                ymax = ymax+borderY
            else:
                ymax = img.shape[0]-1
            
            # conversion before
            if self._gui.getObj("chkCropConvBefore").isChecked():
                img = cvtColor( img, COLOR_BGR2RGB )
                
            # crop image
            try:
                img = img[ymin:ymax, xmin:xmax]
            
                # conversion after
                img = cvtColor( img, COLOR_BGR2RGB )
            except:
                print "ERROR"
        
        return img
            
    def __saveImg(self):
        '''
        Saves current image
        '''
        if self.__imgScene != None:
            img = self.__imgScene
            
            # stop video
            active = self._imageGrabber.isActive()
            self._imageGrabber.stopVideo()
            
            # open file dialog
            options = copy(self._gui.dialogOptionsDef)
            options['type'] = self._gui.dialogTypes['FileSave']
            options['filetypes'] = "JPG (*.jpg)"
            options['title'] = "Save current frame as"
            src = str( self._gui.dialog(options) )
            
            # check filepath and save
            if len(src) > 0:
                if not src.endswith(".jpg"):
                    src = src+".jpg"
                self._gui.status( "write to " + src )
                cvtColor(img, COLOR_BGR2RGB)
                imwrite(src, img)
            
            # reset video streaming
            if active:
                self._imageGrabber.startVideo()
    
    def undistortImage(self, img=None):
        '''
        Undistorts image
        @return: Image
        '''
        if self.__camera_matrix != None and self.__dist_coefs != None and img != None:
            return undistortImg( img, self.__camera_matrix, self.__dist_coefs )
        return img
    
    def __loadConfiguration(self):
        '''
        Loads configuration
        '''
        # stop video
        active = self._imageGrabber.isActive()
        self._imageGrabber.stopVideo()
        
        # get path
        options = copy(self._gui.dialogOptionsDef)
        options['filetypes'] = "config file (*cfg)"
        src = str( self._gui.dialog(options) )
        
        if self.__loadConfigData(src):
            self._gui.status("Distortion config loaded.")
            
        # restore video streaming mode
        if active:
            self._imageGrabber.startVideo()
            
    
    def __loadConfigData(self, src):
        '''
        Loads data from config file
        '''
        if len(src) > 0 and isfile(src):           
            # load file
            data = load( open(src, "rb") )
            
            if 'camera_matrix' in data:
                self.__camera_matrix = data['camera_matrix']
            if 'dist_coefs' in data:
                self.__dist_coefs = data['dist_coefs']
            if 'corners' in data:
                self.__corners = data['corners']
            if 'calibrated' in data:
                self.__calibrated = data['calibrated']
            if 'cropmanual' in data:
                self._gui.getObj("chkCropImgManual").setChecked( data['cropmanual'] )
            if 'cropauto' in data:
                self._gui.getObj("chkCropImg").setChecked( data['cropauto'] )
            if 'cropBorderLR' in data:
                self._gui.getObj("txtBorderLR").setText( data['cropBorderLR'] )
            if 'cropBorderTB' in data:
                self._gui.getObj("txtBorderTB").setText( data['cropBorderTB'] )
            if 'cropauto' in data:
                self._gui.getObj("txtCalibrationBorders").setText( data['cropauto'] )
            if 'squareSize' in data:
                self._gui.getObj("txtCalibrationSquareSize").setText( data['squareSize'] )
            if 'calibFrames' in data:
                self._gui.getObj("txtCalibrationFrames").setText( data['calibFrames'] )
            if 'patternX' in data:
                self._gui.getObj("txtPatternX").setText( data['patternX'] )
            if 'patternY' in data:
                self._gui.getObj("txtPatternY").setText( data['patternY'] )
            
            return True
        
        return False
            
                
    def __saveConfiguration(self):
        '''
        Saves configuration
        '''
        # stop video
        active = self._imageGrabber.isActive()
        self._imageGrabber.stopVideo()
        
        options = copy(self._gui.dialogOptionsDef)
        options['type'] = self._gui.dialogTypes['FileSave']
        options['title'] = "Save configuration"
        options['filetypes'] = "Configuration (*cfg *mr)"
        src = str( self._gui.dialog(options) )
        
        if len(src) > 0:
            # check path
            if not src.endswith(".cfg"):
                src += ".cfg"
            
            # save data to file     
            data = {'camera_matrix': self.__camera_matrix,
                    'dist_coefs': self.__dist_coefs,
                    'corners': self.__corners,
                    'calibrated': self.__calibrated,
                    'cropmanual': self._gui.getObj("chkCropImgManual").isChecked(),
                    'cropauto:': self._gui.getObj("chkCropImg").isChecked(),
                    'cropBorder': str( self._gui.getObj("txtCalibrationBorders").text() ),
                    'cropBorderLR': str( self._gui.getObj("txtBorderLR").text() ),
                    'cropBorderTB': str( self._gui.getObj("txtBorderTB").text() ),
                    'squareSize': str( self._gui.getObj("txtCalibrationSquareSize").text() ),
                    'calibFrames': str( self._gui.getObj("txtCalibrationFrames").text() ),
                    'patternX': str( self._gui.getObj("txtPatternX").text() ),
                    'patternY': str( self._gui.getObj("txtPatternY").text() )}
                        
            dump( data, open(src, "wb") )            
            self._gui.status("Configuration saved to: " + src)
            
        # restore video streaming mode
        if active:
            self._imageGrabber.startVideo()
            
    def _showImage(self):
        '''
        Shows image
        '''
        if not self.isCalibrated() or self.isCalibrating():
            self._updateScene( self.__gview, self.__scene, self.__imgScene, convert=False, keepRatio=True )
Esempio n. 23
0
class BrushingModel(QObject):
    brushSizeChanged = pyqtSignal(int)
    brushColorChanged = pyqtSignal(QColor)
    brushStrokeAvailable = pyqtSignal(QPointF, object)
    drawnNumberChanged = pyqtSignal(int)

    minBrushSize = 1
    maxBrushSize = 61
    defaultBrushSize = 3
    defaultDrawnNumber = 1
    defaultColor = Qt.white
    erasingColor = Qt.black
    erasingNumber = 100

    def __init__(self, parent=None):
        QObject.__init__(self, parent=parent)
        self.sliceRect = None
        self.bb = QRect()  #bounding box enclosing the drawing
        self.brushSize = self.defaultBrushSize
        self.drawColor = self.defaultColor
        self._temp_color = None
        self._temp_number = None
        self.drawnNumber = self.defaultDrawnNumber

        self.pos = None
        self.erasing = False
        self._hasMoved = False

        self.drawOnto = None

        #an empty scene, where we add all drawn line segments
        #a QGraphicsLineItem, and which we can use to then
        #render to an image
        self.scene = QGraphicsScene()

    def toggleErase(self):
        self.erasing = not (self.erasing)
        if self.erasing:
            self.setErasing()
        else:
            self.disableErasing()

    def setErasing(self):
        self.erasing = True
        self._temp_color = self.drawColor
        self._temp_number = self.drawnNumber
        self.setBrushColor(self.erasingColor)
        self.brushColorChanged.emit(self.erasingColor)
        self.setDrawnNumber(self.erasingNumber)

    def disableErasing(self):
        self.erasing = False
        self.setBrushColor(self._temp_color)
        self.brushColorChanged.emit(self.drawColor)
        self.setDrawnNumber(self._temp_number)

    def setBrushSize(self, size):
        self.brushSize = size
        self.brushSizeChanged.emit(self.brushSize)

    def setDrawnNumber(self, num):
        self.drawnNumber = num
        self.drawnNumberChanged.emit(num)

    def getBrushSize(self):
        return self.brushSize

    def brushSmaller(self):
        b = self.brushSize
        if b > self.minBrushSize:
            self.setBrushSize(b - 1)

    def brushBigger(self):
        b = self.brushSize
        if self.brushSize < self.maxBrushSize:
            self.setBrushSize(b + 1)

    def setBrushColor(self, color):
        self.drawColor = color
        self.brushColorChanged.emit(self.drawColor)

    def beginDrawing(self, pos, sliceRect):
        '''

        pos -- QPointF-like
        '''
        self.sliceRect = sliceRect
        self.scene.clear()
        self.bb = QRect()
        self.pos = QPointF(pos.x(), pos.y())
        self._hasMoved = False

    def endDrawing(self, pos):
        has_moved = self._hasMoved  # _hasMoved will change after calling moveTo
        if has_moved:
            self.moveTo(pos)
        else:
            assert (self.pos == pos)
            self.moveTo(QPointF(pos.x() + 0.0001,
                                pos.y() + 0.0001))  # move a little

        # Qt seems to use strange rules for determining which pixels to set when rendering a brush stroke to a QImage.
        # We seem to get better results if we do the following:
        # 1) Slightly offset the source window because apparently there is a small shift in the data
        # 2) Render the scene to an image that is MUCH larger than the scene resolution (4x by 4x)
        # 3) Downsample each 4x4 patch from the large image back to a single pixel in the final image,
        #     applying some threshold to determine if the final pixel is on or off.

        tempi = QImage(QSize(4 * self.bb.width(), 4 * self.bb.height()),
                       QImage.Format_ARGB32_Premultiplied)  #TODO: format
        tempi.fill(0)
        painter = QPainter(tempi)
        # Offset the source window.  At first I thought the right offset was 0.5, because
        #  that would seem to make sure points are rounded to pixel CENTERS, but
        #  experimentation indicates that 0.25 is slightly better for some reason...
        source_rect = QRectF(QPointF(self.bb.x() + 0.25,
                                     self.bb.y() + 0.25),
                             QSizeF(self.bb.width(), self.bb.height()))
        target_rect = QRectF(QPointF(0, 0),
                             QSizeF(4 * self.bb.width(), 4 * self.bb.height()))
        self.scene.render(painter, target=target_rect, source=source_rect)
        painter.end()

        # Now downsample: convert each 4x4 patch into a single pixel by summing and dividing
        ndarr = qimage2ndarray.rgb_view(tempi)[:, :, 0].astype(int)
        ndarr = ndarr.reshape((ndarr.shape[0], ) + (ndarr.shape[1] // 4, ) +
                              (4, ))
        ndarr = ndarr.sum(axis=-1)
        ndarr = ndarr.transpose()
        ndarr = ndarr.reshape((ndarr.shape[0], ) + (ndarr.shape[1] // 4, ) +
                              (4, ))
        ndarr = ndarr.sum(axis=-1)
        ndarr = ndarr.transpose()
        ndarr //= 4 * 4

        downsample_threshold = (7. / 16) * 255
        labels = numpy.where(ndarr >= downsample_threshold,
                             numpy.uint8(self.drawnNumber), numpy.uint8(0))
        labels = labels.swapaxes(0, 1)
        assert labels.shape[0] == self.bb.width()
        assert labels.shape[1] == self.bb.height()

        ##
        ## ensure that at least one pixel is label when the brush size is 1
        ##
        ## this happens when the user just clicked without moving
        ## in that case the lineitem will be so tiny, that it won't be rendered
        ## into a single pixel by the code above
        if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(
                labels) == 0:
            labels[labels.shape[0] // 2,
                   labels.shape[1] // 2] = self.drawnNumber

        self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()),
                                       labels)

    def dumpDraw(self, pos):
        res = self.endDrawing(pos)
        self.beginDrawing(pos, self.sliceRect)
        return res

    def moveTo(self, pos):
        #data coordinates
        oldX, oldY = self.pos.x(), self.pos.y()
        x, y = pos.x(), pos.y()

        line = QGraphicsLineItem(oldX, oldY, x, y)
        line.setPen(
            QPen(QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap,
                 Qt.RoundJoin))
        self.scene.addItem(line)
        self._hasMoved = True

        #update bounding Box
        if not self.bb.isValid():
            self.bb = QRect(QPoint(oldX, oldY), QSize(1, 1))
        #grow bounding box
        self.bb.setLeft(
            min(self.bb.left(), max(0, x - self.brushSize // 2 - 1)))
        self.bb.setRight(
            max(self.bb.right(),
                min(self.sliceRect[0] - 1, x + self.brushSize // 2 + 1)))
        self.bb.setTop(min(self.bb.top(), max(0, y - self.brushSize // 2 - 1)))
        self.bb.setBottom(
            max(self.bb.bottom(),
                min(self.sliceRect[1] - 1, y + self.brushSize // 2 + 1)))

        #update/move position
        self.pos = pos
Esempio n. 24
0
class TreeDialog(QDialog):
    def __init__(self):
        import treedialog
        QDialog.__init__(self)
        self.ui = treedialog.Ui_Dialog()
        self.ui.setupUi(self)
        self.ui.draw_buton.clicked.connect(self.new_anim)
        self.scene = QGraphicsScene()
        self.ui.image.setScene(self.scene)
        self.ui.image.setRenderHints(QPainter.HighQualityAntialiasing)

    def get_params(self):
        params = dict()
        params["branch_split"] = self.ui.branch_split.value()
        params["branch_after_range"] = (self.ui.branch_after_min.value(), self.ui.branch_after_max.value())
        params["branch_split_var"] = self.ui.branch_split_var.value()
        params["gravity"] = self.ui.gravity.value()
        params["down_die_probability"] = self.ui.down_die_probability.value()
        params["down_damping_x"] = self.ui.down_damping_x.value()
        params["down_damping_y"] = self.ui.down_damping_x.value()
        params["start_branches"] = self.ui.start_branches.value()
        params["keep_central"] = self.ui.keep_central.value()
        params["color"] = QColor(self.ui.r.value() * 255, self.ui.g.value() * 255, self.ui.b.value() * 255)
        params["color_speed"] = self.ui.color_speed.value()
        params["painter_thickness"] = self.ui.painter_thickness.value()
        params["painter_generations"] = self.ui.painter_generations.value()
        start_rand = [random.uniform(-1, 1) * self.ui.v_start_var.value() for i in range(2)]
        params["v_start"] = complex(self.ui.v_start_x.value()+start_rand[0], self.ui.v_start_y.value()+start_rand[1])
        return params

    def new_anim(self):
        image = None
        painter_id = random.randint(0, 2**32)
        self.active_painer = painter_id
        index = 0
        every = self.ui.repaint.value()

        self.scene.clear()

        tree_count = self.ui.tree_count.value()
        need_spacing = 65
        used_locations = []
        for tree_index in range(tree_count):
            z_range = 80
            base_z = random.uniform(-z_range, z_range)

            def make_base():
                return complex(10 + random.uniform(-350 + 150*tree_count, 350 + 150*tree_count), base_z)
            def closest_distance_to_used(base):
                return min([np.abs(np.real(base - item)) for item in used_locations])
            base_location = make_base()
            while not len(used_locations) == 0 and closest_distance_to_used(base_location) < need_spacing:
                base_location = make_base()

            used_locations.append(base_location)
            scale = 1.0 + 0.75 * ((z_range - base_z) / (2*z_range)) ** 2
            self.tree = Tree(self.get_params(), base_location=base_location, scale=scale)
            for iteration in self.tree.grow_iterations(self.ui.generations.value(), yield_every=every):
                self.tree.draw(self.scene, incremental=True)
                self.ui.progress.setText("Working ... displayed frame: {0}".format(index))

                gradient = QLinearGradient(self.scene.itemsBoundingRect().topLeft(),
                                           self.scene.itemsBoundingRect().bottomLeft())
                gradient.setColorAt(0.4, QColor(0, 0, 0))
                gradient.setColorAt(0, QColor(25, 25, 25))
                self.scene.setBackgroundBrush(QBrush(gradient))

                self.ui.image.repaint()
                QApplication.processEvents()
                index += every
                if self.active_painer != painter_id:
                    return

        self.ui.image.fitInView(self.scene.itemsBoundingRect(), 1)
        d = GrassDrawer(self.ui.image)
        d.draw_some_grass(150 + 75*tree_count)
        #self.ui.image.fitInView(self.scene.itemsBoundingRect(), 1)
        self.ui.progress.setText("Done. Displayed frame: {0}".format(index))
Esempio n. 25
0
class OWQualityControl(widget.OWWidget):
    name = "Quality Control"
    description = "Experiment quality control"
    icon = "../widgets/icons/QualityControl.svg"
    priority = 5000

    inputs = [("Experiment Data", Orange.data.Table, "set_data")]
    outputs = []

    DISTANCE_FUNCTIONS = [("Distance from Pearson correlation",
                           dist_pcorr),
                          ("Euclidean distance",
                           dist_eucl),
                          ("Distance from Spearman correlation",
                           dist_spearman)]

    settingsHandler = SetContextHandler()

    split_by_labels = settings.ContextSetting({})
    sort_by_labels = settings.ContextSetting({})

    selected_distance_index = settings.Setting(0)

    def __init__(self, parent=None):
        super().__init__(parent)

        ## Attributes
        self.data = None
        self.distances = None
        self.groups = None
        self.unique_pos = None
        self.base_group_index = 0

        ## GUI
        box = gui.widgetBox(self.controlArea, "Info")
        self.info_box = gui.widgetLabel(box, "\n")

        ## Separate By box
        box = gui.widgetBox(self.controlArea, "Separate By")
        self.split_by_model = itemmodels.PyListModel(parent=self)
        self.split_by_view = QListView()
        self.split_by_view.setSelectionMode(QListView.ExtendedSelection)
        self.split_by_view.setModel(self.split_by_model)
        box.layout().addWidget(self.split_by_view)

        self.split_by_view.selectionModel().selectionChanged.connect(
            self.on_split_key_changed)

        ## Sort By box
        box = gui.widgetBox(self.controlArea, "Sort By")
        self.sort_by_model = itemmodels.PyListModel(parent=self)
        self.sort_by_view = QListView()
        self.sort_by_view.setSelectionMode(QListView.ExtendedSelection)
        self.sort_by_view.setModel(self.sort_by_model)
        box.layout().addWidget(self.sort_by_view)

        self.sort_by_view.selectionModel().selectionChanged.connect(
            self.on_sort_key_changed)

        ## Distance box
        box = gui.widgetBox(self.controlArea, "Distance Measure")
        gui.comboBox(box, self, "selected_distance_index",
                     items=[name for name, _ in self.DISTANCE_FUNCTIONS],
                     callback=self.on_distance_measure_changed)

        self.scene = QGraphicsScene()
        self.scene_view = QGraphicsView(self.scene)
        self.scene_view.setRenderHints(QPainter.Antialiasing)
        self.scene_view.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.mainArea.layout().addWidget(self.scene_view)

        self.scene_view.installEventFilter(self)

        self._disable_updates = False
        self._cached_distances = {}
        self._base_index_hints = {}
        self.main_widget = None

        self.resize(800, 600)

    def clear(self):
        """Clear the widget state."""
        self.data = None
        self.distances = None
        self.groups = None
        self.unique_pos = None

        with disable_updates(self):
            self.split_by_model[:] = []
            self.sort_by_model[:] = []

        self.main_widget = None
        self.scene.clear()
        self.info_box.setText("\n")
        self._cached_distances = {}

    def set_data(self, data=None):
        """Set input experiment data."""
        self.closeContext()
        self.clear()

        self.error(0)
        self.warning(0)

        if data is not None:
            keys = self.get_suitable_keys(data)
            if not keys:
                self.error(0, "Data has no suitable feature labels.")
                data = None

        self.data = data
        if data is not None:
            self.on_new_data()

    def update_label_candidates(self):
        """Update the label candidates selection GUI 
        (Group/Sort By views).

        """
        keys = self.get_suitable_keys(self.data)
        with disable_updates(self):
            self.split_by_model[:] = keys
            self.sort_by_model[:] = keys

    def get_suitable_keys(self, data):
        """ Return suitable attr label keys from the data where
        the key has at least two unique values in the data.

        """
        attrs = [attr.attributes.items() for attr in data.domain.attributes]
        attrs = reduce(operator.iadd, attrs, [])
        # in case someone put non string values in attributes dict
        attrs = [(str(key), str(value)) for key, value in attrs]
        attrs = set(attrs)
        values = defaultdict(set)
        for key, value in attrs:
            values[key].add(value)
        keys = [key for key in values if len(values[key]) > 1]
        return keys

    def selected_split_by_labels(self):
        """Return the current selected split labels.
        """
        sel_m = self.split_by_view.selectionModel()
        indices = [r.row() for r in sel_m.selectedRows()]
        return [self.sort_by_model[i] for i in indices]

    def selected_sort_by_labels(self):
        """Return the current selected sort labels
        """
        sel_m = self.sort_by_view.selectionModel()
        indices = [r.row() for r in sel_m.selectedRows()]
        return [self.sort_by_model[i] for i in indices]

    def selected_distance(self):
        """Return the selected distance function.
        """
        return self.DISTANCE_FUNCTIONS[self.selected_distance_index][1]

    def selected_base_group_index(self):
        """Return the selected base group index
        """
        return self.base_group_index

    def selected_base_indices(self, base_group_index=None):
        indices = []
        for g, ind in self.groups:
            if base_group_index is None:
                label = group_label(self.selected_split_by_labels(), g)
                ind = [i for i in ind if i is not None]
                i = self._base_index_hints.get(label, ind[0] if ind else None)
            else:
                i = ind[base_group_index]
            indices.append(i)
        return indices

    def on_new_data(self):
        """We have new data and need to recompute all.
        """
        self.closeContext()

        self.update_label_candidates()
        self.info_box.setText(
            "%s genes \n%s experiments" %
            (len(self.data),  len(self.data.domain.attributes))
        )

        self.base_group_index = 0

        keys = self.get_suitable_keys(self.data)
        self.openContext(keys)

        ## Restore saved context settings (split/sort selection)
        split_by_labels = self.split_by_labels
        sort_by_labels = self.sort_by_labels

        def select(model, selection_model, selected_items):
            """Select items in a Qt item model view
            """
            all_items = list(model)
            try:
                indices = [all_items.index(item) for item in selected_items]
            except:
                indices = []
            for ind in indices:
                selection_model.select(model.index(ind),
                                       QItemSelectionModel.Select)

        with disable_updates(self):
            select(self.split_by_view.model(),
                   self.split_by_view.selectionModel(),
                   split_by_labels)

            select(self.sort_by_view.model(),
                   self.sort_by_view.selectionModel(),
                   sort_by_labels)

        with widget_disable(self):
            self.split_and_update()

    def on_split_key_changed(self, *args):
        """Split key has changed
        """
        with widget_disable(self):
            if not self._disable_updates:
                self.base_group_index = 0
                self.split_by_labels = self.selected_split_by_labels()
                self.split_and_update()

    def on_sort_key_changed(self, *args):
        """Sort key has changed
        """
        with widget_disable(self):
            if not self._disable_updates:
                self.base_group_index = 0
                self.sort_by_labels = self.selected_sort_by_labels()
                self.split_and_update()

    def on_distance_measure_changed(self):
        """Distance measure has changed
        """
        if self.data is not None:
            with widget_disable(self):
                self.update_distances()
                self.replot_experiments()

    def on_view_resize(self, size):
        """The view with the quality plot has changed
        """
        if self.main_widget:
            current = self.main_widget.size()
            self.main_widget.resize(size.width() - 6,
                                    current.height())

            self.scene.setSceneRect(self.scene.itemsBoundingRect())

    def on_rug_item_clicked(self, item):
        """An ``item`` in the quality plot has been clicked.
        """
        update = False
        sort_by_labels = self.selected_sort_by_labels()
        if sort_by_labels and item.in_group:
            ## The item is part of the group
            if item.group_index != self.base_group_index:
                self.base_group_index = item.group_index
                update = True

        else:
            if sort_by_labels:
                # If the user clicked on an background item it
                # invalidates the sorted labels selection
                with disable_updates(self):
                    self.sort_by_view.selectionModel().clear()
                    update = True

            index = item.index
            group = item.group
            label = group_label(self.selected_split_by_labels(), group)

            if self._base_index_hints.get(label, 0) != index:
                self._base_index_hints[label] = index
                update = True

        if update:
            with widget_disable(self):
                self.split_and_update()

    def eventFilter(self, obj, event):
        if obj is self.scene_view and event.type() == QEvent.Resize:
            self.on_view_resize(event.size())
        return super().eventFilter(obj, event)

    def split_and_update(self):
        """
        Split the data based on the selected sort/split labels
        and update the quality plot.

        """
        split_labels = self.selected_split_by_labels()
        sort_labels = self.selected_sort_by_labels()

        self.warning(0)
        if not split_labels:
            self.warning(0, "No separate by label selected.")

        self.groups, self.unique_pos = \
                exp.separate_by(self.data, split_labels,
                                consider=sort_labels,
                                add_empty=True)

        self.groups = sorted(self.groups.items(),
                             key=lambda t: list(map(float_if_posible, t[0])))
        self.unique_pos = sorted(self.unique_pos.items(),
                                 key=lambda t: list(map(float_if_posible, t[0])))

        if self.groups:
            if sort_labels:
                group_base = self.selected_base_group_index()
                base_indices = self.selected_base_indices(group_base)
            else:
                base_indices = self.selected_base_indices()
            self.update_distances(base_indices)
            self.replot_experiments()

    def get_cached_distances(self, measure):
        if measure not in self._cached_distances:
            attrs = self.data.domain.attributes
            mat = numpy.zeros((len(attrs), len(attrs)))

            self._cached_distances[measure] = \
                (mat, set(zip(range(len(attrs)), range(len(attrs)))))

        return self._cached_distances[measure]

    def get_cached_distance(self, measure, i, j):
        matrix, computed = self.get_cached_distances(measure)
        key = (i, j) if i < j else (j, i)
        if key in computed:
            return matrix[i, j]
        else:
            return None

    def get_distance(self, measure, i, j):
        d = self.get_cached_distance(measure, i, j)
        if d is None:
            vec_i = take_columns(self.data, [i])
            vec_j = take_columns(self.data, [j])
            d = measure(vec_i, vec_j)

            mat, computed = self.get_cached_distances(measure)
            mat[i, j] = d
            key = key = (i, j) if i < j else (j, i)
            computed.add(key)
        return d

    def store_distance(self, measure, i, j, dist):
        matrix, computed = self.get_cached_distances(measure)
        key = (i, j) if i < j else (j, i)
        matrix[j, i] = matrix[i, j] = dist
        computed.add(key)

    def update_distances(self, base_indices=()):
        """Recompute the experiment distances.
        """
        distance = self.selected_distance()
        if base_indices == ():
            base_group_index = self.selected_base_group_index()
            base_indices = [ind[base_group_index] \
                            for _, ind in self.groups]

        assert(len(base_indices) == len(self.groups))

        base_distances = []
        attributes = self.data.domain.attributes
        pb = gui.ProgressBar(self, len(self.groups) * len(attributes))

        for (group, indices), base_index in zip(self.groups, base_indices):
            # Base column of the group
            if base_index is not None:
                base_vec = take_columns(self.data, [base_index])
                distances = []
                # Compute the distances between base column
                # and all the rest data columns.
                for i in range(len(attributes)):
                    if i == base_index:
                        distances.append(0.0)
                    elif self.get_cached_distance(distance, i, base_index) is not None:
                        distances.append(self.get_cached_distance(distance, i, base_index))
                    else:
                        vec_i = take_columns(self.data, [i])
                        dist = distance(base_vec, vec_i)
                        self.store_distance(distance, i, base_index, dist)
                        distances.append(dist)
                    pb.advance()

                base_distances.append(distances)
            else:
                base_distances.append(None)

        pb.finish()
        self.distances = base_distances

    def replot_experiments(self):
        """Replot the whole quality plot.
        """
        self.scene.clear()
        labels = []

        max_dist = numpy.nanmax(list(filter(None, self.distances)))
        rug_widgets = []

        group_pen = QPen(Qt.black)
        group_pen.setWidth(2)
        group_pen.setCapStyle(Qt.RoundCap)
        background_pen = QPen(QColor(0, 0, 250, 150))
        background_pen.setWidth(1)
        background_pen.setCapStyle(Qt.RoundCap)

        main_widget = QGraphicsWidget()
        layout = QGraphicsGridLayout()
        attributes = self.data.domain.attributes
        if self.data is not None:
            for (group, indices), dist_vec in zip(self.groups, self.distances):
                indices_set = set(indices)
                rug_items = []
                if dist_vec is not None:
                    for i, attr in enumerate(attributes):
                        # Is this a within group distance or background
                        in_group = i in indices_set
                        if in_group:
                            rug_item = ClickableRugItem(dist_vec[i] / max_dist,
                                           1.0, self.on_rug_item_clicked)
                            rug_item.setPen(group_pen)
                            tooltip = experiment_description(attr)
                            rug_item.setToolTip(tooltip)
                            rug_item.group_index = indices.index(i)
                            rug_item.setZValue(rug_item.zValue() + 1)
                        else:
                            rug_item = ClickableRugItem(dist_vec[i] / max_dist,
                                           0.85, self.on_rug_item_clicked)
                            rug_item.setPen(background_pen)
                            tooltip = experiment_description(attr)
                            rug_item.setToolTip(tooltip)

                        rug_item.group = group
                        rug_item.index = i
                        rug_item.in_group = in_group

                        rug_items.append(rug_item)

                rug_widget = RugGraphicsWidget(parent=main_widget)
                rug_widget.set_rug(rug_items)

                rug_widgets.append(rug_widget)

                label = group_label(self.selected_split_by_labels(), group)
                label_item = QGraphicsSimpleTextItem(label, main_widget)
                label_item = GraphicsSimpleTextLayoutItem(label_item, parent=layout)
                label_item.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
                labels.append(label_item)

        for i, (label, rug_w) in enumerate(zip(labels, rug_widgets)):
            layout.addItem(label, i, 0, Qt.AlignVCenter)
            layout.addItem(rug_w, i, 1)
            layout.setRowMaximumHeight(i, 30)

        main_widget.setLayout(layout)
        self.scene.addItem(main_widget)
        self.main_widget = main_widget
        self.rug_widgets = rug_widgets
        self.labels = labels
        self.on_view_resize(self.scene_view.size())
class CoLocation(QMainWindow, Ui_MainWindow):
    flag = True
    categories = {}
    valid_images = ["jpg","png","tga", "pgm", "jpeg"]
    valid_videos = ["mp4", "avi"]
    edge_threshold = 100
    to_disp = [] 
    
    def __init__(self, ):
        super(CoLocation, self).__init__()        #initialise from the ui designed by Designer App
        self.setupUi(self)
        self.setupUi_custom()
        
    def update_categories(self):
        #update selected categories
        for radiobox in self.findChildren(QtGui.QRadioButton):
            self.categories[radiobox.text()] = radiobox.isChecked()
    
    def setupUi_custom(self,):    
        
        self.scene = QGraphicsScene()
        self.scene2 = QGraphicsScene()
        #TODO [WEIRD PROBLEM] QPixmap needs to be called at least once with JPG image before tensorFlow, otherwise program crashes
        self.scene.addPixmap(QPixmap(os.getcwd()+"/demo.jpg").scaled(self.graphicsView.size(), QtCore.Qt.KeepAspectRatio))
        self.graphicsView.setScene(self.scene)  
        
        import Yolo_module as yolo
        self.classifier = yolo.YOLO_TF()
        #Create thread for heavy processing and tensorflow, pass the instance of itself to modify GUI
        self.image_thread = ImageThread(self, self.classifier)
        #add connect SIGNAL here 
                
        self.pushButton.clicked.connect(self.selectFile)        
        self.horizontalSlider.valueChanged.connect(self.updateLCD)
        self.pushButton_2.clicked.connect(self.image_thread.disp_graph)
        self.pushButton_3.clicked.connect(self.selectFile_from_folder)
        
        #Add blank canvas initially
        fig1 = Figure()            
        self.addmpl(fig1)

    def updateLCD(self):
        #update edge_threshold variable based on slider
        self.edge_threshold = self.horizontalSlider.value()
        self.lcdNumber.display(self.edge_threshold)        
        
    def selectFile(self):  
        #Clear previous image displays        
        self.scene.clear()
        self.scene2.clear()
        self.update_categories()
             
        filename = QFileDialog.getOpenFileName(directory = '/home/yash/Downloads/Pascal VOC 2012/samples')
        self.lineEdit.setText(filename)
        
        if filename.split('.')[1] in self.valid_videos:
            self.image_thread.temp = filename #disp_video(filename)
            self.image_thread.start()
        
        elif filename.split('.')[1] in self.valid_images:
            self.image_thread.disp_img(filename = filename)
            self.image_thread.disp_graph()
            
        else:
            print("Invalid file format")
        
    def selectFile_from_folder(self):
        #Read all the images in the folder
        path = QFileDialog.getExistingDirectory(None, 'Select a folder:', '/home/yash/Downloads/Pascal VOC 2012', QtGui.QFileDialog.ShowDirsOnly)
        self.lineEdit_2.setText(path)
        
        for f in os.listdir(path):              #list all the files in the folder
            ext = f.split('.')[1]        #get the file extension
            if ext.lower() not in self.valid_images: #check if the extension is valid for the image
                continue
            filename = path+'/'+f               #create the path of the image
            print(filename)
            
            self.image_thread.tag_image(filename, batch = True)
        
        #clear the image regions during batch upload
        self.scene.clear()
        self.scene2.clear()    
        
        self.image_thread.disp_graph(batch = True)
        
    def addmpl(self, fig):
        #Add figure to canvas and widget
        self.canvas = FigureCanvas(fig)
        self.mplvl.addWidget(self.canvas)
        self.canvas.draw()
 
    def rmmpl(self,):
        #remove the canvas and widget
        self.mplvl.removeWidget(self.canvas)
        self.canvas.close()
class QtImageViewer(QGraphicsView):
    """ PyQt image viewer widget for a QPixmap in a QGraphicsView scene with mouse zooming and panning.

    Displays a QImage or QPixmap (QImage is internally converted to a QPixmap).
    To display any other image format, you must first convert it to a QImage or QPixmap.

    Some useful image format conversion utilities:
        qimage2ndarray: NumPy ndarray <==> QImage    (https://github.com/hmeine/qimage2ndarray)
        ImageQt: PIL Image <==> QImage  (https://github.com/python-pillow/Pillow/blob/master/PIL/ImageQt.py)

    """

    # Mouse button signals emit image scene (x, y) coordinates.
    # !!! For image (row, column) matrix indexing, row = y and column = x.
    hover = pyqtSignal(float, float)
    leftMouseButtonPressed = pyqtSignal(float, float, object)
    rightMouseButtonPressed = pyqtSignal(float, float)
    leftMouseButtonReleased = pyqtSignal(float, float)
    leftMouseButtonDoubleClicked = pyqtSignal(float, float)
    rightMouseButtonDoubleClicked = pyqtSignal(float, float)
    areaSelected = pyqtSignal(float, float, float, float)
    pixelSelected = pyqtSignal(float, float)

    def __init__(self, parent=None, center=None, thumbnail=False):
        QGraphicsView.__init__(self, parent)

        # Image is displayed as a QPixmap in a QGraphicsScene attached to this QGraphicsView.
        self.scene = QGraphicsScene()
        self.setScene(self.scene)

        # Store a local handle to the scene's current image pixmap.
        self._pixmapHandle = None

        # Image aspect ratio mode.
        # !!! ONLY applies to full image. Aspect ratio is always ignored when zooming.
        #   Qt.IgnoreAspectRatio: Scale image to fit viewport.
        #   Qt.KeepAspectRatio: Scale image to fit inside viewport, preserving aspect ratio.
        #   Qt.KeepAspectRatioByExpanding: Scale image to fill the viewport, preserving aspect ratio.
        self.aspectRatioMode = Qt.KeepAspectRatio

        # Scroll bar behaviour.
        #   Qt.ScrollBarAlwaysOff: Never shows a scroll bar.
        #   Qt.ScrollBarAlwaysOn: Always shows a scroll bar.
        #   Qt.ScrollBarAsNeeded: Shows a scroll bar only when zoomed.
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)

        # Stack of QRectF zoom boxes in scene coordinates.
        self.zoomStack = []
        self.dragSelect = False
        # Flags for enabling/disabling mouse interaction.
        self.canZoom = True
        self.canPan = True
        self.center = center
        self.thumbnail = thumbnail

    def hasImage(self):
        """ Returns whether or not the scene contains an image pixmap.
        """
        return self._pixmapHandle is not None

    def clearImage(self):
        """ Removes the current image pixmap from the scene if it exists.
        """
        if self.hasImage():
            self.scene.removeItem(self._pixmapHandle)
            self.scene.clear()
            self._pixmapHandle = None

    def pixmap(self):
        """ Returns the scene's current image pixmap as a QPixmap, or else None if no image exists.
        :rtype: QPixmap | None
        """
        if self.hasImage():
            return self._pixmapHandle.pixmap()
        return None

    def image(self):
        """ Returns the scene's current image pixmap as a QImage, or else None if no image exists.
        :rtype: QImage | None
        """
        if self.hasImage():
            return self._pixmapHandle.pixmap().toImage()
        return None

    def setImage(self, image):
        """ Set the scene's current image pixmap to the input QImage or QPixmap.
        Raises a RuntimeError if the input image has type other than QImage or QPixmap.
        :type image: QImage | QPixmap
        """
        if type(image) is QPixmap:
            pixmap = image
        elif type(image) is QImage:
            pixmap = QPixmap.fromImage(image)
        else:
            raise RuntimeError(
                "ImageViewer.setImage: Argument must be a QImage or QPixmap.")
        if self.hasImage():
            self._pixmapHandle.setPixmap(pixmap)
        else:
            self._pixmapHandle = self.scene.addPixmap(pixmap)
        self.setSceneRect(QRectF(
            pixmap.rect()))  # Set scene size to image size.
        self.updateViewer()

    def loadImageFromFile(self, fileName=""):
        """ Load an image from file.
        Without any arguments, loadImageFromFile() will popup a file dialog to choose the image file.
        With a fileName argument, loadImageFromFile(fileName) will attempt to load the specified image file directly.
        """
        if len(fileName) == 0:
            if QT_VERSION_STR[0] == '4':
                fileName = QFileDialog.getOpenFileName(self,
                                                       "Open image file.")
            elif QT_VERSION_STR[0] == '5':
                fileName, dummy = QFileDialog.getOpenFileName(
                    self, "Open image file.")
        if len(fileName) and os.path.isfile(fileName):
            image = QImage(fileName)
            self.setImage(image)

    def updateViewer(self):
        """ Show current zoom (if showing entire image, apply current aspect ratio mode).
        """
        if not self.hasImage():
            return
        if len(self.zoomStack) and self.sceneRect().contains(
                self.zoomStack[-1]):
            self.fitInView(self.zoomStack[-1], Qt.IgnoreAspectRatio
                           )  # Show zoomed rect (ignore aspect ratio).
        else:
            self.zoomStack = [
            ]  # Clear the zoom stack (in case we got here because of an invalid zoom).
            if self.thumbnail == True:
                self.fitInView(
                    self.sceneRect(), self.aspectRatioMode
                )  # Show entire image (use current aspect ratio mode).

    def resizeEvent(self, event):
        """ Maintain current zoom on resize.
        """
        self.updateViewer()

    def mouseMoveEvent(self, event):
        if self.hasImage():
            scenePos = self.mapToScene(event.pos())
            self.hover.emit(scenePos.x(), scenePos.y())
            if event.buttons() == Qt.RightButton:
                self.rightMouseButtonPressed.emit(scenePos.x(), scenePos.y())
            else:
                pass
        QGraphicsView.mouseMoveEvent(self, event)

    def mousePressEvent(self, event):
        """ Start mouse pan or zoom mode.
        """
        scenePos = self.mapToScene(event.pos())
        if event.button() == Qt.LeftButton:
            if self.canPan:
                self.setDragMode(QGraphicsView.ScrollHandDrag)
            if self.hasImage():
                self.leftMouseButtonPressed.emit(scenePos.x(), scenePos.y(),
                                                 self)
        elif event.button() == Qt.RightButton:
            if self.dragSelect:
                if self.hasImage():
                    self.setDragMode(QGraphicsView.RubberBandDrag)
                    self.viewport().setCursor(QCursor(Qt.CrossCursor))
                    self.rightMouseButtonPressed.emit(scenePos.x(),
                                                      scenePos.y())
        QGraphicsView.mousePressEvent(self, event)

    def mouseReleaseEvent(self, event):
        """ Stop mouse pan or zoom mode (apply zoom if valid).
        """
        QGraphicsView.mouseReleaseEvent(self, event)
        scenePos = self.mapToScene(event.pos())
        if event.button() == Qt.LeftButton:
            self.setDragMode(QGraphicsView.NoDrag)
            if self.hasImage():
                self.leftMouseButtonReleased.emit(scenePos.x(), scenePos.y())
        elif event.button() == Qt.RightButton:
            self.setDragMode(QGraphicsView.NoDrag)
            if self.hasImage():
                self.viewport().setCursor(QCursor(Qt.OpenHandCursor))
                if self.dragSelect:
                    viewBBox = self.zoomStack[-1] if len(
                        self.zoomStack) else self.sceneRect()
                    selectionBBox = self.scene.selectionArea().boundingRect(
                    ).intersected(viewBBox)
                    print(selectionBBox)
                    self.areaSelected.emit(selectionBBox.x(),
                                           selectionBBox.y(),
                                           selectionBBox.width(),
                                           selectionBBox.height())
                else:
                    self.pixelSelected.emit(scenePos.x(), scenePos.y())

    def mouseDoubleClickEvent(self, event):
        """ Show entire image.
        """
        scenePos = self.mapToScene(event.pos())
        if event.button() == Qt.LeftButton:
            self.leftMouseButtonDoubleClicked.emit(scenePos.x(), scenePos.y())
        elif event.button() == Qt.RightButton:
            if self.canZoom:
                self.zoomStack = []  # Clear zoom stack.
                self.updateViewer()
            self.rightMouseButtonDoubleClicked.emit(scenePos.x(), scenePos.y())
        QGraphicsView.mouseDoubleClickEvent(self, event)

    def wheelEvent(self, event):
        try:
            if self.thumbnail == True:
                return
            zoomInFactor = 1.2
            zoomOutFactor = .8
            # Zoom
            if event.angleDelta().y() > 0:
                zoomFactor = zoomInFactor
            else:
                zoomFactor = zoomOutFactor
            self.scale(zoomFactor, zoomFactor)
            # Get the new position
            newPos = self.mapToScene(event.pos())
            self.centerOn(newPos)
        except Exception as e:
            logging.info(e)

    def zoomToArea(self, center, scale):
        if self.hasImage():
            self.setTransform(QTransform())
            pos = QPoint(center[0], center[1])
            self.centerOn(pos)
            self.scale(scale, scale)

    def resetZoom(self):
        self.setTransform(QTransform())
        self.fitInView(self.sceneRect(), self.aspectRatioMode
                       )  # Show entire image (use current aspect ratio mode).

    def showEvent(self, event):
        self.resetZoom()
Esempio n. 28
0
class ProfileGraphViewer( QWidget ):
    " Profiling results as a graph "

    escapePressed = pyqtSignal()

    def __init__( self, scriptName, params, reportTime,
                        dataFile, stats, parent = None ):
        QWidget.__init__( self, parent )

        self.__dataFile = dataFile
        self.__script = scriptName
        self.__reportTime = reportTime
        self.__params = params
        self.__stats = stats

        project = GlobalData().project
        if project.isLoaded():
            self.__projectPrefix = os.path.dirname( project.fileName )
        else:
            self.__projectPrefix = os.path.dirname( scriptName )
        if not self.__projectPrefix.endswith( os.path.sep ):
            self.__projectPrefix += os.path.sep

        self.__createLayout()
        self.__getDiagramLayout()

        self.__viewer.setScene( self.__scene )
        return

    def setFocus( self ):
        " Sets the focus properly "
        self.__viewer.setFocus()
        return

    def __isOutsideItem( self, fileName ):
        " Detects if the record should be shown as an outside one "
        return not fileName.startswith( self.__projectPrefix )

    def __createLayout( self ):
        " Creates the widget layout "
        totalCalls = self.__stats.total_calls
        totalPrimitiveCalls = self.__stats.prim_calls  # The calls were not induced via recursion
        totalTime = self.__stats.total_tt

        txt = "<b>Script:</b> " + self.__script + " " + self.__params.arguments + "<br>" \
              "<b>Run at:</b> " + self.__reportTime + "<br>" + \
              str( totalCalls ) + " function calls (" + \
              str( totalPrimitiveCalls ) + " primitive calls) in " + \
              FLOAT_FORMAT % totalTime + " CPU seconds"
        summary = QLabel( txt )
        summary.setToolTip( txt )
        summary.setSizePolicy( QSizePolicy.Ignored, QSizePolicy.Fixed )
        summary.setFrameStyle( QFrame.StyledPanel )
        summary.setAutoFillBackground( True )
        summaryPalette = summary.palette()
        summaryBackground = summaryPalette.color( QPalette.Background )
        summaryBackground.setRgb( min( summaryBackground.red() + 30, 255 ),
                                  min( summaryBackground.green() + 30, 255 ),
                                  min( summaryBackground.blue() + 30, 255 ) )
        summaryPalette.setColor( QPalette.Background, summaryBackground )
        summary.setPalette( summaryPalette )

        self.__scene = QGraphicsScene()
        self.__viewer = DiagramWidget()
        self.__viewer.escapePressed.connect( self.__onESC )

        vLayout = QVBoxLayout()
        vLayout.setContentsMargins( 0, 0, 0, 0 )
        vLayout.setSpacing( 0 )
        vLayout.addWidget( summary )
        vLayout.addWidget( self.__viewer )

        self.setLayout( vLayout )
        return


    def __getDiagramLayout( self ):
        " Runs external tools to get the diagram layout "

        # Preparation: build a map of func ID -> fileName + line
        funcMap = {}
        index = 0
        for func, props in self.__stats.stats.items():
            funcMap[ index ] = ( func[ 0 ], func[ 1 ] )
            index += 1

        # First step is to run grpof2dot
        gprof2dot = thirdpartyDir + "gprof2dot" + os.path.sep + "gprof2dot.py"
        outputFile = self.__dataFile + ".dot"
        nodeLimit = Settings().profileNodeLimit
        edgeLimit = Settings().profileEdgeLimit
        dotSpec = safeRun( [ gprof2dot, '-n', str( nodeLimit ),
                             '-e', str( edgeLimit ),
                             '-f', 'pstats', '-o', outputFile,
                             self.__dataFile ] )
        graphDescr = safeRun( [ "dot", "-Tplain", outputFile ] )
        graph = getGraphFromPlainDotData( graphDescr )
        graph.normalize( self.physicalDpiX(), self.physicalDpiY() )

        self.__scene.clear()
        self.__scene.setSceneRect( 0, 0, graph.width, graph.height )

        for edge in graph.edges:
            self.__scene.addItem( FuncConnection( edge ) )
            if edge.label != "":
                self.__scene.addItem( FuncConnectionLabel( edge ) )

        for node in graph.nodes:
            fileName = ""
            lineNumber = 0
            isOutside = True
            nodeID, newLabel = extractNodeID( node.label )
            if nodeID != -1:
                node.label = newLabel

                # Now, detect the file name/line number and
                # if it belongs to the project
                ( fileName, lineNumber ) = funcMap[ nodeID ]
            self.__scene.addItem( Function( node, fileName, lineNumber,
                                            self.__isOutsideItem( fileName ) ) )

        return

    def __onESC( self ):
        " Triggered when ESC is clicked "
        self.escapePressed.emit()
        return

    def onCopy( self ):
        " Copies the diagram to the exchange buffer "
        self.__viewer.onCopy()
        return

    def onSaveAs( self, fileName ):
        " Saves the diagram to a file "
        self.__viewer.onSaveAs( fileName )
        return

    def zoomIn( self ):
        " Triggered on the 'zoom in' button "
        self.__viewer.zoomIn()
        return

    def zoomOut( self ):
        " Triggered on the 'zoom out' button "
        self.__viewer.zoomOut()
        return

    def resetZoom( self ):
        " Triggered on the 'zoom reset' button "
        self.__viewer.resetZoom()
        return
Esempio n. 29
0
class FlowChartView(QWidget):
    """
    Flowchart view
    """
    def __init__(self, parent):
        """
        Constructs FlowChartView widget 

        @param parent:
        @type parent: 
        """
        QWidget.__init__(self, parent)

        self.steps = []
        self.timestamps = []
        self.arrows = []

        self.createWidget()

    def createWidget(self):
        """
        Create the widget
        """
        self.diagramScene = QGraphicsScene(self)

        self.view = QGraphicsView(self.diagramScene)

        self.view.setRenderHint(QPainter.Antialiasing)

        # set the main layout
        layout = QVBoxLayout()

        self.logEdit = QTextEdit()
        self.logEdit.setReadOnly(True)

        hSplitter2 = QSplitter(self)
        hSplitter2.setOrientation(Qt.Vertical)

        hSplitter2.addWidget(self.view)
        hSplitter2.addWidget(self.logEdit)

        hSplitter2.setStretchFactor(0, 1)

        layout.addWidget(hSplitter2)
        self.setLayout(layout)

    def reset(self):
        """
        Clear all 
        """
        #self.diagramScene.clear()

        for stp in self.steps:
            self.diagramScene.removeItem(stp)

        for stp in self.arrows:
            self.diagramScene.removeItem(stp)

        for stamp in self.timestamps:
            self.diagramScene.removeItem(stamp)

        self.diagramScene.clear()
        self.diagramScene.update()
        self.view.resetCachedContent()

        self.steps = []
        self.arrows = []
        self.timestamps = []
        self.logEdit.setText("")

    def addStep(self,
                text,
                color="#A5A2A5",
                width=400,
                height=40,
                data=None,
                textBold=False,
                textItalic=False,
                timestamp="00:00:00"):
        """
        Add step
        """
        # take the last one
        if len(self.steps):
            latestBlock = self.steps[-1:][0]
        else:
            latestBlock = None

        newBlock = BlockItem(self,
                             text,
                             blockColor=color,
                             width=width,
                             height=height,
                             data=data,
                             bold=textBold,
                             italic=textItalic)
        if width == 100:
            newBlock.setPos(400 / 2 - 100 / 2, len(self.steps) * 80)
        elif width == 300:
            newBlock.setPos(400 / 2 - 300 / 2, len(self.steps) * 80)
        else:
            newBlock.setPos(0, len(self.steps) * 80)

        self.steps.append(newBlock)
        self.diagramScene.addItem(newBlock)

        newTimestampBlock = TimestampItem(self, timestamp)
        newTimestampBlock.setPos(-200, len(self.timestamps) * 80)

        self.timestamps.append(newTimestampBlock)
        self.diagramScene.addItem(newTimestampBlock)

        if latestBlock is not None:
            newArrow = LineItem(latestBlock, newBlock)
            self.diagramScene.addItem(newArrow)
            self.arrows.append(newArrow)

        if QtHelper.str2bool(Settings.instance().readValue(
                key='TestRun/auto-scrolling-graph')):
            self.view.centerOn(newBlock)
        return newBlock
Esempio n. 30
0
class Canvas(QGraphicsView):
    def __init__(self, window, resultDict, imagePath):
        QGraphicsView.__init__(self)
        self.window = window
        self.pen = QPen(QColor("red"))
        self.pen.setWidth(0.5)
        self.canvasScene = QGraphicsScene()
        self.setScene(self.canvasScene)
        self.resultDict = resultDict
        self.imagePath = imagePath
        self.setBackgroundBrush(QBrush(Qt.black, Qt.SolidPattern))

    def drawImage(self, imageFile):
        """Draw an image on the canvas"""
        image = QPixmap(imageFile)
        self.canvasScene.addPixmap(image)
        return image

    def drawFeaturePoint(self, pointList):
        """Draw a feature point on the canvas"""
        radius = 0.5
        width, height = 2, 2

        x1, y1, x2, y2 = pointList

        #Draw ellipse and bounding rect. Is a hacked version!
        self.canvasScene.addEllipse(x1 - radius + 5, y1 - radius + 3, 2 * radius, 2 * radius, self.pen)
        self.canvasScene.addEllipse(x2 - radius + self.imageWidth + 10, y2 - radius + 3, 2 * radius, 2 * radius, self.pen)
        self.canvasScene.addRect(x1 - width / 2. + 5, y1 - height / 2. + 3, width, height, self.pen)
        self.canvasScene.addRect(x2 - width / 2. + self.imageWidth + 10, y2 - height / 2. + 3, width, height, self.pen)

    def drawFeatureImages(self, imageFile):
        """Draw two consecutive images on the screen"""
        #Load image files
        path, file_ = os.path.split(imageFile)
        image1 = QPixmap(os.path.join(path, 'first_' + file_))
        image2 = QPixmap(os.path.join(path, 'second_' + file_))
        self.imageWidth = image1.width()

        #Add pixmaps
        image1Map = self.canvasScene.addPixmap(image1)
        image2Map = self.canvasScene.addPixmap(image2)

        #Shift pixmaps to the right position
        image1Map.setOffset(QPointF(5, 3))
        image2Map.setOffset(QPointF(10 + image1.width(), 3))

    def drawPolygon(self, Polygon):
        """Draw a polygon on the canvas"""
        polygon = QPolygonF()
        for point in Polygon:
            polygon.append(QPointF(point[0], point[1]))
        self.canvasScene.addPolygon(polygon, self.pen)

    def getWorkerId(self):
        return self.resultDict.values()[self.index][0][0]

    def getAssignmentId(self):
        return self.resultDict.keys()[self.index]

    def nextImage(self):
        """Load next image"""
        self.index += 1
        self.canvasScene.clear()
        if self.index > len(self.resultDict) - 1 or len(self.resultDict) <= 0:
            self.canvasScene.addText("No annotations to review")
            self.window.reviewFlag = False
            self.window.updateTable()

        else:
            #Draw Image and Polygon
            assignmentId = self.resultDict.keys()[self.index]
            result = self.resultDict[assignmentId]
            image = result[0][1]
            pointList = result[0][2]
            if self.window.segmentation_mode:
                pointList = [round(float(point), 3) for point in pointList]
                pointList = zip(*[iter(pointList)] * 2)
                self.drawImage(os.path.join(self.imagePath, image))
                self.drawPolygon(pointList)
            else:
                pointList = [round(float(point), 3) for point in pointList]
                pointList = zip(*[iter(pointList)] * 4)
                self.drawFeatureImages(os.path.join(self.imagePath, image))
                for point in pointList:
                    self.drawFeaturePoint(point)

        #update scene
        self.window.setWindowTitle("MTurk Review Tool ({0}/{1})   Rejected: {2}   Approved: {3}".format(self.index + 1,
                                        len(self.resultDict), len(self.window.rejected), len(self.window.approved)))
        self.canvasScene.setSceneRect(self.canvasScene.itemsBoundingRect())
        self.fitInView(0, 0, self.canvasScene.width(), self.canvasScene.height(), 1)    
        self.canvasScene.update(0, 0, self.canvasScene.width(), self.canvasScene.height())
Esempio n. 31
0
class BrushingModel(QObject):
    brushSizeChanged     = pyqtSignal(int)
    brushColorChanged    = pyqtSignal(QColor)
    brushStrokeAvailable = pyqtSignal(QPointF, object)
    drawnNumberChanged   = pyqtSignal(int)

    minBrushSize       = 1
    maxBrushSize       = 61
    defaultBrushSize   = 3
    defaultDrawnNumber = 1
    defaultColor       = Qt.white
    erasingColor       = Qt.black
    erasingNumber      = 100

    def __init__(self, parent=None):
        QObject.__init__(self, parent=parent)
        self.sliceRect = None
        self.bb    = QRect() #bounding box enclosing the drawing
        self.brushSize = self.defaultBrushSize
        self.drawColor = self.defaultColor
        self._temp_color = None
        self._temp_number = None
        self.drawnNumber = self.defaultDrawnNumber

        self.pos = None
        self.erasing = False
        self._hasMoved = False

        self.drawOnto = None

        #an empty scene, where we add all drawn line segments
        #a QGraphicsLineItem, and which we can use to then
        #render to an image
        self.scene = QGraphicsScene()

    def toggleErase(self):
        self.erasing = not(self.erasing)
        if self.erasing:
            self.setErasing()
        else:
            self.disableErasing()

    def setErasing(self):
        self.erasing = True
        self._temp_color = self.drawColor
        self._temp_number = self.drawnNumber
        self.setBrushColor(self.erasingColor)
        self.brushColorChanged.emit(self.erasingColor)
        self.setDrawnNumber(self.erasingNumber)

    def disableErasing(self):
        self.erasing = False
        self.setBrushColor(self._temp_color)
        self.brushColorChanged.emit(self.drawColor)
        self.setDrawnNumber(self._temp_number)

    def setBrushSize(self, size):
        self.brushSize = size
        self.brushSizeChanged.emit(self.brushSize)

    def setDrawnNumber(self, num):
        self.drawnNumber = num
        self.drawnNumberChanged.emit(num)

    def getBrushSize(self):
        return self.brushSize

    def brushSmaller(self):
        b = self.brushSize
        if b > self.minBrushSize:
            self.setBrushSize(b-1)

    def brushBigger(self):
        b = self.brushSize
        if self.brushSize < self.maxBrushSize:
            self.setBrushSize(b+1)

    def setBrushColor(self, color):
        self.drawColor = color
        self.brushColorChanged.emit(self.drawColor)

    def beginDrawing(self, pos, sliceRect):
        '''

        pos -- QPointF-like
        '''
        self.sliceRect = sliceRect
        self.scene.clear()
        self.bb = QRect()
        self.pos = QPointF(pos.x(), pos.y())
        self._hasMoved = False

    def endDrawing(self, pos):
        has_moved = self._hasMoved # _hasMoved will change after calling moveTo
        if has_moved:
            self.moveTo(pos)
        else:
            assert(self.pos == pos)
            self.moveTo(QPointF(pos.x()+0.0001, pos.y()+0.0001)) # move a little

        tempi = QImage(QSize(self.bb.width(), self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format
        tempi.fill(0)
        painter = QPainter(tempi)
        self.scene.render(painter, target=QRectF(), source=QRectF(QPointF(self.bb.x(), self.bb.y()), QSizeF(self.bb.width(), self.bb.height())))
        painter.end()

        ndarr = qimage2ndarray.rgb_view(tempi)[:,:,0]
        labels = numpy.where(ndarr>0,numpy.uint8(self.drawnNumber),numpy.uint8(0))
        labels = labels.swapaxes(0,1)
        assert labels.shape[0] == self.bb.width()
        assert labels.shape[1] == self.bb.height()

        ##
        ## ensure that at least one pixel is label when the brush size is 1
        ##
        ## this happens when the user just clicked without moving
        ## in that case the lineitem will be so tiny, that it won't be rendered
        ## into a single pixel by the code above
        if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(labels) == 0:
            labels[labels.shape[0]//2, labels.shape[1]//2] = self.drawnNumber

        self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels)

    def dumpDraw(self, pos):
        res = self.endDrawing(pos)
        self.beginDrawing(pos, self.sliceRect)
        return res

    def moveTo(self, pos):
        #data coordinates
        oldX, oldY = self.pos.x(), self.pos.y()
        x,y = pos.x(), pos.y()

        line = QGraphicsLineItem(oldX, oldY, x, y)
        line.setPen(QPen( QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        self.scene.addItem(line)
        self._hasMoved = True

        #update bounding Box
        if not self.bb.isValid():
            self.bb = QRect(QPoint(oldX,oldY), QSize(1,1))
        #grow bounding box
        self.bb.setLeft(  min(self.bb.left(),   max(0,                   x-self.brushSize/2-1) ) )
        self.bb.setRight( max(self.bb.right(),  min(self.sliceRect[0]-1, x+self.brushSize/2+1) ) )
        self.bb.setTop(   min(self.bb.top(),    max(0,                   y-self.brushSize/2-1) ) )
        self.bb.setBottom(max(self.bb.bottom(), min(self.sliceRect[1]-1, y+self.brushSize/2+1) ) )

        #update/move position
        self.pos = pos
Esempio n. 32
0
class ConductorGraph(Plugin):

    _deferred_fit_in_view=Signal()
    _client_list_update_signal=Signal()
    
    def __init__(self, context):
        self._context=context
        super(ConductorGraph, self).__init__(context)
        self.initialised=False
        self.setObjectName('Conductor Graph')
        self._current_dotcode=None
        self._node_items=None
        self._edge_items=None
        self._node_item_events={}
        self._edge_item_events={}
        self._client_info_list={}
        self._widget=QWidget()
        self.cur_selected_client_name = ""
        self.pre_selected_client_name = ""
            
        # factory builds generic dotcode items
        self.dotcode_factory=PydotFactory()
        # self.dotcode_factory=PygraphvizFactory()
        self.dotcode_generator=RosGraphDotcodeGenerator()
        self.dot_to_qt=DotToQtGenerator()
        
        self._graph=ConductorGraphInfo()
        self._graph._reg_event_callback(self._update_client_list)
        self._graph._reg_period_callback(self._set_network_statisics)
        
        rospack=rospkg.RosPack()
        ui_file=os.path.join(rospack.get_path('concert_conductor_graph'), 'ui', 'conductor_graph.ui')
        loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView})
        self._widget.setObjectName('ConductorGraphUi')

        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number()))

        self._scene=QGraphicsScene()
        self._scene.setBackgroundBrush(Qt.white)
        self._widget.graphics_view.setScene(self._scene)

        #self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('view-refresh'))
        self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('window-new'))
        self._widget.refresh_graph_push_button.pressed.connect(self._update_conductor_graph)

        self._widget.highlight_connections_check_box.toggled.connect(self._redraw_graph_view)
        self._widget.auto_fit_graph_check_box.toggled.connect(self._redraw_graph_view)
        self._widget.fit_in_view_push_button.setIcon(QIcon.fromTheme('zoom-original'))
        self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view)

        self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection)
        self._deferred_fit_in_view.emit()
        
        self._widget.tabWidget.currentChanged.connect(self._change_client_tab)
        self._client_list_update_signal.connect(self._update_conductor_graph)
        
        #rospy.Subscriber(concert_msgs.Strings.CONCERT_CLIENT_CHANGES, ConcertClients, self._update_client_list)
        
        context.add_widget(self._widget)
    
    def restore_settings(self, plugin_settings, instance_settings):
        self.initialised=True
        self._refresh_rosgraph()
    def shutdown_plugin(self):
        pass
    
    def _update_conductor_graph(self):
        # re-enable controls customizing fetched ROS graph

        self._refresh_rosgraph()
        self._update_client_tab()

    def _refresh_rosgraph(self):
        if not self.initialised:
            return
        self._update_graph_view(self._generate_dotcode())
        
    def _generate_dotcode(self):
        return self.dotcode_generator.generate_dotcode(rosgraphinst=self._graph,
                                                       dotcode_factory=self.dotcode_factory,
                                                       orientation='LR'
                                                       )
    def _update_graph_view(self, dotcode): 
        #if dotcode==self._current_dotcode:
        #    return
        self._current_dotcode=dotcode
        self._redraw_graph_view()
   
    def _update_client_list(self):
        print "[conductor graph]: _update_client_list"       
        self._client_list_update_signal.emit()
        pass
    
    def _start_service(self,node_name,service_name):
        
        service=self._graph._client_info_list[node_name]['gateway_name']+"/"+service_name  
        info_text='' 
        
        if service_name=='status':
            service_handle=rospy.ServiceProxy(service, Status)
            call_result=service_handle()
            
            info_text="<html>"
            info_text +="<p>-------------------------------------------</p>"
            info_text +="<p><b>application_namespace: </b>" +call_result.application_namespace+"</p>"
            info_text +="<p><b>remote_controller: </b>" +call_result.remote_controller+"</p>"
            info_text +="<p><b>application_status: </b>" +call_result.application_status+"</p>"
            info_text +="</html>"
            self._client_list_update_signal.emit()

        elif service_name=='platform_info':
            service_handle=rospy.ServiceProxy(service, GetPlatformInfo)
            call_result=service_handle()

            info_text = "<html>"
            info_text += "<p>-------------------------------------------</p>"
            info_text += "<p><b>rocon_uri: </b>" + call_result.platform_info.uri + "</p>"
            info_text += "<p><b>concert_version: </b>" + call_result.platform_info.version + "</p>"
            info_text += "</html>"
            self._client_list_update_signal.emit()
            
        elif service_name=='invite':
            #sesrvice
            service_handle=rospy.ServiceProxy(service, Invite) 
            #dialog
            dlg=QDialog(self._widget) 
            dlg.setMinimumSize(400,0)
            dlg.setMaximumSize(400,0)
            dlg.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Expanding)
            #dialog layout
            ver_layout=QVBoxLayout(dlg)           
            ver_layout.setContentsMargins (0,0,0,0)

            dynamic_arg=[]
            dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Remote Target Name',False,[('remote_target_name','string')]))
            dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Application Namespace',False,[('application_namespace','string')]))
            dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Cancel',False,[('cancel','bool')]))
            #button
            button_hor_sub_widget=QWidget()
            button_hor_layout=QHBoxLayout(button_hor_sub_widget)   
                   
            btn_call=QPushButton("Call")
            btn_cancel=QPushButton("cancel")
            
            btn_call.clicked.connect(lambda: dlg.done(0))
            btn_call.clicked.connect(lambda : self._call_invite_service(service,service_handle,dynamic_arg))

            btn_cancel.clicked.connect(lambda: dlg.done(0))
            #add button
            button_hor_layout.addWidget(btn_call)            
            button_hor_layout.addWidget(btn_cancel)
            #add button layout            
            ver_layout.addWidget(button_hor_sub_widget)

            dlg.setVisible(True)        

        elif service_name=='start_app':
            #sesrvice
            service_handle=rospy.ServiceProxy(service, StartApp) 
            #dialog
            dlg=QDialog(self._widget) 
            dlg.setMinimumSize(400,0)
            dlg.setMaximumSize(400,0)
            dlg.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Expanding)
            #dialog layout
            ver_layout=QVBoxLayout(dlg)           
            ver_layout.setContentsMargins (0,0,0,0)

            dynamic_arg=[]
            dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Name',False,[('name','string')]))
            dynamic_arg.append(DynamicArgumentLayer(ver_layout,'Remappings',True,[('remap to','string'),('remap from','string')]))
            #button
            button_hor_sub_widget=QWidget()
            button_hor_layout=QHBoxLayout(button_hor_sub_widget)   
                   
            btn_call=QPushButton("Call")
            btn_cancel=QPushButton("cancel")
            
            btn_call.clicked.connect(lambda: dlg.done(0))
            btn_call.clicked.connect(lambda : self._call_start_app_service(service,service_handle,dynamic_arg))
            
            btn_cancel.clicked.connect(lambda: dlg.done(0))
            #add button
            button_hor_layout.addWidget(btn_call)            
            button_hor_layout.addWidget(btn_cancel)
            #add button layout            
            ver_layout.addWidget(button_hor_sub_widget)

            dlg.setVisible(True)        

        elif service_name=='stop_app':
            service_handle=rospy.ServiceProxy(service, StopApp)
            call_result=service_handle()

            info_text="<html>"
            info_text +="<p>-------------------------------------------</p>"
            info_text +="<p><b>stopped: </b>" +str(call_result.stopped)+"</p>"
            info_text +="<p><b>error_code: </b>" +str(call_result.error_code)+"</p>"
            info_text +="<p><b>message: </b>" +call_result.message+"</p>"
            info_text +="</html>"

            self._update_client_tab()
        else:
            print 'has no service'
            return
        
        # display the result of calling service  
        # get tab widget handle
        service_text_widget=None
        cur_tab_widget=self._widget.tabWidget.currentWidget()        
        
        if cur_tab_widget==None:
            return
            
        object_name='services_text_widget'
        for k in cur_tab_widget.children():
            if k.objectName().count(object_name) >=1 :
                service_text_widget=k
                break
        if service_text_widget==None:
            return
            
        service_text_widget.clear()
        service_text_widget.appendHtml(info_text)

    def _call_invite_service(self,service,service_handle,dynamic_arg):        
        remote_target_name=""
        application_namespace=""
        cancel=False

        for k in dynamic_arg:
            if k.name=='Remote Target Name':
                item_widget=k._get_param_list()[0][0][1]
                remote_target_name=item_widget.toPlainText()
            
            elif k.name=='Application Namespace':
                item_widgetwidget=k._get_param_list()[0][0][1]
                application_namespace=item_widget.toPlainText()
            
            elif k.name=='Cancel':
                item_widget=k._get_param_list()[0][0][1]    
                cancel=item_widget.itemData(item_widget.currentIndex())
        #calling service
        call_result=service_handle(remote_target_name,application_namespace,cancel)
        #status update
        self._client_list_update_signal.emit()
        # display the result of calling service  

        info_text="<html>"
        info_text +="<p>-------------------------------------------</p>"
        info_text +="<p><b>result: </b>" +str(call_result.result)+"</p>"
        info_text +="<p><b>error_code: </b>" +str(call_result.error_code)+"</p>"
        info_text +="<p><b>message: </b>" +call_result.message+"</p>"
        info_text +="</html>"        
        # get tab widget handle
        service_text_widget=None
        cur_tab_widget=self._widget.tabWidget.currentWidget()        
        if cur_tab_widget==None:
            return

        object_name='services_text_widget'
        for k in cur_tab_widget.children():
            if k.objectName().count(object_name) >=1 :
                service_text_widget=k
                break
        if service_text_widget==None:
            return
            
        service_text_widget.clear()
        service_text_widget.appendHtml(info_text)

        pass
    
    def _call_start_app_service(self,service,service_handle,dynamic_arg):
        name=""
        remappings=[]
        for k in dynamic_arg:
            if k.name=='Name':
                name=k._get_param_list()[0][0][1].toPlainText()
            elif k.name=='Remappings':    
                for l in k._get_param_list():
                    remap_to=l[0][1].toPlainText()
                    remap_from=l[1][1].toPlainText()
                    remappings.append(Remapping(remap_to,remap_from))
        #calling service
        call_result=service_handle(name,remappings)
        #status update
        self._client_list_update_signal.emit()

        # display the result of calling service          
        info_text = ''
        info_text="<html>"
        info_text +="<p>-------------------------------------------</p>"
        info_text +="<p><b>started: </b>" +str(call_result.started)+"</p>"
        info_text +="<p><b>error_code: </b>" +str(call_result.error_code)+"</p>"
        info_text +="<p><b>message: </b>" +call_result.message+"</p>"
        info_text +="<p><b>app_namespace: </b>" +call_result.app_namespace+"</p>"
        info_text +="</html>"
        # get tab widget handle
        service_text_widget=None
        cur_tab_widget=self._widget.tabWidget.currentWidget()        
        if cur_tab_widget==None:
            return
        object_name='services_text_widget'
        for k in cur_tab_widget.children():
            if k.objectName().count(object_name) >=1 :
                service_text_widget=k
                break
        if service_text_widget==None:
            return
            
        service_text_widget.clear()
        service_text_widget.appendHtml(info_text)

        pass

    def _update_client_tab(self):
        print '[_update_client_tab]'
        self.pre_selected_client_name = self.cur_selected_client_name
        self._widget.tabWidget.clear()   
        
        for k in self._graph._client_info_list.values(): 
            main_widget=QWidget()
           
            ver_layout=QVBoxLayout(main_widget)
           
            ver_layout.setContentsMargins (9,9,9,9)
            ver_layout.setSizeConstraint (ver_layout.SetDefaultConstraint)
            
            #button layout
            sub_widget=QWidget()
            sub_widget.setAccessibleName('sub_widget')
            btn_grid_layout=QGridLayout(sub_widget)

            btn_grid_layout.setContentsMargins (9,9,9,9)

            btn_grid_layout.setColumnStretch (1, 0)
            btn_grid_layout.setRowStretch (2, 0)

            invite_btn=QPushButton("Invite")
            platform_info_btn=QPushButton("Get Platform Info")
            status_btn=QPushButton("Get Status")
            start_app_btn=QPushButton("Start App")
            stop_app_btn=QPushButton("Stop App")              

            invite_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"invite"))
            platform_info_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"platform_info"))  
            status_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"status"))  
            start_app_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"start_app"))  
            stop_app_btn.clicked.connect(lambda: self._start_service(self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex()),"stop_app"))
                    
            btn_grid_layout.addWidget(invite_btn)
            btn_grid_layout.addWidget(platform_info_btn)
            btn_grid_layout.addWidget(status_btn)
            btn_grid_layout.addWidget(start_app_btn)
            btn_grid_layout.addWidget(stop_app_btn)             
            ver_layout.addWidget(sub_widget)            

            #client information layout
            context_label = QLabel()
            context_label.setText("Client information")
            ver_layout.addWidget(context_label)
            
            app_context_widget=QPlainTextEdit()
            app_context_widget.setObjectName(k["name"]+'_'+'app_context_widget')
            app_context_widget.setAccessibleName('app_context_widget')
            app_context_widget.appendHtml(k["app_context"])
            app_context_widget.setReadOnly(True) 
            
            cursor = app_context_widget.textCursor()
            cursor.movePosition(QTextCursor.Start,QTextCursor.MoveAnchor,0)
            app_context_widget.setTextCursor(cursor)
            ver_layout.addWidget(app_context_widget)
            
            #service layout
            context_label = QLabel()
            context_label.setText("Service result")
            ver_layout.addWidget(context_label)
            
            services_text_widget=QPlainTextEdit()
            services_text_widget.setObjectName(k["name"]+'_'+'services_text_widget')
            services_text_widget.setReadOnly(True) 
            cursor = services_text_widget.textCursor()
            cursor.movePosition(QTextCursor.Start,QTextCursor.MoveAnchor,0)
            services_text_widget.setTextCursor(cursor)            
            ver_layout.addWidget(services_text_widget)
            
            # new icon
            path=""
            if k["is_new"]==True:
                path=os.path.join(os.path.dirname(os.path.abspath(__file__)),"../../resources/images/new.gif")            

            #add tab
            self._widget.tabWidget.addTab(main_widget,QIcon(path), k["name"]);

        #set previous selected tab
        for k in range(self._widget.tabWidget.count()):
            tab_text=self._widget.tabWidget.tabText(k)
            if tab_text == self.pre_selected_client_name:
                self._widget.tabWidget.setCurrentIndex(k)

    def _change_client_tab(self,index):
        self.cur_selected_client_name = self._widget.tabWidget.tabText(self._widget.tabWidget.currentIndex())
        if self._widget.tabWidget.widget(index) !=None:
            for k in  self._widget.tabWidget.widget(index).children():
                if k.objectName().count("services_text_widget"):
                    k.clear()
        pass    
        
    def _set_network_statisics(self):
        if self._edge_items == None:
            return
        else:
            for edge_items in self._edge_items.itervalues():
                for edge_item in edge_items:
                     edge_dst_name=edge_item.to_node._label.text()
                     edge_item.setToolTip(str(self._graph._client_info_list[edge_dst_name]['conn_stats']))
                     
    def _redraw_graph_view(self):
        self._scene.clear()
        self._node_item_events={}
        self._edge_item_events={}
        self._node_items=None
        self._edge_items=None

        if self._widget.highlight_connections_check_box.isChecked():
            highlight_level=3
        else:
            highlight_level=1
            
        highlight_level=3 if self._widget.highlight_connections_check_box.isChecked() else 1

        # layout graph and create qt items
        (nodes, edges)=self.dot_to_qt.dotcode_to_qt_items(self._current_dotcode,
                                                            highlight_level=highlight_level,
                                                            same_label_siblings=True)
        self._node_items=nodes
        self._edge_items=edges

        # if we wish to make special nodes, do that here (maybe subclass GraphItem, just like NodeItem does)
        #node
        for node_item in nodes.itervalues():
            # set the color of conductor to orange           
            if node_item._label.text()==self._graph._concert_conductor_name:
                royal_blue=QColor(65, 105, 255)
                node_item._default_color=royal_blue
                node_item.set_color(royal_blue)

            # redefine mouse event
            self._node_item_events[node_item._label.text()]=GraphEventHandler(self._widget.tabWidget,node_item,node_item.mouseDoubleClickEvent);
            node_item.mouseDoubleClickEvent=self._node_item_events[node_item._label.text()].NodeEvent;
            
            self._scene.addItem(node_item)
            
        #edge
        for edge_items in edges.itervalues():
            for edge_item in edge_items:
                #redefine the edge hover event
                
                self._edge_item_events[edge_item._label.text()]=GraphEventHandler(self._widget.tabWidget,edge_item,edge_item._label.hoverEnterEvent);
                edge_item._label.hoverEnterEvent =self._edge_item_events[edge_item._label.text()].EdgeEvent;
                
                #self._edge_item_events[edge_item._label.text()]=GraphEventHandler(self._widget.tabWidget,edge_item,edge_item.mouseDoubleClickEvent);
                #edge_item.mouseDoubleClickEvent=self._edge_item_events[edge_item._label.text()].EdgeEvent;

                edge_item.add_to_scene(self._scene)

                #set the color of node as connection strength one of red, yellow, green
                edge_dst_name=edge_item.to_node._label.text()
                if edge_dst_name in self._graph._client_info_list.keys():
                  connection_strength=self._graph._client_info_list[edge_dst_name]['connection_strength']
                  if connection_strength=='very_strong':
                      green=QColor(0, 255, 0)
                      edge_item._default_color=green
                      edge_item.set_color(green)

                  elif connection_strength=='strong':
                      green_yellow=QColor(125, 255,0)
                      edge_item._default_color=green_yellow
                      edge_item.set_color(green_yellow)
                        
                  elif connection_strength=='normal':
                      yellow=QColor(238, 238,0)
                      edge_item._default_color=yellow
                      edge_item.set_color(yellow)

                  elif connection_strength=='weak':
                      yellow_red=QColor(255, 125,0)
                      edge_item._default_color=yellow_red
                      edge_item.set_color(yellow_red)
                      
                  elif connection_strength=='very_weak':
                      red=QColor(255, 0,0)
                      edge_item._default_color=red
                      edge_item.set_color(red)
                #set the tooltip about network information
                edge_item.setToolTip(str(self._graph._client_info_list[edge_dst_name]['conn_stats']))    

        self._scene.setSceneRect(self._scene.itemsBoundingRect())
  
        if self._widget.auto_fit_graph_check_box.isChecked():
            self._fit_in_view()

    def _fit_in_view(self):
        self._widget.graphics_view.fitInView(self._scene.itemsBoundingRect(), Qt.KeepAspectRatio)
Esempio n. 33
0
class FlowUIWidget( QWidget ):
    " The widget which goes along with the text editor "

    def __init__( self, editor, parent ):
        QWidget.__init__( self, parent )

        # It is always not visible at the beginning because there is no
        # editor content at the start
        self.setVisible( False )

        self.__editor = editor
        self.__parentWidget = parent
        self.__connected = False
        self.__needPathUpdate = False

        self.cflowSettings = getDefaultCflowSettings( self )

        hLayout = QHBoxLayout()
        hLayout.setContentsMargins( 0, 0, 0, 0 )
        hLayout.setSpacing( 0 )

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

        # Make pylint happy
        self.__toolbar = None
        self.__navBar = None
        self.__cf = None

        # Create the update timer
        self.__updateTimer = QTimer( self )
        self.__updateTimer.setSingleShot( True )
        self.__updateTimer.timeout.connect( self.process )

        vLayout.addWidget( self.__createNavigationBar() )
        vLayout.addWidget( self.__createGraphicsView() )

        hLayout.addLayout( vLayout )
        hLayout.addWidget( self.__createToolbar() )
        self.setLayout( hLayout )

        self.updateSettings()

        # Connect to the change file type signal
        mainWindow = GlobalData().mainWindow
        editorsManager = mainWindow.editorsManagerWidget.editorsManager
        self.connect( editorsManager, SIGNAL( 'fileTypeChanged' ),
                      self.__onFileTypeChanged )
        return

    def __createToolbar( self ):
        " Creates the toolbar "
        self.__toolbar = QToolBar( self )
        self.__toolbar.setOrientation( Qt.Vertical )
        self.__toolbar.setMovable( False )
        self.__toolbar.setAllowedAreas( Qt.RightToolBarArea )
        self.__toolbar.setIconSize( QSize( 16, 16 ) )
        self.__toolbar.setFixedWidth( 28 )
        self.__toolbar.setContentsMargins( 0, 0, 0, 0 )

        return self.__toolbar

    def __createNavigationBar( self ):
        " Creates the navigation bar "
        self.__navBar = ControlFlowNavigationBar( self )
        return self.__navBar

    def __createGraphicsView( self ):
        """ Creates the graphics view """
        self.scene = QGraphicsScene( self )
        self.view = CFGraphicsView( self )
        self.view.setScene( self.scene )
        self.view.zoomTo( Settings().flowScale )
        return self.view

    def process( self ):
        """ Parses the content and displays the results """

        if not self.__connected:
            self.__connectEditorSignals()

        content = self.__editor.text()
        self.__cf = getControlFlowFromMemory( content )
        if len( self.__cf.errors ) != 0:
            self.__navBar.updateInfoIcon( self.__navBar.STATE_BROKEN_UTD )
            return

        self.__navBar.updateInfoIcon( self.__navBar.STATE_OK_UTD )

#        if len( self.__cf.warnings ) != 0:
#            self.logMessage( "Parser warnings: " )
#            for warn in self.__cf.warnings:
#                print str( warn[0] ) + ": " + warn[1]

        self.scene.clear()
        try:
            # Top level canvas has no adress and no parent canvas
            canvas = VirtualCanvas( self.cflowSettings, None, None, None )
            canvas.layout( self.__cf )
            canvas.setEditor( self.__editor )
            width, height = canvas.render()
            self.scene.setSceneRect( 0, 0, width, height )
            canvas.draw( self.scene, 0, 0 )
        except Exception, exc:
            print "Exception:\n" + str( exc )
        return
Esempio n. 34
0
class BrushingModel(QObject):
    brushSizeChanged     = pyqtSignal(int)
    brushColorChanged    = pyqtSignal(QColor)
    brushStrokeAvailable = pyqtSignal(QPointF, object)
    drawnNumberChanged   = pyqtSignal(int)

    minBrushSize       = 1
    maxBrushSize       = 61
    defaultBrushSize   = 3
    defaultDrawnNumber = 1
    defaultColor       = Qt.white
    erasingColor       = Qt.black
    erasingNumber      = 100

    def __init__(self, parent=None):
        QObject.__init__(self, parent=parent)
        self.sliceRect = None
        self.bb    = QRect() #bounding box enclosing the drawing
        self.brushSize = self.defaultBrushSize
        self.drawColor = self.defaultColor
        self._temp_color = None
        self._temp_number = None
        self.drawnNumber = self.defaultDrawnNumber

        self.pos = None
        self.erasing = False
        self._hasMoved = False

        self.drawOnto = None

        #an empty scene, where we add all drawn line segments
        #a QGraphicsLineItem, and which we can use to then
        #render to an image
        self.scene = QGraphicsScene()

    def toggleErase(self):
        self.erasing = not(self.erasing)
        if self.erasing:
            self.setErasing()
        else:
            self.disableErasing()

    def setErasing(self):
        self.erasing = True
        self._temp_color = self.drawColor
        self._temp_number = self.drawnNumber
        self.setBrushColor(self.erasingColor)
        self.brushColorChanged.emit(self.erasingColor)
        self.setDrawnNumber(self.erasingNumber)

    def disableErasing(self):
        self.erasing = False
        self.setBrushColor(self._temp_color)
        self.brushColorChanged.emit(self.drawColor)
        self.setDrawnNumber(self._temp_number)

    def setBrushSize(self, size):
        self.brushSize = size
        self.brushSizeChanged.emit(self.brushSize)

    def setDrawnNumber(self, num):
        self.drawnNumber = num
        self.drawnNumberChanged.emit(num)

    def getBrushSize(self):
        return self.brushSize

    def brushSmaller(self):
        b = self.brushSize
        if b > self.minBrushSize:
            self.setBrushSize(b-1)

    def brushBigger(self):
        b = self.brushSize
        if self.brushSize < self.maxBrushSize:
            self.setBrushSize(b+1)

    def setBrushColor(self, color):
        self.drawColor = color
        self.brushColorChanged.emit(self.drawColor)

    def beginDrawing(self, pos, sliceRect):
        '''

        pos -- QPointF-like
        '''
        self.sliceRect = sliceRect
        self.scene.clear()
        self.bb = QRect()
        self.pos = QPointF(pos.x(), pos.y())
        self._hasMoved = False

    def endDrawing(self, pos):
        has_moved = self._hasMoved # _hasMoved will change after calling moveTo
        if has_moved:
            self.moveTo(pos)
        else:
            assert(self.pos == pos)
            self.moveTo(QPointF(pos.x()+0.0001, pos.y()+0.0001)) # move a little

        # Qt seems to use strange rules for determining which pixels to set when rendering a brush stroke to a QImage.
        # We seem to get better results if we do the following:
        # 1) Slightly offset the source window because apparently there is a small shift in the data
        # 2) Render the scene to an image that is MUCH larger than the scene resolution (4x by 4x)
        # 3) Downsample each 4x4 patch from the large image back to a single pixel in the final image,
        #     applying some threshold to determine if the final pixel is on or off. 

        tempi = QImage(QSize(4*self.bb.width(), 4*self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format
        tempi.fill(0)
        painter = QPainter(tempi)
        # Offset the source window.  At first I thought the right offset was 0.5, because 
        #  that would seem to make sure points are rounded to pixel CENTERS, but 
        #  experimentation indicates that 0.25 is slightly better for some reason...
        source_rect = QRectF( QPointF(self.bb.x()+0.25, self.bb.y()+0.25), 
                              QSizeF(self.bb.width(), self.bb.height()) )
        target_rect = QRectF( QPointF(0,0),
                             QSizeF(4*self.bb.width(), 4*self.bb.height()) )
        self.scene.render(painter, target=target_rect, source=source_rect)
        painter.end()

        # Now downsample: convert each 4x4 patch into a single pixel by summing and dividing
        ndarr = qimage2ndarray.rgb_view(tempi)[:,:,0].astype(int)
        ndarr = ndarr.reshape( (ndarr.shape[0],) + (ndarr.shape[1]//4,) + (4,) )
        ndarr = ndarr.sum(axis=-1)
        ndarr = ndarr.transpose()
        ndarr = ndarr.reshape( (ndarr.shape[0],) + (ndarr.shape[1]//4,) + (4,) )
        ndarr = ndarr.sum(axis=-1)
        ndarr = ndarr.transpose()
        ndarr //= 4*4

        downsample_threshold = (7./16)*255
        labels = numpy.where(ndarr>=downsample_threshold, numpy.uint8(self.drawnNumber), numpy.uint8(0))
        labels = labels.swapaxes(0,1)
        assert labels.shape[0] == self.bb.width()
        assert labels.shape[1] == self.bb.height()

        ##
        ## ensure that at least one pixel is label when the brush size is 1
        ##
        ## this happens when the user just clicked without moving
        ## in that case the lineitem will be so tiny, that it won't be rendered
        ## into a single pixel by the code above
        if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(labels) == 0:
            labels[labels.shape[0]//2, labels.shape[1]//2] = self.drawnNumber

        self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels)

    def dumpDraw(self, pos):
        res = self.endDrawing(pos)
        self.beginDrawing(pos, self.sliceRect)
        return res

    def moveTo(self, pos):
        #data coordinates
        oldX, oldY = self.pos.x(), self.pos.y()
        x,y = pos.x(), pos.y()

        line = QGraphicsLineItem(oldX, oldY, x, y)
        line.setPen(QPen( QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        self.scene.addItem(line)
        self._hasMoved = True

        #update bounding Box
        if not self.bb.isValid():
            self.bb = QRect(QPoint(oldX,oldY), QSize(1,1))
        #grow bounding box
        self.bb.setLeft(  min(self.bb.left(),   max(0,                   x-self.brushSize//2-1) ) )
        self.bb.setRight( max(self.bb.right(),  min(self.sliceRect[0]-1, x+self.brushSize//2+1) ) )
        self.bb.setTop(   min(self.bb.top(),    max(0,                   y-self.brushSize//2-1) ) )
        self.bb.setBottom(max(self.bb.bottom(), min(self.sliceRect[1]-1, y+self.brushSize//2+1) ) )

        #update/move position
        self.pos = pos
class histogramDialog(QDialog, FORM_CLASS):

    def __init__(self, iface, parent=None):
        self.iface = iface
        self.plugin_dir = os.path.dirname(__file__)

        # Some constants
        self.HISTOGRAM = self.tr('Histogram')
        self.BROWSE = self.tr('Browse')
        self.CANCEL = self.tr('Cancel')
        self.CLOSE = self.tr('Close')
        self.OK = self.tr('OK')
        self.NUMBEROFRINGS = 10  # Number of concentric rings in the histogram

        """Constructor."""
        super(histogramDialog, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)

        okButton = self.button_box.button(QDialogButtonBox.Ok)
        okButton.setText(self.OK)
        cancelButton = self.button_box.button(QDialogButtonBox.Cancel)
        cancelButton.setText(self.CANCEL)

        browseButton = self.BrowseButton
        browseButton.setText(self.BROWSE)
        closeButton = self.button_box.button(QDialogButtonBox.Close)
        closeButton.setText(self.CLOSE)

        # Connect signals
        okButton.clicked.connect(self.startWorker)
        cancelButton.clicked.connect(self.killWorker)
        closeButton.clicked.connect(self.reject)
        browseButton.clicked.connect(self.browse)
        #minvalSBCh = self.minValueSpinBox.valueChanged[str]
        #minvalSBCh.connect(self.updateBins)
        #minvalSBCh.connect(function ....)
        #binsSBCh = self.binsSpinBox.valueChanged[str]
        #binsSBCh.connect(self.updateBins)

        #self.iface.legendInterface().itemAdded.connect(
        #    self.layerlistchanged)
        #self.iface.legendInterface().itemRemoved.connect(
        #    self.layerlistchanged)
        inpIndexCh = self.InputLayer.currentIndexChanged['QString']
        inpIndexCh.connect(self.layerchanged)
        fieldIndexCh = self.inputField.currentIndexChanged['QString']
        fieldIndexCh.connect(self.fieldchanged)

        QObject.disconnect(self.button_box, SIGNAL("rejected()"),
                           self.reject)

        # Set instance variables
        self.worker = None
        self.inputlayerid = None
        self.layerlistchanging = False
        self.bins = 8
        self.binsSpinBox.setValue(self.bins)
        self.selectedFeaturesCheckBox.setChecked(True)
        self.scene = QGraphicsScene(self)
        self.histogramGraphicsView.setScene(self.scene)
        self.result = None

    def startWorker(self):
        #self.showInfo('Ready to start worker')
        # Get the input layer
        layerindex = self.InputLayer.currentIndex()
        layerId = self.InputLayer.itemData(layerindex)
        inputlayer = QgsMapLayerRegistry.instance().mapLayer(layerId)
        if inputlayer is None:
            self.showError(self.tr('No input layer defined'))
            return
        if inputlayer.featureCount() == 0:
            self.showError(self.tr('No features in input layer'))
            self.scene.clear()
            return
        self.bins = self.binsSpinBox.value()
        self.outputfilename = self.outputFile.text()
        self.minValue = self.minValueSpinBox.value()
        self.maxValue = self.maxValueSpinBox.value()
        if self.maxValue - self.minValue < 0:
            self.showError(self.tr('Max value less than min value'))
            return
        if self.inputField.count() == 0:
            self.showError(self.tr('Missing numerical field'))
            self.scene.clear()
            return
        fieldindex = self.inputField.currentIndex()
        fieldname = self.inputField.itemData(fieldindex)
        self.result = None
        # create a new worker instance
        worker = Worker(inputlayer, self.bins, self.minValue,
                        self.maxValue,
                        self.selectedFeaturesCheckBox.isChecked(), fieldname)
        ## configure the QgsMessageBar
        #msgBar = self.iface.messageBar().createMessage(self.tr('Joining'), '')
        #self.aprogressBar = QProgressBar()
        #self.aprogressBar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        #acancelButton = QPushButton()
        #acancelButton.setText(self.CANCEL)
        #acancelButton.clicked.connect(self.killWorker)
        #msgBar.layout().addWidget(self.aprogressBar)
        #msgBar.layout().addWidget(acancelButton)
        ## Has to be popped after the thread has finished (in
        ## workerFinished).
        #self.iface.messageBar().pushWidget(msgBar,
        #                                   self.iface.messageBar().INFO)
        #self.messageBar = msgBar
        # start the worker in a new thread
        thread = QThread(self)
        worker.moveToThread(thread)
        worker.finished.connect(self.workerFinished)
        worker.error.connect(self.workerError)
        worker.status.connect(self.workerInfo)
        worker.progress.connect(self.progressBar.setValue)
        #worker.progress.connect(self.aprogressBar.setValue)
        thread.started.connect(worker.run)
        thread.start()
        self.thread = thread
        self.worker = worker
        self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
        self.button_box.button(QDialogButtonBox.Close).setEnabled(False)
        self.InputLayer.setEnabled(False)
        self.inputField.setEnabled(False)

    def workerFinished(self, ok, ret):
        """Handles the output from the worker and cleans up after the
           worker has finished."""
        # clean up the worker and thread
        self.worker.deleteLater()
        self.thread.quit()
        self.thread.wait()
        self.thread.deleteLater()
        # remove widget from the message bar (pop)
        #self.iface.messageBar().popWidget(self.messageBar)
        if ok and ret is not None:
            #self.showInfo("Histogram: " + str(ret))
            self.result = ret
            # report the result
            # As a CSV file:
            if self.outputfilename != "":
                try:
                    with open(self.outputfilename, 'wb') as csvfile:
                        csvwriter = csv.writer(csvfile, delimiter=';',
                                    quotechar='"', quoting=csv.QUOTE_MINIMAL)
                        csvwriter.writerow(["StartValue", "EndValue",
                                            "Number"])
                        for i in range(len(ret)-1):
                            csvwriter.writerow([ret[i][0],ret[i+1][0],
                                                   ret[i][1]])
                        csvwriter.writerow([ret[len(ret)-1][0],self.maxValue,
                                                   ret[len(ret)-1][1]])
                    with open(self.outputfilename + 't', 'wb') as csvtfile:
                        csvtfile.write('"Real","Real","Integer"')
                except IOError, e:
                    self.showInfo("Trouble writing the CSV file: " + str(e))
            # Draw the histogram
            self.drawHistogram()
        else:
Esempio n. 36
0
class WsnViewer(QtGui.QMainWindow, Ui_WsnViewerUI):
    def __init__(self, parent=None):
        super(WsnViewer, self).__init__(parent)
        self.setupUi (self)
        self.m_nodeNumber = 10
        self.m_maxRfRange = 70
        self.m_macAddr = MacAddress ()
        self.m_nodeLoc = Coordonate ()
        self.m_nodeList = self.m_macAddr.GetListAddr(10)
        self.m_edgeList = 0 
        self.m_edgeDict = {}
        self.m_nodeLocDict = {}
        
        self.m_scene = QGraphicsScene (self.graphicsView)
        #self.m_paramWin = Ui_paramWindow ()
        self.m_graph = nx.Graph()
        self.m_data = list ()
        self.DataReader = Data ()
        
        self.graphicsView.setDragMode (self.graphicsView.RubberBandDrag)
        self.graphicsView.setRenderHints (QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
        self.graphicsView.setScene (self.m_scene)
        self.ConnectActions ()
    
    def ConnectActions(self):
        self.actionQuit.triggered.connect (QtGui.qApp.quit)
        self.actionOpen.triggered.connect (self.OpenWsnTopology)
        self.actionRandom_topology.triggered.connect (self.GenerateRandWsn)
        self.actionTools.triggered.connect(self.SetRadioRange)
        self.actionSave.triggered.connect(self.Save)
        
    def OpenWsnTopology (self):
        fileName = QtGui.QFileDialog.getOpenFileName(
                        self,
                        "Ouvrir un fichier des positions des noeuds",
                        QtCore.QDir.homePath(),
                        "Fichiers texte (*.txt)"
                    )
        if (fileName):
            self.m_data = self.DataReader.ReadFile(fileName)
            
    def GenerateRandWsn (self):
        self.m_nodeList = self.m_macAddr.GetListAddr(self.m_nodeNumber)
        #print(self.m_nodeList)
        self.m_edgeList, self.m_nodeLocDict = self.m_nodeLoc.EdgeCreate (self.m_nodeList)
        #print(self.m_nodeLocDict)
        #print(self.m_edgeList)
        self.m_scene.clear()
        self.DrawGraph ()
             
    def main (self):
        self.show()
        
    def OpenDialog(self):
        self.dlg = OpenFileDialog ()
        self.dlg.show()
        
    def DrawGraph (self):
        for edge in self.m_edgeList:
            self.m_edgeDict [edge] = EdgeItem (self.m_nodeLocDict, edge[0], edge[1])
            self.m_scene.addItem(self.m_edgeDict [edge])
        for node in self.m_nodeLocDict.iterkeys():
            nodeItem = NodeItem (self.m_scene, self.m_nodeLocDict, node)
            #nodeItem.m_signalLinkNode.nodeItemSignal.connect (self.UpdateNodeLocDict)
            self.m_scene.addItem (nodeItem)
    
    def Save (self):
        filename = QtGui.QFileDialog.getSaveFileName (
                        self,
                        "Ouvrir un fichier des positions des noeuds",
                        QtCore.QDir.homePath(),
                        "Fichiers texte (*.txt)"
                    )
        if self.m_edgeList and filename:
            self.DataReader.WriteWSn(self.m_edgeList, self.m_nodeLocDict, filename)
    
    def UpdateNodeLocDict (self, nodeName, nodePos):
        self.m_nodeLocDict [nodeName] = nodePos
        for node, pos in self.m_nodeLocDict.items():
            if node != nodeName:
                edge = (nodeName, node)
                if self.Distance(nodePos, pos) <= self.m_maxRfRange:
                    if not edge in self.m_edgeList and not edge[::-1] in self.m_edgeList:
                        self.m_edgeList.append (edge)
                        self.m_edgeDict [edge] = EdgeItem (self.m_nodeLocDict, edge[0], edge[1])
                        self.m_scene.addItem(self.m_edgeDict [edge])
                        #print ("%s %s %s" % (node, pos[0], pos[1]))
                else:
                    self.RemoveLink (edge)
                    self.UpdateNodeList (edge)
                    #print ("%s %s %s" % (node, pos[0], pos[1]))
               
    def UpdateNodeList (self, edge):
        while edge in self.m_edgeList:
            self.m_edgeList.remove (edge)
        
        #while edge[::-1] in self.m_edgeList:
        #    self.m_edgeList.remove (edge[::-1])
            
    def RemoveLink (self, edge):
        if edge in self.m_edgeDict:
            self.m_scene.removeItem (self.m_edgeDict [edge])
            del self.m_edgeDict [edge]
            self.m_scene.update()
            print ("%s %s" % (edge[0], edge[1]))
            
        
    def UpdateScene (self, edge):
        self.m_scene.addItem(EdgeItem (self.m_nodeLocDict, edge[0], edge[1]))
                
    def Distance (self, u, v):
        x0, y0 = u
        x1, y1 = v
        return math.sqrt((x0 - x1)**2 + (y0 - y1)**2)
    
    def SetRadioRange (self):
        self.rfWindow = RfSettingWindow ()
        resultat = self.rfWindow.exec_()
        
        if resultat:
            self.rfWindow.SetRadioValues ()
            self.m_nodeNumber = self.rfWindow.GetNodeNumber ()
            self.m_maxRfRange = self.rfWindow.GetRfRange ()
            self.GenerateRandWsn ()
Esempio n. 37
0
class OWMosaicDisplay(OWWidget):
    name = "Mosaic Display"
    description = "Display data in a mosaic plot."
    icon = "icons/MosaicDisplay.svg"

    inputs = [("Data", Table, "set_data", Default),
              ("Data Subset", Table, "set_subset_data")]
    outputs = [("Selected Data", Table)]

    settingsHandler = DomainContextHandler()
    use_boxes = Setting(True)
    variable1 = ContextSetting("")
    variable2 = ContextSetting("")
    variable3 = ContextSetting("")
    variable4 = ContextSetting("")
    selection = ContextSetting({})
    # interior_coloring is context setting to properly reset it
    # if the widget switches to regression and back (set setData)
    interior_coloring = ContextSetting(1)

    PEARSON, CLASS_DISTRIBUTION = 0, 1
    interior_coloring_opts = ["Pearson residuals", "Class distribution"]
    BAR_WIDTH = 5
    SPACING = 4
    ATTR_NAME_OFFSET = 20
    ATTR_VAL_OFFSET = 3
    BLUE_COLORS = [
        QColor(255, 255, 255),
        QColor(210, 210, 255),
        QColor(110, 110, 255),
        QColor(0, 0, 255)
    ]
    RED_COLORS = [
        QColor(255, 255, 255),
        QColor(255, 200, 200),
        QColor(255, 100, 100),
        QColor(255, 0, 0)
    ]

    graph_name = "canvas"

    def __init__(self):
        super().__init__()

        self.data = None
        self.discrete_data = None
        self.unprocessed_subset_data = None
        self.subset_data = None

        self.areas = []

        self.canvas = QGraphicsScene()
        self.canvas_view = ViewWithPress(self.canvas,
                                         handler=self.clear_selection)
        self.mainArea.layout().addWidget(self.canvas_view)
        self.canvas_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.canvas_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.canvas_view.setRenderHint(QPainter.Antialiasing)

        box = gui.vBox(self.controlArea, box=True)
        self.attr_combos = [
            gui.comboBox(box,
                         self,
                         value="variable{}".format(i),
                         orientation=Qt.Horizontal,
                         contentsLength=12,
                         callback=self.reset_graph,
                         sendSelectedValue=True,
                         valueType=str) for i in range(1, 5)
        ]
        self.rb_colors = gui.radioButtonsInBox(self.controlArea,
                                               self,
                                               "interior_coloring",
                                               self.interior_coloring_opts,
                                               box="Interior Coloring",
                                               callback=self.update_graph)
        self.bar_button = gui.checkBox(gui.indentedBox(self.rb_colors),
                                       self,
                                       'use_boxes',
                                       label='Compare with total',
                                       callback=self._compare_with_total)
        gui.rubber(self.controlArea)

    def sizeHint(self):
        return QSize(530, 720)

    def _compare_with_total(self):
        if self.data and self.data.domain.has_discrete_class:
            self.interior_coloring = 1
            self.update_graph()

    def init_combos(self, data):
        for combo in self.attr_combos:
            combo.clear()
        if data is None:
            return
        for combo in self.attr_combos[1:]:
            combo.addItem("(None)")

        icons = gui.attributeIconDict
        for attr in chain(data.domain, data.domain.metas):
            if attr.is_discrete or attr.is_continuous:
                for combo in self.attr_combos:
                    combo.addItem(icons[attr], attr.name)

        if self.attr_combos[0].count() > 0:
            self.variable1 = self.attr_combos[0].itemText(0)
            self.variable2 = self.attr_combos[1].itemText(
                2 * (self.attr_combos[1].count() > 2))
        self.variable3 = self.attr_combos[2].itemText(0)
        self.variable4 = self.attr_combos[3].itemText(0)

    def get_attr_list(self):
        return [
            a for a in
            [self.variable1, self.variable2, self.variable3, self.variable4]
            if a and a != "(None)"
        ]

    def resizeEvent(self, e):
        OWWidget.resizeEvent(self, e)
        self.update_graph()

    def showEvent(self, ev):
        OWWidget.showEvent(self, ev)
        self.update_graph()

    def set_data(self, data):
        if type(data) == SqlTable and data.approx_len() > LARGE_TABLE:
            data = data.sample_time(DEFAULT_SAMPLE_TIME)

        self.closeContext()
        self.data = data
        self.init_combos(self.data)
        self.information([0, 1, 2])
        if not self.data:
            self.discrete_data = None
            return
        """ TODO: check
        if data.has_missing_class():
            self.information(1, "Examples with missing classes were removed.")
        """
        if any(attr.is_continuous for attr in data.domain):
            self.discrete_data = Discretize(method=EqualFreq(n=4))(data)
        else:
            self.discrete_data = self.data

        if self.data.domain.class_var is None:
            self.rb_colors.setDisabled(True)
            disc_class = False
        else:
            self.rb_colors.setDisabled(False)
            disc_class = self.data.domain.has_discrete_class
            self.rb_colors.group.button(2).setDisabled(not disc_class)
            self.bar_button.setDisabled(not disc_class)
        self.interior_coloring = bool(disc_class)
        self.openContext(self.data)

        # if we first received subset we now call setSubsetData to process it
        if self.unprocessed_subset_data:
            self.set_subset_data(self.unprocessed_subset_data)
            self.unprocessed_subset_data = None

    def set_subset_data(self, data):
        if self.data is None:
            self.unprocessed_subset_data = data
            self.warning(10)
            return
        try:
            self.subset_data = data.from_table(self.data.domain, data)
            self.warning(10)
        except:
            self.subset_data = None
            self.warning(
                10, "'Data' and 'Data Subset' are incompatible"
                if data is not None else "")

    # this is called by widget after setData and setSubsetData are called.
    # this way the graph is updated only once
    def handleNewSignals(self):
        self.reset_graph()

    def clear_selection(self):
        self.selection = {}
        self.update_selection_rects()
        self.send_selection()

    def reset_graph(self):
        self.clear_selection()
        self.update_graph()

    def update_selection_rects(self):
        for i, (attr, vals, area) in enumerate(self.areas):
            if i in self.selection:
                area.setPen(QPen(Qt.black, 3, Qt.DotLine))
            else:
                area.setPen(QPen())

    def select_area(self, index, ev):
        if ev.button() != Qt.LeftButton:
            return
        if ev.modifiers() & Qt.ControlModifier:
            self.selection ^= {index}
        else:
            self.selection = {index}
        self.update_selection_rects()
        self.send_selection()

    def send_selection(self):
        if not self.selection or self.data is None:
            self.send("Selected Data", None)
            return
        filters = []
        self.warning(6)
        if self.discrete_data is not self.data:
            if isinstance(self.data, SqlTable):
                self.warning(
                    6,
                    "Selection of continuous variables on SQL is not supported"
                )
        for i in self.selection:
            cols, vals, area = self.areas[i]
            filters.append(
                filter.Values(
                    filter.FilterDiscrete(col, [val])
                    for col, val in zip(cols, vals)))
        if len(filters) > 1:
            filters = filter.Values(filters, conjunction=False)
        else:
            filters = filters[0]
        selection = filters(self.discrete_data)
        if self.discrete_data is not self.data:
            idset = set(selection.ids)
            sel_idx = [i for i, id in enumerate(self.data.ids) if id in idset]
            selection = self.discrete_data[sel_idx]
        self.send("Selected Data", selection)

    def send_report(self):
        self.report_plot(self.canvas)

    def update_graph(self):
        spacing = self.SPACING
        bar_width = self.BAR_WIDTH

        def draw_data(attr_list,
                      x0_x1,
                      y0_y1,
                      side,
                      condition,
                      total_attrs,
                      used_attrs=[],
                      used_vals=[],
                      attr_vals=""):
            x0, x1 = x0_x1
            y0, y1 = y0_y1
            if conditionaldict[attr_vals] == 0:
                add_rect(x0,
                         x1,
                         y0,
                         y1,
                         "",
                         used_attrs,
                         used_vals,
                         attr_vals=attr_vals)
                # store coordinates for later drawing of labels
                draw_text(side, attr_list[0], (x0, x1), (y0, y1), total_attrs,
                          used_attrs, used_vals, attr_vals)
                return

            attr = attr_list[0]
            # how much smaller rectangles do we draw
            edge = len(attr_list) * spacing
            values = get_variable_values_sorted(data.domain[attr])
            if side % 2:
                values = values[::-1]  # reverse names if necessary

            if side % 2 == 0:  # we are drawing on the x axis
                # remove the space needed for separating different attr. values
                whole = max(0, (x1 - x0) - edge * (len(values) - 1))
                if whole == 0:
                    edge = (x1 - x0) / float(len(values) - 1)
            else:  # we are drawing on the y axis
                whole = max(0, (y1 - y0) - edge * (len(values) - 1))
                if whole == 0:
                    edge = (y1 - y0) / float(len(values) - 1)

            if attr_vals == "":
                counts = [conditionaldict[val] for val in values]
            else:
                counts = [
                    conditionaldict[attr_vals + "-" + val] for val in values
                ]
            total = sum(counts)

            # if we are visualizing the third attribute and the first attribute
            # has the last value, we have to reverse the order in which the
            # boxes will be drawn otherwise, if the last cell, nearest to the
            # labels of the fourth attribute, is empty, we wouldn't be able to
            # position the labels
            valrange = list(range(len(values)))
            if len(attr_list + used_attrs) == 4 and len(used_attrs) == 2:
                attr1values = get_variable_values_sorted(
                    data.domain[used_attrs[0]])
                if used_vals[0] == attr1values[-1]:
                    valrange = valrange[::-1]

            for i in valrange:
                start = i * edge + whole * float(sum(counts[:i]) / total)
                end = i * edge + whole * float(sum(counts[:i + 1]) / total)
                val = values[i]
                htmlval = getHtmlCompatibleString(val)
                if attr_vals != "":
                    newattrvals = attr_vals + "-" + val
                else:
                    newattrvals = val

                tooltip = condition + 4 * "&nbsp;" + attr + \
                    ": <b>" + htmlval + "</b><br>"
                attrs = used_attrs + [attr]
                vals = used_vals + [val]
                common_args = attrs, vals, newattrvals
                if side % 2 == 0:  # if we are moving horizontally
                    if len(attr_list) == 1:
                        add_rect(x0 + start, x0 + end, y0, y1, tooltip,
                                 *common_args)
                    else:
                        draw_data(attr_list[1:], (x0 + start, x0 + end),
                                  (y0, y1), side + 1, tooltip, total_attrs,
                                  *common_args)
                else:
                    if len(attr_list) == 1:
                        add_rect(x0, x1, y0 + start, y0 + end, tooltip,
                                 *common_args)
                    else:
                        draw_data(attr_list[1:], (x0, x1),
                                  (y0 + start, y0 + end), side + 1, tooltip,
                                  total_attrs, *common_args)

            draw_text(side, attr_list[0], (x0, x1), (y0, y1), total_attrs,
                      used_attrs, used_vals, attr_vals)

        def draw_text(side, attr, x0_x1, y0_y1, total_attrs, used_attrs,
                      used_vals, attr_vals):
            x0, x1 = x0_x1
            y0, y1 = y0_y1
            if side in drawn_sides:
                return

            # the text on the right will be drawn when we are processing
            # visualization of the last value of the first attribute
            if side == 3:
                attr1values = \
                    get_variable_values_sorted(data.domain[used_attrs[0]])
                if used_vals[0] != attr1values[-1]:
                    return

            if not conditionaldict[attr_vals]:
                if side not in draw_positions:
                    draw_positions[side] = (x0, x1, y0, y1)
                return
            else:
                if side in draw_positions:
                    # restore the positions of attribute values and name
                    (x0, x1, y0, y1) = draw_positions[side]

            drawn_sides.add(side)

            values = get_variable_values_sorted(data.domain[attr])
            if side % 2:
                values = values[::-1]

            spaces = spacing * (total_attrs - side) * (len(values) - 1)
            width = x1 - x0 - spaces * (side % 2 == 0)
            height = y1 - y0 - spaces * (side % 2 == 1)

            # calculate position of first attribute
            currpos = 0

            if attr_vals == "":
                counts = [conditionaldict.get(val, 1) for val in values]
            else:
                counts = [
                    conditionaldict.get(attr_vals + "-" + val, 1)
                    for val in values
                ]
            total = sum(counts)
            if total == 0:
                counts = [1] * len(values)
                total = sum(counts)

            aligns = [
                Qt.AlignTop | Qt.AlignHCenter, Qt.AlignRight | Qt.AlignVCenter,
                Qt.AlignBottom | Qt.AlignHCenter,
                Qt.AlignLeft | Qt.AlignVCenter
            ]
            align = aligns[side]
            for i in range(len(values)):
                val = values[i]
                perc = counts[i] / float(total)
                if distributiondict[val] != 0:
                    if side == 0:
                        CanvasText(self.canvas, str(val),
                                   x0 + currpos + width * 0.5 * perc,
                                   y1 + self.ATTR_VAL_OFFSET, align)
                    elif side == 1:
                        CanvasText(self.canvas, str(val),
                                   x0 - self.ATTR_VAL_OFFSET,
                                   y0 + currpos + height * 0.5 * perc, align)
                    elif side == 2:
                        CanvasText(self.canvas, str(val),
                                   x0 + currpos + width * perc * 0.5,
                                   y0 - self.ATTR_VAL_OFFSET, align)
                    else:
                        CanvasText(self.canvas, str(val),
                                   x1 + self.ATTR_VAL_OFFSET,
                                   y0 + currpos + height * 0.5 * perc, align)

                if side % 2 == 0:
                    currpos += perc * width + spacing * (total_attrs - side)
                else:
                    currpos += perc * height + spacing * (total_attrs - side)

            if side == 0:
                CanvasText(self.canvas,
                           attr,
                           x0 + (x1 - x0) / 2,
                           y1 + self.ATTR_VAL_OFFSET + self.ATTR_NAME_OFFSET,
                           align,
                           bold=1)
            elif side == 1:
                CanvasText(self.canvas,
                           attr,
                           x0 - max_ylabel_w1 - self.ATTR_VAL_OFFSET,
                           y0 + (y1 - y0) / 2,
                           align,
                           bold=1,
                           vertical=True)
            elif side == 2:
                CanvasText(self.canvas,
                           attr,
                           x0 + (x1 - x0) / 2,
                           y0 - self.ATTR_VAL_OFFSET - self.ATTR_NAME_OFFSET,
                           align,
                           bold=1)
            else:
                CanvasText(self.canvas,
                           attr,
                           x1 + max_ylabel_w2 + self.ATTR_VAL_OFFSET,
                           y0 + (y1 - y0) / 2,
                           align,
                           bold=1,
                           vertical=True)

        def add_rect(x0,
                     x1,
                     y0,
                     y1,
                     condition="",
                     used_attrs=[],
                     used_vals=[],
                     attr_vals=""):
            area_index = len(self.areas)
            if x0 == x1:
                x1 += 1
            if y0 == y1:
                y1 += 1

            # rectangles of width and height 1 are not shown - increase
            if x1 - x0 + y1 - y0 == 2:
                y1 += 1

            if class_var and class_var.is_discrete:
                colors = [QColor(*col) for col in class_var.colors]
            else:
                colors = None

            def select_area(_, ev):
                self.select_area(area_index, ev)

            def rect(x, y, w, h, z, pen_color=None, brush_color=None, **args):
                if pen_color is None:
                    return CanvasRectangle(self.canvas,
                                           x,
                                           y,
                                           w,
                                           h,
                                           z=z,
                                           onclick=select_area,
                                           **args)
                if brush_color is None:
                    brush_color = pen_color
                return CanvasRectangle(self.canvas,
                                       x,
                                       y,
                                       w,
                                       h,
                                       pen_color,
                                       brush_color,
                                       z=z,
                                       onclick=select_area,
                                       **args)

            def line(x1, y1, x2, y2):
                r = QGraphicsLineItem(x1, y1, x2, y2, None)
                self.canvas.addItem(r)
                r.setPen(QPen(Qt.white, 2))
                r.setZValue(30)

            outer_rect = rect(x0, y0, x1 - x0, y1 - y0, 30)
            self.areas.append((used_attrs, used_vals, outer_rect))
            if not conditionaldict[attr_vals]:
                return

            if self.interior_coloring == self.PEARSON:
                s = sum(apriori_dists[0])
                expected = s * reduce(
                    mul, (apriori_dists[i][used_vals[i]] / float(s)
                          for i in range(len(used_vals))))
                actual = conditionaldict[attr_vals]
                pearson = (actual - expected) / sqrt(expected)
                if pearson == 0:
                    ind = 0
                else:
                    ind = max(0, min(int(log(abs(pearson), 2)), 3))
                color = [self.RED_COLORS, self.BLUE_COLORS][pearson > 0][ind]
                rect(x0, y0, x1 - x0, y1 - y0, -20, color)
                outer_rect.setToolTip(
                    condition + "<hr/>" + "Expected instances: %.1f<br>"
                    "Actual instances: %d<br>"
                    "Standardized (Pearson) residual: %.1f" %
                    (expected, conditionaldict[attr_vals], pearson))
            else:
                cls_values = get_variable_values_sorted(class_var)
                prior = get_distribution(data, class_var.name)
                total = 0
                for i, value in enumerate(cls_values):
                    val = conditionaldict[attr_vals + "-" + value]
                    if val == 0:
                        continue
                    if i == len(cls_values) - 1:
                        v = y1 - y0 - total
                    else:
                        v = ((y1 - y0) * val) / conditionaldict[attr_vals]
                    rect(x0, y0 + total, x1 - x0, v, -20, colors[i])
                    total += v

                if self.use_boxes and \
                        abs(x1 - x0) > bar_width and \
                        abs(y1 - y0) > bar_width:
                    total = 0
                    line(x0 + bar_width, y0, x0 + bar_width, y1)
                    n = sum(prior)
                    for i, (val, color) in enumerate(zip(prior, colors)):
                        if i == len(prior) - 1:
                            h = y1 - y0 - total
                        else:
                            h = (y1 - y0) * val / n
                        rect(x0, y0 + total, bar_width, h, 20, color)
                        total += h

                if conditionalsubsetdict:
                    if conditionalsubsetdict[attr_vals]:
                        counts = [
                            conditionalsubsetdict[attr_vals + "-" + val]
                            for val in cls_values
                        ]
                        if sum(counts) == 1:
                            rect(x0 - 2,
                                 y0 - 2,
                                 x1 - x0 + 5,
                                 y1 - y0 + 5,
                                 -550,
                                 colors[counts.index(1)],
                                 Qt.white,
                                 penWidth=2,
                                 penStyle=Qt.DashLine)
                        if self.subset_data is not None:
                            line(x1 - bar_width, y0, x1 - bar_width, y1)
                            total = 0
                            n = conditionalsubsetdict[attr_vals]
                            if n:
                                for i, (cls, color) in \
                                        enumerate(zip(cls_values, colors)):
                                    val = conditionalsubsetdict[attr_vals +
                                                                "-" + cls]
                                    if val == 0:
                                        continue
                                    if i == len(prior) - 1:
                                        v = y1 - y0 - total
                                    else:
                                        v = ((y1 - y0) * val) / n
                                    rect(x1 - bar_width, y0 + total, bar_width,
                                         v, 15, color)
                                    total += v

                actual = [
                    conditionaldict[attr_vals + "-" + cls_values[i]]
                    for i in range(len(prior))
                ]
                n_actual = sum(actual)
                if n_actual > 0:
                    apriori = [prior[key] for key in cls_values]
                    n_apriori = sum(apriori)
                    text = "<br/>".join(
                        "<b>%s</b>: %d / %.1f%% (Expected %.1f / %.1f%%)" %
                        (cls, act, 100.0 * act / n_actual,
                         apr / n_apriori * n_actual, 100.0 * apr / n_apriori)
                        for cls, act, apr in zip(cls_values, actual, apriori))
                else:
                    text = ""
                outer_rect.setToolTip("{}<hr>Instances: {}<br><br>{}".format(
                    condition, n_actual, text[:-4]))

        def draw_legend(x0_x1, y0_y1):
            x0, x1 = x0_x1
            y0, y1 = y0_y1
            if self.interior_coloring == self.PEARSON:
                names = [
                    "<-8", "-8:-4", "-4:-2", "-2:2", "2:4", "4:8", ">8",
                    "Residuals:"
                ]
                colors = self.RED_COLORS[::-1] + self.BLUE_COLORS[1:]
            else:
                names = get_variable_values_sorted(class_var) + \
                        [class_var.name + ":"]
                colors = [QColor(*col) for col in class_var.colors]

            names = [
                CanvasText(self.canvas, name, alignment=Qt.AlignVCenter)
                for name in names
            ]
            totalwidth = sum(text.boundingRect().width() for text in names)

            # compute the x position of the center of the legend
            y = y1 + self.ATTR_NAME_OFFSET + self.ATTR_VAL_OFFSET + 35
            distance = 30
            startx = (x0 + x1) / 2 - (totalwidth + (len(names)) * distance) / 2

            names[-1].setPos(startx + 15, y)
            names[-1].show()
            xoffset = names[-1].boundingRect().width() + distance

            size = 8

            for i in range(len(names) - 1):
                if self.interior_coloring == self.PEARSON:
                    edgecolor = Qt.black
                else:
                    edgecolor = colors[i]

                CanvasRectangle(self.canvas, startx + xoffset, y - size / 2,
                                size, size, edgecolor, colors[i])
                names[i].setPos(startx + xoffset + 10, y)
                xoffset += distance + names[i].boundingRect().width()

        self.canvas.clear()
        self.areas = []

        data = self.discrete_data
        if data is None:
            return
        subset = self.subset_data
        attr_list = self.get_attr_list()
        class_var = data.domain.class_var
        if class_var:
            sql = type(data) == SqlTable
            name = not sql and data.name
            # save class_var because it is removed in the next line
            data = data[:, attr_list + [class_var]]
            data.domain.class_var = class_var
            if not sql:
                data.name = name
        else:
            data = data[:, attr_list]
        # TODO: check this
        # data = Preprocessor_dropMissing(data)
        if len(data) == 0:
            self.warning(5, "No valid data for current attributes.")
            return
        else:
            self.warning(5)

        if self.interior_coloring == self.PEARSON:
            apriori_dists = [
                get_distribution(data, attr) for attr in attr_list
            ]
        else:
            apriori_dists = []

        def get_max_label_width(attr):
            values = get_variable_values_sorted(data.domain[attr])
            maxw = 0
            for val in values:
                t = CanvasText(self.canvas, val, 0, 0, bold=0, show=False)
                maxw = max(int(t.boundingRect().width()), maxw)
            return maxw

        # get the maximum width of rectangle
        xoff = 20
        width = 20
        if len(attr_list) > 1:
            text = CanvasText(self.canvas, attr_list[1], bold=1, show=0)
            max_ylabel_w1 = min(get_max_label_width(attr_list[1]), 150)
            width = 5 + text.boundingRect().height() + \
                self.ATTR_VAL_OFFSET + max_ylabel_w1
            xoff = width
            if len(attr_list) == 4:
                text = CanvasText(self.canvas, attr_list[3], bold=1, show=0)
                max_ylabel_w2 = min(get_max_label_width(attr_list[3]), 150)
                width += text.boundingRect().height() + \
                    self.ATTR_VAL_OFFSET + max_ylabel_w2 - 10

        # get the maximum height of rectangle
        height = 100
        yoff = 45
        square_size = min(self.canvas_view.width() - width - 20,
                          self.canvas_view.height() - height - 20)

        if square_size < 0:
            return  # canvas is too small to draw rectangles
        self.canvas_view.setSceneRect(0, 0, self.canvas_view.width(),
                                      self.canvas_view.height())

        drawn_sides = set()
        draw_positions = {}

        conditionaldict, distributiondict = \
            get_conditional_distribution(data, attr_list)
        conditionalsubsetdict = None
        if subset:
            conditionalsubsetdict, _ = \
                get_conditional_distribution(subset, attr_list)

        # draw rectangles
        draw_data(attr_list, (xoff, xoff + square_size),
                  (yoff, yoff + square_size), 0, "", len(attr_list))
        draw_legend((xoff, xoff + square_size), (yoff, yoff + square_size))
        self.update_selection_rects()
Esempio n. 38
0
class pageView(QGraphicsView):
    def __init__(self, wpage):
        QGraphicsView.__init__(self)
        self.init(wpage)
        self.initShape()

#        self.selection = pageSelection(self.heditor)

    def init(self, wpage):
        self.wpage = wpage
        self.heditor = wpage.heditor
        self.filesize = self.heditor.filesize
        self.start = True

        self.pagew = 20
        self.pageh = 20

        self.pageItems = []
        self.offsetItems = []
        self.displayLines = 0

    def initShape(self):
        #Scene
        self.scene = QGraphicsScene()
        self.setScene(self.scene)
        #Font
        self.initFont()
        #Headers
        self.setHeads(self.heditor.pagesPerBlock)

        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setAlignment(Qt.AlignLeft)

    def initFont(self):
        self.font = QFont("Gothic")
        self.font.setFixedPitch(1)
        self.font.setBold(False)
        self.font.setPixelSize(14)

    def setHeads(self, pagesPerBlock):
        if self.heditor.pageOffView:
            self.setOffsetHead()
        else:
            self.setBlockHead()
        self.setPageHead(self.heditor.pagesPerBlock)

        linesize = 95 + (self.heditor.pagesPerBlock * (self.pagew + 2))
        #Decoration
        headLine = QGraphicsLineItem(QLineF(0, 20, linesize, 20))
        self.scene.addItem(headLine)
        headOffLine = QGraphicsLineItem(QLineF(90, 0, 90, 700))
        self.scene.addItem(headOffLine)


    def setOffsetHead(self):
        self.offHead = QGraphicsTextItem()
        self.offHead.setDefaultTextColor(QColor(Qt.red))
        self.offHead.setFont(self.font)
        self.offHead.setPlainText("Offset(Kb)")
        self.offHead.setPos(5, 0)
        self.scene.addItem(self.offHead)

    def setPageHead(self, len):
        count = 0
        x = 95
        while count < len:
            item = QGraphicsSimpleTextItem()
            item.setFont(self.font)
            item.setText("%.2x" % count)
            item.setPos(x, 3)
            self.scene.addItem(item)
            x += self.pagew + 2
            count += 1

    def setBlockHead(self):
        self.blockHead = QGraphicsTextItem()
        self.blockHead.setDefaultTextColor(QColor(Qt.red))
        self.blockHead.setFont(self.font)
        self.blockHead.setPlainText("Block")
        self.blockHead.setPos(15, 0)
        self.scene.addItem(self.blockHead)

    def initOffsetItems(self):
        count = 0
        x = 0
        y = 25
        while count <= self.displayLines:
            item = QGraphicsTextItem()
            item.setDefaultTextColor(QColor(Qt.red))
            item.setFont(self.font)
            item.setPos(x, y)
            self.offsetItems.append(item)
            y += self.pageh + 2
            count += 1
        #Add Items in scene
        for item in self.offsetItems:
            self.scene.addItem(item)

    def initPageItems(self):
        id = 0
        countpage = 0
        startx = 95
        starty = 25
        x = startx
        y = starty
        line = 0
        while line <= self.displayLines:
            while countpage < self.heditor.pagesPerBlock:
                p = page(x, y, id, self)
                self.pageItems.append(p)
                id += 1
#                self.scene.addItem(sec)
                x += self.pagew + 2
                countpage += 1
            x = startx
            y += self.pageh + 2
            countpage = 0
            line += 1
        #Add items in scene
        for item in self.pageItems:
            self.scene.addItem(item)

    def hidePageItems(self, startid):
        end = len(self.pageItems)
        for item in self.pageItems[startid:end]:
            item.setVisible(False)

    def setAllPageItemsVisible(self):
        for item in self.pageItems:
            item.setVisible(True)

    def hideOffsetItems(self, startid):
        end = len(self.offsetItems)
        for item in self.offsetItems[startid:end]:
            item.setVisible(False)

    def setAllOffsetItemsVisible(self):
        for item in self.offsetItems:
            item.setVisible(True)

    def appendOffsetItems(self, linesToAppend):
        count = 0
        x = 0
        y = 25 + (len(self.offsetItems) * (self.pageh + 2))
#        print "Y append offset ", y
        while count <= linesToAppend:
            item = QGraphicsTextItem()
            item.setDefaultTextColor(QColor(Qt.red))
            item.setFont(self.font)
            item.setPos(x, y)
            self.offsetItems.append(item)
            self.scene.addItem(item)
            y += self.pageh + 2
            count += 1

    def appendPageItems(self, linesToAppend):
        count = 0
        cp = 0
        x = 95
        y = 25 + ((len(self.pageItems) / self.heditor.pagesPerBlock) * (self.pageh + 2))
        id = len(self.pageItems)

        while count <= linesToAppend:
            while cp < self.heditor.pagesPerBlock:
                item = page(x, y, id, self)
                self.pageItems.append(item)
                self.scene.addItem(item)
                id += 1
                x += self.pagew + 2
                cp += 1
            count += 1
            x = 95
            y += self.pageh + 2

    def refreshOffsetItems(self, offset):
        #Check if end of pages or if number of pages < display pages
        self.setAllOffsetItemsVisible()

        block = (offset / self.heditor.pageSize) / self.heditor.pagesPerBlock
        startBlockOffset = block * (self.heditor.pagesPerBlock * self.heditor.pageSize)


        lineToDisplay = ((self.filesize - offset) / self.heditor.pageSize) / self.heditor.pagesPerBlock


        if ((self.filesize - offset) / self.heditor.pageSize) % self.heditor.pagesPerBlock > 0:
            lineToDisplay += 1

        if lineToDisplay >= self.displayLines:
            offset = startBlockOffset
            for item in self.offsetItems[0:self.displayLines]:
                if self.heditor.decimalview:
                    if self.heditor.pageOffView:
                        offlabel = QString("%.10d" % (offset / 1024))
                    else:
                        offlabel = QString("%.10d" % (offset / (self.heditor.pageSize * self.heditor.pagesPerBlock)))
                else:
                    if self.heditor.pageOffView:
                        offlabel = QString("%.10x" % (offset / 1024))
                    else:
                        offlabel = QString("%.10x" % (offset / (self.heditor.pageSize * self.heditor.pagesPerBlock)))
                item.setPlainText(offlabel)
                offset = offset + (self.heditor.pagesPerBlock * self.heditor.pageSize)
            self.heditor.startBlockOffset = startBlockOffset
        else:
            if lineToDisplay == 0:
                lineToDisplay = 5
                offset = startBlockOffset - (lineToDisplay * self.heditor.pagesPerBlock * self.heditor.pageSize)
                if ((self.filesize - offset) / self.heditor.pageSize) % self.heditor.pagesPerBlock > 0:
                    lineToDisplay += 1

                self.heditor.startBlockOffset = offset

            for item in self.offsetItems[0:lineToDisplay]:
                if self.heditor.decimalview:
                    if self.heditor.pageOffView:
                        offlabel = QString("%.10d" % (offset / 1024))
                    else:
                        offlabel = QString("%.10d" % (offset / (self.heditor.pageSize * self.heditor.pagesPerBlock)))
                else:
                    if self.heditor.pageOffView:
                        offlabel = QString("%.10x" % (offset / 1024))
                    else:
                        offlabel = QString("%.10x" % (offset / (self.heditor.pageSize * self.heditor.pagesPerBlock)))
                item.setPlainText(offlabel)
                offset = offset + (self.heditor.pagesPerBlock * self.heditor.pageSize)
            self.hideOffsetItems(lineToDisplay)

    def refreshPageItems(self, offset):
        self.setAllPageItemsVisible()
        maxpages = self.displayLines * self.heditor.pagesPerBlock
        displaypages = (self.filesize - offset) / self.heditor.pageSize

        if displaypages <= maxpages:
            if displaypages == 0:
                startline = self.lines - 5
                startOffset = startline * (self.heditor.pageSize * self.heditor.pagesPerBlock)
                rangeOffset = self.filesize - startOffset
                newdisplaypages = rangeOffset / self.heditor.pageSize
                if rangeOffset % self.heditor.pageSize > 0:
                    newdisplaypages += 1

                self.hidePageItems(newdisplaypages)
                self.heditor.startBlockOffset = startOffset
            else:
                rangeOffset = self.filesize - offset
                rangePages = rangeOffset / self.heditor.pageSize
                rangeLines = rangePages / self.heditor.pagesPerBlock
                newdisplaypages = rangeOffset / self.heditor.pageSize

                if rangeOffset % self.heditor.pageSize > 0:
                    newdisplaypages += 1
 
                self.hidePageItems(newdisplaypages)
                self.heditor.startBlockOffset = offset
        else:
            self.heditor.startBlockOffset = offset

        self.heditor.pageselection.update()

    def refreshAllContent(self):
        self.scene.clear()
        del self.offsetItems[:]
        del self.pageItems[:]

        self.setHeads(self.heditor.pagesPerBlock)
        self.initOffsetItems()
        self.initPageItems()
        self.refreshOffsetItems(self.heditor.startBlockOffset)
        self.refreshPageItems(self.heditor.startBlockOffset)

    def lineToOffset(self, line):
        offset = (line * (self.heditor.pagesPerBlock * self.heditor.pageSize))
        return offset
 
    def lineToOffsetKb(self, line):
        offset = (line * (self.heditor.pagesPerBlock * self.heditor.pageSize)) / 1024
        return offset

    def lineToOffsetMb(self, line):
        offset = ((line * (self.heditor.pagesPerBlock * self.heditor.pageSize)) / 1024) / 1024
        return offset

    def lineToOffsetGb(self, line):
        offset = (((line * (self.heditor.pagesPerBlock * self.heditor.pageSize)) / 1024) / 1024) / 1024
        return offset

############################
#       Colorize Pages     #
############################

    def refreshPagesColor(self, id):
#        print "Refresh: ", id
        self.cleanSelection()
        self.pageItems[id].setBrush(QBrush(Qt.green, Qt.SolidPattern))

    def cleanSelection(self):
        item = self.pageItems[self.selectedPage]
        item.setBrush(item.brush)


############################
#       Resize Event       #
############################

    def resizeEvent(self, sizEvent):
        y = sizEvent.size().height()
        disline = (y / self.pageh)
        #Start
        if self.start == True:
            if self.height() < self.heditor.mainWindow.height():
                if disline > self.displayLines:
                    self.displayLines = (y / self.pageh)
                    #Lines
                    self.lines = self.filesize / (self.heditor.pagesPerBlock * self.heditor.pageSize)
                    #Init
                    self.initOffsetItems()
                    self.initPageItems()
                    #Refresh
                    self.refreshOffsetItems(0)
                    self.refreshPageItems(0)

                    if self.lines > self.displayLines:
                        self.wpage.setScrollBar()
                    else:
                        self.wpage.scroll = False
                    self.start = False
        else:
            range = disline - self.displayLines
            if range > 0:
                self.displayLines = (y / self.pageh)
                #Append
                self.appendOffsetItems(range)
                self.appendPageItems(range)
                #Refresh
            self.refreshOffsetItems(self.heditor.startBlockOffset)
            self.refreshPageItems(self.heditor.startBlockOffset)
#            self.heditor.footer.pixel.view.resizeEvent(sizEvent)


############################
#       CallBacks          #
############################

    def wheelEvent(self, event):
        offset = self.heditor.startBlockOffset
#        up = False
        if self.wpage.scroll:
            if event.delta() > 0:
            #UP
                subOffset = 3 * self.heditor.pagesPerBlock * self.heditor.pageSize
                if offset - subOffset > 0:
                    offset = offset - subOffset
                else:
                    offset = 0
            else:
            #DOWN
                addOffset = 3 * self.heditor.pagesPerBlock * self.heditor.pageSize
                if offset + addOffset < self.filesize:
                    offset = offset + addOffset
                else:
                    offset = self.filesize - (5 * self.heditor.pagesPerBlock * self.heditor.pageSize)
        #Set ScrollBar value:
            if offset < self.filesize - (5 * self.heditor.pagesPerBlock * self.heditor.pageSize):
                value = self.wpage.scroll.offsetToValue(offset)
                self.wpage.scroll.setValue(value)
                
                self.refreshOffsetItems(offset)
                self.refreshPageItems(offset)


    def keyPressEvent(self, keyEvent):
	pass
        #if keyEvent.matches(QKeySequence.MoveToNextPage):
            #print "Next block"
        #elif keyEvent.matches(QKeySequence.MoveToPreviousPage):
            #print "Previous block"
        #elif keyEvent.matches(QKeySequence.MoveToNextLine):
            #print "Next Line"
        #elif keyEvent.matches(QKeySequence.MoveToPreviousLine):
            #print "Previous Line"
        #else:
            #pass

    def resetSelection(self):
        for item in self.pageItems:
            item.setBrush(item.brush)

    def getPageID(self, x, y):
        startx = 95
        starty = 25

        #Set scrollbar seek
        hscroll = self.horizontalScrollBar()
        if hscroll.value() > 0:
            startx -= hscroll.value()

        xrange = x - startx
        if xrange > 0:
            xcut = (xrange / (self.pagew + 2))
#            print xcut
        else:
            xcut = 0

        yrange = y - starty
        if yrange > 0:
            ycut = yrange / (self.pageh + 2)
        else:
            ycut = 0
        id = (ycut * self.heditor.pagesPerBlock) + xcut
        return id

    def mousePressEvent(self, event):
        button = event.button()
        pos = event.pos()
        if event.button() == 1:
            #Get CLicked coordonates
            x = pos.x()
            y = pos.y()
            id = self.getPageID(x, y)
            self.resetSelection()
            self.heditor.pageselection.select(id, self.heditor.startBlockOffset, 0)

    def mouseMoveEvent(self, event):
        pos = event.pos()
        x = pos.x()
        y = pos.y()
        if self.heditor.pageselection.mode == 1:
            id = self.getPageID(x, y)
            self.resetSelection()
            self.heditor.pageselection.select(id, self.heditor.startBlockOffset, 1)
#        else:
#            id = self.getPageID(x, y)
#            self.pageItems[id].setBrush(self)
        
    def mouseReleaseEvent(self, event):
        self.heditor.pageselection.mode = 0