-
Notifications
You must be signed in to change notification settings - Fork 220
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
Specifiers rewrite #91
Conversation
…-- elements (previously called neurons) correspond to neurons for NeuronGroup but to synapses for Synapses and to compartments for the upcoming SpatialNeuron class.
…p. post pathway is used.
…uiring a duplicate definition of dtypes
Conflicts: brian2/monitors/statemonitor.py brian2/synapses/synapses.py
…e mapping from specifiers to indices (will be further simplified)
Conflicts: brian2/equations/unitcheck.py brian2/monitors/statemonitor.py brian2/stateupdaters/exact.py docs_sphinx/developer/codegen.rst
…, Synapses, etc. yet, only getting/setting of state variables
…ex, _num_element is always available
With the last commit, the propagation works correctly with subgroups. Recording spikes from a subgroup with a spike monitor does not, though. I guess we can handle the details of the subgroup implementation in a different issue/pull request anyway. One thing I realized: Writing |
Awesome work. I think I'm happy with it, just one comment below really that would take a little bit of work if you think it's a good idea. Just having one
Subgroups: shouldn't it all be reasonably simple if we use the Brian 1 way of doing it? Namely, for each Synapses object we would store a
|
This is currently not quite possible since
You might be right that the other direction is easier -- I thought that some stuff would automatically work using my current technique (e.g. setting a synaptic weight depended on a neuronal parameter, e.g. Ok, I'll give it a go, will report back soon :) |
…SpikeMonitor work with subgroups
…res due to incomplete namespaces)
…ices dictionary -- otherwise we have problems for variables known under two different names (see gapjunction example)
I fixed some smaller issues (that are only captured by the examples, not by the test suite :-/ ) -- I think it is good to go now if you don't see anything that is still missing. |
I think given the importance of this I'll go ahead and merge now. The branches that will be affected are Romain's spatial neurons, and my devices. For the devices branch, I think it's no big deal - I think I'll actually start a new branch anyway because I think the way we're doing it we're not actually going to use anything from the current devices branch. |
I can do a manual merge for Romain's branch later, it's not a big deal. And as always: Until we merge master into the spatialneuron branch, it is not affected at all :) |
Done! |
Ok, I think this is the big chunk of what I want to do for now, it's missing quite a bit of documentation but apart from that it's mostly ready (some subgroup details are still open, see below). I made a couple of decisions that are worth discussing before merging (since it's a massive merge, we do want to get this right...).
I decided to have only exactly one
Variable
(previously:Specifier
) for each state variable -- this means thatVariable
does neither store the name of the variable (since the name might be e.g.v_pre
inSynapses
instead ofv
) nor the index (since the index forv
can be_element
inNeuronGroup
but e.g._postsynaptic
inSynapses
). The advantage: InSynapses
,Subgroup
and other future places where we refer to the variables from anotherGroup
, we can simply refer to theVariable
objects instead of copying them by hand, replacing some parts like the name. This means we don't have to change anything if a new attribute appears, etc. How are names and indices handled: names are simply the keys in the dictionary, a mapping to indices is done via avariable_indices
dictionary inGroup
-- by default it is adefaultdict
mapping everything to_element
(this means thatNeuronGroup
does not have to care about this at all). Also it means no longer writing redundant things likespecifiers['var'] = Specifier('var', ...)
.Somewhat related to this: The
iterate_all
information is now stored in the templates (only used in Python anyway), soNeuronGroup
etc. do not have to care about this.I also implemented subgroups, although the implementation is not quite correct yet. I think the best thing for subgroups is that it is a user-interface feature and the internal code does not have to care about this. So for example, if we write
Synapses(G[5:], G[5:]); S.connect(0, 0)
this will be internally stored as a connection from neuron 5 to neuron 5, so the propagation code does not have to care about this. This would also avoid having to copy the spikes at every timestep, the only place where we need spike numbers that are specific to the subgroup is inSpikeMonitor
-- but I think it's best to makeSpikeMonitor
handle this explicitly. This also means that subgroups do not have to be added to aNetwork
. There's one weakness in the current implementation, though: If one uses subgroups in theSynapses
constructor, we store source/target numbers twice to both support correct propagation and state variable assignments involvingi
andj
(relative to the subgroup).To summarize some of the renames:
brian2.core.specifiers
-->brian2.core.variables
,Specifier
-->Variable
,USE_SPECIFIERS
-->USES_VARIABLES
,_neuron_idx
-->_element_idx
(since it's used for synapses etc. as well).