/*
 *  ticket-156.sli
 *
 *  This file is part of NEST.
 *
 *  Copyright (C) 2004 The NEST Initiative
 *
 *  NEST is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  NEST is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with NEST.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/*
   Test for Ticket 156.

   This test verifies that:
   poisson_generator_ps generates identical spike trains for given
   start and stop for different simulation resolutions, and different
   trains for different targets.

   Protocol:
   1. poisson_generator_ps projects to two spike_detectors
   2. run for different resolutions, record precise spike times is ms
   3. test all spikes are in (start, stop]
   3. test for different results between spike_detectors
   4. test for identical results across resolutions
*/

/unittest (6335) require
/unittest using

/ps_params <<
  /origin 0.0
  /start 1.0
  /stop  2.0
  /rate 12345.0  % expect ~ 12.3 spikes
>> def 

/sd_params <<
  /to_memory     true
  /precise_times true
  /time_in_steps false
>> def

/resolutions [0.01 0.1 0.2 0.5 1.0] def

% ensure all spikes arrive at detector
/simtime ps_params /stop get 2.0 add def  

/check_limits % true if all spikes in (origin+start, origin+stop]
{
  << >> begin
    /spks Set
    /ori ps_params /origin get def
    spks Min ps_params /start get ori add gt
    spks Max ps_params /stop get ori add leq
    and
  end
} def

/single_trial
{
  << >> begin
    /h Set
    ResetKernel
    0 << /resolution h >> SetStatus
  
    /poisson_generator_ps Create /pg Set
    pg ps_params SetStatus

    /spike_detector sd_params SetDefaults
    [ /spike_detector Create
      /spike_detector Create
    ] /sds Set
    sds { pg exch 1.0 1.0 Connect } forall

    simtime Simulate
    sds { [/events /times] get cva } Map
  end
} def

resolutions { single_trial } Map
/res Set

% first test: limits
res Flatten check_limits

% second test: different results between targets
res { 
  arrayload ; neq 
} Map

% third test: equality among runs
% Test for spike time equality to within 2.3e-16 ms.
res Transpose { 
  dup 0 get /ref Set 
  Rest true exch { ref sub 0 exch { abs max } Fold 2.3e-16 lt and } Fold
} Map 

% collect 
3 arraystore Flatten 
true exch { and } Fold

assert_or_die