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

Fix for multimeter origin bug. #669

Merged
merged 8 commits into from May 30, 2017

Conversation

Projects
None yet
5 participants
@zbarni

zbarni commented Mar 3, 2017

Modified multimeter to actually consider the origin variable when sampling. Modification of the DataLoggingRequest class was also required to keep track of the origin. Main issue was that the initial sampling timepoint (relative to which the next intervals are calculated) was computed without regard to the origin.

Modified multimeter to actually consider the origin variable when sam…
…pling. Modification of the DataLoggingRequest class was also required to keep track of the origin.
@heplesser

This comment has been minimized.

Show comment
Hide comment
@heplesser

heplesser Mar 6, 2017

Contributor

@zbarni As I explained in #670, multimeter works as intended, although some documentation is misleading. The main problem with your proposal here is that the purpose of origin is to allow the user to move the start-stop window along the time axis by changing origin during stimulation breaks. Your intended use of origin would conflict with this. Also, a logger will only take into account the value of origin at the first Simulate call after the multimeter is first connected. Any later changes would be difficult, because it would require resizing of logger buffers and thus risk losing or invalidating data that has been recorded already in the logger inside the neuron recorded from, but that has not yet been fetched by the multimeter.

I therefore think that you approach is not feasible.

Contributor

heplesser commented Mar 6, 2017

@zbarni As I explained in #670, multimeter works as intended, although some documentation is misleading. The main problem with your proposal here is that the purpose of origin is to allow the user to move the start-stop window along the time axis by changing origin during stimulation breaks. Your intended use of origin would conflict with this. Also, a logger will only take into account the value of origin at the first Simulate call after the multimeter is first connected. Any later changes would be difficult, because it would require resizing of logger buffers and thus risk losing or invalidating data that has been recorded already in the logger inside the neuron recorded from, but that has not yet been fetched by the multimeter.

I therefore think that you approach is not feasible.

@zbarni

This comment has been minimized.

Show comment
Hide comment
@zbarni

zbarni Mar 6, 2017

I think the discussion has moved to #670 .

zbarni commented Mar 6, 2017

I think the discussion has moved to #670 .

@heplesser

This comment has been minimized.

Show comment
Hide comment
@heplesser

heplesser Mar 7, 2017

Contributor

I think we should aim for a more general solution along the lines of what I sketched in #505. Therefore, I will close this PR for now.

Contributor

heplesser commented Mar 7, 2017

I think we should aim for a more general solution along the lines of what I sketched in #505. Therefore, I will close this PR for now.

@heplesser heplesser closed this Mar 7, 2017

@heplesser

This comment has been minimized.

Show comment
Hide comment
@heplesser

heplesser Mar 7, 2017

Contributor

@zbarni After thinking it through a bit further, here a suggestion for how to handle subsampling with arbitrary offset:

  1. Sampling is parameterized in terms of offset and interval such that data is recorded at all times t == n h == offset + k interval, where h is the simulation resolution and n and k are non-negative integers (n>=1, k>=0).
  2. Just as interval, offset can only be set before the multimeter is connected to any neurons; we cannot change it later because that would require modifying the recording buffers, risking loss of data. Since interval already has this restriction, this should not be problematic.
  3. Windowing (anything that has to do with start, stop, origin) is orthogonal to this and handled entirely by base classes.

Could you try to implement this? It would also be excellent if you could add a test for the new offset feature, including tests that modifying offset after connecting is prohibited.

Sorry for the back-and-forth!

Contributor

heplesser commented Mar 7, 2017

@zbarni After thinking it through a bit further, here a suggestion for how to handle subsampling with arbitrary offset:

  1. Sampling is parameterized in terms of offset and interval such that data is recorded at all times t == n h == offset + k interval, where h is the simulation resolution and n and k are non-negative integers (n>=1, k>=0).
  2. Just as interval, offset can only be set before the multimeter is connected to any neurons; we cannot change it later because that would require modifying the recording buffers, risking loss of data. Since interval already has this restriction, this should not be problematic.
  3. Windowing (anything that has to do with start, stop, origin) is orthogonal to this and handled entirely by base classes.

Could you try to implement this? It would also be excellent if you could add a test for the new offset feature, including tests that modifying offset after connecting is prohibited.

Sorry for the back-and-forth!

