From 6fe2e9ab74837ccf0ea65c895da9dfd387c50c2c Mon Sep 17 00:00:00 2001 From: Igor Podolak Date: Fri, 20 Mar 2020 18:36:58 +0100 Subject: [PATCH 01/15] Updated drawing of network (network_status_graph.py; vertically centered); marking of true/predicted classes (record.py), randomization of starting weights (ebner_agent.py) --- neuronpp/utils/network_status_graph.py | 19 +++++++-- neuronpp/utils/record.py | 54 ++++++++++++++++++++------ 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/neuronpp/utils/network_status_graph.py b/neuronpp/utils/network_status_graph.py index e62b30ab..99a2da15 100644 --- a/neuronpp/utils/network_status_graph.py +++ b/neuronpp/utils/network_status_graph.py @@ -26,6 +26,7 @@ def __init__(self, cells, weight_name='w', plot_fixed_weight_edges=True): self.correct_position = (0.1, 0.1) + self.population_sizes = dict() self.population_names = self._get_population_names() self.edges = self._get_edges(weight_name) @@ -38,6 +39,8 @@ def plot(self): self.y_list[cell_num], s=300, color=self.colors[cell_num], alpha=0.5)) for target in edge: + if target[0][0] == 2 and target[0][1] == 1 and target[1][1] == 5: + pass line, = ax2.plot(target[0], target[1], lw=target[2], color='grey') self.lines.append(line) n = 0 @@ -69,6 +72,10 @@ def update_spikes(self, sim_time): def _get_edges(self, weight_name): result = [] + # compute the number of cells in each layer + for c in self.cells: + pop_name = c.name.split('[')[0] + self.population_sizes[pop_name] = self.population_sizes.get(pop_name, 0) + 1 for c in self.cells: soma = c.filter_secs('soma') if c._spike_detector is None: @@ -81,11 +88,13 @@ def _get_edges(self, weight_name): except ValueError: x_pos = self.population_names.index(pop_name) - y_pos = int(split_name[-1][:-1]) + # shift down the layer by half its size to vertically center graph + y_pos = int(split_name[-1][:-1]) - self.population_sizes[pop_name] // 2 if 'inh' in c.name: self.colors.append('red') - y_pos -= 5 + # todo center vertically by half width of the hid layer + y_pos -= 6 elif 'hid' in c.name: self.colors.append('blue') else: @@ -110,7 +119,8 @@ def _find_target(self, c, x_pos, y_pos, weight_name): except ValueError: x_trg = self.population_names.index(pop_name) - y_trg = int(split_target[-1][:-1]) + # center veritically + y_trg = int(split_target[-1][:-1]) - self.population_sizes[pop_name] // 2 weight = None if self.plot_constant_connections and hasattr(nc.target.hoc, weight_name): @@ -125,7 +135,8 @@ def _find_weights(c, weight_name): for nc in c.ncs: if "SpikeDetector" in nc.name: continue - elif isinstance(nc.source, Seg) and isinstance(nc.target, PointProcess) and hasattr(nc.target.hoc, weight_name): + elif isinstance(nc.source, Seg) and isinstance(nc.target, PointProcess) and hasattr(nc.target.hoc, + weight_name): weight = getattr(nc.target.hoc, weight_name) targets.append(weight) return targets diff --git a/neuronpp/utils/record.py b/neuronpp/utils/record.py index 13b6e2d3..275a233d 100644 --- a/neuronpp/utils/record.py +++ b/neuronpp/utils/record.py @@ -1,11 +1,9 @@ -from nrn import Segment, Section from collections import defaultdict +import matplotlib.pyplot as plt import numpy as np import pandas as pd from neuron import h -import matplotlib.pyplot as plt - from neuronpp.core.hocwrappers.seg import Seg @@ -39,7 +37,8 @@ def __init__(self, elements, variables='v'): try: s = getattr(elem.hoc, "_ref_%s" % var) except AttributeError: - raise AttributeError("there is no attribute of %s. Maybe you forgot to append loc param for sections?" % var) + raise AttributeError( + "there is no attribute of %s. Maybe you forgot to append loc param for sections?" % var) rec = h.Vector().record(s) self.recs[var].append((name, rec)) @@ -84,16 +83,19 @@ def _plot_static(self, position=None): for i, (name, rec) in enumerate(section_recs): rec_np = rec.as_numpy() if np.max(np.isnan(rec_np)): - raise ValueError("Vector recorded for variable: '%s' and segment: '%s' contains nan values." % (var_name, name)) + raise ValueError( + "Vector recorded for variable: '%s' and segment: '%s' contains nan values." % (var_name, name)) if position is not "merge": - ax = self._get_subplot(fig=fig, var_name=var_name, position=position, row_len=len(section_recs), index=i + 1) + ax = self._get_subplot(fig=fig, var_name=var_name, position=position, row_len=len(section_recs), + index=i + 1) ax.set_title("Variable: %s" % var_name) ax.plot(self.t, rec, label=name) ax.set(xlabel='t (ms)', ylabel=var_name) ax.legend() - def _plot_animate(self, steps=10000, y_lim=None, position=None): + def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, pred_class=None, stepsize=None, + dt=None): """ Call each time you want to redraw plot. @@ -125,13 +127,14 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None): if position == 'merge': ax = fig.add_subplot(1, 1, 1) else: - ax = self._get_subplot(fig=fig, var_name=var_name, position=position, row_len=len(section_recs), index=i + 1) + ax = self._get_subplot(fig=fig, var_name=var_name, position=position, row_len=len(section_recs), + index=i + 1) if y_lim: ax.set_ylim(y_lim[0], y_lim[1]) line, = ax.plot([], lw=1) - ax.set_title("Variable: %s" % var_name) - ax.set_ylabel(var_name) + # ax.set_title("Variable: %s" % var_name) + ax.set_ylabel("{}_{}".format(var_name, i)) ax.set_xlabel("t (ms)") ax.legend() @@ -143,17 +146,44 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None): ax.set_xlim(t.min(), t.max()) if y_lim is None: - ax.set_ylim(r.min()-(np.abs(r.min()*0.05)), r.max()+(np.abs(r.max()*0.05))) + ax.set_ylim(r.min() - (np.abs(r.min() * 0.05)), r.max() + (np.abs(r.max() * 0.05))) # update data line.set_data(t, r) - + # info draw triangles for true and predicted classes + true_x, true_y, pred_x, pred_y = self._class_tcks(label=i, true_class=true_class, pred_class=pred_class, + t=t, stepsize=stepsize, dt=dt) + ax.scatter(true_x, true_y, c="orange", marker="^", alpha=0.95) + ax.scatter(pred_x, pred_y, c="magenta", marker="v", alpha=0.95) + + # info join plots by removing labels and ticks from subplots that are not on the edge + for key in self.axs: + for ax in self.axs[key]: + ax[0].label_outer() + fig.subplots_adjust(left=0.09, bottom=0.075, right=0.99, top=0.98, wspace=None, hspace=0.00) fig.canvas.draw() fig.canvas.flush_events() if create_fig: plt.show(block=False) + def _class_tcks(self, label, true_class, pred_class, t, stepsize, dt): + n = len(true_class) + x = t[::int(2 * stepsize / dt)][-n:] + true_x = [] + true_y = [] + pred_x = [] + pred_y = [] + for k in range(n): + # get the true classes for the current label + if true_class[k] == label: + true_x.append(x[k]) + true_y.append(-69) + if pred_class[k] == label: + pred_x.append(x[k]) + pred_y.append(30) + return true_x, true_y, pred_x, pred_y + def to_csv(self, filename): cols = ['time'] data = [self.t.as_numpy().tolist()] From d5df4243762226175488c184ca0d4bd6264e709c Mon Sep 17 00:00:00 2001 From: Igor Podolak Date: Sun, 22 Mar 2020 10:02:33 +0100 Subject: [PATCH 02/15] "selection of output in record.py" --- neuronpp/utils/record.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/neuronpp/utils/record.py b/neuronpp/utils/record.py index 275a233d..af235d48 100644 --- a/neuronpp/utils/record.py +++ b/neuronpp/utils/record.py @@ -152,7 +152,7 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, line.set_data(t, r) # info draw triangles for true and predicted classes true_x, true_y, pred_x, pred_y = self._class_tcks(label=i, true_class=true_class, pred_class=pred_class, - t=t, stepsize=stepsize, dt=dt) + t=t, r=r, stepsize=stepsize, dt=dt) ax.scatter(true_x, true_y, c="orange", marker="^", alpha=0.95) ax.scatter(pred_x, pred_y, c="magenta", marker="v", alpha=0.95) @@ -167,21 +167,19 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, if create_fig: plt.show(block=False) - def _class_tcks(self, label, true_class, pred_class, t, stepsize, dt): + def _class_tcks(self, label, true_class, pred_class, t, r, stepsize, dt): n = len(true_class) x = t[::int(2 * stepsize / dt)][-n:] true_x = [] - true_y = [] pred_x = [] - pred_y = [] for k in range(n): # get the true classes for the current label if true_class[k] == label: true_x.append(x[k]) - true_y.append(-69) if pred_class[k] == label: pred_x.append(x[k]) - pred_y.append(30) + true_y = [min(r) + 2] * len(true_x) + pred_y = [max(r) - 2] * len(pred_x) return true_x, true_y, pred_x, pred_y def to_csv(self, filename): From e5fe31f661e8a537cdea87c765cb44116676a651 Mon Sep 17 00:00:00 2001 From: Igor Podolak Date: Mon, 23 Mar 2020 11:41:39 +0100 Subject: [PATCH 03/15] "centered display of graph in network_status_graph.py; selection of output in record.py" --- neuronpp/utils/network_status_graph.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/neuronpp/utils/network_status_graph.py b/neuronpp/utils/network_status_graph.py index 99a2da15..1382d732 100644 --- a/neuronpp/utils/network_status_graph.py +++ b/neuronpp/utils/network_status_graph.py @@ -39,8 +39,6 @@ def plot(self): self.y_list[cell_num], s=300, color=self.colors[cell_num], alpha=0.5)) for target in edge: - if target[0][0] == 2 and target[0][1] == 1 and target[1][1] == 5: - pass line, = ax2.plot(target[0], target[1], lw=target[2], color='grey') self.lines.append(line) n = 0 From 4fb520fa2a7e26f077fd1692a20a052c1ba7b039 Mon Sep 17 00:00:00 2001 From: Igor Podolak Date: Tue, 24 Mar 2020 18:18:57 +0100 Subject: [PATCH 04/15] Display of true/predicted classes in record.py; true_labels added as class labels parameter --- neuronpp/utils/record.py | 49 ++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/neuronpp/utils/record.py b/neuronpp/utils/record.py index af235d48..a6ad80b1 100644 --- a/neuronpp/utils/record.py +++ b/neuronpp/utils/record.py @@ -95,7 +95,7 @@ def _plot_static(self, position=None): ax.legend() def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, pred_class=None, stepsize=None, - dt=None): + dt=None, show_true_predicted=True, true_labels=None): """ Call each time you want to redraw plot. @@ -118,7 +118,7 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, fig = self.figs[var_name] if fig is None: create_fig = True - fig = plt.figure() + fig = plt.figure(figsize=(15, 5)) fig.canvas.draw() self.figs[var_name] = fig @@ -136,7 +136,6 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, # ax.set_title("Variable: %s" % var_name) ax.set_ylabel("{}_{}".format(var_name, i)) ax.set_xlabel("t (ms)") - ax.legend() self.axs[var_name].append((ax, line)) @@ -146,28 +145,46 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, ax.set_xlim(t.min(), t.max()) if y_lim is None: - ax.set_ylim(r.min() - (np.abs(r.min() * 0.05)), r.max() + (np.abs(r.max() * 0.05))) + y_limits = (r.min() - (np.abs(r.min() * 0.05)), r.max() + (np.abs(r.max() * 0.05))) + ax.set_ylim(y_limits) # update data line.set_data(t, r) - # info draw triangles for true and predicted classes - true_x, true_y, pred_x, pred_y = self._class_tcks(label=i, true_class=true_class, pred_class=pred_class, - t=t, r=r, stepsize=stepsize, dt=dt) - ax.scatter(true_x, true_y, c="orange", marker="^", alpha=0.95) - ax.scatter(pred_x, pred_y, c="magenta", marker="v", alpha=0.95) + if show_true_predicted: + # info draw triangles for true and predicted classes + # todo pass true labels from the, not the iterator value + if true_labels is not None: + true_x, pred_x = self._true_predicted_class_marks(label=true_labels[i], true_class=true_class, + pred_class=pred_class, t=t, r=r, + stepsize=stepsize, dt=dt) + else: + raise ValueError("True_labels parameter need to be given if show_true_prediction is True") + if y_lim is None: + true_y = [y_limits[0] + np.abs(y_limits[0]) * 0.09] * len(true_x) + pred_y = [y_limits[1] - np.abs(y_limits[1] * 0.11)] * len(pred_x) + else: + true_y = [y_lim[0]] * len(true_x) + pred_y = [y_lim[1]] * len(pred_x) + ax.scatter(true_x, true_y, c="orange", marker="^", alpha=0.95, label="true") + ax.scatter(pred_x, pred_y, c="magenta", marker="v", alpha=0.95, label="predicted") + if create_fig and i == 0: + # draw legend only the first time and only on the uppermost graph + ax.legend() # info join plots by removing labels and ticks from subplots that are not on the edge - for key in self.axs: - for ax in self.axs[key]: - ax[0].label_outer() - fig.subplots_adjust(left=0.09, bottom=0.075, right=0.99, top=0.98, wspace=None, hspace=0.00) + if create_fig: + for key in self.axs: + for ax in self.axs[key]: + ax[0].label_outer() + fig.subplots_adjust(left=0.09, bottom=0.075, right=0.99, top=0.98, wspace=None, hspace=0.00) fig.canvas.draw() fig.canvas.flush_events() if create_fig: plt.show(block=False) - def _class_tcks(self, label, true_class, pred_class, t, r, stepsize, dt): + # todo lejbel szud bi imported from de oridzinal fankszion + def _true_predicted_class_marks(self, label, true_class, pred_class, t, r, stepsize, dt): n = len(true_class) x = t[::int(2 * stepsize / dt)][-n:] true_x = [] @@ -178,9 +195,7 @@ def _class_tcks(self, label, true_class, pred_class, t, r, stepsize, dt): true_x.append(x[k]) if pred_class[k] == label: pred_x.append(x[k]) - true_y = [min(r) + 2] * len(true_x) - pred_y = [max(r) - 2] * len(pred_x) - return true_x, true_y, pred_x, pred_y + return true_x, pred_x def to_csv(self, filename): cols = ['time'] From 7758ed8c9cebcaa14aafc738cac3121b0db0c577 Mon Sep 17 00:00:00 2001 From: Igor Podolak Date: Wed, 25 Mar 2020 10:32:39 +0100 Subject: [PATCH 05/15] "class labels passed to record:plot() --> plot_animate()" --- neuronpp/utils/record.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neuronpp/utils/record.py b/neuronpp/utils/record.py index a6ad80b1..5ff02df3 100644 --- a/neuronpp/utils/record.py +++ b/neuronpp/utils/record.py @@ -118,7 +118,7 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, fig = self.figs[var_name] if fig is None: create_fig = True - fig = plt.figure(figsize=(15, 5)) + fig = plt.figure(figsize=(16, 5)) fig.canvas.draw() self.figs[var_name] = fig From 06fc25d4dbc99bf49ae96d64b1c523ae3dfd8ce7 Mon Sep 17 00:00:00 2001 From: Igor Podolak Date: Thu, 26 Mar 2020 10:15:22 +0100 Subject: [PATCH 06/15] Merge remote-tracking branch 'origin/master' into models_igr # Conflicts: # agents/agent.py # agents/ebner_agent.py --- neuronpp/utils/record.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neuronpp/utils/record.py b/neuronpp/utils/record.py index 5ff02df3..a4d3f010 100644 --- a/neuronpp/utils/record.py +++ b/neuronpp/utils/record.py @@ -118,7 +118,7 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, fig = self.figs[var_name] if fig is None: create_fig = True - fig = plt.figure(figsize=(16, 5)) + fig = plt.figure(figsize=(16.5, 5.5)) fig.canvas.draw() self.figs[var_name] = fig From 3ed9930601f37fa3ad5ce4366a96096d888232a8 Mon Sep 17 00:00:00 2001 From: Igor Podolak Date: Thu, 26 Mar 2020 10:34:11 +0100 Subject: [PATCH 07/15] Plotting of outputs: record.py: true_labels added; names changed --- neuronpp/utils/record.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/neuronpp/utils/record.py b/neuronpp/utils/record.py index a4d3f010..0f84c8e5 100644 --- a/neuronpp/utils/record.py +++ b/neuronpp/utils/record.py @@ -108,6 +108,12 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, * position=(3,3) -> if you have 9 neurons and want to display 'v' on 3x3 matrix * position='merge' -> it will display all figures on the same graph. * position=None -> Default, each neuron has separated axis (row) on the figure. + :param true_class: list of true class labels in this window + :param pred_class: list of predicted class labels in window + :param stepsize: agent readout time step + :param dt: agent integration time step + :param show_true_predicted: whther to print true/predicted class' marks on the plot + :param true_labels: list of true labels for the consecutive plots :return: """ create_fig = False @@ -152,7 +158,6 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, line.set_data(t, r) if show_true_predicted: # info draw triangles for true and predicted classes - # todo pass true labels from the, not the iterator value if true_labels is not None: true_x, pred_x = self._true_predicted_class_marks(label=true_labels[i], true_class=true_class, pred_class=pred_class, t=t, r=r, @@ -183,8 +188,17 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, if create_fig: plt.show(block=False) - # todo lejbel szud bi imported from de oridzinal fankszion - def _true_predicted_class_marks(self, label, true_class, pred_class, t, r, stepsize, dt): + def _true_predicted_class_marks(self, label, true_class, pred_class, t, stepsize, dt): + """ + find and return lists of time steps for true and predicted labels + :param label: the label id (an int) + :param true_class: list of true classes for the whole time region + :param pred_class: list of predicted labels (class ids) for the whole time region + :param t: the region time steps + :param stepsize: original agent stepsize; class selections are 2 * stepsize / dt + :param dt: integration step + :return: lists of marks for true_x: true classes, pred_x: predicted classes + """ n = len(true_class) x = t[::int(2 * stepsize / dt)][-n:] true_x = [] From c8fb1e2cbb779e7499df3bc0b2fedadfe0b92ec2 Mon Sep 17 00:00:00 2001 From: Igor Podolak Date: Fri, 27 Mar 2020 10:13:44 +0100 Subject: [PATCH 08/15] record.py: namedtuple as parameter method --- neuronpp/utils/record.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/neuronpp/utils/record.py b/neuronpp/utils/record.py index 0f84c8e5..1248b453 100644 --- a/neuronpp/utils/record.py +++ b/neuronpp/utils/record.py @@ -94,8 +94,9 @@ def _plot_static(self, position=None): ax.set(xlabel='t (ms)', ylabel=var_name) ax.legend() - def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, pred_class=None, stepsize=None, - dt=None, show_true_predicted=True, true_labels=None): + def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, pred_class=None, + run_params=None): + # stepsize=None,; dt=None, show_true_predicted=True, true_labels=None): """ Call each time you want to redraw plot. @@ -110,10 +111,13 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, * position=None -> Default, each neuron has separated axis (row) on the figure. :param true_class: list of true class labels in this window :param pred_class: list of predicted class labels in window - :param stepsize: agent readout time step - :param dt: agent integration time step - :param show_true_predicted: whther to print true/predicted class' marks on the plot - :param true_labels: list of true labels for the consecutive plots + :param run_class: a namedtuple containing + :param agent_stepsize: agent readout time step + :param dt: agent integration time step + :param input_cell_num: number of input cells + :param output_cell_num: number of output cells + :param true_labels: list of true labels for the consecutive plots + :param show_true_predicted: whther to print true/predicted class' marks on the plot :return: """ create_fig = False @@ -156,12 +160,13 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, # update data line.set_data(t, r) - if show_true_predicted: + if run_params.show_true_predicted: # info draw triangles for true and predicted classes - if true_labels is not None: - true_x, pred_x = self._true_predicted_class_marks(label=true_labels[i], true_class=true_class, - pred_class=pred_class, t=t, r=r, - stepsize=stepsize, dt=dt) + if run_params.true_labels is not None: + true_x, pred_x = self._true_predicted_class_marks(label=run_params.true_label[i], + true_class=true_class, + pred_class=pred_class, t=t, + run_params=run_params) else: raise ValueError("True_labels parameter need to be given if show_true_prediction is True") if y_lim is None: @@ -188,7 +193,7 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, if create_fig: plt.show(block=False) - def _true_predicted_class_marks(self, label, true_class, pred_class, t, stepsize, dt): + def _true_predicted_class_marks(self, label, true_class, pred_class, t, run_params): """ find and return lists of time steps for true and predicted labels :param label: the label id (an int) @@ -200,9 +205,10 @@ def _true_predicted_class_marks(self, label, true_class, pred_class, t, stepsize :return: lists of marks for true_x: true classes, pred_x: predicted classes """ n = len(true_class) - x = t[::int(2 * stepsize / dt)][-n:] + x = t[::int(2 * run_params.agent_stepsize / run_params.dt)][-n:] true_x = [] pred_x = [] + # todo change lists into numpy arrays for speed for k in range(n): # get the true classes for the current label if true_class[k] == label: From 597409ece41322f942949aa881eec5e6aa566da6 Mon Sep 17 00:00:00 2001 From: Igor Podolak Date: Fri, 27 Mar 2020 10:32:52 +0100 Subject: [PATCH 09/15] record.py: simulation parameters to _plot_animate passed with a namedtuple --- neuronpp/utils/record.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/neuronpp/utils/record.py b/neuronpp/utils/record.py index 1248b453..bb0df180 100644 --- a/neuronpp/utils/record.py +++ b/neuronpp/utils/record.py @@ -15,6 +15,9 @@ def __init__(self, elements, variables='v'): :param variables: str or list_of_str of variable names to track """ + if h.t > 0: + raise ConnectionRefusedError("Record cannot be created after simulation have been initiated. " + "You need to specify Record before creation of SimRun object.") if not isinstance(elements, (list, set, tuple)): elements = [elements] From cf742d93ca67e0237be6375f351ab9f4c17d9426 Mon Sep 17 00:00:00 2001 From: Igor Podolak Date: Fri, 27 Mar 2020 11:54:39 +0100 Subject: [PATCH 10/15] minor errors (due to tragic namedtuple --- neuronpp/utils/record.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/neuronpp/utils/record.py b/neuronpp/utils/record.py index bb0df180..b40b999f 100644 --- a/neuronpp/utils/record.py +++ b/neuronpp/utils/record.py @@ -135,6 +135,8 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, fig.canvas.draw() self.figs[var_name] = fig + if len(run_params.output_labels) != len(section_recs): + raise ValueError("Number of labels given is not equal to actual number of sections in current plot") for i, (name, rec) in enumerate(section_recs): if create_fig: if position == 'merge': @@ -165,8 +167,8 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, line.set_data(t, r) if run_params.show_true_predicted: # info draw triangles for true and predicted classes - if run_params.true_labels is not None: - true_x, pred_x = self._true_predicted_class_marks(label=run_params.true_label[i], + if run_params.output_labels is not None: + true_x, pred_x = self._true_predicted_class_marks(label=run_params.output_labels[i], true_class=true_class, pred_class=pred_class, t=t, run_params=run_params) From 79f38d8e5cac38f0fa83e28cd59b6f33f3eeda5d Mon Sep 17 00:00:00 2001 From: Ziemowit S Date: Fri, 27 Mar 2020 14:58:56 +0100 Subject: [PATCH 11/15] fixed Record to work with markers, not work yet --- neuronpp/utils/record.py | 80 ++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 44 deletions(-) diff --git a/neuronpp/utils/record.py b/neuronpp/utils/record.py index ecb435b6..5a963de9 100644 --- a/neuronpp/utils/record.py +++ b/neuronpp/utils/record.py @@ -1,4 +1,4 @@ -from collections import defaultdict +from collections import defaultdict, namedtuple import numpy as np import pandas as pd @@ -7,6 +7,7 @@ from neuronpp.core.hocwrappers.seg import Seg +MarkerParams = namedtuple("MarkerParams", "agent_stepsize dt input_cell_num output_cell_num true_labels true_class pred_class") class Record: def __init__(self, elements, variables='v'): @@ -98,8 +99,7 @@ def _plot_static(self, position=None): ax.set(xlabel='t (ms)', ylabel=var_name) ax.legend() - def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, pred_class=None, - run_params=None): + def _plot_animate(self, steps=10000, y_lim=None, position=None, marker_params: MarkerParams = None): # stepsize=None,; dt=None, show_true_predicted=True, true_labels=None): """ Call each time you want to redraw plot. @@ -113,16 +113,8 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, * position=(3,3) -> if you have 9 neurons and want to display 'v' on 3x3 matrix * position='merge' -> it will display all figures on the same graph. * position=None -> Default, each neuron has separated axis (row) on the figure. - :param true_class: list of true class labels in this window - :param pred_class: list of predicted class labels in window - :param run_class: a namedtuple containing - :param agent_stepsize: agent readout time step - :param dt: agent integration time step - :param input_cell_num: number of input cells - :param output_cell_num: number of output cells - :param true_labels: list of true labels for the consecutive plots - :param show_true_predicted: whther to print true/predicted class' marks on the plot - :return: + :param marker_params: + parameters for marker creation """ create_fig = False for var_name, section_recs in self.recs.items(): @@ -136,8 +128,6 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, fig.canvas.draw() self.figs[var_name] = fig - if len(run_params.output_labels) != len(section_recs): - raise ValueError("Number of labels given is not equal to actual number of sections in current plot") for i, (name, rec) in enumerate(section_recs): if create_fig: if position == 'merge': @@ -164,29 +154,14 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, if y_lim is None: y_limits = (r.min() - (np.abs(r.min() * 0.05)), r.max() + (np.abs(r.max() * 0.05))) ax.set_ylim(y_limits) + else: + y_limits = None # update data line.set_data(t, r) - if run_params.show_true_predicted: - # info draw triangles for true and predicted classes - if run_params.output_labels is not None: - true_x, pred_x = self._true_predicted_class_marks(label=run_params.output_labels[i], - true_class=true_class, - pred_class=pred_class, t=t, - run_params=run_params) - else: - raise ValueError("True_labels parameter need to be given if show_true_prediction is True") - if y_lim is None: - true_y = [y_limits[0] + np.abs(y_limits[0]) * 0.09] * len(true_x) - pred_y = [y_limits[1] - np.abs(y_limits[1] * 0.11)] * len(pred_x) - else: - true_y = [y_lim[0]] * len(true_x) - pred_y = [y_lim[1]] * len(pred_x) - ax.scatter(true_x, true_y, c="orange", marker="^", alpha=0.95, label="true") - ax.scatter(pred_x, pred_y, c="magenta", marker="v", alpha=0.95, label="predicted") - if create_fig and i == 0: - # draw legend only the first time and only on the uppermost graph - ax.legend() + if marker_params: + self._make_markers(marker_params, y_lim=y_lim, y_limits=y_limits, + section_recs=section_recs, create_fig=create_fig, t=t, i=i, ax=ax) # info join plots by removing labels and ticks from subplots that are not on the edge if create_fig: @@ -200,27 +175,26 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, if create_fig: plt.show(block=False) - def _true_predicted_class_marks(self, label, true_class, pred_class, t, run_params): + @staticmethod + def _get_labels_timestep(label, t, marker_params): """ - find and return lists of time steps for true and predicted labels + Find and return lists of time steps for true and predicted labels. + :param label: the label id (an int) - :param true_class: list of true classes for the whole time region - :param pred_class: list of predicted labels (class ids) for the whole time region :param t: the region time steps :param stepsize: original agent stepsize; class selections are 2 * stepsize / dt - :param dt: integration step :return: lists of marks for true_x: true classes, pred_x: predicted classes """ - n = len(true_class) - x = t[::int(2 * run_params.agent_stepsize / run_params.dt)][-n:] + n = len(marker_params.true_class) + x = t[::int(2 * marker_params.agent_stepsize / marker_params.dt)][-n:] true_x = [] pred_x = [] # todo change lists into numpy arrays for speed for k in range(n): # get the true classes for the current label - if true_class[k] == label: + if marker_params.true_class[k] == label: true_x.append(x[k]) - if pred_class[k] == label: + if marker_params.pred_class[k] == label: pred_x.append(x[k]) return true_x, pred_x @@ -254,3 +228,21 @@ def _get_subplot(fig, var_name, position, row_len=1, index=1): ax = fig.add_subplot(position[0], position[1], index) return ax + + def _make_markers(self, marker_params, y_lim, ax, section_recs, y_limits, create_fig, i, t): + if marker_params.true_labels is None or len(marker_params.true_labels) != len(section_recs): + raise ValueError("Number of labels given is not equal to actual number of sections in current plot") + + # info draw triangles for true and predicted classes + true_x, pred_x = self._get_labels_timestep(label=marker_params.true_labels[i], t=t, marker_params=marker_params) + if y_lim is None: + true_y = [y_limits[0] + np.abs(y_limits[0]) * 0.09] * len(true_x) + pred_y = [y_limits[1] - np.abs(y_limits[1] * 0.11)] * len(pred_x) + else: + true_y = [y_lim[0]] * len(true_x) + pred_y = [y_lim[1]] * len(pred_x) + ax.scatter(true_x, true_y, c="orange", marker="^", alpha=0.95, label="true") + ax.scatter(pred_x, pred_y, c="magenta", marker="v", alpha=0.95, label="predicted") + if create_fig and i == 0: + # draw legend only the first time and only on the uppermost graph + ax.legend() From 34a73363aea484de4c9ce4d85e92cc2cecaa2c52 Mon Sep 17 00:00:00 2001 From: Igor Podolak Date: Fri, 27 Mar 2020 16:47:22 +0100 Subject: [PATCH 12/15] Corrected errors in record.py; changed its parameters a bit --- neuronpp/utils/record.py | 73 ++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/neuronpp/utils/record.py b/neuronpp/utils/record.py index b40b999f..db790b27 100644 --- a/neuronpp/utils/record.py +++ b/neuronpp/utils/record.py @@ -98,8 +98,7 @@ def _plot_static(self, position=None): ax.legend() def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, pred_class=None, - run_params=None): - # stepsize=None,; dt=None, show_true_predicted=True, true_labels=None): + show_true_predicted=False, run_params=None): """ Call each time you want to redraw plot. @@ -114,15 +113,18 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, * position=None -> Default, each neuron has separated axis (row) on the figure. :param true_class: list of true class labels in this window :param pred_class: list of predicted class labels in window - :param run_class: a namedtuple containing + :param run_params: a namedtuple containing :param agent_stepsize: agent readout time step :param dt: agent integration time step :param input_cell_num: number of input cells :param output_cell_num: number of output cells - :param true_labels: list of true labels for the consecutive plots - :param show_true_predicted: whther to print true/predicted class' marks on the plot + :param output_labels: list of true labels for the consecutive plots + :param show_true_predicted: whether to print true/predicted class' marks on the plot :return: """ + if show_true_predicted and run_params is None: + raise ValueError( + "Running parameters run_params need to be passed if true/predicted markers are to be shown") create_fig = False for var_name, section_recs in self.recs.items(): if var_name not in self.figs: @@ -135,8 +137,10 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, fig.canvas.draw() self.figs[var_name] = fig - if len(run_params.output_labels) != len(section_recs): - raise ValueError("Number of labels given is not equal to actual number of sections in current plot") + if show_true_predicted: + if len(run_params.output_labels) != len(section_recs): + raise ValueError( + "show_predicted is true but the number of labels given is not equal to actual number of sections in current plot") for i, (name, rec) in enumerate(section_recs): if create_fig: if position == 'merge': @@ -160,28 +164,20 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, ax.set_xlim(t.min(), t.max()) if y_lim is None: - y_limits = (r.min() - (np.abs(r.min() * 0.05)), r.max() + (np.abs(r.max() * 0.05))) - ax.set_ylim(y_limits) + # compute per-plot OY limits if global are not given + this_plot_y_limits = (r.min() - (np.abs(r.min() * 0.05)), r.max() + (np.abs(r.max() * 0.05))) + ax.set_ylim(this_plot_y_limits) + else: + this_plot_y_limits = y_lim # update data line.set_data(t, r) - if run_params.show_true_predicted: + # --------------------------------------------- + if show_true_predicted: # info draw triangles for true and predicted classes - if run_params.output_labels is not None: - true_x, pred_x = self._true_predicted_class_marks(label=run_params.output_labels[i], - true_class=true_class, - pred_class=pred_class, t=t, - run_params=run_params) - else: - raise ValueError("True_labels parameter need to be given if show_true_prediction is True") - if y_lim is None: - true_y = [y_limits[0] + np.abs(y_limits[0]) * 0.09] * len(true_x) - pred_y = [y_limits[1] - np.abs(y_limits[1] * 0.11)] * len(pred_x) - else: - true_y = [y_lim[0]] * len(true_x) - pred_y = [y_lim[1]] * len(pred_x) - ax.scatter(true_x, true_y, c="orange", marker="^", alpha=0.95, label="true") - ax.scatter(pred_x, pred_y, c="magenta", marker="v", alpha=0.95, label="predicted") + self._show_true_predicted_marks(ax=ax, label=run_params.output_labels[i], true_class=true_class, + pred_class=pred_class, + t=t, y_limits=this_plot_y_limits, run_params=run_params) if create_fig and i == 0: # draw legend only the first time and only on the uppermost graph ax.legend() @@ -198,6 +194,33 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, if create_fig: plt.show(block=False) + def _show_true_predicted_marks(self, ax, label, true_class, pred_class, t, y_limits, run_params): + """ + draw triangles for true and predicted classes + :param ax: the canvas + :param true_class: list of true class labels in this window + :param pred_class: list of predicted class labels in window + :param y_limits: this canvas OY limits for y axis. Default is (-80, 50) + :param run_params: a namedtuple containing + :param agent_stepsize: agent readout time step + :param dt: agent integration time step + :param input_cell_num: number of input cells + :param output_cell_num: number of output cells + :param output_labels: list of true labels for the consecutive plots + :return: + """ + if run_params.output_labels is not None: + true_x, pred_x = self._true_predicted_class_marks(label=label, + true_class=true_class, + pred_class=pred_class, t=t, + run_params=run_params) + else: + raise ValueError("True_labels parameter need to be given if show_true_prediction is True") + true_y = [y_limits[0] + np.abs(y_limits[0]) * 0.09] * len(true_x) + pred_y = [y_limits[1] - np.abs(y_limits[1] * 0.12)] * len(pred_x) + ax.scatter(true_x, true_y, c="orange", marker="^", alpha=0.95, label="true") + ax.scatter(pred_x, pred_y, c="magenta", marker="v", alpha=0.95, label="predicted") + def _true_predicted_class_marks(self, label, true_class, pred_class, t, run_params): """ find and return lists of time steps for true and predicted labels From f2d346e37d3ae7d571d8dc1d4acd43614fac7cc3 Mon Sep 17 00:00:00 2001 From: Igor Podolak Date: Fri, 27 Mar 2020 18:21:51 +0100 Subject: [PATCH 13/15] minor errors in record.py, plot_animate() --- neuronpp/utils/record.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/neuronpp/utils/record.py b/neuronpp/utils/record.py index cb9a2d91..231452f4 100644 --- a/neuronpp/utils/record.py +++ b/neuronpp/utils/record.py @@ -1,13 +1,14 @@ from collections import defaultdict, namedtuple +import matplotlib.pyplot as plt import numpy as np import pandas as pd from neuron import h -import matplotlib.pyplot as plt - from neuronpp.core.hocwrappers.seg import Seg -MarkerParams = namedtuple("MarkerParams", "agent_stepsize dt input_cell_num output_cell_num true_labels true_class pred_class") +MarkerParams = namedtuple("MarkerParams", + "agent_stepsize dt input_cell_num output_cell_num true_labels true_class pred_class") + class Record: def __init__(self, elements, variables='v'): @@ -211,10 +212,10 @@ def _show_true_predicted_marks(self, ax, label, true_class, pred_class, t, y_lim :return: """ if marker_params.output_labels is not None: - true_x, pred_x = self._get_labels_timesteps(label=label, - true_class=true_class, - pred_class=pred_class, t=t, - run_params=marker_params) + true_x, pred_x = self._get_labels_timestamps(label=label, + true_class=true_class, + pred_class=pred_class, t=t, + marker_params=marker_params) else: raise ValueError("True_labels parameter need to be given if show_true_prediction is True") true_y = [y_limits[0] + np.abs(y_limits[0]) * 0.09] * len(true_x) @@ -223,7 +224,7 @@ def _show_true_predicted_marks(self, ax, label, true_class, pred_class, t, y_lim ax.scatter(pred_x, pred_y, c="magenta", marker="v", alpha=0.95, label="predicted") @staticmethod - def _get_labels_timestaps(label, true_class, pred_class, t, marker_params): + def _get_labels_timestamps(label, true_class, pred_class, t, marker_params): """ find and return lists of time steps for true and predicted labels :param label: the label id (an int) From 8411e8117b13f40a4f652367a3d25563e960c6d1 Mon Sep 17 00:00:00 2001 From: Igor Podolak Date: Fri, 27 Mar 2020 19:09:00 +0100 Subject: [PATCH 14/15] minor errors in inheritance in record.py --- neuronpp/utils/record.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neuronpp/utils/record.py b/neuronpp/utils/record.py index 231452f4..e7aa64da 100644 --- a/neuronpp/utils/record.py +++ b/neuronpp/utils/record.py @@ -6,8 +6,8 @@ from neuron import h from neuronpp.core.hocwrappers.seg import Seg -MarkerParams = namedtuple("MarkerParams", - "agent_stepsize dt input_cell_num output_cell_num true_labels true_class pred_class") +MarkerParams = namedtuple("Simulation_params", + "agent_class agent_stepsize dt input_cell_num output_cell_num output_labels") class Record: From be385e8e894a02138d2d766057f18f973e69aa3a Mon Sep 17 00:00:00 2001 From: Ziemowit S Date: Thu, 2 Apr 2020 14:17:16 +0200 Subject: [PATCH 15/15] changes to Record --- neuronpp/utils/record.py | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/neuronpp/utils/record.py b/neuronpp/utils/record.py index e7aa64da..e68d30e6 100644 --- a/neuronpp/utils/record.py +++ b/neuronpp/utils/record.py @@ -1,9 +1,13 @@ from collections import defaultdict, namedtuple -import matplotlib.pyplot as plt import numpy as np import pandas as pd from neuron import h +import matplotlib.pyplot as plt +from neuronpp.core.hocwrappers.sec import Sec + +from neuronpp.core.hocwrappers.point_process import PointProcess + from neuronpp.core.hocwrappers.seg import Seg MarkerParams = namedtuple("Simulation_params", @@ -37,7 +41,13 @@ def __init__(self, elements, variables='v'): for elem in elements: for var in variables: if isinstance(elem, Seg): - name = elem.parent.name + cell_name = elem.parent.parent.name + name = "%s_%s" % (cell_name, elem.name) + elif isinstance(elem, PointProcess): + cell_name = elem.cell.name + name = "%s_%s" % (cell_name, elem.name) + elif isinstance(elem, Sec): + raise TypeError("Record element cannot be of type Sec, however you can specify Seg eg. soma(0.5) and pass as element.") else: name = elem.name try: @@ -117,7 +127,7 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, :param true_class: list of true class labels in this window :param pred_class: list of predicted class labels in window :param show_true_predicted: whther to print true/predicted class' marks on the plot - :param marker_params: MarkerParams namedtuple containing + :param marker_params: MarkerParams namedtuple contains inner params: :param agent_stepsize: agent readout time step :param dt: agent integration time step :param input_cell_num: number of input cells @@ -143,7 +153,7 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, if show_true_predicted: if len(marker_params.output_labels) != len(section_recs): raise ValueError( - "show_predicted is true but the number of labels given is not equal to actual number of sections in current plot") + "show_predicted is true but the number of true labels given is not equal to actual number of elemens to plot.") for i, (name, rec) in enumerate(section_recs): if create_fig: if position == 'merge': @@ -154,10 +164,10 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, if y_lim: ax.set_ylim(y_lim[0], y_lim[1]) - line, = ax.plot([], lw=1) - # ax.set_title("Variable: %s" % var_name) - ax.set_ylabel("{}_{}".format(var_name, i)) + line, = ax.plot([], lw=1, label=name) + ax.set_ylabel(var_name) ax.set_xlabel("t (ms)") + ax.legend() self.axs[var_name].append((ax, line)) @@ -168,10 +178,10 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, ax.set_xlim(t.min(), t.max()) if y_lim is None: # compute per-plot OY limits if global are not given - this_plot_y_limits = (r.min() - (np.abs(r.min() * 0.05)), r.max() + (np.abs(r.max() * 0.05))) - ax.set_ylim(this_plot_y_limits) + current_y_lim = (r.min() - (np.abs(r.min() * 0.05)), r.max() + (np.abs(r.max() * 0.05))) + ax.set_ylim(current_y_lim) else: - this_plot_y_limits = y_lim + current_y_lim = y_lim # update data line.set_data(t, r) @@ -179,16 +189,13 @@ def _plot_animate(self, steps=10000, y_lim=None, position=None, true_class=None, # info draw markers for true and predicted classes self._show_true_predicted_marks(ax=ax, label=marker_params.output_labels[i], true_class=true_class, pred_class=pred_class, - t=t, y_limits=this_plot_y_limits, marker_params=marker_params) + t=t, y_limits=current_y_lim, marker_params=marker_params) if create_fig and i == 0: # draw legend only the first time and only on the uppermost graph ax.legend() # info join plots by removing labels and ticks from subplots that are not on the edge if create_fig: - for key in self.axs: - for ax in self.axs[key]: - ax[0].label_outer() fig.subplots_adjust(left=0.09, bottom=0.075, right=0.99, top=0.98, wspace=None, hspace=0.00) fig.canvas.draw() fig.canvas.flush_events()