diff --git a/pyext/GApplicationPars.i b/pyext/GApplicationPars.i
index abf7792..eed4773 100644
--- a/pyext/GApplicationPars.i
+++ b/pyext/GApplicationPars.i
@@ -1,7 +1,7 @@
/***************************************************************************
* GApplicationPars.i - Application parameter container *
* ----------------------------------------------------------------------- *
- * copyright (C) 2010-2016 by Juergen Knoedlseder *
+ * copyright (C) 2010-2017 by Juergen Knoedlseder *
* ----------------------------------------------------------------------- *
* *
* This program is free software: you can redistribute it and/or modify *
@@ -36,7 +36,7 @@
*
* @brief Application parameter container class
***************************************************************************/
-class GApplicationPars : public GBase {
+class GApplicationPars : public GContainer {
public:
// Constructors and destructors
@@ -76,9 +76,14 @@ public:
***************************************************************************/
%extend GApplicationPars {
GApplicationPar& __getitem__(const int& index) {
+ // Counting from start, e.g. [2]
if (index >= 0 && index < self->size()) {
return (*self)[index];
}
+ // Counting from end, e.g. [-1]
+ else if (index < 0 && self->size()+index >= 0) {
+ return (*self)[self->size()+index];
+ }
else {
throw GException::out_of_range("__getitem__(int)", index, self->size());
}
@@ -86,11 +91,45 @@ public:
GApplicationPar& __getitem__(const std::string& name) {
return (*self)[name];
}
+ GApplicationPars* __getitem__(PyObject *param) {
+ if (PySlice_Check(param)) {
+ Py_ssize_t start = 0;
+ Py_ssize_t stop = 0;
+ Py_ssize_t step = 0;
+ Py_ssize_t len = self->size();
+ if (PySlice_GetIndices((PySliceObject*)param, len, &start, &stop, &step) == 0) {
+ GApplicationPars* pars = new GApplicationPars;
+ if (step > 0) {
+ for (int i = (int)start; i < (int)stop; i += (int)step) {
+ pars->append((*self)[i]);
+ }
+ }
+ else {
+ for (int i = (int)start; i > (int)stop; i += (int)step) {
+ pars->append((*self)[i]);
+ }
+ }
+ return pars;
+ }
+ else {
+ throw GException::invalid_argument("__getitem__(PyObject)",
+ "Invalid slice indices");
+ }
+ }
+ else {
+ throw GException::invalid_argument("__getitem__(PyObject)","");
+ }
+ }
void __setitem__(const int& index, const GApplicationPar& par) {
- if (index>=0 && index < self->size()) {
+ // Counting from start, e.g. [2]
+ if (index >= 0 && index < self->size()) {
(*self)[index] = par;
return;
}
+ // Counting from end, e.g. [-1]
+ else if (index < 0 && self->size()+index >= 0) {
+ (*self)[self->size()+index] = par;
+ }
else {
throw GException::out_of_range("__setitem__(int)", index, self->size());
}
diff --git a/pyext/GModels.i b/pyext/GModels.i
index 75f7733..8bae192 100644
--- a/pyext/GModels.i
+++ b/pyext/GModels.i
@@ -125,9 +125,13 @@ public:
}
}
void __setitem__(const int& index, const GModel& val) {
+ // Counting from start, e.g. [2]
if (index >= 0 && index < self->size()) {
self->set(index, val);
- return;
+ }
+ // Counting from end, e.g. [-1]
+ else if (index < 0 && self->size()+index >= 0) {
+ self->set(self->size()+index, val);
}
else {
throw GException::out_of_range("__setitem__(int)", "Model index",
diff --git a/pyext/GObservations.i b/pyext/GObservations.i
index 6d602a8..c25f423 100644
--- a/pyext/GObservations.i
+++ b/pyext/GObservations.i
@@ -151,9 +151,13 @@ typedef GObservations::likelihood likelihood;
}
}
void __setitem__(const int& index, const GObservation& val) {
- if (index>=0 && index < self->size()) {
+ // Counting from start, e.g. [2]
+ if (index >= 0 && index < self->size()) {
self->set(index, val);
- return;
+ }
+ // Counting from end, e.g. [-1]
+ else if (index < 0 && self->size()+index >= 0) {
+ self->set(self->size()+index, val);
}
else {
throw GException::out_of_range("__setitem__(int)", index, self->size());
diff --git a/test/Makefile.am b/test/Makefile.am
index c6f8d8d..f72ca28 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -120,7 +120,8 @@ EXTRA_DIST = data reports testinst \
test_GXml.py \
test_GXspec.py \
test_examples.py \
- test_python.py
+ test_python.py \
+ test_support.py
# Standard test sources and links
test_GSupport_SOURCES = test_GSupport.cpp test_GSupport.hpp
diff --git a/test/test_GApplication.py b/test/test_GApplication.py
index 955cd43..b6ffc01 100755
--- a/test/test_GApplication.py
+++ b/test/test_GApplication.py
@@ -1,7 +1,7 @@
# ==========================================================================
# This module performs unit tests for the GammaLib application module
#
-# Copyright (C) 2012-2016 Juergen Knoedlseder
+# Copyright (C) 2012-2017 Juergen Knoedlseder
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
# ==========================================================================
import os
import gammalib
+import test_support
# ========================================== #
@@ -42,8 +43,7 @@ class Test(gammalib.GPythonTestSuite):
# Return
return
-
- # Private methods
+ # Check log file versus a reference
def _check_log_file(self, ref, calls):
"""
Check log file versus a reference
@@ -74,24 +74,28 @@ class Test(gammalib.GPythonTestSuite):
# Return
return
-
- # Public methods
- def set(self):
- """
- Set all test functions
+ # Setup GApplicationPars container
+ def _setup_pars(self):
"""
- # Set test name
- self.name('app')
+ Setup GApplicationPars container
- # Append tests
- self.append(self.test_log, 'Test GLog')
- self.append(self.test_app, 'Test GApplication')
- self.append(self.test_pars, 'Test GApplicationPars')
+ Returns
+ -------
+ pars : `~gammalib.GApplicationPars`
+ Parameter container
+ """
+ # Setup application parameter container
+ pars = gammalib.GApplicationPars()
+ for i in range(10):
+ name = '%s' % i
+ par = gammalib.GApplicationPar(name,'r','a','1.0','0.0','2.0','Dummy')
+ pars.append(par)
- # Return
- return
+ # Return application parameter container
+ return pars
- def test_log(self):
+ # Test GLog class
+ def _test_log(self):
"""
Test GLog class
"""
@@ -192,7 +196,8 @@ class Test(gammalib.GPythonTestSuite):
# Return
return
- def test_app(self):
+ # Test GApplication class
+ def _test_app(self):
"""
Test GApplication class
"""
@@ -224,7 +229,8 @@ class Test(gammalib.GPythonTestSuite):
# Return
return
- def test_pars(self):
+ # Test GApplicationPars class
+ def _test_pars(self):
"""
Test GApplicationPars class
"""
@@ -240,3 +246,59 @@ class Test(gammalib.GPythonTestSuite):
# Return
return
+
+ # Test GApplicationPars class access operators
+ def _test_pars_access(self):
+ """
+ Test GApplicationPars class model access
+ """
+ # Setup application parameter container
+ pars = self._setup_pars()
+
+ # Perform application parameter access tests
+ test_support._container_access_index(self, pars)
+
+ # Check application parameter setting by index from start
+ par = gammalib.GApplicationPar('98','r','a','1.0','0.0','2.0','Dummy')
+ pars[3] = par
+ self.test_value(pars[3].name(), '98')
+
+ # Check application parameter setting by index from end
+ par = gammalib.GApplicationPar('99','r','a','1.0','0.0','2.0','Dummy')
+ pars[-2] = par
+ self.test_value(pars[-2].name(), '99')
+
+ # Return
+ return
+
+ # Test GApplicationPars class slicing
+ def _test_pars_slicing(self):
+ """
+ Test GApplicationPars class slicing
+ """
+ # Setup application parameter container
+ pars = self._setup_pars()
+
+ # Perform slicing tests
+ test_support._container_slicing(self, pars)
+
+ # Return
+ return
+
+ # Set test functions
+ def set(self):
+ """
+ Set all test functions
+ """
+ # Set test name
+ self.name('app')
+
+ # Append tests
+ self.append(self._test_log, 'Test GLog')
+ self.append(self._test_app, 'Test GApplication')
+ self.append(self._test_pars, 'Test GApplicationPars')
+ self.append(self._test_pars_access, 'Test GApplicationPars class parameter access')
+ self.append(self._test_pars_access, 'Test GApplicationPars class slicing')
+
+ # Return
+ return
diff --git a/test/test_GModel.py b/test/test_GModel.py
index 9c396f1..e2415f4 100755
--- a/test/test_GModel.py
+++ b/test/test_GModel.py
@@ -17,8 +17,8 @@
# along with this program. If not, see .
#
# ==========================================================================
-import os
import gammalib
+import test_support
# ==================================== #
@@ -36,134 +36,87 @@ class Test(gammalib.GPythonTestSuite):
# Call base class constructor
gammalib.GPythonTestSuite.__init__(self)
- # Set test data directory
- self._datadir = os.environ['TEST_DATA']
-
# Return
return
- # Set test functions
- def set(self):
+ # Setup GModels container
+ def _setup_models(self):
"""
- Set all test functions
- """
- # Set test name
- self.name('model')
-
- # Append tests
- self.append(self.test_models_access, 'Test GModels class model access')
- self.append(self.test_models_slicing, 'Test GModels class slicing')
-
- # Return
- return
+ Setup GModels container
- # Test function
- def test_models_access(self):
- """
- Test GModels class model access
+ Returns
+ -------
+ models : `~gammalib.GModels`
+ Models container
"""
- # Set model filename
- filename = self._datadir + '/model_point_plaw.xml'
-
- # Read model container and create a copy of its first model (the
- # copy is needed since the model container will go out of scope
- # later)
- models = gammalib.GModels(filename)
- model = models[0].copy()
- name = model.name()
-
- # Create an empty model container
+ # Setup model container
models = gammalib.GModels()
-
- # Append 10 identical models to model container
+ model = gammalib.GModelSky()
for i in range(10):
- model.name(name+'_'+str(i))
+ model.name('%s' % i)
models.append(model)
-
- # Loop over all models using the container iterator and count the
- # number of iterations
- nmodels = 0
- for m in models:
- self.test_value(m.name(), name+'_'+str(nmodels))
- nmodels += 1
- # Check that looping was successful
- self.test_value(models.size(), 10, 'Check model container size')
- self.test_value(nmodels, 10, 'Check model iterator')
+ # Return model container
+ return models
- # Check model access from end
- self.test_value(models[-1].name(), name+'_9')
+ # Test GModels class access operators
+ def _test_models_access(self):
+ """
+ Test GModels class model access
+ """
+ # Setup model container and sky model
+ models = self._setup_models()
+ model = gammalib.GModelSky()
- # Check model access by name
- self.test_value(models[name+'_7'].name(), name+'_7')
+ # Perform model access tests
+ test_support._container_access_index(self, models)
- # Check model setting by index
- model.name('Test index')
- models[0] = model
- self.test_value(models[0].name(), 'Test index')
+ # Check model getting by name
+ self.test_value(models['7'].name(), '7')
# Check model setting by name
model.name('Test name')
- models[name+'_3'] = model
+ models['3'] = model
self.test_value(models['Test name'].name(), 'Test name')
+ # Check model setting by index from start
+ model.name('Test index from start')
+ models[1] = model
+ self.test_value(models[1].name(), 'Test index from start')
+
+ # Check model setting by index from end
+ model.name('Test index from end')
+ models[-2] = model
+ self.test_value(models[-2].name(), 'Test index from end')
+
# Return
return
-
# Test GModels class slicing
- def test_models_slicing(self):
+ def _test_models_slicing(self):
"""
Test GModels class slicing
"""
- # Setup model container
- models = gammalib.GModels()
- model = gammalib.GModelSky()
- for i in range(10):
- model.name('%s' % i)
- models.append(model)
+ # Setup models container
+ models = self._setup_models()
- # Test models[start:end]
- self.test_value(len(models[3:5]), 2)
- self.test_value(models[3:5][0].name(), '3')
- self.test_value(models[3:5][1].name(), '4')
+ # Perform slicing tests
+ test_support._container_slicing(self, models)
- # Test models[start:]
- self.test_value(len(models[7:]), 3)
- self.test_value(models[7:][0].name(), '7')
- self.test_value(models[7:][1].name(), '8')
- self.test_value(models[7:][2].name(), '9')
+ # Return
+ return
- # Test models[:end]
- self.test_value(len(models[:2]), 2)
- self.test_value(models[:2][0].name(), '0')
- self.test_value(models[:2][1].name(), '1')
+ # Set test functions
+ def set(self):
+ """
+ Set all test functions
+ """
+ # Set test name
+ self.name('model')
- # Test models[:]
- self.test_value(len(models[:]), 10)
- for i in range(10):
- self.test_value(models[:][i].name(), '%s' % i)
-
- # Test models[start:end:step]
- self.test_value(len(models[3:7:2]), 2)
- self.test_value(models[3:7:2][0].name(), '3')
- self.test_value(models[3:7:2][1].name(), '5')
-
- # Test models[start:end:step]
- self.test_value(len(models[6:3:-2]), 2)
- self.test_value(models[6:3:-2][0].name(), '6')
- self.test_value(models[6:3:-2][1].name(), '4')
-
- # Test models[-start:]
- self.test_value(len(models[-2:]), 2)
- self.test_value(models[-2:][0].name(), '8')
- self.test_value(models[-2:][1].name(), '9')
-
- # Test models[:-end]
- self.test_value(len(models[:-7]), 3)
- self.test_value(models[:-7][0].name(), '0')
- self.test_value(models[:-7][1].name(), '1')
- self.test_value(models[:-7][2].name(), '2')
+ # Append tests
+ self.append(self._test_models_access, 'Test GModels class model access')
+ self.append(self._test_models_slicing, 'Test GModels class slicing')
# Return
return
diff --git a/test/test_GObservation.py b/test/test_GObservation.py
index 6860c5a..d42b514 100755
--- a/test/test_GObservation.py
+++ b/test/test_GObservation.py
@@ -18,6 +18,7 @@
#
# ==========================================================================
import gammalib
+import test_support
# ========================================== #
@@ -38,26 +39,39 @@ class Test(gammalib.GPythonTestSuite):
# Return
return
- # Set test functions
- def set(self):
+ # Setup GObservations container
+ def _setup_obs(self):
"""
- Set all test functions
+ Setup GObservations container
+
+ Returns
+ -------
+ obs : `~gammalib.GObservations`
+ Observation container
"""
- # Set test name
- self.name('obs')
+ # Setup observation container
+ obs = gammalib.GObservations()
+ run = gammalib.GCTAObservation()
+ for i in range(10):
+ run.name('%s' % i)
+ run.id('%s' % i)
+ obs.append(run)
- # Append tests
- self.append(self.test_energy, 'Test GEnergy class')
- self.append(self.test_energies, 'Test GEnergies class')
- self.append(self.test_time, 'Test GTime class')
- self.append(self.test_observations_slicing,
- 'Test GObservations class slicing')
+ # Setup model container
+ models = gammalib.GModels()
+ model = gammalib.GModelSky()
+ for i in range(10):
+ model.name('%s' % i)
+ models.append(model)
- # Return
- return
+ # Set observation's model container
+ obs.models(models)
+
+ # Return observations container
+ return obs
# Test GEnergy class
- def test_energy(self):
+ def _test_energy(self):
"""
Test GEnergy class
"""
@@ -131,7 +145,7 @@ class Test(gammalib.GPythonTestSuite):
return
# Test GEnergies class
- def test_energies(self):
+ def _test_energies(self):
"""
Test GEnergies class
"""
@@ -149,7 +163,7 @@ class Test(gammalib.GPythonTestSuite):
return
# Test GTime class
- def test_time(self):
+ def _test_time(self):
"""
Test GTime class
"""
@@ -217,78 +231,69 @@ class Test(gammalib.GPythonTestSuite):
# Return
return
+ # Test GObservations class access operators
+ def _test_observations_access(self):
+ """
+ Test GObservations class observation access
+ """
+ # Setup observation container and CTA observation
+ obs = self._setup_obs()
+ run = gammalib.GCTAObservation()
+
+ # Perform observation access tests
+ test_support._container_access_index(self, obs)
+
+ # Check observation setting by index from start
+ run.id('98')
+ obs[3] = run
+ self.test_value(obs[3].id(), '98')
+
+ # Check observation setting by index from end
+ run.id('99')
+ obs[-2] = run
+ self.test_value(obs[-2].id(), '99')
+
+ # Return
+ return
# Test GObservations class slicing
- def test_observations_slicing(self):
+ def _test_observations_slicing(self):
"""
Test GObservations class slicing
"""
# Setup observation container
- obs = gammalib.GObservations()
- run = gammalib.GCTAObservation()
- for i in range(10):
- run.id('%s' % i)
- obs.append(run)
+ obs = self._setup_obs()
- # Setup model container
- models = gammalib.GModels()
- model = gammalib.GModelSky()
- for i in range(10):
- model.name('%s' % i)
- models.append(model)
-
- # Set observation's model container
- obs.models(models)
+ # Perform slicing tests
+ test_support._container_slicing(self, obs)
- # Test obs[start:end]
- self.test_value(len(obs[3:5]), 2)
+ # Perform additional slicing tests
self.test_value(len(obs[3:5].models()), 10)
- self.test_value(obs[3:5][0].id(), '3')
- self.test_value(obs[3:5][1].id(), '4')
-
- # Test obs[start:]
- self.test_value(len(obs[7:]), 3)
self.test_value(len(obs[7:].models()), 10)
- self.test_value(obs[7:][0].id(), '7')
- self.test_value(obs[7:][1].id(), '8')
- self.test_value(obs[7:][2].id(), '9')
-
- # Test obs[:end]
- self.test_value(len(obs[:2]), 2)
self.test_value(len(obs[:2].models()), 10)
- self.test_value(obs[:2][0].id(), '0')
- self.test_value(obs[:2][1].id(), '1')
-
- # Test obs[:]
- self.test_value(len(obs[:]), 10)
self.test_value(len(obs[:].models()), 10)
- for i in range(10):
- self.test_value(obs[:][i].id(), '%s' % i)
-
- # Test obs[start:end:step]
- self.test_value(len(obs[3:7:2]), 2)
self.test_value(len(obs[3:7:2].models()), 10)
- self.test_value(obs[3:7:2][0].id(), '3')
- self.test_value(obs[3:7:2][1].id(), '5')
-
- # Test obs[start:end:step]
- self.test_value(len(obs[6:3:-2]), 2)
self.test_value(len(obs[6:3:-2].models()), 10)
- self.test_value(obs[6:3:-2][0].id(), '6')
- self.test_value(obs[6:3:-2][1].id(), '4')
-
- # Test obs[-start:]
- self.test_value(len(obs[-2:]), 2)
self.test_value(len(obs[-2:].models()), 10)
- self.test_value(obs[-2:][0].id(), '8')
- self.test_value(obs[-2:][1].id(), '9')
-
- # Test obs[:-end]
- self.test_value(len(obs[:-7]), 3)
self.test_value(len(obs[:-7].models()), 10)
- self.test_value(obs[:-7][0].id(), '0')
- self.test_value(obs[:-7][1].id(), '1')
- self.test_value(obs[:-7][2].id(), '2')
+
+ # Return
+ return
+
+ # Set test functions
+ def set(self):
+ """
+ Set all test functions
+ """
+ # Set test name
+ self.name('obs')
+
+ # Append tests
+ self.append(self._test_energy, 'Test GEnergy class')
+ self.append(self._test_energies, 'Test GEnergies class')
+ self.append(self._test_time, 'Test GTime class')
+ self.append(self._test_observations_access, 'Test GObservations class observation access')
+ self.append(self._test_observations_slicing, 'Test GObservations class slicing')
# Return
return
diff --git a/test/test_support.py b/test/test_support.py
new file mode 100755
index 0000000..f281fe4
--- /dev/null
+++ b/test/test_support.py
@@ -0,0 +1,114 @@
+# ==========================================================================
+# This module provides support functions for the Python unit tests
+#
+# Copyright (C) 2017 Juergen Knoedlseder
+#
+# This program 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program. If not, see .
+#
+# ==========================================================================
+
+
+# ============================== #
+# Test container access by index #
+# ============================== #
+def _container_access_index(testsuite, container):
+ """
+ Test container access by index
+
+ Parameters
+ ----------
+ testsuite : `~gammalib.GPythonTestSuite`
+ Test suite class
+ container : `~gammalib.GContainer`
+ Container class
+ """
+ # Loop over all elements using the container iterator and count the number
+ # of iterations
+ niter = 0
+ for element in container:
+ testsuite.test_value(element.name(), '%s' % niter)
+ niter += 1
+
+ # Check that looping was successful
+ testsuite.test_value(container.size(), 10, 'Check container size')
+ testsuite.test_value(niter, 10, 'Check container iterator')
+
+ # Test access from start
+ testsuite.test_value(container[3].name(), '3')
+
+ # Check access from end
+ testsuite.test_value(container[-2].name(), '8')
+
+ # Return
+ return
+
+
+# ====================== #
+# Test container slicing #
+# ====================== #
+def _container_slicing(testsuite, container):
+ """
+ Test container slicing
+
+ Parameters
+ ----------
+ testsuite : `~gammalib.GPythonTestSuite`
+ Test suite class
+ container : `~gammalib.GContainer`
+ Container class
+ """
+ # Test container[start:end]
+ testsuite.test_value(len(container[3:5]), 2)
+ testsuite.test_value(container[3:5][0].name(), '3')
+ testsuite.test_value(container[3:5][1].name(), '4')
+
+ # Test container[start:]
+ testsuite.test_value(len(container[7:]), 3)
+ testsuite.test_value(container[7:][0].name(), '7')
+ testsuite.test_value(container[7:][1].name(), '8')
+ testsuite.test_value(container[7:][2].name(), '9')
+
+ # Test container[:end]
+ testsuite.test_value(len(container[:2]), 2)
+ testsuite.test_value(container[:2][0].name(), '0')
+ testsuite.test_value(container[:2][1].name(), '1')
+
+ # Test container[:]
+ testsuite.test_value(len(container[:]), 10)
+ for i in range(10):
+ testsuite.test_value(container[:][i].name(), '%s' % i)
+
+ # Test container[start:end:step]
+ testsuite.test_value(len(container[3:7:2]), 2)
+ testsuite.test_value(container[3:7:2][0].name(), '3')
+ testsuite.test_value(container[3:7:2][1].name(), '5')
+
+ # Test container[start:end:step]
+ testsuite.test_value(len(container[6:3:-2]), 2)
+ testsuite.test_value(container[6:3:-2][0].name(), '6')
+ testsuite.test_value(container[6:3:-2][1].name(), '4')
+
+ # Test container[-start:]
+ testsuite.test_value(len(container[-2:]), 2)
+ testsuite.test_value(container[-2:][0].name(), '8')
+ testsuite.test_value(container[-2:][1].name(), '9')
+
+ # Test container[:-end]
+ testsuite.test_value(len(container[:-7]), 3)
+ testsuite.test_value(container[:-7][0].name(), '0')
+ testsuite.test_value(container[:-7][1].name(), '1')
+ testsuite.test_value(container[:-7][2].name(), '2')
+
+ # Return
+ return