@heplesser heplesser reopened this Mar 7, 2017

@zbarni

This comment has been minimized.

Show comment
Hide comment
@zbarni

zbarni Mar 12, 2017

@heplesser no problem, probably the role of offset is clearer this way. Finished the changes you suggested (offset as a new variable instead of overlapping with origin), and added a simple unit test for correctness and changing the offset after connection. Let me know if anything else should be changed or extended.

zbarni commented Mar 12, 2017

@heplesser no problem, probably the role of offset is clearer this way. Finished the changes you suggested (offset as a new variable instead of overlapping with origin), and added a simple unit test for correctness and changing the offset after connection. Let me know if anything else should be changed or extended.

@heplesser

@zbarni Thanks for the changes. It looks pretty good now, see the comments in the code for some detailed suggestions.

Show outdated Hide outdated models/multimeter.cpp
Show outdated Hide outdated models/multimeter.cpp
Show outdated Hide outdated models/multimeter.cpp
Show outdated Hide outdated models/multimeter.cpp
Show outdated Hide outdated models/multimeter.cpp
Show outdated Hide outdated models/multimeter.h
Show outdated Hide outdated models/multimeter.h
@@ -582,18 +587,22 @@ class DataLoggingRequest : public Event
inline DataLoggingRequest::DataLoggingRequest()
: Event()
, recording_interval_( Time::neg_inf() )
, recording_offset_( Time::ms( 0. ) )

This comment has been minimized.

@heplesser

heplesser Mar 13, 2017

Contributor

0 would suffice

@heplesser

heplesser Mar 13, 2017

Contributor

0 would suffice

This comment has been minimized.

@zbarni

zbarni Mar 13, 2017

This doesn't work.. initializing recording_offset_ with ( 0 ) leads to a compile error.

@zbarni

zbarni Mar 13, 2017

This doesn't work.. initializing recording_offset_ with ( 0 ) leads to a compile error.

This comment has been minimized.

@apeyser

apeyser Apr 3, 2017

Contributor

@zbarni But Time::ms(0) rather than (0.) should be enough.

@apeyser

apeyser Apr 3, 2017

Contributor

@zbarni But Time::ms(0) rather than (0.) should be enough.

This comment has been minimized.

@apeyser

apeyser Apr 3, 2017

Contributor

Good to know -- I should open an issue on ambiguities in time.

@apeyser

apeyser Apr 3, 2017

Contributor

Good to know -- I should open an issue on ambiguities in time.

This comment has been minimized.

@apeyser

apeyser Apr 4, 2017

Contributor

There's an explicit ms(long t). I wonder why there's an ambiguity on the constructor. The long/double constructors should probably anyway be reduced to just the double constructor.

@apeyser

apeyser Apr 4, 2017

Contributor

There's an explicit ms(long t). I wonder why there's an ambiguity on the constructor. The long/double constructors should probably anyway be reduced to just the double constructor.

Show outdated Hide outdated testsuite/unittests/test_multimeter_offset.sli
Show outdated Hide outdated nestkernel/event.h

@heplesser heplesser requested a review from apeyser Mar 13, 2017

@heplesser

This comment has been minimized.

Show comment
Hide comment
@heplesser

heplesser Mar 13, 2017

Contributor

@zbarni Thanks for the fixes, nice work!

Contributor

heplesser commented Mar 13, 2017

@zbarni Thanks for the fixes, nice work!

@zbarni

This comment has been minimized.

Show comment
Hide comment
@zbarni

zbarni Mar 13, 2017

Glad I could contribute!

zbarni commented Mar 13, 2017

Glad I could contribute!

Show outdated Hide outdated models/multimeter.cpp
Show outdated Hide outdated models/multimeter.cpp
@@ -582,18 +587,22 @@ class DataLoggingRequest : public Event
inline DataLoggingRequest::DataLoggingRequest()
: Event()
, recording_interval_( Time::neg_inf() )
, recording_offset_( Time::ms( 0. ) )

This comment has been minimized.

@apeyser

apeyser Apr 3, 2017

Contributor

@zbarni But Time::ms(0) rather than (0.) should be enough.

@apeyser

apeyser Apr 3, 2017

Contributor

@zbarni But Time::ms(0) rather than (0.) should be enough.

@apeyser

I'm sure it exists in the referenced issues, but I didn't manage to pull it out. Why is an offset for recording being added to multimeter?

