<commit_before>from __future__ import absolute_import, division, print_function

import sys

import numpy as np
from ..extern.vispy import scene
from ..extern.vispy.geometry import create_cube

try:
    from glue.external.qt import QtGui as QtWidgets, get_qapp
except ImportError:
    from qtpy import QtWidgets
    from glue.utils.qt import get_qapp

from glue.config import settings
from glue.external.echo import CallbackProperty, add_callback

from glue.utils import nonpartial

from matplotlib.colors import ColorConverter

rgb = ColorConverter().to_rgb


class VispyWidget(QtWidgets.QWidget):

    visible_axes = CallbackProperty()
    perspective_view = CallbackProperty()

    def _update_appearance_from_settings(self):
        self.canvas.bgcolor = rgb(settings.BACKGROUND_COLOR)
        self.axis.color = rgb(settings.FOREGROUND_COLOR)

    def __init__(self, parent=None):

        super(VispyWidget, self).__init__(parent=parent)

        # Prepare Vispy canvas. We set the depth_size to 24 to avoid issues
        # with isosurfaces on MacOS X
        self.canvas = scene.SceneCanvas(keys='interactive', show=False,
                                        config={'depth_size': 24}, bgcolor=rgb(settings.BACKGROUND_COLOR))

        # Set up a viewbox
        self.view = self.canvas.central_widget.add_view()
        self.view.parent = self.canvas.scene

        # Set whether we are emulating a 3D texture. This needs to be enabled
        # as a workaround on Windows otherwise VisPy crashes.
        self.emulate_texture = (sys.platform == 'win32' and
                                sys.version_info[0] < 3)

        self.scene_transform = scene.STTransform()
        self.limit_transforms = {}

        # Add a 3D cube to show us the unit cube. The 1.001 factor is to make
        # sure that the grid lines are not 'hidden' by volume renderings on the
        # front side due to numerical precision.
        vertices, filled_indices, outline_indices = create_cube()
        self.axis = scene.visuals.Mesh(vertices['position'],
                                       outline_indices,
                                       color=rgb(settings.FOREGROUND_COLOR), mode='lines')
        self.axis.transform = self.scene_transform
        self.view.add(self.axis)

        # Create a turntable camera. For now, this is the only camerate type
        # we support, but if we support more in future, we should implement
        # that here

        # Orthographic perspective view as default
        self.view.camera = scene.cameras.TurntableCamera(parent=self.view.scene, fov=0., distance=4.0)

        # Add the native canvas widget to this widget
        layout = QtWidgets.QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.canvas.native)
        self.setLayout(layout)

        # We need to call render here otherwise we'll later encounter an OpenGL
        # program validation error.
        self.canvas.render()

        # Set up callbacks
        add_callback(self, 'visible_axes', nonpartial(self._toggle_axes))
        add_callback(self, 'perspective_view', nonpartial(self._toggle_perspective))

    def _toggle_axes(self):
        if self.visible_axes:
            self.axis.parent = self.view.scene
        else:
            self.axis.parent = None
        self.canvas.update()

    def _toggle_perspective(self):
        if self.perspective_view:
            self.view.camera.fov = 60
        else:
            self.view.camera.fov = 0

    def add_data_visual(self, visual):
        self.limit_transforms[visual] = scene.STTransform()
        visual.transform = self.limit_transforms[visual]
        self.view.add(visual)

    def _update_stretch(self, *stretch):
        self.scene_transform.scale = stretch
        self._update_limits()

    def _update_limits(self):

        if len(self.limit_transforms) == 0:
            return

        if (self.options.x_min is None or self.options.x_max is None or<commit_msg>add 3d axis with ticks<commit_after>from __future__ import absolute_import, division, print_function

import sys

import numpy as np
from ..extern.vispy import scene
from ..extern.vispy.geometry import create_cube

try:
    from glue.external.qt import QtGui as QtWidgets, get_qapp
except ImportError:
    from qtpy import QtWidgets
    from glue.utils.qt import get_qapp

from glue.config import settings
from glue.external.echo import CallbackProperty, add_callback

from glue.utils import nonpartial

from matplotlib.colors import ColorConverter

rgb = ColorConverter().to_rgb


class VispyWidget(QtWidgets.QWidget):

    visible_axes = CallbackProperty()
    perspective_view = CallbackProperty()

    def _update_appearance_from_settings(self):
        self.canvas.bgcolor = rgb(settings.BACKGROUND_COLOR)
        self.axis.color = rgb(settings.FOREGROUND_COLOR)

    def __init__(self, parent=None):

        super(VispyWidget, self).__init__(parent=parent)

        # Prepare Vispy canvas. We set the depth_size to 24 to avoid issues
        # with isosurfaces on MacOS X
        self.canvas = scene.SceneCanvas(keys='interactive', show=False,
                                        config={'depth_size': 24}, bgcolor=rgb(settings.BACKGROUND_COLOR))

        # Set up a viewbox
        self.view = self.canvas.central_widget.add_view()
        self.view.parent = self.canvas.scene

        # Set whether we are emulating a 3D texture. This needs to be enabled
        # as a workaround on Windows otherwise VisPy crashes.
        self.emulate_texture = (sys.platform == 'win32' and
                                sys.version_info[0] < 3)

        self.scene_transform = scene.STTransform()
        self.limit_transforms = {}

        # Add a 3D cube to show us the unit cube. The 1.001 factor is to make
        # sure that the grid lines are not 'hidden' by volume renderings on the
        # front side due to numerical precision.
        vertices, filled_indices, outline_indices = create_cube()
        self.axis = scene.visuals.Mesh(vertices['position'],
                                       outline_indices,
                                       color=rgb(settings.FOREGROUND_COLOR), mode='lines')
        self.axis.transform = self.scene_transform
        self.view.add(self.axis)

        # add the axis visual from Vispy library, with 2D ticks and labels, more refer to:
        # https://github.com/vispy/vispy/blob/959fe5643ec9d717f9f01ba97552ec1c1668ec04/vispy/visuals/axis.py
        # TODO: move this 3d axis into a subclass, set domain as data shape, add coordinate labels
        self.xax = scene.visuals.Axis(pos=[[-1.0, -1.0], [1.0, -1.0]], domain=(5., 10.), tick_direction=(0, -1),
                         font_size=10, axis_color='w', tick_color='w', text_color='w',
                         parent=self.view.scene)

        self.yax = scene.visuals.Axis(pos=[[-1.0, -1.0], [-1.0, 1.0]], tick_direction=(-1, 0),
                         font_size=10, axis_color='w', tick_color='w', text_color='w',
                         parent=self.view.scene)

        self.zax = scene.visuals.Axis(pos=[[-1.0, -1.0], [-1.0, 1.0]], tick_direction=(-1, 0),
                         font_size=10, axis_color='w', tick_color='w', text_color='w',
                         parent=self.view.scene)

        self.xytr = STTransform()
        self.xytr.translate = [0., 0., -1.]

        self.xax.transform = self.xytr
        self.yax.transform = self.xytr

        # zax is the 180 rotation of yax
        self.ztr = STTransform()
        try:
            self.ztr = self.ztr.as_matrix()
        except AttributeError:   # Vispy <= 0.4
            self.ztr = self.ztr.as_affine()

        self.ztr.rotate(180, (0, 1, 1))
        self.ztr.translate((-2., -1., 0.))
        self.zax.transform = self.ztr

        # Create a turntable camera. For now, this is the only camerate type
        # we support, but if we support more in future, we should implement
        # that here

        # Orthographic perspective view as default
        self.view.camera = scene.cameras.TurntableCamera(parent=self.view.scene, fov=0., distance=4.0)

        # Add the native canvas widget to this widget
        layout = QtWidgets.QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.canvas.native)
        self.setLayout(layout)

        # We need to call render here otherwise we'll later encounter an OpenGL
        # program validation error.
        self.canvas.render()

        # Set up callbacks
        add_callback(self, 'visible_axes', nonpartial(self._toggle_axes))
        add_callback(self, 'perspective_view', nonpartial(self._toggle_perspective))

    def _toggle_axes(self):
        if self.visible_axes:
            self.axis.parent = self.view.scene
        else:
            self.axis.parent = None
        self.canvas.update()

    def _toggle_perspective(self):
        if self.perspective_view:
            self.view.camera.fov = 60
        else:
            self.view.camera.fov = 0

    def add_data_visual(self, visual):
        self.limit_transforms[visual] = scene.STTransform()
        visual.transform = self.limit_transforms[visual]
        self.view.add(visual)

    def _update_stretch(self, *stretch):
        self.scene_transform.scale = stretch

        # set stretch for 3d axis here
        self.xytr.scale = stretch
        self.xytr.translate = [0., 0., -stretch[2]]

        # self.ztr.scale will accumulate with previous settings, so we need reset
        self.ztr.reset()
        self.ztr.rotate(180, (0, 1, 1))
        self.ztr.translate((-2., -1., 0.))
        self.ztr.scale(stretch)
        self._update_limits()

    def _update_limits(self):

        if len(self.limit_transforms) == 0:
            return

        if (self.options.x_min is None or self.options.x_max is None or
{'fraction_non_alphanumeric': 0.09434345485934803, 'fraction_numerical': 0.015029958362953184, 'mean_word_length': 2.3633879781420766, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 3, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6426878', 'n_tokens_mistral': 3030, 'n_tokens_neox': 2822, 'n_words': 753}