diff --git a/testsuite/pytests/sli2py_regressions/test_ticket_800.py b/testsuite/pytests/sli2py_regressions/test_ticket_800.py new file mode 100644 index 0000000000..6e0077c44e --- /dev/null +++ b/testsuite/pytests/sli2py_regressions/test_ticket_800.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +# +# test_ticket_800.py +# +# 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 . + +import nest +import pytest + +# --- Good and bad parameter sets --- +good_random_parameters = [ + ("uniform", {"min": 0.0, "max": 1.0}), + ("normal", {"mean": 0.0, "std": 1.0}), + ("lognormal", {"mean": 0.0, "std": 1.0}), + ("exponential", {"beta": 1.0}), +] +good_distance_parameters = [ + ("distance", {}), + ("distance", {"dimension": 1}), + ("distance", {"dimension": 2}), +] +good_parameters = good_random_parameters + good_distance_parameters + +bad_random_parameters = [ + ("uniform", {"min": 0.0, "max": 0.0}), + ("normal", {"mean": 0.0, "sigma": 1.0}), # bad param name + ("normal", {"mean": 0.0, "std": 0.0}), + ("normal", {"mean": 0.0, "std": -1.0}), + ("lognormal", {"mu": 0.0, "std": 0.0}), + ("lognormal", {"mu": 0.0, "std": -1.0}), + ("lognormal", {"mu": 0.0, "std": 1.0}), +] +bad_distance_parameters = [ + ("distance", {"dim": 1}), + ("distance", {"dimension": 1, "min": 0.0}), +] +bad_parameters = bad_random_parameters + bad_distance_parameters + +# --- Good and bad masks --- +good_masks_2d = [ + ("circular", {"radius": 1.0}), + ("circular", {"radius": 1.0, "anchor": [0.5, 0.5]}), + ("rectangular", {"lower_left": [-0.1, -0.1], "upper_right": [0.1, 0.1]}), + ("doughnut", {"inner_radius": 0.1, "outer_radius": 0.2}), +] +good_masks_3d = [ + ("spherical", {"radius": 1.0}), + ("box", {"lower_left": [-0.1, -0.1, -0.1], "upper_right": [0.1, 0.1, 0.1]}), +] +good_masks = good_masks_2d + good_masks_3d + +bad_masks_2d = [ + ("circular", {"r": 0.0}), + ("circular", {"radius": 1.0, "foo": 1}), + ("circular", {"radius": 0.0}), + ("circular", {"radius": -1.0}), + ("rectangular", {"lower_left": [-0.1, -0.1], "upper_right": [-0.1, 0.1]}), + ("rectangular", {"lower_left": [-0.1, -0.1], "upper_right": [0.1, -0.1]}), + ("doughnut", {"inner_radius": 0.1, "outer_radius": 0.1}), +] +bad_masks_3d = [ + ("spherical", {"radius": 0.0}), + ("spherical", {"radius": -1.0}), + ("box", {"lower_left": [-0.1, -0.1, -0.1], "upper_right": [-0.1, 0.1, 0.1]}), + ("box", {"lower_left": [-0.1, -0.1, -0.1], "upper_right": [0.1, -0.1, 0.1]}), + ("box", {"lower_left": [-0.1, -0.1, -0.1], "upper_right": [0.1, 0.1, -0.1]}), +] +bad_masks = bad_masks_2d + bad_masks_3d + +# --- Good and bad layer specs --- +good_layers = [ + {"shape": [2, 2], "elements": "iaf_psc_alpha"}, + {"shape": [2, 2], "elements": "iaf_psc_alpha", "extent": [2.0, 0.5], "center": [0.2, 0.3], "edge_wrap": True}, + {"shape": [2, 2], "elements": "iaf_psc_alpha", "extent": [2.0, 0.5], "center": [0.2, 0.3], "edge_wrap": False}, + {"positions": [[0.1, 0.1], [0.2, 0.2]], "elements": "iaf_psc_alpha", "extent": [2.0, 0.5], "edge_wrap": True}, + { + "positions": [[0.1, 0.1, 0.1], [0.2, 0.2, 0.2]], + "elements": "iaf_psc_alpha", + "extent": [2.0, 0.5, 3.0], + "edge_wrap": True, + }, +] +bad_layers = [ + {"shape": [1], "elements": "iaf_psc_alpha"}, + {"shape": [2, 2], "elementsss": "iaf_psc_alpha"}, + {"shape": [2, 2], "elements": "iaf_psc_alpha", "extent": [2.0, 0.5], "center": [0.2, 0.3], "edge_wrap": 3}, + {"positions": [[0.1, 0.1], [0.2, 0.2, 0.2]], "elements": "iaf_psc_alpha", "extent": [2.0, 0.5], "edge_wrap": True}, + { + "positions": [[0.1, 0.1, 0.1], [0.2, 0.2, 0.2]], + "elements": "iaf_psc_alpha", + "extent": [2.0, 0.5], + "edge_wrap": True, + }, +] + + +@pytest.mark.parametrize("kind, params", good_parameters) +def test_good_parameters(kind, params): + nest.CreateParameter(kind, params) + + +@pytest.mark.parametrize("kind, params", bad_parameters) +def test_bad_parameters(kind, params): + with pytest.raises(Exception): + nest.CreateParameter(kind, params) + + +@pytest.mark.parametrize("mask_type, maskdict", good_masks) +def test_good_masks(mask_type, maskdict): + nest.CreateMask(mask_type, maskdict) + + +@pytest.mark.parametrize("mask_type, maskdict", bad_masks) +def test_bad_masks(mask_type, maskdict): + with pytest.raises(Exception): + nest.CreateMask(mask_type, maskdict) + + +@pytest.mark.parametrize("layer_spec", good_layers) +def test_good_layers(layer_spec): + # Use grid or free depending on positions + nest.ResetKernel() + if "positions" in layer_spec: + positions = layer_spec["positions"] + nest.Create( + layer_spec.get("elements", "iaf_psc_alpha"), + positions=positions, + extent=layer_spec.get("extent"), + edge_wrap=layer_spec.get("edge_wrap"), + ) + else: + shape = layer_spec["shape"] + nest.Create( + layer_spec.get("elements", "iaf_psc_alpha"), + positions=nest.spatial.grid( + shape, + extent=layer_spec.get("extent"), + center=layer_spec.get("center"), + edge_wrap=layer_spec.get("edge_wrap"), + ), + ) + + +@pytest.mark.parametrize("layer_spec", bad_layers) +def test_bad_layers(layer_spec): + nest.ResetKernel() + with pytest.raises(Exception): + if "positions" in layer_spec: + positions = layer_spec["positions"] + nest.Create( + layer_spec.get("elements", "iaf_psc_alpha"), + positions=positions, + extent=layer_spec.get("extent"), + edge_wrap=layer_spec.get("edge_wrap"), + ) + else: + shape = layer_spec["shape"] + nest.Create( + layer_spec.get("elements", "iaf_psc_alpha"), + positions=nest.spatial.grid( + shape, + extent=layer_spec.get("extent"), + center=layer_spec.get("center"), + edge_wrap=layer_spec.get("edge_wrap"), + ), + ) diff --git a/testsuite/regressiontests/ticket-800.sli b/testsuite/regressiontests/ticket-800.sli deleted file mode 100644 index e6f0601a20..0000000000 --- a/testsuite/regressiontests/ticket-800.sli +++ /dev/null @@ -1,373 +0,0 @@ -/* - * ticket-800.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 . - * - */ - -/** @BeginDocumentation - -Name: testsuite::ticket-800 Ensure that spatial parameters check their parameters - -Synopsis: (ticket-800) run -> NEST exits if test fails - -Description: -This ticket ensures that spatial parameters check their parameters for -validity, e.g., strictly positive sigma for a Gaussian. - -Author: Hans Ekkehard Plesser, 2014-12-13 - */ - -(unittest) run -/unittest using - -M_ERROR setverbosity - -/good_random_parameters -[ - << /uniform << /min 0. /max 1. >> >> - << /normal << /mean 0. /std 1. >> >> - << /lognormal << /mean 0. /std 1. >> >> - << /exponential << /beta 1. >> >> -] -def - -/good_distance_parameters -[ - << /distance << >> >> - << /distance << /dimension 1 >> >> - << /distance << /dimension 2 >> >> -] -def - -/good_parameters good_random_parameters good_distance_parameters join def - -/bad_random_parameters -[ - << /uniform << /min 0. /max 0. >> >> - << /normal << /mean 0. /sigma 1. >> >> % check if bad parameter names are detected - << /normal << /mean 0. /std 0. >> >> - << /normal << /mean 0. /std -1. >> >> - << /lognormal << /mu 0. /std 0. >> >> - << /lognormal << /mu 0. /std -1. >> >> - << /lognormal << /mu 0. /std 1. >> >> -] -def - -/bad_distance_parameters -[ - << /distance << /dim 1 >> >> - << /distance << /dimension 1 /min 0. >> >> -] -def - -/bad_parameters bad_random_parameters bad_distance_parameters join def - -/good_masks_2d -[ - << /circular << /radius 1. >> >> - << /circular << /radius 1. >> /anchor [0.5 0.5] >> - << /rectangular << /lower_left [-0.1 -0.1] /upper_right [0.1 0.1] >> >> - << /doughnut << /inner_radius 0.1 /outer_radius 0.2 >> >> -] -def - -/bad_masks_2d -[ - << /circular << /r 0. >> >> % check if bad parameter names are detected - << /circular << /radius 1. /foo 1 >> >> % spurious parameter - << /circular << /radius 0. >> >> - << /circular << /radius -1. >> >> - << /rectangular << /lower_left [-0.1 -0.1] /upper_right [-0.1 0.1] >> >> - << /rectangular << /lower_left [-0.1 -0.1] /upper_right [0.1 -0.1] >> >> - << /doughnut << /inner_radius 0.1 /outer_radius 0.1 >> >> -] -def - -/good_masks_3d -[ - << /spherical << /radius 1. >> >> - << /box << /lower_left [-0.1 -0.1 -0.1] /upper_right [0.1 0.1 0.1] >> >> -] -def - -/bad_masks_3d -[ - << /spherical << /radius 0. >> >> - << /spherical << /radius -1. >> >> - << /box << /lower_left [-0.1 -0.1 -0.1] /upper_right [-0.1 0.1 0.1] >> >> - << /box << /lower_left [-0.1 -0.1 -0.1] /upper_right [0.1 -0.1 0.1] >> >> - << /box << /lower_left [-0.1 -0.1 -0.1] /upper_right [0.1 0.1 -0.1] >> >> -] -def - -/good_layers -[ - << /shape [ 2 2 ] /elements /iaf_psc_alpha >> - << /shape [ 2 2 ] /elements /iaf_psc_alpha - /extent [2. .5] /center [.2 .3] /edge_wrap true >> - << /shape [ 2 2 ] /elements /iaf_psc_alpha - /extent [2. .5] /center [.2 .3] /edge_wrap false >> - << /positions [[0.1 0.1] [0.2 0.2]] /elements /iaf_psc_alpha - /extent [2. .5] /edge_wrap true >> - << /positions [[0.1 0.1 0.1] [0.2 0.2 0.2]] /elements /iaf_psc_alpha - /extent [2. .5 3.] /edge_wrap true >> -] -def - -/bad_layers -[ - << /shape [ 1 ] /elements /iaf_psc_alpha >> % too few elements in shape - << /shape [ 2 2 ] /elementsss /iaf_psc_alpha >> % misspelling - << /shape [ 2 2 ] /elements /iaf_psc_alpha - /extent [2. .5] /center [.2 .3] /edge_wrap 3 >> % bad data type - << /positions [[0.1 0.1] [0.2 0.2 0.2]] /elements /iaf_psc_alpha % dim mix - /extent [2. .5] /edge_wrap true >> - << /positions [[0.1 0.1 0.1] [0.2 0.2 0.2]] /elements /iaf_psc_alpha % dim mix - /extent [2. .5] /edge_wrap true >> -] -def - -/good_connspecs -[ - << /connection_type /pairwise_bernoulli_on_source >> - << /connection_type /pairwise_bernoulli_on_target >> - << /connection_type /pairwise_bernoulli_on_source /allow_oversized_mask true >> - << /connection_type /pairwise_bernoulli_on_source /synapse_model /static_synapse >> - << /connection_type /pairwise_bernoulli_on_source /allow_multapses false >> - << /connection_type /pairwise_bernoulli_on_source /allow_autapses false >> - << /connection_type /pairwise_bernoulli_on_source /allow_oversized_mask true >> - << /connection_type /pairwise_bernoulli_on_source /number_of_connections 2 >> - << /connection_type /pairwise_bernoulli_on_target /number_of_connections 2 >> - << /connection_type /pairwise_bernoulli_on_source /delay 2.0 >> -] -def - -/bad_connspecs -[ - << /connection_type /population >> % unknown type - << /kernel 0.1 >> % type missing -] -def - -%% Test runner for 2d connections -/conn_layers_test_2d -{ - /conndict Set - - ResetKernel - << /elements /iaf_psc_alpha /shape [ 1 1 ] >> CreateLayer - dup - conndict ConnectLayers -} def - -%% Test runner for 3d connections -/conn_layers_test_3d -{ - /conndict Set - - ResetKernel - << /elements /iaf_psc_alpha /positions [ [0. 0. 0.] ] /extent [1.0 1.0 1.0] >> CreateLayer - dup - conndict ConnectLayers -} def - - -%% first: test CreateParameter on good parameter sets -good_parameters -{ - /pset Set - (Test 1: ) =only - pset keys == - { pset CreateParameter } pass_or_die - clear -} forall - -%% second: test CreateParameter on bad parameter sets -bad_parameters -{ - /pset Set - (Test 2: ) =only - pset keys == - { pset CreateParameter } fail_or_die - clear -} forall - -%% third: test CreateMask on good masks -good_masks_2d good_masks_3d join -{ - /mask Set - (Test 3: ) =only - mask keys == - { mask CreateMask } pass_or_die - clear -} forall - -%% fourth: test CreateMask on bad masks -bad_masks_2d bad_masks_3d join -{ - /mask Set - (Test 4: ) =only - mask keys == - { mask CreateMask } fail_or_die - clear -} forall - -%% fifth: test CreateLayer on good specs -good_layers -{ - /lspec Set - ResetKernel - (Test 5: ) =only - lspec keys == - { lspec CreateLayer } pass_or_die - clear -} forall - -%% sixth: test CreateLayer on bad specs -bad_layers -{ - /lspec Set - ResetKernel - (Test 6: ) =only - lspec keys == - { lspec CreateLayer } fail_or_die - clear -} forall - -%% seventh: test ConnectLayers with good kernels -good_distance_parameters [ 0.5 1.0 ] join -{ - /kspec Set - (Test 7: ) =only - kspec DictQ { keys == } { == } ifelse - { << /connection_type /pairwise_bernoulli_on_source /kernel kspec >> - conn_layers_test_2d - } pass_or_die - clear -} forall - -%% eighth: test ConnectLayers with bad kernels -bad_distance_parameters -{ - /kspec Set - (Test 8: ) =only - kspec DictQ { keys == } { == } ifelse - { << /connection_type /pairwise_bernoulli_on_source /kernel kspec >> - conn_layers_test_2d - } fail_or_die - clear -} forall - -%% ninth: test ConnectLayers with good weights -good_parameters [ 0.5 1.0 ] join -{ - /wspec Set - (Test 9: ) =only - wspec DictQ { keys == } { == } ifelse - { << /connection_type /pairwise_bernoulli_on_source /weight wspec >> - conn_layers_test_2d - } pass_or_die - clear -} forall - -%% tenth: test ConnectLayers with bad weights -bad_parameters -{ - /wspec Set - (Test 10: ) =only - wspec DictQ { keys == } { == } ifelse - { << /connection_type /pairwise_bernoulli_on_source /weight wspec >> - conn_layers_test_2d - } fail_or_die - clear -} forall - -%% elevnth: test ConnectLayers with good 2d masks -good_masks_2d -{ - /mspec Set - (Test 11: ) =only - mspec DictQ { keys == } { == } ifelse - { << /connection_type /pairwise_bernoulli_on_source /mask mspec >> - conn_layers_test_2d - } pass_or_die - clear -} forall - -%% twelfth: test ConnectLayers with bad 2d masks -bad_masks_2d -{ - /mspec Set - (Test 12: ) =only - mspec DictQ { keys == } { == } ifelse - { << /connection_type /pairwise_bernoulli_on_source /mask mspec >> - conn_layers_test_2d - } fail_or_die - clear -} forall - -%% thirteenth: test ConnectLayers with good 3d masks -good_masks_3d -{ - /mspec Set - (Test 13: ) =only - mspec DictQ { keys == } { == } ifelse - { << /connection_type /pairwise_bernoulli_on_source /mask mspec >> - conn_layers_test_3d - } pass_or_die - clear -} forall - -%% fourteenth: test ConnectLayers with bad 3d masks -bad_masks_3d -{ - /mspec Set - (Test 14: ) =only - mspec DictQ { keys == } { == } ifelse - { << /connection_type /pairwise_bernoulli_on_source /mask mspec >> - conn_layers_test_3d - } fail_or_die - clear -} forall - -%% fifteenth test: various good cases -good_connspecs -{ - /cspec Set - (Test 15: ) =only - cspec DictQ { keys == } { == } ifelse - { cspec - conn_layers_test_2d - } pass_or_die - clear -} forall - -%% sixteenth test: various bad cases -bad_connspecs -{ - /cspec Set - (Test 16: ) =only - cspec DictQ { keys == } { == } ifelse - { cspec - conn_layers_test_2d - } fail_or_die - clear -} forall - -endusing