LEMS / jLEMS

Java Interpreter for the Low Entropy Model Specification language
https://docs.neuroml.org/Userdocs/Software/jLEMS.html
MIT License
8 stars 11 forks source link

Rootfinding based events #39

Open borismarin opened 10 years ago

borismarin commented 10 years ago

In NeuroML, we do

            <StateVariable name="spiking" dimension="none"/>
            <OnCondition test="v .gt. thresh .and. spiking .lt. 0.5">
                <StateAssignment variable="spiking" value="1"/>
                <EventOut port="spike"/>
            </OnCondition>

            <OnCondition test="v .lt. thresh">
                <StateAssignment variable="spiking" value="0"/>
            </OnCondition>

to detect spikes. This involves the creation of a new state variable, and some "ad hoc" logic. This degree of "imperativeness" seems to go against the declarative philosophy of NeuroML/LEMS. I would suggest defining and detecting events as zero-crossings of state functions in a given direction, i.e., we would just need to say something like

            <OnCondition test="v - thresh" direction="increasing">
                <EventOut port="spike"/>
            </OnCondition>

this would simplify the component, but jLEMS would then need to store history in order to detect events. @robertcannon, would that require drastic changes to the interpreter?

pgleeson commented 10 years ago

The advantage of the existing method is that it's explicit what the implementation of the "spiking" concept is, as opposed to being buried in the LEMS docs and being an extra requirement for every new LEMS implementation.

It probably wouldn't be more efficient to implement this internally in Lems as the parser would just have to have its own internal (hidden) spiking variable anyway.

One last point, there could be slightly different implementations of how to signal spiking in this way and this is just one, which also make the spiking variable accessible if it's to be used in any other expressions.

borismarin commented 10 years ago

I still see the need for having a way to define localized, punctual events (in opposition to your example where "spiking" extends for more than one timestep) such as threshold crossings.

robertcannon commented 10 years ago

I had a few discussions about this with Mike Hull in relation to LemsLite. In the end, we postponed doing anything there, but I think it is a concept that belongs in LEMS. The spiking thing is a bit of a fudge.

It shouldn't be very hard to implement, but I'm not sure what the XLM should say. I suspect OnCondition isn't quite the right thing because it is currently used where the system crosses from a regime where the condition is false into one where it is true. For a threshold crossing with a condition you would want the test on "v .eq. threshold" which needs to carry with it the assumption that when v goes from a to b it momentarily passes through all values in between.

But in fact you still want to trigger the event even if you don't assume that v takes all intermediate values in succession. Maybe that justifies a new operator, as in test="v .crosses_from_below. threshold" ?

So we could have OnCondition test="v .crosses_from_below. threshold" ... but this isn't really a condition any more. OnEvent would work but we already use that for receiving events. But perhaps that is OK: we can have events that are triggered externally by receiving things on a port and events that are triggered internally when one of the event operators fires?

borismarin commented 10 years ago

I see the current onConditon constructs as logical constructs, mirroring "control flow driven" imperative programming. The zero crossing idea fits together more closely (at least for the cases described by ODEs, i.e. components with TimeDerivative) with the geometric concept of trajectories (defined by the dynamics) intercepting hypersurfaces (defined by the conditions).

As an example, for a 1d case (stateVariable x), we would just have the concept of crossing a point (parameter thresh) in in(de)creasing way, which in other words is a zero crossing of (x - thresh). Notice that by defining things this way we can detect events with better precision than the time discretization (don't know if that would be useful, but for spiking models would at least see nice homogenous spike), via (newton-like potentially?) rootfinding.

On 17 July 2014 10:15, robertcannon notifications@github.com wrote:

I had a few discussions about this with Mike Hull in relation to LemsLite. In the end, we postponed doing anything there, but I think it is a concept that belongs in LEMS. The spiking thing is a bit of a fudge.

It shouldn't be very hard to implement, but I'm not sure what the XLM should say. I suspect OnCondition isn't quite the right thing because it is currently used where the system crosses from a regime where the condition is false into one where it is true. For a threshold crossing with a condition you would want the test on "v .eq. threshold" which needs to carry with it the assumption that when v goes from a to b it momentarily passes through all values in between.

But in fact you still want to trigger the event even if you don't assume that v doesn't take all intermediate values in succession. Maybe that justifies a new operator, as in test="v .crosses_from_below. threshold" ?

So we could have ... but this isn't really a condition any more. OnEvent would work but we already use that for receiving events. But perhaps that is OK: we can have events that are triggered externally by receiving things on a port and events that are triggered internally when one of event operators fires?

Reply to this email directly or view it on GitHub https://github.com/LEMS/jLEMS/issues/39#issuecomment-49280424.

robertcannon commented 10 years ago

Even a simple interpolation to generate a time for an event within a timestep when the crossing occurred would be an improvement on the current implementation.

From the trajectory idea, perhaps the element should be called "When" then? Or maybe we define hypervolumes with conditions such as "v .gt. threshold" and have OnEntry and OnExit elements for the events when the trajectory enters or leaves such a volume.

borismarin commented 10 years ago

Do we have any example where "diffuse" events -- i.e, events fired at a continuous range of conditions, as those defined via inequalities -- are conceptually needed? I see "events" as the OnEntry/Exit ideas that Robert has just described above, being fired once a "boundary" (defined by the equality condition, hence my using of "rootfinding") is crossed. I still think that the "spiking" state variable is just a workaround, existing precisely because we don't have the idea of directionality embedded into our "event model".