-
Notifications
You must be signed in to change notification settings - Fork 191
Description
Describe the bug
If model.probes = [] or self.probes = [] (within a sub-network) then any probes that are added afterwards won't be built into the model. That is, any subsequent nengo.Probe calls aren't being appended to the same list that the backend uses to build the probes.
Similar variants of this issue exist for other attributes such as ensembles. Note that the EnsembleArray creates a list called ea_ensembles.
To reproduce
import nengo
with nengo.Network() as model:
model.probes = []
x = nengo.Ensemble(100, 1)
p = nengo.Probe(x)
with nengo.Simulator(model) as sim:
sim.run_steps(2)
print(model.probes)
print(sim.data[p])Expected behavior
I would expect a more helpful error message, or an error / warning when reassigning a new list to model.probes. Or an error when a probe is added to a different list than the one used by the builder.
Error message and logs
[]
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-12-c33a13ecfdd4> in <module>()
10
11 print(model.probes)
---> 12 print(sim.data[p])
~/git/nengo/nengo/simulator.py in __getitem__(self, key)
37 if (key not in self._cache
38 or len(self._cache[key]) != len(self.raw[key])):
---> 39 rval = self.raw[key]
40 if isinstance(rval, list):
41 rval = np.asarray(rval)
KeyError: <Probe at 0x7f71780cd160 of 'decoded_output' of <Ensemble (unlabeled) at 0x7f71780c6c88>>
Versions
- OS: N/A
- Python: N/A
- Nengo: master
- Other: N/A
Additional context
Posting on behalf of a summer school participant who had difficulty debugging this issue in the context of a custom sub-network they created. They were using self.probes to keep a list of probed ensembles within a for loop, and then probing the final output. Their final output probe did not exist. They didn't realize they were overwriting an attribute of the network.
Possible solutions
We could limit the number of ways for users to 'shoot themselves in the foot' by hiding such attributes (e.g., self._probes) and exposing them as properties. While the list could still be mutated by the user, it would at least throw an error if they tried to do something like self.probes = [].