@zbarni

This comment has been minimized.

Show comment
Hide comment
@zbarni

zbarni Apr 3, 2017

@apeyser as @rcfduarte put it in #670:

...we're running very long simulations where we need to sample the values of population state variables at regular intervals. For example, we would like to sample the population activity at 100.1, 200.1, 300.1, etc (where the extra 0.1 ms is added to account for a delay of 0.1 ms from an input generator to the network). As @zbarni mentioned, as it is currently implemented, the multimeter doesn't allow this (unless we set interval=0.1, which is not a very efficient solution for long simulations)...

Let me know if this answers your question.

zbarni commented Apr 3, 2017

@apeyser as @rcfduarte put it in #670:

...we're running very long simulations where we need to sample the values of population state variables at regular intervals. For example, we would like to sample the population activity at 100.1, 200.1, 300.1, etc (where the extra 0.1 ms is added to account for a delay of 0.1 ms from an input generator to the network). As @zbarni mentioned, as it is currently implemented, the multimeter doesn't allow this (unless we set interval=0.1, which is not a very efficient solution for long simulations)...

Let me know if this answers your question.

@zbarni

This comment has been minimized.

Show comment
Hide comment
@zbarni

zbarni Apr 3, 2017

@apeyser regarding

But Time::ms(0) rather than (0.) should be enough.

Doesn't compile, yielding the error

.....event.h:591:36: error: call of overloaded ‘ms(int)’ is ambiguous
   , recording_offset_( Time::ms( 0 ) )

Same case for recording_offset_( 0 )

zbarni commented Apr 3, 2017

@apeyser regarding

But Time::ms(0) rather than (0.) should be enough.

Doesn't compile, yielding the error

.....event.h:591:36: error: call of overloaded ‘ms(int)’ is ambiguous
   , recording_offset_( Time::ms( 0 ) )

Same case for recording_offset_( 0 )

@apeyser

Thanks for the information -- if you can just add some information on the copied code, I'll accept.

Show outdated Hide outdated models/multimeter.cpp
@@ -582,18 +587,22 @@ class DataLoggingRequest : public Event
inline DataLoggingRequest::DataLoggingRequest()
: Event()
, recording_interval_( Time::neg_inf() )
, recording_offset_( Time::ms( 0. ) )

This comment has been minimized.

@apeyser

apeyser Apr 3, 2017

Contributor

Good to know -- I should open an issue on ambiguities in time.

@apeyser

apeyser Apr 3, 2017

Contributor

Good to know -- I should open an issue on ambiguities in time.

@mschmidt87

This comment has been minimized.

Show comment
Hide comment
@mschmidt87

mschmidt87 May 29, 2017

Hi, I just stumbled upon the same issue in my simulations. I have read this PR and the related issue #670 . If I understood it correctly, this PR now aims to implement the suggestion by @heplesser , namely that the recording device should sample at times

t == n h == offset + k interval, where h is the simulation resolution and n and k are non-negative integers (n>=1, k>=0).

However, it seems to me that with the code implements k>0. Executing the following code:

import nest
nest.ResetKernel()
n = nest.Create('iaf_psc_exp', 1)
vm = nest.Create('voltmeter', 1)
nest.SetStatus(vm, {'interval': 5.,
                    'offset': 30.1})
nest.Connect(vm, n)
nest.Simulate(100.)
data = nest.GetStatus(vm, 'events')[0]['times']

gives recorded times [ 35.1 40.1 45.1], whereas I would have expected [30.1 35.1 40.1 45.1], which would be equivalent to setting k=[0,1,2,3] in the equation suggested by @heplesser (with offset=30.1, interval=5.).

Did I misunderstand something here?

mschmidt87 commented May 29, 2017

Hi, I just stumbled upon the same issue in my simulations. I have read this PR and the related issue #670 . If I understood it correctly, this PR now aims to implement the suggestion by @heplesser , namely that the recording device should sample at times

t == n h == offset + k interval, where h is the simulation resolution and n and k are non-negative integers (n>=1, k>=0).

However, it seems to me that with the code implements k>0. Executing the following code:

import nest
nest.ResetKernel()
n = nest.Create('iaf_psc_exp', 1)
vm = nest.Create('voltmeter', 1)
nest.SetStatus(vm, {'interval': 5.,
                    'offset': 30.1})
