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
Finalize the refractoriness mechanism #66
Conversation
(cherry-picked from synapses branch)
… -- we have to find a more convenient way to handle this
A couple of questions before merging:
How does the string evaluating to a duration or boolean work? Can the string use the state variables, time, etc.? How do you parse which it is? |
Yeah, I'm not too fond of
Yes, it can use everything. I'm not actually parsing it but I'm using the unit-checking mechanism for expressions (which evaluates the expression, after substituting all external variables/state variables with their unit). If it results in a quantity with unit second it is considered a time expression, if it is a dimensionless quantity (or array/scalar), it is considered a boolean. If it is a quantity with a non-time unit, an error is raised. Treating every dimensionless value as boolean is certainly not foolproof -- I'm wondering whether maybe introducing a special boolean "unit" would make sense here, we could then detect it properly. |
No, let's not abuse the units system to put booleans in there (although with regard to the other thread, writing bool in the unit slot seems fine). If we know which variables are booleans, with the ast parser it's pretty easy to determine what is a boolean expression. We simply search through the tree and check at each level that EITHER the operation is logical (and or) and each of the arguments are logical recursively OR the operation is an inequality OR it is a variable with boolean type. |
In general this sounds good. However the advantage of evaluating (as it is done in the unit-checking) is that in can deal with arbitrary functions, as long as those functions manage to deal with pure units. E.g. this would work right now (ignoring the problem of specifying the function for C++): def in_refractory(t, lastspike):
return (t - lastspike) > 5*ms
G = NeuronGroup(...refractory='in_refractory(t, lastspike)'...) In the above example there's of course no need for a function in the first place, but I like the generality of the mechanism. There are some other issues with units and functions that prevent that from working ATM, though. |
That's true, but on the other hand decorating the function with |
I'm not really attached to the |
I like that idea, it feels more consistent and less ad hoc and error prone. It fits with our general strategy of trying not to do quite as much guessing as we did in Brian 1 to avoid difficult to debug errors. So the proposal would be: whenever a function is used, the user has to declare with |
I think that would be a good idea -- slightly annoying for some users, maybe, but it's the only way to make unit-checking work reliably and simple. Most user functions are quite simple in their inputs/outputs anyway (and even more users never use such user-defined functions in the first place). We could use |
I like it! |
I opened an issue for the user-provided functions as #67 -- we should deal with this independently of the refractoriness. |
Shall I merge this now or did you want to finish anything up? |
Not working on anything in this branch right now, good to merge from my side. |
Finalize the refractoriness mechanism
This should implement the new refractoriness mechanism that came out of our discussion. The major differences to the previous (Brian2) implementation: The flag is called
unless-refractory
instead ofactive
, the variable storing the state of neurons is callednot_refractory
instead ofis_active
. Specifying the length of the refractory period works with a newrefractory
keyword inNeuronGroup
, it accepts a duration or a string that evaluates to a duration or a string that evaluates to a boolean (the condition to stay in the refractory state after a spike). Closes #41Also includes some tests and a bit of "user documentation".