def normalize_signals(signals, normalization=None, axis=None, percent=None): # Following pylab demean: def matrix_subtract_along_axis(x, y, axis=0): "Return x minus y, where y corresponds to some statistic of x along the specified axis" if axis == 0 or axis is None or x.ndim <= 1: return x - y ind = [slice(None)] * x.ndim ind[axis] = np.newaxis return x - y[ind] def matrix_divide_along_axis(x, y, axis=0): "Return x divided by y, where y corresponds to some statistic of x along the specified axis" if axis == 0 or axis is None or x.ndim <= 1: return x / y ind = [slice(None)] * x.ndim ind[axis] = np.newaxis return x / y[ind] for norm, ax, prcnd in zip(ensure_list(normalization), cycle(ensure_list(axis)), cycle(ensure_list(percent))): if isinstance(norm, string_types): if isequal_string(norm, "zscore"): signals = zscore(signals, axis=ax) # / 3.0 elif isequal_string(norm, "baseline-std"): signals = normalize_signals(["baseline", "std"], axis=axis) elif norm.find("baseline") == 0 and norm.find("amplitude") >= 0: signals = normalize_signals(signals, ["baseline", norm.split("-")[1]], axis=axis, percent=percent) elif isequal_string(norm, "minmax"): signals = normalize_signals(signals, ["min", "max"], axis=axis) elif isequal_string(norm, "mean"): signals = demean(signals, axis=ax) elif isequal_string(norm, "baseline"): if prcnd is None: prcnd = 1 signals = matrix_subtract_along_axis(signals, np.percentile(signals, prcnd, axis=ax), axis=ax) elif isequal_string(norm, "min"): signals = matrix_subtract_along_axis(signals, np.min(signals, axis=ax), axis=ax) elif isequal_string(norm, "max"): signals = matrix_divide_along_axis(signals, np.max(signals, axis=ax), axis=ax) elif isequal_string(norm, "std"): signals = matrix_divide_along_axis(signals, signals.std(axis=ax), axis=ax) elif norm.find("amplitude") >= 0: if prcnd is None: prcnd = [1, 99] amplitude = np.percentile(signals, prcnd[1], axis=ax) - np.percentile(signals, prcnd[0], axis=ax) this_ax = ax if isequal_string(norm.split("amplitude")[0], "max"): amplitude = amplitude.max() this_ax = None elif isequal_string(norm.split("amplitude")[0], "mean"): amplitude = amplitude.mean() this_ax = None signals = matrix_divide_along_axis(signals, amplitude, axis=this_ax) else: raise_value_error("Ignoring signals' normalization " + normalization + ",\nwhich is not one of the currently available " + str(NORMALIZATION_METHODS) + "!", logger) return signals
def update_dimension_names(self, dim_names, dim_indices=None): dim_names = ensure_list(dim_names) if dim_indices is None: dim_indices = list(range(len(dim_names))) else: dim_indices = ensure_list(dim_indices) labels_ordering = list(self.labels_ordering) for dim_name, dim_index in zip(dim_names, dim_indices): labels_ordering[dim_index] = dim_name try: old_dim_name = self.labels_ordering[dim_index] dim_labels = list(self.labels_dimensions[old_dim_name]) del self.labels_dimensions[old_dim_name] self.labels_dimensions[dim_name] = dim_labels except: pass self.labels_ordering = labels_ordering
def _check_indices(self, indices, dimension): dim_index = self.get_dimension_index(dimension) for index in ensure_list(indices): if index < 0 or index > self.data.shape[dim_index]: self.logger.error( "Some of the given indices are out of %s range: [0, %s]", (self.get_dimension_name(dim_index), self.data.shape[dim_index])) raise IndexError
def _index_or_label_or_slice(self, inputs): inputs = ensure_list(inputs) if numpy.all([is_integer(inp) for inp in inputs]): return "index" elif numpy.all([isinstance(inp, string_types) for inp in inputs]): return "label" elif numpy.all([isinstance(inp, slice) for inp in inputs]): return "slice" else: raise ValueError( "input %s is not of type integer, string or slice!" % str(inputs))
def _get_index_of_label(self, labels, dimension): indices = [] data_labels = list(self.get_dimension_labels(dimension)) for label in ensure_list(labels): try: indices.append(data_labels.index(label)) # TODO: force list error here to be IndexError instead of ValueError except IndexError: self.logger.error( "Cannot access index of %s label: %s. Existing %s labels: %s" % (dimension, label, dimension, str(data_labels))) raise IndexError return indices
def slice_data_across_dimension_by_index(self, indices, dimension, **kwargs): dim_index = self.get_dimension_index(dimension) indices = ensure_list(indices) self._check_indices(indices, dim_index) slices = [slice(None)] * 4 slices[dim_index] = indices data = self.data[tuple(slices)] labels_dimensions = deepcopy(self.labels_dimensions) try: labels_dimensions[self.get_dimension_name(dim_index)] = \ (numpy.array(labels_dimensions[self.get_dimension_name(dim_index)])[indices]).tolist() except: self.logger.warn( "Failed to get labels subset for indices %s of dimension %d!" % (str(indices), dim_index)) labels_dimensions[self.get_dimension_name(dim_index)] = [] return self.duplicate(data=data, labels_dimensions=labels_dimensions, **kwargs)
def _slice_to_indices(self, slices, dim_index): indices = [] for slice in ensure_list(slices): if slice.start is None: start = 0 else: start = slice.start if slice.stop is None: stop = self.data.shape[dim_index] else: stop = slice.stop if slice.step is None: step = 1 else: step = slice.step slice.step = 1 indices.append(list(range(start, stop, step))) if len(indices) == 1: return indices[0] return tuple(indices)
def plot_bars(self, data, ax=None, fig=None, title="", group_names=[], legend_prefix="", figsize=None): def barlabel(ax, rects, positions): """ Attach a text label on each bar displaying its height """ for rect, pos in zip(rects, positions): height = rect.get_height() if pos < 0: y = -height pos = 0.75 * pos else: y = height pos = 0.25 * pos ax.text(rect.get_x() + rect.get_width() / 2., pos, '%0.2f' % y, color="k", ha='center', va='bottom', rotation=90) if fig is None: if not isinstance(figsize, (tuple, list)): figsize = self.config.VERY_LARGE_SIZE fig, ax = pyplot.subplots(1, 1, figsize=figsize) show_and_save = True else: show_and_save = False if ax is None: ax = pyplot.gca() if isinstance( data, (list, tuple)): # If, there are many groups, data is a list: # Fill in with nan in case that not all groups have the same number of elements data = numpy.array( list(zip_longest(*ensure_list(data), fillvalue=numpy.nan))).T elif data.ndim == 1: # This is the case where there is only one group... data = numpy.expand_dims(data, axis=1).T n_groups, n_elements = data.shape posmax = numpy.nanmax(data) negmax = numpy.nanmax(-(-data)) n_groups_names = len(group_names) if n_groups_names != n_groups: if n_groups_names != 0: self.logger.warning( "Ignoring group_names because their number (" + str(n_groups_names) + ") is not equal to the number of groups (" + str(n_groups) + ")!") group_names = n_groups * [""] colorcycle = pyplot.rcParams['axes.prop_cycle'].by_key()['color'] n_colors = len(colorcycle) x_inds = numpy.arange(n_groups) width = 0.9 / n_elements elements = [] for iE in range(n_elements): elements.append( ax.bar(x_inds + iE * width, data[:, iE], width, color=colorcycle[iE % n_colors])) positions = numpy.array( [negmax if d < 0 else posmax for d in data[:, iE]]) positions[numpy.logical_or(numpy.isnan(positions), numpy.isinf( numpy.abs(positions)))] = 0.0 barlabel(ax, elements[-1], positions) if n_elements > 1: legend = [ legend_prefix + str(ii) for ii in range(1, n_elements + 1) ] ax.legend(tuple([element[0] for element in elements]), tuple(legend)) ax.set_xticks(x_inds + n_elements * width / 2) ax.set_xticklabels(tuple(group_names)) ax.set_title(title) ax.autoscale() # tight=True ax.set_xlim([-1.05 * width, n_groups * 1.05]) if show_and_save: fig.tight_layout() self._save_figure(fig) self._check_show() return fig, ax
def pair_plots(self, data, keys, diagonal_plots={}, transpose=False, skip=0, title='Pair plots', legend_prefix="", subtitles=None, figure_name=None, figsize=None): def confirm_y_coordinate(data, ymax): data = list(data) data.append(ymax) return tuple(data) if not isinstance(figsize, (tuple, list)): figsize = self.config.VERY_LARGE_SIZE if subtitles is None: subtitles = keys data = ensure_list(data) n = len(keys) fig, axes = pyplot.subplots(n, n, figsize=figsize) fig.set_label(title) colorcycle = pyplot.rcParams['axes.prop_cycle'].by_key()['color'] for i, key_i in enumerate(keys): for j, key_j in enumerate(keys): for datai in data: if transpose: di = datai[key_i].T[skip:] else: di = datai[key_i][skip:] if i == j: if di.shape[0] > 1: hist_data = axes[i, j].hist( di, int(numpy.round(numpy.sqrt(len(di)))), log=True)[0] if i == 0 and len( di.shape) > 1 and di.shape[1] > 1: axes[i, j].legend([ legend_prefix + str(ii + 1) for ii in range(di.shape[1]) ]) y_max = numpy.array(hist_data).max() # The mean line axes[i, j].vlines(di.mean(axis=0), 0, y_max, color=colorcycle, linestyle='dashed', linewidth=1) else: # This is for the case of only 1 sample (optimization) y_max = 1.0 for ii in range(di.shape[1]): axes[i, j].plot( di[0, ii], y_max, "D", color=colorcycle[ii % di.shape[1]], markersize=20, label=legend_prefix + str(ii + 1)) if i == 0 and len( di.shape) > 1 and di.shape[1] > 1: axes[i, j].legend() # Plot a line (or marker) in the same axis diag_line_plot = ensure_list( diagonal_plots.get(key_i, ((), ()))[0]) if len(diag_line_plot) in [1, 2]: if len(diag_line_plot) == 1: diag_line_plot = confirm_y_coordinate( diag_line_plot, y_max) else: diag_line_plot[1] = diag_line_plot[ 1] / numpy.max(diag_line_plot[1]) * y_max if len(ensure_list(diag_line_plot[0])) == 1: axes[i, j].plot(diag_line_plot[0], diag_line_plot[1], "o", mfc="k", mec="k", markersize=10) else: axes[i, j].plot(diag_line_plot[0], diag_line_plot[1], color='k', linestyle="dashed", linewidth=1) # Plot a marker in the same axis diag_marker_plot = ensure_list( diagonal_plots.get(key_i, ((), ()))[1]) if len(diag_marker_plot) in [1, 2]: if len(diag_marker_plot) == 1: diag_marker_plot = confirm_y_coordinate( diag_marker_plot, y_max) axes[i, j].plot(diag_marker_plot[0], diag_marker_plot[1], "*", color='k', markersize=10) axes[i, j].autoscale() axes[i, j].set_ylim([0, 1.1 * y_max]) else: if transpose: dj = datai[key_j].T[skip:] else: dj = datai[key_j][skip:] axes[i, j].plot(dj, di, '.') if i == 0: axes[i, j].set_title(subtitles[j]) if j == 0: axes[i, j].set_ylabel(key_i) fig.tight_layout() self._save_figure(fig, figure_name) self._check_show() return fig, axes
def plot_ts(self, data, time=None, var_labels=[], mode="ts", subplots=None, special_idx=[], subtitles=[], labels=[], offset=0.5, time_unit="ms", title='Time series', figure_name=None, figsize=None): if not isinstance(figsize, (list, tuple)): figsize = self.config.LARGE_SIZE if isinstance(data, dict): var_labels = data.keys() data = data.values() elif isinstance(data, numpy.ndarray): if len(data.shape) < 3: if len(data.shape) < 2: data = numpy.expand_dims(data, 1) data = numpy.expand_dims(data, 2) data = [data] else: # Assuming a structure of Time X Space X Variables X Samples data = [ data[:, :, iv].squeeze() for iv in range(data.shape[2]) ] elif isinstance(data, (list, tuple)): data = ensure_list(data) else: LOG.error("Input timeseries: %s \n" "is not on of one of the following types: " "[numpy.ndarray, dict, list, tuple]" % str(data)) n_vars = len(data) data_lims = [] for id, d in enumerate(data): if isequal_string(mode, "raster"): data[id] = (d - d.mean(axis=0)) drange = numpy.max(data[id].max(axis=0) - data[id].min(axis=0)) data[id] = data[id] / drange # zscore(d, axis=None) data_lims.append([d.min(), d.max()]) data_shape = data[0].shape if len(data_shape) == 1: n_times = data_shape[0] nTS = 1 for iV in range(n_vars): data[iV] = data[iV][:, numpy.newaxis] else: n_times, nTS = data_shape[:2] if len(data_shape) > 2: nSamples = data_shape[2] else: nSamples = 1 if special_idx is None: special_idx = [] n_special_idx = len(special_idx) if len(subtitles) == 0: subtitles = var_labels if isinstance(labels, list) and len(labels) == n_vars: labels = [ generate_region_labels(nTS, label, ". ", self.print_ts_indices) for label in labels ] else: labels = [ generate_region_labels(nTS, labels, ". ", self.print_ts_indices) for _ in range(n_vars) ] if isequal_string(mode, "traj"): data_fun, plot_lines, projection, n_rows, n_cols, def_alpha, loopfun, \ subtitle, subtitle_col, axlabels, axlimits = \ self._trajectories_plot(n_vars, nTS, nSamples, subplots) else: if isequal_string(mode, "raster"): data_fun, time, plot_lines, projection, n_rows, n_cols, def_alpha, loopfun, \ subtitle, subtitle_col, axlabels, axlimits, axYticks = \ self._ts_plot(time, n_vars, nTS, n_times, time_unit, 0, offset, data_lims) else: data_fun, time, plot_lines, projection, n_rows, n_cols, def_alpha, loopfun, \ subtitle, subtitle_col, axlabels, axlimits, axYticks = \ self._ts_plot(time, n_vars, nTS, n_times, time_unit, ensure_list(subplots)[0]) alpha_ratio = 1.0 / nSamples alphas = numpy.maximum( numpy.array([def_alpha] * nTS) * alpha_ratio, 0.1) alphas[special_idx] = numpy.maximum(alpha_ratio, 0.1) if isequal_string(mode, "traj") and (n_cols * n_rows > 1): colors = numpy.zeros((nTS, 4)) colors[special_idx] = \ numpy.array([numpy.array([1.0, 0, 0, 1.0]) for _ in range(n_special_idx)]).reshape((n_special_idx, 4)) else: cmap = matplotlib.cm.get_cmap('jet') colors = numpy.array([cmap(0.5 * iTS / nTS) for iTS in range(nTS)]) colors[special_idx] = \ numpy.array([cmap(1.0 - 0.25 * iTS / nTS) for iTS in range(n_special_idx)]).reshape((n_special_idx, 4)) colors[:, 3] = alphas lines = [] pyplot.figure(title, figsize=figsize) axes = [] for icol in range(n_cols): if n_rows == 1: # If there are no more rows, create axis, and set its limits, labels and possible subtitle axes += ensure_list( pyplot.subplot(n_rows, n_cols, icol + 1, projection=projection)) axlimits(data_lims, time, n_vars, icol) axlabels(labels[icol % n_vars], var_labels, n_vars, n_rows, 1, 0) pyplot.gca().set_title(subtitles[icol]) for iTS in loopfun(nTS, n_rows, icol): if n_rows > 1: # If there are more rows, create axes, and set their limits, labels and possible subtitles axes += ensure_list( pyplot.subplot(n_rows, n_cols, iTS + 1, projection=projection)) axlimits(data_lims, time, n_vars, icol) subtitle(labels[icol % n_vars], iTS) axlabels(labels[icol % n_vars], var_labels, n_vars, n_rows, (iTS % n_rows) + 1, iTS) lines += ensure_list( plot_lines(data_fun(data, time, icol), iTS, colors, labels[icol % n_vars])) if isequal_string( mode, "raster"): # set yticks as labels if this is a raster plot axYticks(labels[icol % n_vars], nTS) yticklabels = pyplot.gca().yaxis.get_ticklabels() self.tick_font_size = numpy.minimum( self.tick_font_size, int(numpy.round(self.tick_font_size * 100.0 / nTS))) for iTS in range(nTS): yticklabels[iTS].set_fontsize(self.tick_font_size) if iTS in special_idx: yticklabels[iTS].set_color(colors[iTS, :3].tolist() + [1]) pyplot.gca().yaxis.set_ticklabels(yticklabels) pyplot.gca().invert_yaxis() if self.config.MOUSE_HOOVER: for line in lines: self.HighlightingDataCursor(line, formatter='{label}'.format, bbox=dict(fc='white'), arrowprops=dict( arrowstyle='simple', fc='white', alpha=0.5)) self._save_figure(pyplot.gcf(), figure_name) self._check_show() return pyplot.gcf(), axes, lines
def plot_time_series(self, **kwargs): """ Plot a view on the timeseries. """ # Set title and axis labels # time_series_type = self.time_series.__class__.__name__ # self.ts_ax.set(title = time_series_type) # self.ts_ax.set(xlabel = "Time (%s)" % self.units) # This assumes shape => (time, space) step = self.scaling * self.peak_to_peak if step == 0: offset = 0.0 else: # NOTE: specifying step in arange is faster, but it fence-posts. offset = numpy.arange(0, self.nsrs) * step if hasattr(self.ts_ax, 'autoscale'): self.ts_ax.autoscale(enable=True, axis='both', tight=True) self.ts_ax.set_yticks(offset) self.ts_ax.set_yticklabels(self.labels, fontsize=10) # import pdb; pdb.set_trace() # Light gray guidelines self.ts_ax.plot([ self.nsrs * [self.time[self.time_view[0]]], self.nsrs * [self.time[self.time_view[-1]]] ], numpy.vstack(2 * (offset, )), "0.85") # Determine colors and linestyles for each variable of the Timeseries linestyle = ensure_list(kwargs.pop("linestyle", "-")) colors = kwargs.pop("linestyle", None) if colors is not None: colors = ensure_list(colors) if self.data.shape[1] > 1: linestyle = rotate_n_list_elements(linestyle, self.data.shape[1]) if not isinstance(colors, list): colors = (rcParams['axes.prop_cycle']).by_key()['color'] colors = rotate_n_list_elements(colors, self.data.shape[1]) else: # If no color, # or a color sequence is given in the input # but there is only one variable to plot, # choose the black color if colors is None or len(colors) > 1: colors = ["k"] linestyle = linestyle[:1] # Determine the alpha value depending on the number of modes/samples of the Timeseries alpha = 1.0 if len(self.data.shape) > 3 and self.data.shape[3] > 1: alpha /= self.data.shape[3] # Plot the timeseries per variable and sample self.ts_view = [] for i_var in range(self.data.shape[1]): for ii in range(self.data.shape[3]): # Plot the timeseries self.ts_view.append( self.ts_ax.plot(self.time[self.time_view], offset + self.data[self.time_view, i_var, :, ii], alpha=alpha, color=colors[i_var], linestyle=linestyle[i_var], **kwargs)) self.hereiam[0].remove() self.hereiam = self.whereami_ax.plot(self.time_view, numpy.zeros( (len(self.time_view), )), 'b-', linewidth=4) pylab.draw()
def get_sensors_inds_by_sensors_labels(self, lbls): # Make sure that the labels are not bipolar: lbls = [label.split("-")[0] for label in ensure_list(lbls)] return labels_to_inds(self._tvb.labels, lbls)