/*
 *  test_sinusoidal_poisson_generator_6.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/>.
 *
 */

 /* BeginDocumentation
Name: testsuite::test_sinusoidal_poisson_generator_6 - Test parallel generation of sinusoidally modulate Poissonian trains with individual spike trains

Synopsis: nest_indirect test_sinusoidal_poisson_generator_6.sli -> -

Description:
   Creates a sinusoidally modulated Poisson generator emitting an
   individual spike train to each of its targets and sends spikes to spike
   detectors. Ensures that all targets receive identical spike trains.

NOTE: THIS TEST DOES NOT WORK AUTOMATICALLY, DUE TO PROBLEMS WITH UNITTEST.
      You can run it manually and see if the output is as expected with

      mpirun -np 2 nest test_sinusoidal_poisson_generator_6.sli

Author:  December 2012, May 2013, Plesser, based on test_poisson_generator.sli

See also: test_sinusoidal_poisson_generator_{1,2,3,4,6}, test_sinusoidal_poisson_generator_nostat
*/

(unittest) run
/unittest using


/total_vps 4 def


% return true if all arrays inside an array are different from each other
% [l1 l2 ...] all_different -> bool
/all_different
{
  empty
  {
    ; true 
  }
  {
    /items Set
    items [ 1 -2 ] Take  % all except last element
    { 1 add -1 2 arraystore items exch Take 
      exch /item Set 
      true exch { item neq and } Fold
    } MapIndexed 
    true exch { and } Fold
  } ifelse

} def


% function building n neuron network with spike detectors
% num_nrns individual run_simple_net -> [ spike_detectors ]
/run_simple_net
{
  /individual Set
  /n Set

  % set resolution and total/local number of threads
  0
  <<
  /resolution  0.1
  /total_num_virtual_procs total_vps
  >> SetStatus

  /sinusoidal_poisson_generator 
  << 
     /dc  1000.
     /ac   1000.
     /freq 100.
     /individual_spike_trains individual
  >> SetDefaults

  /parrots [ n ] { ; /parrot_neuron Create } Table def
  /sdets   [ n ] 
    { ;   /spike_detector n << /withtime true /withgid false >> Create } 
    Table def  

  /gen /sinusoidal_poisson_generator Create def

  gen parrots DivergentConnect
  [parrots sdets] { Connect } ScanThread

  10. Simulate

  sdets
} def


% we only run for two MPI with two threads each
% thus, each MP process returns an array with two spike-train arrays
% we pool all the arrays (i.e., total spike trains) and they must all
% be identical 
[ 2 ]
{
  /sdets 16 true run_simple_net def

  % get events, replace vectors with SLI arrays
  % keep only non-empty arrays; empty ones are from off-process parrots
  (ALL LINES SHOULD BE DIFFERENT) ==  
  sdets { [/events /times] get cva } Map { empty not exch ; } Select
  { == } forall
} exec

% code below leads to error in data collection routine

{
  % expect array with two arrays of spike times
  arrayload ; join
  all_different
}
% distributed_collect_assert_or_die