nest.Connect(vm, n)
nest.Simulate(100.)
data = nest.GetStatus(vm, 'events')[0]['times']

gives recorded times [ 35.1 40.1 45.1], whereas I would have expected [30.1 35.1 40.1 45.1], which would be equivalent to setting k=[0,1,2,3] in the equation suggested by @heplesser (with offset=30.1, interval=5.).

Did I misunderstand something here?

@heplesser

@zbarni Sorry for the long delay. I added a suggestion of how to address the issues raised by @apeyser. Could you also check the issue raise by @mschmidt87? His expectation is correct, recording in his case should start with 30.1, not 35.1. Could you add his case to the unittest?

Show outdated Hide outdated models/multimeter.cpp
Show outdated Hide outdated models/multimeter.cpp
@heplesser

This comment has been minimized.

Show comment
Hide comment
@heplesser

heplesser May 29, 2017

Contributor

@zbarni The conflict reported by Github seem to be just line break/empty line/whitespace changes and should be easy to fix. The easiest is probably to pull the current master into your branch.

Contributor

heplesser commented May 29, 2017

@zbarni The conflict reported by Github seem to be just line break/empty line/whitespace changes and should be easy to fix. The easiest is probably to pull the current master into your branch.

@heplesser

@zbarni Looks good, just some tiny details left (see individual comments). And could you add one more test case, just to check that DataLogger initiatialization works correctly: Create network with multimeter so that if records between 20 and 30 ms, e.g.. Then simulate 10 ms, and add another multimeter that also should record between 20 and 30 ms. Both should return the same data.

Show outdated Hide outdated models/multimeter.cpp
Show outdated Hide outdated nestkernel/universal_data_logger_impl.h
@zbarni

This comment has been minimized.

Show comment
Hide comment
@zbarni

zbarni May 29, 2017

@heplesser I'm actually unsure whether the offset is supposed to be relative to 0. or relative to the elapsed simulation time since 0.? For instance,

nest.Simulate(10.)
nest.Create("multimeter", 1, {"interval": 3., "offset": 5.})
(...)
nest.Simulate(10.)

should give [15. 18.] (relative to elapsed time, 10. ms) or [11. 14. 17. 20.] (relative to 0.)? Currently, the intervals are calculated relative to 0. when a new multimeter is created and not the elapsed time..

zbarni commented May 29, 2017

@heplesser I'm actually unsure whether the offset is supposed to be relative to 0. or relative to the elapsed simulation time since 0.? For instance,

nest.Simulate(10.)
nest.Create("multimeter", 1, {"interval": 3., "offset": 5.})
(...)
nest.Simulate(10.)

should give [15. 18.] (relative to elapsed time, 10. ms) or [11. 14. 17. 20.] (relative to 0.)? Currently, the intervals are calculated relative to 0. when a new multimeter is created and not the elapsed time..

@heplesser

This comment has been minimized.

Show comment
Hide comment
@heplesser

heplesser May 30, 2017

Contributor

@zbarni We should stick to the current approach (relative to 0.), so that the recording times are given by t_k = offset + k * interval. This makes offset/interval semantics consistent with the origin/start/stop semantics which also use 0 as a reference point. Furthermore, it ensures that recording times remain fixed even if you change simulation intervals or move code lines around.

I just suggested to add the test to ensure that recording times are correctly based on 0 even if a multimeter is created after the simulation has run for some time.

Contributor

heplesser commented May 30, 2017

@zbarni We should stick to the current approach (relative to 0.), so that the recording times are given by t_k = offset + k * interval. This makes offset/interval semantics consistent with the origin/start/stop semantics which also use 0 as a reference point. Furthermore, it ensures that recording times remain fixed even if you change simulation intervals or move code lines around.

I just suggested to add the test to ensure that recording times are correctly based on 0 even if a multimeter is created after the simulation has run for some time.

@heplesser

This comment has been minimized.

Show comment
Hide comment
@heplesser

heplesser May 30, 2017

Contributor

Add possiblity to set offset for multimeter recording. Thanks, @zbarni!

Contributor

heplesser commented May 30, 2017

Add possiblity to set offset for multimeter recording. Thanks, @zbarni!

@heplesser heplesser merged commit 08e830b into nest:master May 30, 2017

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment