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

"""Manual clustering GUI component."""


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

from functools import partial
import logging

import numpy as np

from ._history import GlobalHistory
from ._utils import create_cluster_meta
from .clustering import Clustering
from phy.stats.clusters import (mean,
                                max_waveform_amplitude,
                                mean_masked_features_distance,
                                )
from phy.gui.actions import Actions
from phy.gui.widgets import Table
from phy.io.array import select_spikes

logger = logging.getLogger(__name__)


# -----------------------------------------------------------------------------
# Utility functions
# -----------------------------------------------------------------------------

def _process_ups(ups):  # pragma: no cover
    """This function processes the UpdateInfo instances of the two
    undo stacks (clustering and cluster metadata) and concatenates them
    into a single UpdateInfo instance."""
    if len(ups) == 0:
        return
    elif len(ups) == 1:
        return ups[0]
    elif len(ups) == 2:
        up = ups[0]
        up.update(ups[1])
        return up
    else:
        raise NotImplementedError()


def default_wizard_functions(waveforms=None,
                             features=None,
                             masks=None,
                             n_features_per_channel=None,
                             spikes_per_cluster=None,
                             ):
    spc = spikes_per_cluster
    nfc = n_features_per_channel

    def max_waveform_amplitude_quality(cluster):
        spike_ids = select_spikes(cluster_ids=[cluster],
                                  max_n_spikes_per_cluster=100,
                                  spikes_per_cluster=spc,
                                  )
        m = np.atleast_2d(masks[spike_ids])
        w = np.atleast_3d(waveforms[spike_ids])
        mean_masks = mean(m)
        mean_waveforms = mean(w)
        q = max_waveform_amplitude(mean_masks, mean_waveforms)
        logger.debug("Computed cluster quality for %d: %.3f.",
                     cluster, q)
        return q

    def mean_masked_features_similarity(c0, c1):
        s0 = select_spikes(cluster_ids=[c0],
                           max_n_spikes_per_cluster=100,
                           spikes_per_cluster=spc,
                           )
        s1 = select_spikes(cluster_ids=[c1],
                           max_n_spikes_per_cluster=100,
                           spikes_per_cluster=spc,
                           )

        f0 = features[s0]
        m0 = np.atleast_2d(masks[s0])

        f1 = features[s1]
        m1 = np.atleast_2d(masks[s1])

        mf0 = mean(f0)
        mm0 = mean(m0)

        mf1 = mean(f1)
        mm1 = mean(m1)

        d = mean_masked_features_distance(mf0, mf1, mm0, mm1,
                                          n_features_per_channel=nfc,
                                          )
        d = 1. / max(1e-10, d)  # From distance to similarity.
        logger.log(5, "Computed cluster similarity for (%d, %d): %.3f.",
                   c0, c1, d)
        return d

    return (max_waveform_amplitude_quality,
            mean_masked_features_similarity)


# -----------------------------------------------------------------------------
# Clustering GUI component
# -----------------------------------------------------------------------------

class ClusterView(Table):
    def __init__(self):
        super(ClusterView, self).__init__()
        self.add_styles('''
                        table tr[data-good='true'] {
                            color: #B4DEA6;
                        }
                        ''')


class ManualClustering(object):<commit_msg>Clearer color of good clusters<commit_after># -*- coding: utf-8 -*-

"""Manual clustering GUI component."""


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

from functools import partial
import logging

import numpy as np

from ._history import GlobalHistory
from ._utils import create_cluster_meta
from .clustering import Clustering
from phy.stats.clusters import (mean,
                                max_waveform_amplitude,
                                mean_masked_features_distance,
                                )
from phy.gui.actions import Actions
from phy.gui.widgets import Table
from phy.io.array import select_spikes

logger = logging.getLogger(__name__)


# -----------------------------------------------------------------------------
# Utility functions
# -----------------------------------------------------------------------------

def _process_ups(ups):  # pragma: no cover
    """This function processes the UpdateInfo instances of the two
    undo stacks (clustering and cluster metadata) and concatenates them
    into a single UpdateInfo instance."""
    if len(ups) == 0:
        return
    elif len(ups) == 1:
        return ups[0]
    elif len(ups) == 2:
        up = ups[0]
        up.update(ups[1])
        return up
    else:
        raise NotImplementedError()


def default_wizard_functions(waveforms=None,
                             features=None,
                             masks=None,
                             n_features_per_channel=None,
                             spikes_per_cluster=None,
                             ):
    spc = spikes_per_cluster
    nfc = n_features_per_channel

    def max_waveform_amplitude_quality(cluster):
        spike_ids = select_spikes(cluster_ids=[cluster],
                                  max_n_spikes_per_cluster=100,
                                  spikes_per_cluster=spc,
                                  )
        m = np.atleast_2d(masks[spike_ids])
        w = np.atleast_3d(waveforms[spike_ids])
        mean_masks = mean(m)
        mean_waveforms = mean(w)
        q = max_waveform_amplitude(mean_masks, mean_waveforms)
        logger.debug("Computed cluster quality for %d: %.3f.",
                     cluster, q)
        return q

    def mean_masked_features_similarity(c0, c1):
        s0 = select_spikes(cluster_ids=[c0],
                           max_n_spikes_per_cluster=100,
                           spikes_per_cluster=spc,
                           )
        s1 = select_spikes(cluster_ids=[c1],
                           max_n_spikes_per_cluster=100,
                           spikes_per_cluster=spc,
                           )

        f0 = features[s0]
        m0 = np.atleast_2d(masks[s0])

        f1 = features[s1]
        m1 = np.atleast_2d(masks[s1])

        mf0 = mean(f0)
        mm0 = mean(m0)

        mf1 = mean(f1)
        mm1 = mean(m1)

        d = mean_masked_features_distance(mf0, mf1, mm0, mm1,
                                          n_features_per_channel=nfc,
                                          )
        d = 1. / max(1e-10, d)  # From distance to similarity.
        logger.log(5, "Computed cluster similarity for (%d, %d): %.3f.",
                   c0, c1, d)
        return d

    return (max_waveform_amplitude_quality,
            mean_masked_features_similarity)


# -----------------------------------------------------------------------------
# Clustering GUI component
# -----------------------------------------------------------------------------

class ClusterView(Table):
    def __init__(self):
        super(ClusterView, self).__init__()
        self.add_styles('''
                        table tr[data-good='true'] {
                            color: #86D16D;
                        }
                        ''')


class ManualClustering(object):
{'fraction_non_alphanumeric': 0.18959155108792466, 'fraction_numerical': 0.014760147601476014, 'mean_word_length': 1.154014798574952, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3205398', 'n_tokens_mistral': 2139, 'n_tokens_neox': 1992, 'n_words': 423}