<commit_before># -*- coding: utf-8 -*-

"""Plotting features."""


#------------------------------------------------------------------------------
# Imports
#------------------------------------------------------------------------------

import numpy as np

from vispy import gloo

from ._vispy_utils import (BaseSpikeVisual,
                           BaseSpikeCanvas,
                           BoxVisual,
                           AxisVisual,
                           LassoVisual,
                           _enable_depth_mask,
                           _wrap_vispy,
                           )
from ._panzoom import PanZoomGrid
from ..ext.six import string_types
from ..utils._types import _as_array, _is_integer
from ..utils.array import _index_of, _unique
from ..utils._color import _selected_clusters_colors


#------------------------------------------------------------------------------
# Features visual
#------------------------------------------------------------------------------

def _alternative_dimension(dim, n_features=None, n_channels=None):
    assert n_features >= 1
    assert n_channels >= 1
    if dim == 'time':
        return (0, 0)
    else:
        channel, fet = dim
        if n_features >= 2:
            return (channel, (fet + 1) % n_features)
        elif n_channels >= 2:
            return ((channel + 1) % n_channels, fet)
        else:
            return 'time'


def _matrix_from_dimensions(dimensions, n_features=None, n_channels=None):
    n = len(dimensions)
    matrix = np.empty((n, n), dtype=object)
    for i in range(n):
        for j in range(n):
            dim_x, dim_y = dimensions[i], dimensions[j]
            if dim_x == dim_y:
                dim_y = _alternative_dimension(dim_x,
                                               n_features=n_features,
                                               n_channels=n_channels,
                                               )
                # For aesthetical reasons, put time on the x axis if it is
                # the alternative dimension.
                if dim_y == 'time':
                    dim_x, dim_y = dim_y, dim_x
            matrix[i, j] = (dim_x, dim_y)
    return matrix


class BaseFeatureVisual(BaseSpikeVisual):
    """Display a grid of multidimensional features."""

    _shader_name = None
    _gl_draw_mode = 'points'

    def __init__(self, **kwargs):
        super(BaseFeatureVisual, self).__init__(**kwargs)

        self._features = None
        self._spike_samples = None
        self._dimensions_matrix = np.empty((0, 0), dtype=object)
        self.n_channels, self.n_features = None, None
        self.n_rows = None

        _enable_depth_mask()

    # Data properties
    # -------------------------------------------------------------------------

    @property
    def spike_samples(self):
        """Time samples of the displayed spikes."""
        return self._spike_samples

    @spike_samples.setter
    def spike_samples(self, value):
        assert isinstance(value, np.ndarray)
        assert value.shape == (self.n_spikes,)
        self._spike_samples = value

    @property
    def features(self):
        """Displayed features.

        This is a `(n_spikes, n_features)` array.

        """
        return self._features

    @features.setter
    def features(self, value):
        self._set_features_to_bake(value)

    def _set_features_to_bake(self, value):
        # WARNING: when setting new data, features need to be set first.
        # n_spikes will be set as a function of features.
        value = _as_array(value)
        # TODO: support sparse structures
        assert value.ndim == 3
        self.n_spikes, self.n_channels, self.n_features = value.shape
        self._features = value
        self._empty = self.n_spikes == 0
        self.set_to_bake('spikes',)

    def _check_dimension(self, dim):
        if _is_integer(dim):
            dim = (dim, 0)
        if isinstance(dim, tuple):
            assert len(dim) == 2
            channel, feature = dim
            assert _is_integer(channel)
            assert _is_integer(feature)
            assert 0 <= channel < self.n_channels
            assert 0 <= feature < self.n_features
        elif isinstance(dim, string_types):
            assert dim == 'time'
        else:
            raise ValueError('{0} should be (channel, feature) '.format(dim) +
                             'or "time".')

    def _get_feature_dim(self, data, dim):
        if isinstance(dim, (tuple, list)):
            channel, feature = dim
            return data[:, channel, feature]
        elif dim == 'time':
            t = self._spike_samples
            # Default times.
            if t is None:
                t = np.arange(self.n_spikes)
            # Normalize time feature.
            m = t.max()
            if m > 0:
                t = (-1. + 2 * t / m) * .8
            return t

    def project(self, data, box):
        """Project data to a subplot's two-dimensional subspace.

        Parameters
        ----------
        data : array
            The shape is `(n_points, n_channels, n_features)`.
        box : 2-tuple
            The `(row, col)` of the box.

        Notes
        -----

        The coordinate system is always the world coordinate system, i.e.
        `[-1, 1]`.

        """
        i, j = box
        dim_x, dim_y = self._dimensions_matrix[i, j]<commit_msg>Fixed float divison bug with time in feature view.<commit_after># -*- coding: utf-8 -*-

"""Plotting features."""


