def _plot_cluster(self, bunch): wave = bunch.data if wave is None or not wave.size: return channel_ids_loc = bunch.channel_ids n_channels = len(channel_ids_loc) masks = bunch.get('masks', np.ones((wave.shape[0], n_channels))) # By default, this is 0, 1, 2 for the first 3 clusters. # But it can be customized when displaying several sets # of waveforms per cluster. n_spikes_clu, n_samples = wave.shape[:2] assert wave.shape[2] == n_channels assert masks.shape == (n_spikes_clu, n_channels) # Find the x coordinates. t = get_linear_x(n_spikes_clu * n_channels, n_samples) t = _overlap_transform(t, offset=bunch.offset, n=bunch.n_clu, overlap=self.overlap) # HACK: on the GPU, we get the actual masks with fract(masks) # since we add the relative cluster index. We need to ensure # that the masks is never 1.0, otherwise it is interpreted as # 0. masks *= .99999 # NOTE: we add the cluster index which is used for the # computation of the depth on the GPU. masks += bunch.index # Generate the box index (one number per channel). box_index = _index_of(channel_ids_loc, self.channel_ids) box_index = np.repeat(box_index, n_samples) box_index = np.tile(box_index, n_spikes_clu) assert box_index.shape == (n_spikes_clu * n_channels * n_samples, ) # Generate the waveform array. wave = np.transpose(wave, (0, 2, 1)) wave = wave.reshape((n_spikes_clu * n_channels, n_samples)) self.waveform_visual.add_batch_data(x=t, y=wave, color=bunch.color, masks=masks, box_index=box_index, data_bounds=self.data_bounds)
def _plot_cluster(self, bunch, color=None): """Plot one cluster.""" wave = bunch.template # shape: (n_samples, n_channels) channel_ids_loc = bunch.channel_ids n_channels_loc = len(channel_ids_loc) n_samples, nc = wave.shape assert nc == n_channels_loc # Find the x coordinates. t = get_linear_x(n_channels_loc, n_samples) color = color or self.cluster_colors[bunch.cluster_rel] assert len(color) == 4 box_index = self._get_box_index(bunch) return Bunch( x=t, y=wave.T, color=color, box_index=box_index, data_bounds=self.data_bounds)
def _plot_cluster(self, bunch): wave = bunch.data if wave is None or not wave.size: return channel_ids_loc = bunch.channel_ids n_channels = len(channel_ids_loc) masks = bunch.get('masks', np.ones((wave.shape[0], n_channels))) # By default, this is 0, 1, 2 for the first 3 clusters. # But it can be customized when displaying several sets # of waveforms per cluster. n_spikes_clu, n_samples = wave.shape[:2] assert wave.shape[2] == n_channels assert masks.shape == (n_spikes_clu, n_channels) # Find the x coordinates. t = get_linear_x(n_spikes_clu * n_channels, n_samples) t = _overlap_transform(t, offset=bunch.offset, n=bunch.n_clu, overlap=self.overlap) # HACK: on the GPU, we get the actual masks with fract(masks) # since we add the relative cluster index. We need to ensure # that the masks is never 1.0, otherwise it is interpreted as # 0. eps = .001 masks = eps + (1 - 2 * eps) * masks # NOTE: we add the cluster index which is used for the # computation of the depth on the GPU. masks += bunch.index # Generate the box index (one number per channel). box_index = _index_of(channel_ids_loc, self.channel_ids) box_index = np.tile(box_index, n_spikes_clu) # Find the correct number of vertices depending on the current waveform visual. if self._current_visual == self.waveform_visual: # PlotVisual box_index = np.repeat(box_index, n_samples) assert box_index.size == n_spikes_clu * n_channels * n_samples else: # PlotAggVisual box_index = np.repeat(box_index, 2 * (n_samples + 2)) assert box_index.size == n_spikes_clu * n_channels * 2 * ( n_samples + 2) # Generate the waveform array. wave = np.transpose(wave, (0, 2, 1)) nw = n_spikes_clu * n_channels wave = wave.reshape((nw, n_samples)) assert self.data_bounds is not None self._current_visual.add_batch_data(x=t, y=wave, color=bunch.color, masks=masks, box_index=box_index, data_bounds=self.data_bounds) # Waveform axes. # -------------- # Horizontal y=0 lines. ax_db = self.data_bounds a, b = _overlap_transform(np.array([-1, 1]), offset=bunch.offset, n=bunch.n_clu, overlap=self.overlap) box_index = _index_of(channel_ids_loc, self.channel_ids) box_index = np.repeat(box_index, 2) box_index = np.tile(box_index, n_spikes_clu) hpos = np.tile([[a, 0, b, 0]], (nw, 1)) assert box_index.size == hpos.shape[0] * 2 self.line_visual.add_batch_data( pos=hpos, color=self.ax_color, data_bounds=ax_db, box_index=box_index, ) # Vertical ticks every millisecond. steps = np.arange(np.round(self.wave_duration * 1000)) # A vline every millisecond. x = .001 * steps # Scale to [-1, 1], same coordinates as the waveform points. x = -1 + 2 * x / self.wave_duration # Take overlap into account. x = _overlap_transform(x, offset=bunch.offset, n=bunch.n_clu, overlap=self.overlap) x = np.tile(x, len(channel_ids_loc)) # Generate the box index. box_index = _index_of(channel_ids_loc, self.channel_ids) box_index = np.repeat(box_index, x.size // len(box_index)) assert x.size == box_index.size self.tick_visual.add_batch_data( x=x, y=np.zeros_like(x), data_bounds=ax_db, box_index=box_index, )