Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create plots for the input and the output of the SPA Basal Ganglia #567

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions nengo_gui/components/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from .spa_similarity import SpaSimilarity
from .htmlview import HTMLView
from .spike_grid import SpikeGrid
from .bg_plot import BGPlot

# Old versions of the .cfg files used Templates which had slightly different
# names than the Components currently use. This code allows us to
Expand Down
68 changes: 68 additions & 0 deletions nengo_gui/components/bg_plot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import nengo

from nengo_gui.components.value import Value


class BGPlot(Value):
"""The server-side system for the SPA Basal Ganglia plot."""

# the parameters to be stored in the .cfg file
config_defaults = Value.config_defaults.copy()
config_defaults["show_legend"] = True

def __init__(self, obj, **kwargs):
super(BGPlot, self).__init__(obj)

args = kwargs["args"]

# default legends to show
self.def_legend_labels = args["legend_labels"]

# the item to connect to
self.probe_target = args["probe_target"]

self.label = "bg " + self.probe_target

def attach(self, page, config, uid):
super(Value, self).attach(page, config, uid)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this isn't doing anything other than calling the constructor, I'm not sure it should be defined at all

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference between this calling of the constructor and not defining it at all, is that in this call, I don't assign a label. If this were not defined, a label, which I do not want, would be assigned.


def add_nengo_objects(self, page):
# create a Node and a Connection so the Node will be given the
# data we want to show while the model is running.
with page.model:
self.node = nengo.Node(self.gather_data,
size_in=self.n_lines)
if self.probe_target == "input":
self.conn = nengo.Connection(self.obj.input, self.node,
synapse=0.01)
else:
self.conn = nengo.Connection(self.obj.output, self.node,
synapse=0.01)

def javascript(self):
# generate the javascript that will create the client-side object
info = dict(uid=id(self), label=self.label,
n_lines=self.n_lines, synapse=0)

# get the default labels from the bg object
def_lbl = []
for ac in self.obj.actions.actions:
if ac.name is None:
def_lbl.append(ac.condition.expression.__str__())
else:
def_lbl.append(ac.name)

# replace missing labels with defaults
cfg_lbl_len = len(getattr(self.config, "legend_labels"))
for lbl in def_lbl[cfg_lbl_len:]:
self.config.legend_labels.append(lbl)

json = self.javascript_config(info)
return 'new Nengo.Value(main, sim, %s);' % json

def code_python_args(self, uids):
return [
uids[self.obj],
' args=dict(n_lines=%s, legend_labels=%s, probe_target="%s")'
% (self.n_lines, self.config.legend_labels, self.probe_target,)
]
9 changes: 9 additions & 0 deletions nengo_gui/components/netgraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,15 @@ def get_extra_info(self, obj):
elif isinstance(obj, nengo.Ensemble):
info['dimensions'] = int(obj.size_out)
info['n_neurons'] = int(obj.n_neurons)
# TODO: Add the same functionality for the BasalGanglia non-spa net
elif isinstance(obj, spa.BasalGanglia):
info['bg_inputs'] = obj.input.size_in
info['input_labels'] = []
for ac in obj.actions.actions:
if ac.name is None:
info['input_labels'].append(ac.condition.expression.__str__())
else:
info['input_labels'].append(ac.name)
elif Value.default_output(obj) is not None:
info['default_output'] = True

Expand Down
2 changes: 2 additions & 0 deletions nengo_gui/components/value.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ def default_output(obj):
if isinstance(obj, spa.module.Module):
if 'default' in obj.outputs.keys():
output = obj.outputs['default'][0]
elif isinstance(obj, spa.BasalGanglia):
output = obj.output
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be the first thing checked in the if, just in case in the future someone defines a default output for the BasalGanglia and is surprised that the plots suddenly stop working.

elif isinstance(obj, nengo.network.Network):
if hasattr(obj, 'output'):
output = obj.output
Expand Down
27 changes: 24 additions & 3 deletions nengo_gui/static/components/netgraph_item.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ Nengo.NetGraphItem = function(ng, info, minimap, mini_item) {
this.g_networks = ng.g_networks_mini;
this.g_items = ng.g_items_mini;
}


// SPA network specific parameter
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what this means

this.sp_targets = info.sp_targets;
// Basal Ganglia network specific parameters
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also not sure what this means.

this.bg_inputs = info.bg_inputs;
this.input_labels = info.input_labels;

var width = info.size[0];
Object.defineProperty(this, 'width', {
get: function() {
Expand Down Expand Up @@ -85,7 +91,7 @@ Nengo.NetGraphItem = function(ng, info, minimap, mini_item) {
}
}
});

/** if this is a network, the children list is the set of NetGraphItems
* and NetGraphConnections that are inside this network */
this.children = [];
Expand Down Expand Up @@ -410,7 +416,22 @@ Nengo.NetGraphItem.prototype.generate_menu = function () {
items.push(['Semantic pointer plot',
function() {self.create_graph('SpaSimilarity', self.sp_targets[0]);}]);
}
// TODO: Enable input and output value plots for basal ganglia network
if (this.bg_inputs) {
items.push(['Input Plot',
function () {
self.create_graph('BGPlot',
{"n_lines":self.bg_inputs, "legend_labels":self.input_labels, "probe_target":"input"}
);
}
]);
items.push(['Output Plot',
function () {
self.create_graph('BGPlot',
{"n_lines":self.bg_inputs, "legend_labels":self.input_labels, "probe_target":"output"}
);
}
]);
}
items.push(['Details ...', function() {self.create_modal();}]);
return items;
};
Expand Down
4 changes: 4 additions & 0 deletions nengo_gui/static/components/value.js
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,10 @@ Nengo.Value.prototype.set_legend_labels = function() {

Nengo.modal.title('Enter comma seperated legend label values');
Nengo.modal.single_input_body('Legend label', 'New value');
var body = Nengo.modal.$body;
body.prepend("Blank strings and excessive entries are ignored. \
Blank entries that are still delimited by commas will be replaced \
with a default value. ")
Nengo.modal.footer('ok_cancel', function(e) {
var label_csv = $('#singleInput').val();
var modal = $('#myModalForm').data('bs.validator');
Expand Down