#------------------------------------------------------------------------------
# Imports
#------------------------------------------------------------------------------

import numpy as np

from vispy import gloo

from ._vispy_utils import (BaseSpikeVisual,
                           BaseSpikeCanvas,
                           BoxVisual,
                           AxisVisual,
                           LassoVisual,
                           _enable_depth_mask,
                           _wrap_vispy,
                           )
from ._panzoom import PanZoomGrid
from ..ext.six import string_types
from ..utils._types import _as_array, _is_integer
from ..utils.array import _index_of, _unique
from ..utils._color import _selected_clusters_colors


#------------------------------------------------------------------------------
# Features visual
#------------------------------------------------------------------------------

def _alternative_dimension(dim, n_features=None, n_channels=None):
    assert n_features >= 1
    assert n_channels >= 1
    if dim == 'time':
        return (0, 0)
    else:
        channel, fet = dim
        if n_features >= 2:
            return (channel, (fet + 1) % n_features)
        elif n_channels >= 2:
            return ((channel + 1) % n_channels, fet)
        else:
            return 'time'


def _matrix_from_dimensions(dimensions, n_features=None, n_channels=None):
    n = len(dimensions)
    matrix = np.empty((n, n), dtype=object)
    for i in range(n):
        for j in range(n):
            dim_x, dim_y = dimensions[i], dimensions[j]
            if dim_x == dim_y:
                dim_y = _alternative_dimension(dim_x,
                                               n_features=n_features,
                                               n_channels=n_channels,
                                               )
                # For aesthetical reasons, put time on the x axis if it is
                # the alternative dimension.
                if dim_y == 'time':
                    dim_x, dim_y = dim_y, dim_x
            matrix[i, j] = (dim_x, dim_y)
    return matrix


class BaseFeatureVisual(BaseSpikeVisual):
    """Display a grid of multidimensional features."""

    _shader_name = None
    _gl_draw_mode = 'points'

    def __init__(self, **kwargs):
        super(BaseFeatureVisual, self).__init__(**kwargs)

        self._features = None
        self._spike_samples = None
        self._dimensions_matrix = np.empty((0, 0), dtype=object)
        self.n_channels, self.n_features = None, None
        self.n_rows = None

        _enable_depth_mask()

    # Data properties
    # -------------------------------------------------------------------------

    @property
    def spike_samples(self):
        """Time samples of the displayed spikes."""
        return self._spike_samples

    @spike_samples.setter
    def spike_samples(self, value):
        assert isinstance(value, np.ndarray)
        assert value.shape == (self.n_spikes,)
        self._spike_samples = value

    @property
    def features(self):
        """Displayed features.

        This is a `(n_spikes, n_features)` array.

        """
        return self._features

    @features.setter
    def features(self, value):
        self._set_features_to_bake(value)

    def _set_features_to_bake(self, value):
        # WARNING: when setting new data, features need to be set first.
        # n_spikes will be set as a function of features.
        value = _as_array(value)
        # TODO: support sparse structures
        assert value.ndim == 3
        self.n_spikes, self.n_channels, self.n_features = value.shape
        self._features = value
        self._empty = self.n_spikes == 0
        self.set_to_bake('spikes',)

    def _check_dimension(self, dim):
        if _is_integer(dim):
            dim = (dim, 0)
        if isinstance(dim, tuple):
            assert len(dim) == 2
            channel, feature = dim
            assert _is_integer(channel)
            assert _is_integer(feature)
            assert 0 <= channel < self.n_channels
            assert 0 <= feature < self.n_features
        elif isinstance(dim, string_types):
            assert dim == 'time'
        else:
            raise ValueError('{0} should be (channel, feature) '.format(dim) +
                             'or "time".')

    def _get_feature_dim(self, data, dim):
        if isinstance(dim, (tuple, list)):
            channel, feature = dim
            return data[:, channel, feature]
        elif dim == 'time':
            t = self._spike_samples
            # Default times.
            if t is None:
                t = np.arange(self.n_spikes)
            # Normalize time feature.
            m = float(t.max())
            if m > 0:
                t = (-1. + 2 * t / m) * .8
            return t

    def project(self, data, box):
        """Project data to a subplot's two-dimensional subspace.

        Parameters
        ----------
        data : array
            The shape is `(n_points, n_channels, n_features)`.
        box : 2-tuple
            The `(row, col)` of the box.

        Notes
        -----

        The coordinate system is always the world coordinate system, i.e.
        `[-1, 1]`.

        """
        i, j = box
        dim_x, dim_y = self._dimensions_matrix[i, j]
{'fraction_non_alphanumeric': 0.15993731563421829, 'fraction_numerical': 0.004609144542772861, 'mean_word_length': 1.375, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7208121', 'n_tokens_mistral': 2959, 'n_tokens_neox': 2834, 'n_words': 803}