Commit e6d15df1b5ae55579f053c455c267011a3857f2a

Authored by Jürgen Knödlseder
1 parent b8b92464

Support Python container slicing (#2128)

ChangeLog
1   -2017-06-22
  1 +2017-07-22
2 2  
3 3 * Version 1.4.0 released
4 4 =========================
... ...
1 1 New Features and Important Changes in GammaLib 1.4.0
2 2  
3   -22 June 2017
  3 +22 July 2017
4 4  
5 5  
6 6 1. Introduction
... ... @@ -21,7 +21,13 @@ The following classes have been renamed:
21 21 - n.a.
22 22  
23 23 The following methods have been added:
24   -- n.a.
  24 +- GSkyRegion::type(std::string&)
  25 +- GSkyRegion::name(std::string&)
  26 +- GSkyRegion::solidangle(std::string&)
  27 +- GOptimizerPars::append(GOptimizerPar&)
  28 +- GLATEventList::append(GLATEventAtom&)
  29 +- GLATEventList::reserve(int&)
  30 +- GLATEventList::remove(int&,int&)
25 31  
26 32 The following methods have been removed:
27 33 - n.a.
... ... @@ -78,12 +84,13 @@ None
78 84  
79 85 11. Optimization module
80 86 -----------------------
81   -None
  87 +Add GOptimizerPars::append() method to allow appending of parameters to the
  88 +container.
82 89  
83 90  
84 91 12. Sky module
85 92 --------------
86   -None
  93 +Add methods to set the name, type and solid angle of a sky region.
87 94  
88 95  
89 96 13. Support module
... ... @@ -118,7 +125,7 @@ None
118 125  
119 126 19. Fermi-LAT interface
120 127 ----------------------
121   -None
  128 +Add append(), remove() and reserve() methods to GLATEventList class.
122 129  
123 130  
124 131 20. CTA interface
... ...
include/GOptimizerPars.hpp
1 1 /***************************************************************************
2 2 * GOptimizerPars.hpp - Optimizer parameter container class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2009-2015 by Juergen Knoedlseder *
  4 + * copyright (C) 2009-2017 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -75,6 +75,7 @@ public:
75 75 int nfree(void) const;
76 76 GOptimizerPar* set(const int& index, const GOptimizerPar& par);
77 77 GOptimizerPar* set(const std::string& name, const GOptimizerPar& par);
  78 + GOptimizerPar* append(const GOptimizerPar& par);
78 79 void attach(GOptimizerPar* par);
79 80 void attach(const int& index, GOptimizerPar* par);
80 81 void attach(const std::string& name, GOptimizerPar* par);
... ...
include/GSkyRegion.hpp
1 1 /***************************************************************************
2 2 * GSkyRegion.hpp - Abstract virtual sky region base class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2013-2014 by Pierrick Martin *
  4 + * copyright (C) 2013-2017 by Pierrick Martin *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -80,6 +80,9 @@ public:
80 80 const std::string& type(void) const;
81 81 const std::string& name(void) const;
82 82 const double& solidangle(void) const;
  83 + void type(const std::string& type);
  84 + void name(const std::string& name);
  85 + void solidangle(const double& solidangle);
83 86  
84 87 protected:
85 88 // Protected methods
... ... @@ -109,6 +112,21 @@ const std::string& GSkyRegion::name(void) const
109 112  
110 113  
111 114 /***********************************************************************//**
  115 + * @brief Set region name
  116 + *
  117 + * @param[in] name Region name.
  118 + *
  119 + * Sets the region name.
  120 + ***************************************************************************/
  121 +inline
  122 +void GSkyRegion::name(const std::string& name)
  123 +{
  124 + m_name = name;
  125 + return;
  126 +}
  127 +
  128 +
  129 +/***********************************************************************//**
112 130 * @brief Return region type
113 131 *
114 132 * @return Region type
... ... @@ -123,16 +141,46 @@ const std::string& GSkyRegion::type(void) const
123 141  
124 142  
125 143 /***********************************************************************//**
126   - * @brief Return solid angle
  144 + * @brief Set region type
  145 + *
  146 + * @param[in] type Region type.
  147 + *
  148 + * Sets the region type.
  149 + ***************************************************************************/
  150 +inline
  151 +void GSkyRegion::type(const std::string& type)
  152 +{
  153 + m_type = type;
  154 + return;
  155 +}
  156 +
  157 +
  158 +/***********************************************************************//**
  159 + * @brief Return solid angle of region
127 160 *
128   - * @return Solid angle
  161 + * @return Solid angle of region.
129 162 *
130   - * Returns the solid angle subtended by the region (in steradian).
  163 + * Returns the solid angle subtended by the region (in steradians).
131 164 ***************************************************************************/
132 165 inline
133 166 const double& GSkyRegion::solidangle(void) const
134 167 {
135 168 return (m_solid);
136 169 }
137   -
  170 +
  171 +
  172 +/***********************************************************************//**
  173 + * @brief Set solid angle of region
  174 + *
  175 + * @param[in] solidangle Solid angle of region (in steradians).
  176 + *
  177 + * Sets the solid angle subtended by the region (in steradians).
  178 + ***************************************************************************/
  179 +inline
  180 +void GSkyRegion::solidangle(const double& solidangle)
  181 +{
  182 + m_solid = solidangle;
  183 + return;
  184 +}
  185 +
138 186 #endif /* GSKYREGION_HPP */
... ...
inst/cta/pyext/GCTAEventList.i
... ... @@ -90,19 +90,64 @@ public:
90 90 * @brief GCTAEventList class extension
91 91 ***************************************************************************/
92 92 %extend GCTAEventList {
93   - GCTAEventList copy() {
94   - return (*self);
95   - }
96   - GCTAEventAtom* __getitem__(int index) {
97   - if (index >= 0 && index < self->size())
  93 + GCTAEventAtom* __getitem__(const int& index) {
  94 + // Counting from start, e.g. [2]
  95 + if (index >= 0 && index < self->size()) {
98 96 return (*self)[index];
99   - else
100   - throw GException::out_of_range("__getitem__(int)", index, self->size());
  97 + }
  98 + // Counting from end, e.g. [-1]
  99 + else if (index < 0 && self->size()+index >= 0) {
  100 + return (*self)[self->size()+index];
  101 + }
  102 + else {
  103 + throw GException::out_of_range("__getitem__(int)", "Event index",
  104 + index, self->size());
  105 + }
  106 + }
  107 + GCTAEventList* __getitem__(PyObject *param) {
  108 + if (PySlice_Check(param)) {
  109 + Py_ssize_t start = 0;
  110 + Py_ssize_t stop = 0;
  111 + Py_ssize_t step = 0;
  112 + Py_ssize_t len = self->size();
  113 + if (PySlice_GetIndices((PySliceObject*)param, len, &start, &stop, &step) == 0) {
  114 + GCTAEventList* list = new GCTAEventList;
  115 + if (step > 0) {
  116 + for (int i = (int)start; i < (int)stop; i += (int)step) {
  117 + list->append(*(*self)[i]);
  118 + }
  119 + }
  120 + else {
  121 + for (int i = (int)start; i > (int)stop; i += (int)step) {
  122 + list->append(*(*self)[i]);
  123 + }
  124 + }
  125 + return list;
  126 + }
  127 + else {
  128 + throw GException::invalid_argument("__getitem__(PyObject)",
  129 + "Invalid slice indices");
  130 + }
  131 + }
  132 + else {
  133 + throw GException::invalid_argument("__getitem__(PyObject)","");
  134 + }
101 135 }
102   - void __setitem__(int index, const GCTAEventAtom& val) {
103   - if (index>=0 && index < self->size())
104   - *((*self)[index]) = val;
105   - else
106   - throw GException::out_of_range("__setitem__(int)", index, self->size());
  136 + void __setitem__(const int& index, const GCTAEventAtom& event) {
  137 + // Counting from start, e.g. [2]
  138 + if (index >= 0 && index < self->size()) {
  139 + *(*self)[index] = event;
  140 + }
  141 + // Counting from end, e.g. [-1]
  142 + else if (index < 0 && self->size()+index >= 0) {
  143 + *(*self)[self->size()+index] = event;
  144 + }
  145 + else {
  146 + throw GException::out_of_range("__setitem__(int)", "Event index",
  147 + index, self->size());
  148 + }
  149 + }
  150 + GCTAEventList copy() {
  151 + return (*self);
107 152 }
108 153 };
... ...
inst/cta/test/test_CTA.py
... ... @@ -20,6 +20,7 @@
20 20 import os
21 21 import gammalib
22 22 import math
  23 +import test_support
23 24  
24 25  
25 26 # ================================== #
... ... @@ -27,12 +28,12 @@ import math
27 28 # ================================== #
28 29 class Test(gammalib.GPythonTestSuite):
29 30 """
30   - Test class for GammaLib CTA module.
  31 + Test class for GammaLib CTA module
31 32 """
32 33 # Constructor
33 34 def __init__(self):
34 35 """
35   - Constructor.
  36 + Constructor
36 37 """
37 38 # Call base class constructor
38 39 gammalib.GPythonTestSuite.__init__(self)
... ... @@ -44,28 +45,58 @@ class Test(gammalib.GPythonTestSuite):
44 45 # Return
45 46 return
46 47  
47   - # Set test functions
48   - def set(self):
  48 + # Setup GCTAEventList container
  49 + def _setup_eventlist(self):
49 50 """
50   - Set all test functions.
  51 + Setup GCTAEventList container
  52 +
  53 + Returns
  54 + -------
  55 + list : `~gammalib.GCTAEventList`
  56 + GCTAEventList container
51 57 """
52   - # Set test name
53   - self.name('CTA')
  58 + # Setup event list container
  59 + list = gammalib.GCTAEventList()
  60 + atom = gammalib.GCTAEventAtom()
  61 + for i in range(10):
  62 + atom.energy().MeV(float(i))
  63 + list.append(atom)
  64 +
  65 + # Return event list container
  66 + return list
  67 +
  68 + # Test GCTAEventList class access operators
  69 + def _test_eventlist_access(self):
  70 + """
  71 + Test GCTAEventList class observation access
  72 + """
  73 + # Setup event list container
  74 + list = self._setup_eventlist()
54 75  
55   - # Append tests
56   - self.append(self.test_aeff, 'Test CTA effective area classes')
57   - self.append(self.test_psf, 'Test CTA PSF classes')
58   - self.append(self.test_edisp, 'Test CTA energy dispersion classes')
59   - self.append(self.test_response, 'Test CTA response classes')
60   - self.append(self.test_onoff, 'Test CTA On/Off analysis')
  76 + # Perform event list access tests
  77 + test_support._energy_container_access_index(self, list)
  78 +
  79 + # Return
  80 + return
  81 +
  82 + # Test GCTAEventList class slicing
  83 + def _test_eventlist_slicing(self):
  84 + """
  85 + Test GCTAEventList class slicing
  86 + """
  87 + # Setup event list container
  88 + list = self._setup_eventlist()
  89 +
  90 + # Perform slicing tests
  91 + test_support._energy_container_slicing(self, list)
61 92  
62 93 # Return
63 94 return
64 95  
65 96 # Test effective area response
66   - def test_aeff(self):
  97 + def _test_aeff(self):
67 98 """
68   - Test GCTAAeff classes.
  99 + Test GCTAAeff classes
69 100 """
70 101 # Test GCTAAeff2D file constructor
71 102 filename = self._caldb + '/prod1_gauss.fits'
... ... @@ -119,9 +150,9 @@ class Test(gammalib.GPythonTestSuite):
119 150 return
120 151  
121 152 # Test point spread function response
122   - def test_psf(self):
  153 + def _test_psf(self):
123 154 """
124   - Test GCTAPsf classes.
  155 + Test GCTAPsf classes
125 156 """
126 157 # Test GCTAPsf2D file constructor
127 158 filename = self._caldb + '/prod1_gauss.fits'
... ... @@ -175,9 +206,9 @@ class Test(gammalib.GPythonTestSuite):
175 206 return
176 207  
177 208 # Test energy dispersion
178   - def test_edisp(self):
  209 + def _test_edisp(self):
179 210 """
180   - Test GCTAEdisp classes.
  211 + Test GCTAEdisp classes
181 212 """
182 213 # Test GCTAEdispRmf file constructor
183 214 filename = self._caldb + '/dc1/rmf.fits'
... ... @@ -222,7 +253,7 @@ class Test(gammalib.GPythonTestSuite):
222 253 # 0.5, 0.005)
223 254  
224 255 # Test response
225   - def test_response(self):
  256 + def _test_response(self):
226 257 """
227 258 Test response classes
228 259 """
... ... @@ -234,9 +265,9 @@ class Test(gammalib.GPythonTestSuite):
234 265 return
235 266  
236 267 # Test On/Off analysis
237   - def test_onoff(self):
  268 + def _test_onoff(self):
238 269 """
239   - Test On/Off analysis.
  270 + Test On/Off analysis
240 271 """
241 272 # Create On region
242 273 crab = gammalib.GSkyDir()
... ... @@ -271,9 +302,6 @@ class Test(gammalib.GPythonTestSuite):
271 302 lm = gammalib.GOptimizerLM()
272 303 outobs.optimize(lm)
273 304 outobs.errors(lm)
274   - #print(lm)
275   - #print(outobs)
276   - #print(outobs.models())
277 305  
278 306 # Test On/Off model fitting results
279 307 sky = outobs.models()['Crab']
... ... @@ -307,3 +335,23 @@ class Test(gammalib.GPythonTestSuite):
307 335  
308 336 # Return
309 337 return
  338 +
  339 + # Set test functions
  340 + def set(self):
  341 + """
  342 + Set all test functions.
  343 + """
  344 + # Set test name
  345 + self.name('CTA')
  346 +
  347 + # Append tests
  348 + self.append(self._test_eventlist_access, 'Test GCTAEventList event access')
  349 + self.append(self._test_eventlist_slicing, 'Test GCTAEventList slicing')
  350 + self.append(self._test_aeff, 'Test CTA effective area classes')
  351 + self.append(self._test_psf, 'Test CTA PSF classes')
  352 + self.append(self._test_edisp, 'Test CTA energy dispersion classes')
  353 + self.append(self._test_response, 'Test CTA response classes')
  354 + self.append(self._test_onoff, 'Test CTA On/Off analysis')
  355 +
  356 + # Return
  357 + return
... ...
inst/lat/include/GLATEventList.hpp
... ... @@ -61,7 +61,7 @@ public:
61 61 virtual ~GLATEventList(void);
62 62  
63 63 // Operators
64   - virtual GLATEventList& operator= (const GLATEventList& list);
  64 + virtual GLATEventList& operator=(const GLATEventList& list);
65 65 virtual GLATEventAtom* operator[](const int& index);
66 66 virtual const GLATEventAtom* operator[](const int& index) const;
67 67  
... ... @@ -81,6 +81,9 @@ public:
81 81 virtual std::string print(const GChatter& chatter = NORMAL) const;
82 82  
83 83 // Other methods
  84 + void append(const GLATEventAtom& event);
  85 + void reserve(const int& number);
  86 + void remove(const int& index, const int& number = 1);
84 87  
85 88 protected:
86 89 // Protected methods
... ... @@ -93,13 +96,13 @@ protected:
93 96 void read_ds_keys(const GFitsHDU& hdu);
94 97  
95 98 // Protected members
96   - GLATRoi m_roi; //!< Region of interest
97   - std::vector<GLATEventAtom> m_events; //!< Events
98   - std::vector<std::string> m_difrsp_label; //!< Diffuse response model labels
99   - std::vector<std::string> m_ds_type; //!< Data selection types
100   - std::vector<std::string> m_ds_unit; //!< Data selection units
101   - std::vector<std::string> m_ds_value; //!< Data selection values
102   - std::vector<std::string> m_ds_reference; //!< Data selection references
  99 + GLATRoi m_roi; //!< Region of interest
  100 + std::vector<GLATEventAtom> m_events; //!< Events
  101 + std::vector<std::string> m_difrsp_label; //!< Diffuse response model labels
  102 + std::vector<std::string> m_ds_type; //!< Data selection types
  103 + std::vector<std::string> m_ds_unit; //!< Data selection units
  104 + std::vector<std::string> m_ds_value; //!< Data selection values
  105 + std::vector<std::string> m_ds_reference; //!< Data selection references
103 106 };
104 107  
105 108  
... ... @@ -150,4 +153,19 @@ const GLATRoi&amp; GLATEventList::roi(void) const
150 153 return m_roi;
151 154 }
152 155  
  156 +
  157 +/***********************************************************************//**
  158 + * @brief Reserves space for events
  159 + *
  160 + * @param[in] number Number of events.
  161 + *
  162 + * Reserves space for number events in the event list.
  163 + ***************************************************************************/
  164 +inline
  165 +void GLATEventList::reserve(const int& number)
  166 +{
  167 + m_events.reserve(number);
  168 + return;
  169 +}
  170 +
153 171 #endif /* GLATEVENTLIST_HPP */
... ...
inst/lat/pyext/GLATEventList.i
1 1 /***************************************************************************
2 2 * GLATEventList.i - Fermi/LAT event list class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2012-2016 by Juergen Knoedlseder *
  4 + * copyright (C) 2012-2017 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -56,6 +56,11 @@ public:
56 56 virtual int number(void) const;
57 57 virtual void roi(const GRoi& roi);
58 58 virtual const GLATRoi& roi(void) const;
  59 +
  60 + // Other methods
  61 + void append(const GLATEventAtom& event);
  62 + void reserve(const int& number);
  63 + void remove(const int& index, const int& number = 1);
59 64 };
60 65  
61 66  
... ... @@ -63,25 +68,64 @@ public:
63 68 * @brief GLATEventList class extension
64 69 ***************************************************************************/
65 70 %extend GLATEventList {
66   - GLATEventList copy() {
67   - return (*self);
68   - }
69 71 GLATEventAtom* __getitem__(const int& index) {
  72 + // Counting from start, e.g. [2]
70 73 if (index >= 0 && index < self->size()) {
71   - return ((*self)[index]);
  74 + return (*self)[index];
  75 + }
  76 + // Counting from end, e.g. [-1]
  77 + else if (index < 0 && self->size()+index >= 0) {
  78 + return (*self)[self->size()+index];
72 79 }
73 80 else {
74 81 throw GException::out_of_range("__getitem__(int)", "Event index",
75 82 index, self->size());
76 83 }
77 84 }
78   - void __setitem__(const int& index, const GLATEventAtom& value) {
79   - if (index>=0 && index < self->size()) {
80   - *((*self)[index]) = value;
  85 + GLATEventList* __getitem__(PyObject *param) {
  86 + if (PySlice_Check(param)) {
  87 + Py_ssize_t start = 0;
  88 + Py_ssize_t stop = 0;
  89 + Py_ssize_t step = 0;
  90 + Py_ssize_t len = self->size();
  91 + if (PySlice_GetIndices((PySliceObject*)param, len, &start, &stop, &step) == 0) {
  92 + GLATEventList* list = new GLATEventList;
  93 + if (step > 0) {
  94 + for (int i = (int)start; i < (int)stop; i += (int)step) {
  95 + list->append(*(*self)[i]);
  96 + }
  97 + }
  98 + else {
  99 + for (int i = (int)start; i > (int)stop; i += (int)step) {
  100 + list->append(*(*self)[i]);
  101 + }
  102 + }
  103 + return list;
  104 + }
  105 + else {
  106 + throw GException::invalid_argument("__getitem__(PyObject)",
  107 + "Invalid slice indices");
  108 + }
  109 + }
  110 + else {
  111 + throw GException::invalid_argument("__getitem__(PyObject)","");
  112 + }
  113 + }
  114 + void __setitem__(const int& index, const GLATEventAtom& event) {
  115 + // Counting from start, e.g. [2]
  116 + if (index >= 0 && index < self->size()) {
  117 + *(*self)[index] = event;
  118 + }
  119 + // Counting from end, e.g. [-1]
  120 + else if (index < 0 && self->size()+index >= 0) {
  121 + *(*self)[self->size()+index] = event;
81 122 }
82 123 else {
83 124 throw GException::out_of_range("__setitem__(int)", "Event index",
84 125 index, self->size());
85 126 }
86 127 }
  128 + GLATEventList copy() {
  129 + return (*self);
  130 + }
87 131 };
... ...
inst/lat/src/GLATEventList.cpp
... ... @@ -384,9 +384,56 @@ void GLATEventList::roi(const GRoi&amp; roi)
384 384  
385 385  
386 386 /***********************************************************************//**
  387 + * @brief Append event to event list
  388 + *
  389 + * @param[in] event Event.
  390 + *
  391 + * Appends an event to the end of the event list.
  392 + ***************************************************************************/
  393 +void GLATEventList::append(const GLATEventAtom& event)
  394 +{
  395 + // Append event
  396 + m_events.push_back(event);
  397 +
  398 + // Return
  399 + return;
  400 +}
  401 +
  402 +
  403 +/***********************************************************************//**
  404 + * @brief Remove events from event list
  405 + *
  406 + * @param[in] index Index from which on events should be removed.
  407 + * @param[in] number Number of event to remove (default: 1).
  408 + *
  409 + * Removes events from the event list. This method does nothing if @p index
  410 + * points beyond the event list. The method does also gently accept
  411 + * @p number arguments where @p index + @p number reach beyond the event
  412 + * list. In that case, all events from event @p index on will be removed.
  413 + ***************************************************************************/
  414 +void GLATEventList::remove(const int& index, const int& number)
  415 +{
  416 + // Continue only if index is valid
  417 + if (index < size()) {
  418 +
  419 + // Determine number of elements to remove
  420 + int n_remove = (index + number > size()) ? size() - index : number;
  421 +
  422 + // Remove events
  423 + m_events.erase(m_events.begin() + index,
  424 + m_events.begin() + index + n_remove);
  425 +
  426 + } // endif: index was valid
  427 +
  428 + // Return
  429 + return;
  430 +}
  431 +
  432 +
  433 +/***********************************************************************//**
387 434 * @brief Print event list information
388 435 *
389   - * @param[in] chatter Chattiness (defaults to NORMAL).
  436 + * @param[in] chatter Chattiness.
390 437 * @return String containing event list information.
391 438 ***************************************************************************/
392 439 std::string GLATEventList::print(const GChatter& chatter) const
... ...
inst/lat/test/test_LAT.py
1 1 # ==========================================================================
2 2 # This module performs unit tests for the GammaLib LAT module.
3 3 #
4   -# Copyright (C) 2012-2015 Juergen Knoedlseder
  4 +# Copyright (C) 2012-2017 Juergen Knoedlseder
5 5 #
6 6 # This program is free software: you can redistribute it and/or modify
7 7 # it under the terms of the GNU General Public License as published by
... ... @@ -18,6 +18,7 @@
18 18 #
19 19 # ==========================================================================
20 20 import gammalib
  21 +import test_support
21 22  
22 23  
23 24 # ================================== #
... ... @@ -25,12 +26,12 @@ import gammalib
25 26 # ================================== #
26 27 class Test(gammalib.GPythonTestSuite):
27 28 """
28   - Test class for GammaLib LAT module.
  29 + Test class for GammaLib LAT module
29 30 """
30 31 # Constructor
31 32 def __init__(self):
32 33 """
33   - Constructor.
  34 + Constructor
34 35 """
35 36 # Call base class constructor
36 37 gammalib.GPythonTestSuite.__init__(self)
... ... @@ -38,24 +39,65 @@ class Test(gammalib.GPythonTestSuite):
38 39 # Return
39 40 return
40 41  
41   - # Set test functions
42   - def set(self):
  42 + # Setup GLATEventList container
  43 + def _setup_eventlist(self):
43 44 """
44   - Set all test functions.
  45 + Setup GLATEventList container
  46 +
  47 + Returns
  48 + -------
  49 + list : `~gammalib.GLATEventList`
  50 + GLATEventList container
45 51 """
46   - # Set test name
47   - self.name("LAT")
  52 + # Setup event list container
  53 + list = gammalib.GLATEventList()
  54 + atom = gammalib.GLATEventAtom()
  55 + for i in range(10):
  56 + atom.energy().MeV(float(i))
  57 + list.append(atom)
48 58  
49   - # Append tests
50   - self.append(self.test, "LAT dummy test")
  59 + # Return event list container
  60 + return list
  61 +
  62 + # Test GLATEventList class access operators
  63 + def _test_eventlist_access(self):
  64 + """
  65 + Test GLATEventList class observation access
  66 + """
  67 + # Setup event list container
  68 + list = self._setup_eventlist()
  69 +
  70 + # Perform event list access tests
  71 + test_support._energy_container_access_index(self, list)
  72 +
  73 + # Return
  74 + return
  75 +
  76 + # Test GLATEventList class slicing
  77 + def _test_eventlist_slicing(self):
  78 + """
  79 + Test GLATEventList class slicing
  80 + """
  81 + # Setup event list container
  82 + list = self._setup_eventlist()
  83 +
  84 + # Perform slicing tests
  85 + test_support._energy_container_slicing(self, list)
51 86  
52 87 # Return
53 88 return
54 89  
55   - # Test function
56   - def test(self):
  90 + # Set test functions
  91 + def set(self):
57 92 """
58   - Test function.
  93 + Set all test functions.
59 94 """
  95 + # Set test name
  96 + self.name('LAT')
  97 +
  98 + # Append tests
  99 + self.append(self._test_eventlist_access, 'Test GLATEventList event access')
  100 + self.append(self._test_eventlist_slicing, 'Test GLATEventList slicing')
  101 +
60 102 # Return
61 103 return
... ...
pyext/GFits.i
1 1 /***************************************************************************
2 2 * GFits.i - FITS file class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2008-2016 by Juergen Knoedlseder *
  4 + * copyright (C) 2008-2017 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -100,9 +100,14 @@ public:
100 100 ***************************************************************************/
101 101 %extend GFits {
102 102 GFitsHDU* __getitem__(const int& extno) {
  103 + // Counting from start, e.g. [2]
103 104 if (extno >= 0 && extno < self->size()) {
104 105 return (*self)[extno];
105 106 }
  107 + // Counting from end, e.g. [-1]
  108 + else if (extno < 0 && self->size()+extno >= 0) {
  109 + return (*self)[self->size()+extno];
  110 + }
106 111 else {
107 112 throw GException::out_of_range("__getitem__(int)",
108 113 "Extension number",
... ... @@ -112,10 +117,43 @@ public:
112 117 GFitsHDU* __getitem__(const std::string& extname) {
113 118 return (*self)[extname];
114 119 }
  120 + GFits* __getitem__(PyObject *param) {
  121 + if (PySlice_Check(param)) {
  122 + Py_ssize_t start = 0;
  123 + Py_ssize_t stop = 0;
  124 + Py_ssize_t step = 0;
  125 + Py_ssize_t len = self->size();
  126 + if (PySlice_GetIndices((PySliceObject*)param, len, &start, &stop, &step) == 0) {
  127 + GFits* fits = new GFits;
  128 + if (step > 0) {
  129 + for (int i = (int)start; i < (int)stop; i += (int)step) {
  130 + fits->append(*(*self)[i]);
  131 + }
  132 + }
  133 + else {
  134 + for (int i = (int)start; i > (int)stop; i += (int)step) {
  135 + fits->append(*(*self)[i]);
  136 + }
  137 + }
  138 + return fits;
  139 + }
  140 + else {
  141 + throw GException::invalid_argument("__getitem__(PyObject)",
  142 + "Invalid slice indices");
  143 + }
  144 + }
  145 + else {
  146 + throw GException::invalid_argument("__getitem__(PyObject)","");
  147 + }
  148 + }
115 149 void __setitem__(const int& extno, const GFitsHDU& hdu) {
  150 + // Counting from start, e.g. [2]
116 151 if (extno >= 0 && extno < self->size()) {
117 152 self->set(extno, hdu);
118   - return;
  153 + }
  154 + // Counting from end, e.g. [-1]
  155 + else if (extno < 0 && self->size()+extno >= 0) {
  156 + self->set(self->size()+extno, hdu);
119 157 }
120 158 else {
121 159 throw GException::out_of_range("__setitem__(int)",
... ...
pyext/GFitsHeader.i
1 1 /***************************************************************************
2   - * GFitsHeader.i - FITS header cards container class *
  2 + * GFitsHeader.i - FITS header cards container class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2008-2015 by Juergen Knoedlseder *
  4 + * copyright (C) 2008-2017 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -29,15 +29,13 @@
29 29 #include "GTools.hpp"
30 30 %}
31 31  
32   -//%include stl.i
33   -
34 32  
35 33 /***********************************************************************//**
36 34 * @class GFitsHeader
37 35 *
38 36 * @brief Interface for FITS header class
39 37 ***************************************************************************/
40   -class GFitsHeader : public GBase {
  38 +class GFitsHeader : public GContainer {
41 39 public:
42 40 // Constructors and destructors
43 41 GFitsHeader(void);
... ... @@ -77,9 +75,14 @@ public:
77 75 ***************************************************************************/
78 76 %extend GFitsHeader {
79 77 GFitsHeaderCard& __getitem__(const int& cardno) {
  78 + // Counting from start, e.g. [2]
80 79 if (cardno >= 0 && cardno < self->size()) {
81 80 return (*self)[cardno];
82 81 }
  82 + // Counting from end, e.g. [-1]
  83 + else if (cardno < 0 && self->size()+cardno >= 0) {
  84 + return (*self)[self->size()+cardno];
  85 + }
83 86 else {
84 87 throw GException::out_of_range("__getitem__(int)",
85 88 "Header card number",
... ... @@ -89,10 +92,43 @@ public:
89 92 GFitsHeaderCard& __getitem__(const std::string& keyname) {
90 93 return (*self)[keyname];
91 94 }
  95 + GFitsHeader* __getitem__(PyObject *param) {
  96 + if (PySlice_Check(param)) {
  97 + Py_ssize_t start = 0;
  98 + Py_ssize_t stop = 0;
  99 + Py_ssize_t step = 0;
  100 + Py_ssize_t len = self->size();
  101 + if (PySlice_GetIndices((PySliceObject*)param, len, &start, &stop, &step) == 0) {
  102 + GFitsHeader* header = new GFitsHeader;
  103 + if (step > 0) {
  104 + for (int i = (int)start; i < (int)stop; i += (int)step) {
  105 + header->append((*self)[i]);
  106 + }
  107 + }
  108 + else {
  109 + for (int i = (int)start; i > (int)stop; i += (int)step) {
  110 + header->append((*self)[i]);
  111 + }
  112 + }
  113 + return header;
  114 + }
  115 + else {
  116 + throw GException::invalid_argument("__getitem__(PyObject)",
  117 + "Invalid slice indices");
  118 + }
  119 + }
  120 + else {
  121 + throw GException::invalid_argument("__getitem__(PyObject)","");
  122 + }
  123 + }
92 124 void __setitem__(const int& cardno, const GFitsHeaderCard& card) {
  125 + // Counting from start, e.g. [2]
93 126 if (cardno >= 0 && cardno < self->size()) {
94 127 (*self)[cardno] = card;
95   - return;
  128 + }
  129 + // Counting from end, e.g. [-1]
  130 + else if (cardno < 0 && self->size()+cardno >= 0) {
  131 + (*self)[self->size()+cardno] = card;
96 132 }
97 133 else {
98 134 throw GException::out_of_range("__setitem__(int)",
... ...
pyext/GNodeArray.i
... ... @@ -86,17 +86,55 @@ public:
86 86 ***************************************************************************/
87 87 %extend GNodeArray {
88 88 double __getitem__(const int& index) {
  89 + // Counting from start, e.g. [2]
89 90 if (index >= 0 && index < self->size()) {
90 91 return (*self)[index];
91 92 }
  93 + // Counting from end, e.g. [-1]
  94 + else if (index < 0 && self->size()+index >= 0) {
  95 + return (*self)[self->size()+index];
  96 + }
92 97 else {
93 98 throw GException::out_of_range("__getitem__(int)", index, self->size());
94 99 }
95 100 }
  101 + GNodeArray* __getitem__(PyObject *param) {
  102 + if (PySlice_Check(param)) {
  103 + Py_ssize_t start = 0;
  104 + Py_ssize_t stop = 0;
  105 + Py_ssize_t step = 0;
  106 + Py_ssize_t len = self->size();
  107 + if (PySlice_GetIndices((PySliceObject*)param, len, &start, &stop, &step) == 0) {
  108 + GNodeArray* nodes = new GNodeArray;
  109 + if (step > 0) {
  110 + for (int i = (int)start; i < (int)stop; i += (int)step) {
  111 + nodes->append((*self)[i]);
  112 + }
  113 + }
  114 + else {
  115 + for (int i = (int)start; i > (int)stop; i += (int)step) {
  116 + nodes->append((*self)[i]);
  117 + }
  118 + }
  119 + return nodes;
  120 + }
  121 + else {
  122 + throw GException::invalid_argument("__getitem__(PyObject)",
  123 + "Invalid slice indices");
  124 + }
  125 + }
  126 + else {
  127 + throw GException::invalid_argument("__getitem__(PyObject)","");
  128 + }
  129 + }
96 130 void __setitem__(const int& index, const double& val) {
97   - if (index>=0 && index < self->size()) {
  131 + // Counting from start, e.g. [2]
  132 + if (index >= 0 && index < self->size()) {
98 133 (*self)[index] = val;
99   - return;
  134 + }
  135 + // Counting from end, e.g. [-1]
  136 + else if (index < 0 && self->size()+index >= 0) {
  137 + (*self)[self->size()+index] = val;
100 138 }
101 139 else {
102 140 throw GException::out_of_range("__setitem__(int)", index, self->size());
... ...
pyext/GOptimizerPars.i
1 1 /***************************************************************************
2 2 * GOptimizerPars.i - Optimizer parameter container class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2009-2015 by Juergen Knoedlseder *
  4 + * copyright (C) 2009-2017 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -52,6 +52,7 @@ public:
52 52 int nfree(void) const;
53 53 GOptimizerPar* set(const int& index, const GOptimizerPar& par);
54 54 GOptimizerPar* set(const std::string& name, const GOptimizerPar& par);
  55 + GOptimizerPar* append(const GOptimizerPar& par);
55 56 void attach(GOptimizerPar *par);
56 57 void attach(const int& index, GOptimizerPar* par);
57 58 void attach(const std::string& name, GOptimizerPar* par);
... ... @@ -70,9 +71,14 @@ public:
70 71 ***************************************************************************/
71 72 %extend GOptimizerPars {
72 73 GOptimizerPar* __getitem__(const int& index) {
  74 + // Counting from start, e.g. [2]
73 75 if (index >= 0 && index < self->size()) {
74 76 return (*self)[index];
75 77 }
  78 + // Counting from end, e.g. [-1]
  79 + else if (index < 0 && self->size()+index >= 0) {
  80 + return (*self)[self->size()+index];
  81 + }
76 82 else {
77 83 throw GException::out_of_range("__getitem__(int)", "Parameter index",
78 84 index, self->size());
... ... @@ -81,10 +87,43 @@ public:
81 87 GOptimizerPar* __getitem__(const std::string& name) {
82 88 return (*self)[name];
83 89 }
  90 + GOptimizerPars* __getitem__(PyObject *param) {
  91 + if (PySlice_Check(param)) {
  92 + Py_ssize_t start = 0;
  93 + Py_ssize_t stop = 0;
  94 + Py_ssize_t step = 0;
  95 + Py_ssize_t len = self->size();
  96 + if (PySlice_GetIndices((PySliceObject*)param, len, &start, &stop, &step) == 0) {
  97 + GOptimizerPars* pars = new GOptimizerPars;
  98 + if (step > 0) {
  99 + for (int i = (int)start; i < (int)stop; i += (int)step) {
  100 + pars->attach((*self)[i]);
  101 + }
  102 + }
  103 + else {
  104 + for (int i = (int)start; i > (int)stop; i += (int)step) {
  105 + pars->attach((*self)[i]);
  106 + }
  107 + }
  108 + return pars;
  109 + }
  110 + else {
  111 + throw GException::invalid_argument("__getitem__(PyObject)",
  112 + "Invalid slice indices");
  113 + }
  114 + }
  115 + else {
  116 + throw GException::invalid_argument("__getitem__(PyObject)","");
  117 + }
  118 + }
84 119 void __setitem__(const int& index, GOptimizerPar* par) {
  120 + // Counting from start, e.g. [2]
85 121 if (index >= 0 && index < self->size()) {
86 122 self->attach(index, par);
87   - return;
  123 + }
  124 + // Counting from end, e.g. [-1]
  125 + else if (index < 0 && self->size()+index >= 0) {
  126 + self->attach(self->size()+index, par);
88 127 }
89 128 else {
90 129 throw GException::out_of_range("__setitem__(int)", "Parameter index",
... ...
pyext/GSkyRegion.i
1 1 /***************************************************************************
2 2 * GSkyRegion.i - Sky region class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2013-2015 by Michael Mayer *
  4 + * copyright (C) 2013-2017 by Michael Mayer *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -55,6 +55,9 @@ public:
55 55 const std::string& type(void) const;
56 56 const std::string& name(void) const;
57 57 const double& solidangle(void) const;
  58 + void type(const std::string& type);
  59 + void name(const std::string& name);
  60 + void solidangle(const double& solidangle);
58 61 };
59 62  
60 63  
... ...
pyext/GSkyRegions.i
1 1 /***************************************************************************
2 2 * GSkyRegions.i - Sky region container class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2013-2016 by Pierrick Martin *
  4 + * copyright (C) 2013-2017 by Pierrick Martin *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -67,17 +67,55 @@ public:
67 67 ***************************************************************************/
68 68 %extend GSkyRegions {
69 69 GSkyRegion* __getitem__(const int& index) {
  70 + // Counting from start, e.g. [2]
70 71 if (index >= 0 && index < self->size()) {
71 72 return (*self)[index];
72 73 }
  74 + // Counting from end, e.g. [-1]
  75 + else if (index < 0 && self->size()+index >= 0) {
  76 + return (*self)[self->size()+index];
  77 + }
73 78 else {
74 79 throw GException::out_of_range("__getitem__(int)", index, self->size());
75 80 }
76 81 }
  82 + GSkyRegions* __getitem__(PyObject *param) {
  83 + if (PySlice_Check(param)) {
  84 + Py_ssize_t start = 0;
  85 + Py_ssize_t stop = 0;
  86 + Py_ssize_t step = 0;
  87 + Py_ssize_t len = self->size();
  88 + if (PySlice_GetIndices((PySliceObject*)param, len, &start, &stop, &step) == 0) {
  89 + GSkyRegions* regions = new GSkyRegions;
  90 + if (step > 0) {
  91 + for (int i = (int)start; i < (int)stop; i += (int)step) {
  92 + regions->append(*(*self)[i]);
  93 + }
  94 + }
  95 + else {
  96 + for (int i = (int)start; i > (int)stop; i += (int)step) {
  97 + regions->append(*(*self)[i]);
  98 + }
  99 + }
  100 + return regions;
  101 + }
  102 + else {
  103 + throw GException::invalid_argument("__getitem__(PyObject)",
  104 + "Invalid slice indices");
  105 + }
  106 + }
  107 + else {
  108 + throw GException::invalid_argument("__getitem__(PyObject)","");
  109 + }
  110 + }
77 111 void __setitem__(const int& index, const GSkyRegion& val) {
78   - if (index>=0 && index < self->size()) {
  112 + // Counting from start, e.g. [2]
  113 + if (index >= 0 && index < self->size()) {
79 114 self->set(index, val);
80   - return;
  115 + }
  116 + // Counting from end, e.g. [-1]
  117 + else if (index < 0 && self->size()+index >= 0) {
  118 + self->set(self->size()+index, val);
81 119 }
82 120 else {
83 121 throw GException::out_of_range("__setitem__(int)", index, self->size());
... ...
pyext/GTestSuites.i
1 1 /***************************************************************************
2 2 * GTestSuites.i - Test suite container class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2012-2016 Jean-Baptiste Cayrou *
  4 + * copyright (C) 2012-2017 Jean-Baptiste Cayrou *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -73,17 +73,55 @@ public:
73 73 ***************************************************************************/
74 74 %extend GTestSuites {
75 75 GTestSuite* __getitem__(const int& index) {
  76 + // Counting from start, e.g. [2]
76 77 if (index >= 0 && index < self->size()) {
77 78 return (*self)[index];
78 79 }
  80 + // Counting from end, e.g. [-1]
  81 + else if (index < 0 && self->size()+index >= 0) {
  82 + return (*self)[self->size()+index];
  83 + }
79 84 else {
80 85 throw GException::out_of_range("__getitem__(int)", index, self->size());
81 86 }
82 87 }
  88 + GTestSuites* __getitem__(PyObject *param) {
  89 + if (PySlice_Check(param)) {
  90 + Py_ssize_t start = 0;
  91 + Py_ssize_t stop = 0;
  92 + Py_ssize_t step = 0;
  93 + Py_ssize_t len = self->size();
  94 + if (PySlice_GetIndices((PySliceObject*)param, len, &start, &stop, &step) == 0) {
  95 + GTestSuites* tests = new GTestSuites(self->name());
  96 + if (step > 0) {
  97 + for (int i = (int)start; i < (int)stop; i += (int)step) {
  98 + tests->append(*(*self)[i]);
  99 + }
  100 + }
  101 + else {
  102 + for (int i = (int)start; i > (int)stop; i += (int)step) {
  103 + tests->append(*(*self)[i]);
  104 + }
  105 + }
  106 + return tests;
  107 + }
  108 + else {
  109 + throw GException::invalid_argument("__getitem__(PyObject)",
  110 + "Invalid slice indices");
  111 + }
  112 + }
  113 + else {
  114 + throw GException::invalid_argument("__getitem__(PyObject)","");
  115 + }
  116 + }
83 117 void __setitem__(const int& index, const GTestSuite& suite) {
  118 + // Counting from start, e.g. [2]
84 119 if (index >= 0 && index < self->size()) {
85 120 self->set(index, suite);
86   - return;
  121 + }
  122 + // Counting from end, e.g. [-1]
  123 + else if (index < 0 && self->size()+index >= 0) {
  124 + self->set(self->size()+index, suite);
87 125 }
88 126 else {
89 127 throw GException::out_of_range("__setitem__(int)", index, self->size());
... ...
pyext/GXml.i
1 1 /***************************************************************************
2 2 * GXml.i - XML class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2010-2016 by Juergen Knoedlseder *
  4 + * copyright (C) 2010-2017 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -74,27 +74,60 @@ public:
74 74 ***************************************************************************/
75 75 %extend GXml {
76 76 GXmlNode* __getitem__(const int& index) {
  77 + // Counting from start, e.g. [2]
77 78 if (index >= 0 && index < self->size()) {
78 79 return (*self)[index];
79 80 }
  81 + // Counting from end, e.g. [-1]
  82 + else if (index < 0 && self->size()+index >= 0) {
  83 + return (*self)[self->size()+index];
  84 + }
80 85 else {
81   - throw GException::out_of_range("__getitem__(int)", index,
82   - 0, self->size()-1);
  86 + throw GException::out_of_range("__getitem__(int)", index, self->size());
  87 + }
  88 + }
  89 + GXml* __getitem__(PyObject *param) {
  90 + if (PySlice_Check(param)) {
  91 + Py_ssize_t start = 0;
  92 + Py_ssize_t stop = 0;
  93 + Py_ssize_t step = 0;
  94 + Py_ssize_t len = self->size();
  95 + if (PySlice_GetIndices((PySliceObject*)param, len, &start, &stop, &step) == 0) {
  96 + GXml* xml = new GXml;
  97 + if (step > 0) {
  98 + for (int i = (int)start; i < (int)stop; i += (int)step) {
  99 + xml->append(*(*self)[i]);
  100 + }
  101 + }
  102 + else {
  103 + for (int i = (int)start; i > (int)stop; i += (int)step) {
  104 + xml->append(*(*self)[i]);
  105 + }
  106 + }
  107 + return xml;
  108 + }
  109 + else {
  110 + throw GException::invalid_argument("__getitem__(PyObject)",
  111 + "Invalid slice indices");
  112 + }
  113 + }
  114 + else {
  115 + throw GException::invalid_argument("__getitem__(PyObject)","");
83 116 }
84 117 }
85 118 void __setitem__(const int& index, const GXmlNode& node) {
  119 + // Counting from start, e.g. [2]
86 120 if (index >= 0 && index < self->size()) {
87 121 self->set(index, node);
88   - return;
  122 + }
  123 + // Counting from end, e.g. [-1]
  124 + else if (index < 0 && self->size()+index >= 0) {
  125 + self->set(self->size()+index, node);
89 126 }
90 127 else {
91   - throw GException::out_of_range("__setitem__(int)", index,
92   - 0, self->size()-1);
  128 + throw GException::out_of_range("__setitem__(int)", index, self->size());
93 129 }
94 130 }
95   - int __len__() {
96   - return (self->size());
97   - }
98 131 GXml copy() {
99 132 return (*self);
100 133 }
... ...
pyext/GXmlElement.i
1 1 /***************************************************************************
2 2 * GXmlElement.i - XML element node class definition *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2010-2016 by Juergen Knoedlseder *
  4 + * copyright (C) 2010-2017 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -61,6 +61,61 @@ public:
61 61 * @brief GXmlElement class extension
62 62 ***************************************************************************/
63 63 %extend GXmlElement {
  64 + GXmlNode* __getitem__(const int& index) {
  65 + // Counting from start, e.g. [2]
  66 + if (index >= 0 && index < self->size()) {
  67 + return (*self)[index];
  68 + }
  69 + // Counting from end, e.g. [-1]
  70 + else if (index < 0 && self->size()+index >= 0) {
  71 + return (*self)[self->size()+index];
  72 + }
  73 + else {
  74 + throw GException::out_of_range("__getitem__(int)", index, self->size());
  75 + }
  76 + }
  77 + void __setitem__(const int& index, const GXmlNode& node) {
  78 + // Counting from start, e.g. [2]
  79 + if (index >= 0 && index < self->size()) {
  80 + self->set(index, node);
  81 + }
  82 + // Counting from end, e.g. [-1]
  83 + else if (index < 0 && self->size()+index >= 0) {
  84 + self->set(self->size()+index, node);
  85 + }
  86 + else {
  87 + throw GException::out_of_range("__setitem__(int)", index, self->size());
  88 + }
  89 + }
  90 + GXmlElement* __getitem__(PyObject *param) {
  91 + if (PySlice_Check(param)) {
  92 + Py_ssize_t start = 0;
  93 + Py_ssize_t stop = 0;
  94 + Py_ssize_t step = 0;
  95 + Py_ssize_t len = self->size();
  96 + if (PySlice_GetIndices((PySliceObject*)param, len, &start, &stop, &step) == 0) {
  97 + GXmlElement* element = new GXmlElement;
  98 + if (step > 0) {
  99 + for (int i = (int)start; i < (int)stop; i += (int)step) {
  100 + element->append(*(*self)[i]);
  101 + }
  102 + }
  103 + else {
  104 + for (int i = (int)start; i > (int)stop; i += (int)step) {
  105 + element->append(*(*self)[i]);
  106 + }
  107 + }
  108 + return element;
  109 + }
  110 + else {
  111 + throw GException::invalid_argument("__getitem__(PyObject)",
  112 + "Invalid slice indices");
  113 + }
  114 + }
  115 + else {
  116 + throw GException::invalid_argument("__getitem__(PyObject)","");
  117 + }
  118 + }
64 119 GXmlElement copy() {
65 120 return (*self);
66 121 }
... ...
pyext/GXmlNode.i
1 1 /***************************************************************************
2 2 * GXmlNode.i - Abstract XML node base class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2010-2016 by Juergen Knoedlseder *
  4 + * copyright (C) 2010-2017 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -36,7 +36,7 @@
36 36 *
37 37 * @brief Abstract XML node base class
38 38 ***************************************************************************/
39   -class GXmlNode : public GBase {
  39 +class GXmlNode : public GContainer {
40 40 public:
41 41 // Constructors and destructors
42 42 GXmlNode(void);
... ... @@ -89,25 +89,29 @@ public:
89 89 return gammalib::tochar(self->print(NORMAL, 0));
90 90 }
91 91 GXmlNode* __getitem__(const int& index) {
  92 + // Counting from start, e.g. [2]
92 93 if (index >= 0 && index < self->size()) {
93 94 return (*self)[index];
94 95 }
  96 + // Counting from end, e.g. [-1]
  97 + else if (index < 0 && self->size()+index >= 0) {
  98 + return (*self)[self->size()+index];
  99 + }
95 100 else {
96   - throw GException::out_of_range("__getitem__(int)", index,
97   - 0, self->size()-1);
  101 + throw GException::out_of_range("__getitem__(int)", index, self->size());
98 102 }
99 103 }
100 104 void __setitem__(const int& index, const GXmlNode& node) {
  105 + // Counting from start, e.g. [2]
101 106 if (index >= 0 && index < self->size()) {
102 107 self->set(index, node);
103   - return;
  108 + }
  109 + // Counting from end, e.g. [-1]
  110 + else if (index < 0 && self->size()+index >= 0) {
  111 + self->set(self->size()+index, node);
104 112 }
105 113 else {
106   - throw GException::out_of_range("__setitem__(int)", index,
107   - 0, self->size()-1);
  114 + throw GException::out_of_range("__setitem__(int)", index, self->size());
108 115 }
109 116 }
110   - int __len__() {
111   - return (self->size());
112   - }
113 117 };
... ...
src/opt/GOptimizerPar.cpp
1 1 /***************************************************************************
2 2 * GOptimizerPar.cpp - Optimizer parameter class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2013-2015 by Juergen Knoedlseder *
  4 + * copyright (C) 2013-2017 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -700,8 +700,8 @@ std::string GOptimizerPar::print(const GChatter&amp; chatter) const
700 700 void GOptimizerPar::init_members(void)
701 701 {
702 702 // Initialise members
703   - m_name = "";
704   - m_unit = "";
  703 + m_name.clear();
  704 + m_unit.clear();
705 705 m_factor_value = 0.0;
706 706 m_factor_error = 0.0;
707 707 m_factor_gradient = 0.0;
... ...
src/opt/GOptimizerPars.cpp
1 1 /***************************************************************************
2 2 * GOptimizerPars.cpp - Optimizer parameter container class *
3 3 * ----------------------------------------------------------------------- *
4   - * copyright (C) 2009-2013 by Juergen Knoedlseder *
  4 + * copyright (C) 2009-2017 by Juergen Knoedlseder *
5 5 * ----------------------------------------------------------------------- *
6 6 * *
7 7 * This program is free software: you can redistribute it and/or modify *
... ... @@ -392,6 +392,30 @@ GOptimizerPar* GOptimizerPars::set(const std::string&amp; name, const GOptimizerPar&amp;
392 392  
393 393  
394 394 /***********************************************************************//**
  395 + * @brief Append parameter to container
  396 + *
  397 + * @param[in] par Parameter reference.
  398 + * @return Pointer to appended parameter.
  399 + *
  400 + * Appends a parameter to the container. The method stores a copy of the
  401 + * parameter in the container, hence the client may delete the parameter
  402 + * after the method is called.
  403 + ***************************************************************************/
  404 +GOptimizerPar* GOptimizerPars::append(const GOptimizerPar& par)
  405 +{
  406 + // Clone parameter
  407 + GOptimizerPar* ptr = par.clone();
  408 +
  409 + // Inserts deep copy of parameter
  410 + m_alloc.push_back(true);
  411 + m_pars.push_back(ptr);
  412 +
  413 + // Return parameter pointer
  414 + return ptr;
  415 +}
  416 +
  417 +
  418 +/***********************************************************************//**
395 419 * @brief Attach parameter to container
396 420 *
397 421 * @param[in] par Parameter pointer.
... ... @@ -680,6 +704,7 @@ std::string GOptimizerPars::print(const GChatter&amp; chatter) const
680 704  
681 705 // Append parameters
682 706 for (int i = 0; i < size(); ++i) {
  707 +std::cout << i << " " << m_pars[i] << std::endl;
683 708 result.append("\n"+m_pars[i]->print(chatter));
684 709 }
685 710  
... ...
test/test_GFits.py
... ... @@ -27,11 +27,12 @@ import gammalib
27 27 # =================================== #
28 28 class Test(gammalib.GPythonTestSuite):
29 29 """
30   - Test class for GammaLib FITS module.
  30 + Test class for GammaLib FITS module
31 31 """
  32 + # Constructor
32 33 def __init__(self):
33 34 """
34   - Constructor.
  35 + Constructor
35 36 """
36 37 # Call base class constructor
37 38 gammalib.GPythonTestSuite.__init__(self)
... ... @@ -39,25 +40,236 @@ class Test(gammalib.GPythonTestSuite):
39 40 # Return
40 41 return
41 42  
42   - def set(self):
  43 + # Setup GFits container
  44 + def _setup_fits(self):
  45 + """
  46 + Setup GFits container
  47 +
  48 + Returns
  49 + -------
  50 + fits : `~gammalib.GFits`
  51 + GFits container
43 52 """
44   - Set all test functions.
  53 + # Setup GFits container
  54 + fits = gammalib.GFits()
  55 + image = gammalib.GFitsImageDouble()
  56 + for i in range(10):
  57 + image.extname('%s' % i)
  58 + fits.append(image)
  59 +
  60 + # Return GFits container
  61 + return fits
  62 +
  63 + # Setup GFitsHeader container
  64 + def _setup_header(self):
45 65 """
46   - # Set test name
47   - self.name("fits")
  66 + Setup GFitsHeader container
48 67  
49   - # Append tests
50   - self.append(self.test_fits, "Test GFits class")
51   - self.append(self.test_fits_image, "Test GFitsImage class")
52   - self.append(self.test_fits_table, "Test GFitsTable class")
53   - self.append(self.test_fits_table_columns, "Test GFitsTableCol classes")
  68 + Returns
  69 + -------
  70 + header : `~gammalib.GFitsHeader`
  71 + GFitsHeader container
  72 + """
  73 + # Setup GFitsHeader container
  74 + header = gammalib.GFitsHeader()
  75 + card = gammalib.GFitsHeaderCard()
  76 + for i in range(10):
  77 + card.keyname('%s' % i)
  78 + header.append(card)
  79 +
  80 + # Return GFitsHeader container
  81 + return header
  82 +
  83 + # Test GFits class access operators
  84 + def _test_fits_access(self):
  85 + """
  86 + Test GFits class parameter access
  87 + """
  88 + # Setup GFits container and element
  89 + fits = self._setup_fits()
  90 + image = gammalib.GFitsImageDouble()
  91 +
  92 + # Loop over all elements using the container iterator and count the
  93 + # number of iterations
  94 + niter = 0
  95 + for hdu in fits:
  96 + self.test_value(hdu.extname(), '%s' % niter)
  97 + niter += 1
  98 +
  99 + # Check that looping was successful
  100 + self.test_value(fits.size(), 10, 'Check container size')
  101 + self.test_value(niter, 10, 'Check container iterator')
  102 +
  103 + # Test access from start
  104 + self.test_value(fits[3].extname(), '3')
  105 +
  106 + # Check access from end
  107 + self.test_value(fits[-2].extname(), '8')
  108 +
  109 + # Check parameter setting by index from start
  110 + image.extname('98')
  111 + fits[3] = image
  112 + self.test_value(fits[3].extname(), '98')
  113 +
  114 + # Check parameter setting by index from end
  115 + image.extname('99')
  116 + fits[-2] = image
  117 + self.test_value(fits[-2].extname(), '99')
  118 +
  119 + # Return
  120 + return
  121 +
  122 + # Test GFits class slicing
  123 + def _test_fits_slicing(self):
  124 + """
  125 + Test GFits class slicing
  126 + """
  127 + # Setup XML container
  128 + fits = self._setup_fits()
  129 +
  130 + # Test fits[start:end]
  131 + self.test_value(len(fits[3:5]), 2)
  132 + self.test_value(fits[3:5][0].extname(), '3')
  133 + self.test_value(fits[3:5][1].extname(), '4')
  134 +
  135 + # Test fits[start:]
  136 + self.test_value(len(fits[7:]), 3)
  137 + self.test_value(fits[7:][0].extname(), '7')
  138 + self.test_value(fits[7:][1].extname(), '8')
  139 + self.test_value(fits[7:][2].extname(), '9')
  140 +
  141 + # Test fits[:end]
  142 + self.test_value(len(fits[:2]), 2)
  143 + self.test_value(fits[:2][0].extname(), '0')
  144 + self.test_value(fits[:2][1].extname(), '1')
  145 +
  146 + # Test fits[:]
  147 + self.test_value(len(fits[:]), 10)
  148 + for i in range(10):
  149 + self.test_value(fits[:][i].extname(), '%s' % i)
  150 +
  151 + # Test fits[start:end:step]
  152 + self.test_value(len(fits[3:7:2]), 2)
  153 + self.test_value(fits[3:7:2][0].extname(), '3')
  154 + self.test_value(fits[3:7:2][1].extname(), '5')
  155 +
  156 + # Test fits[start:end:step]
  157 + self.test_value(len(fits[6:3:-2]), 2)
  158 + self.test_value(fits[6:3:-2][0].extname(), '6')
  159 + self.test_value(fits[6:3:-2][1].extname(), '4')
  160 +
  161 + # Test fits[-start:]
  162 + self.test_value(len(fits[-2:]), 2)
  163 + self.test_value(fits[-2:][0].extname(), '8')
  164 + self.test_value(fits[-2:][1].extname(), '9')
  165 +
  166 + # Test fits[:-end]
  167 + self.test_value(len(fits[:-7]), 3)
  168 + self.test_value(fits[:-7][0].extname(), '0')
  169 + self.test_value(fits[:-7][1].extname(), '1')
  170 + self.test_value(fits[:-7][2].extname(), '2')
  171 +
  172 + # Return
  173 + return
  174 +
  175 + # Test GFitsHeader class access operators
  176 + def _test_header_access(self):
  177 + """
  178 + Test GFitsHeader class parameter access
  179 + """
  180 + # Setup FITS header
  181 + header = self._setup_header()
  182 +
  183 + # Loop over all elements using the container iterator and count the
  184 + # number of iterations
  185 + niter = 0
  186 + for card in header:
  187 + self.test_value(card.keyname(), '%s' % niter)
  188 + niter += 1
  189 +
  190 + # Check that looping was successful
  191 + self.test_value(header.size(), 10, 'Check container size')
  192 + self.test_value(niter, 10, 'Check container iterator')
  193 +
  194 + # Test access from start
  195 + self.test_value(header[3].keyname(), '3')
  196 +
  197 + # Check access from end
  198 + self.test_value(header[-2].keyname(), '8')
  199 +
  200 + # Setup header card
  201 + card = gammalib.GFitsHeaderCard()
  202 +
  203 + # Check parameter setting by index from start
  204 + card.keyname('98')
  205 + header[3] = card
  206 + self.test_value(header[3].keyname(), '98')
  207 +
  208 + # Check parameter setting by index from end
  209 + card.keyname('99')
  210 + header[-2] = card
  211 + self.test_value(header[-2].keyname(), '99')
54 212  
55 213 # Return
56 214 return
57 215  
58   - def test_fits(self):
  216 + # Test GFitsHeader class slicing
  217 + def _test_header_slicing(self):
  218 + """
  219 + Test GFitsHeader class slicing
59 220 """
60   - Test GFile class interface.
  221 + # Setup FITS header
  222 + header = self._setup_header()
  223 +
  224 + # Test header[start:end]
  225 + self.test_value(len(header[3:5]), 2)
  226 + self.test_value(header[3:5][0].keyname(), '3')
  227 + self.test_value(header[3:5][1].keyname(), '4')
  228 +
  229 + # Test header[start:]
  230 + self.test_value(len(header[7:]), 3)
  231 + self.test_value(header[7:][0].keyname(), '7')
  232 + self.test_value(header[7:][1].keyname(), '8')
  233 + self.test_value(header[7:][2].keyname(), '9')
  234 +
  235 + # Test header[:end]
  236 + self.test_value(len(header[:2]), 2)
  237 + self.test_value(header[:2][0].keyname(), '0')
  238 + self.test_value(header[:2][1].keyname(), '1')
  239 +
  240 + # Test header[:]
  241 + self.test_value(len(header[:]), 10)
  242 + for i in range(10):
  243 + self.test_value(header[:][i].keyname(), '%s' % i)
  244 +
  245 + # Test header[start:end:step]
  246 + self.test_value(len(header[3:7:2]), 2)
  247 + self.test_value(header[3:7:2][0].keyname(), '3')
  248 + self.test_value(header[3:7:2][1].keyname(), '5')
  249 +
  250 + # Test header[start:end:step]
  251 + self.test_value(len(header[6:3:-2]), 2)
  252 + self.test_value(header[6:3:-2][0].keyname(), '6')
  253 + self.test_value(header[6:3:-2][1].keyname(), '4')
  254 +
  255 + # Test header[-start:]
  256 + self.test_value(len(header[-2:]), 2)
  257 + self.test_value(header[-2:][0].keyname(), '8')
  258 + self.test_value(header[-2:][1].keyname(), '9')
  259 +
  260 + # Test header[:-end]
  261 + self.test_value(len(header[:-7]), 3)
  262 + self.test_value(header[:-7][0].keyname(), '0')
  263 + self.test_value(header[:-7][1].keyname(), '1')
  264 + self.test_value(header[:-7][2].keyname(), '2')
  265 +
  266 + # Return
  267 + return
  268 +
  269 + # Test GFile class interface
  270 + def _test_fits(self):
  271 + """
  272 + Test GFile class interface
61 273 """
62 274 # Get test data directory
63 275 datadir = os.environ['TEST_DATA'] + '/'
... ... @@ -66,33 +278,33 @@ class Test(gammalib.GPythonTestSuite):
66 278 file = gammalib.GFilename(datadir+'file.fits')
67 279  
68 280 # Test loading of FITS file
69   - self.test_try("Test GFits file load constructor")
  281 + self.test_try('Test GFits file load constructor')
70 282 try:
71 283 fits = gammalib.GFits(file)
72 284 self.test_try_success()
73 285 except:
74   - self.test_try_failure("Unable to load FITS file.")
  286 + self.test_try_failure('Unable to load FITS file.')
75 287  
76 288 # Test creation of FITS file
77   - self.test_try("Test GFits file creation constructor")
  289 + self.test_try('Test GFits file creation constructor')
78 290 try:
79   - fits = gammalib.GFits("test_file.fits", True)
  291 + fits = gammalib.GFits('test_file.fits', True)
80 292 self.test_try_success()
81 293 except:
82   - self.test_try_failure("Unable to create FITS file.")
  294 + self.test_try_failure('Unable to create FITS file.')
83 295  
84 296 # Open FITS file
85 297 fits = gammalib.GFits(file)
86   - self.test_value(fits["EVENTS"].nrows(), 1231, "Check number of rows")
  298 + self.test_value(fits['EVENTS'].nrows(), 1231, 'Check number of rows')
87 299  
88 300 # Open FITS file with event selection
89   - fits = gammalib.GFits(file+"[EVENTS][ENERGY>1.0]")
90   - self.test_value(fits["EVENTS"].nrows(), 152, "Check number of rows")
  301 + fits = gammalib.GFits(file+'[EVENTS][ENERGY>1.0]')
  302 + self.test_value(fits['EVENTS'].nrows(), 152, 'Check number of rows')
91 303  
92 304 # Open FITS file with non-existing extension name
93   - self.test_try("Test non-existing extension name")
  305 + self.test_try('Test non-existing extension name')
94 306 try:
95   - fits = gammalib.GFits(file+"[DUMMY][ENERGY>1.0]")
  307 + fits = gammalib.GFits(file+'[DUMMY][ENERGY>1.0]')
96 308 self.test_try_failure()
97 309 except:
98 310 self.test_try_success()
... ... @@ -100,13 +312,14 @@ class Test(gammalib.GPythonTestSuite):
100 312 # Return
101 313 return
102 314  
103   - def test_fits_image(self):
  315 + # Test GFitsImage class interface
  316 + def _test_fits_image(self):
104 317 """
105   - Test GFitsImage class interface.
  318 + Test GFitsImage class interface
106 319 """
107 320 # Set test file names
108   - file1 = gammalib.GFilename("test_python_fits_image_v1.fits")
109   - file2 = gammalib.GFilename("test_python_fits_image_v2.fits")
  321 + file1 = gammalib.GFilename('test_python_fits_image_v1.fits')
  322 + file2 = gammalib.GFilename('test_python_fits_image_v2.fits')
110 323  
111 324 # Remove test files
112 325 file1.remove()
... ... @@ -138,15 +351,15 @@ class Test(gammalib.GPythonTestSuite):
138 351 img7[x, y] = x + y * nx
139 352 img8[x, y] = x + y * nx
140 353 img9[x, y] = x + y * nx
141   - img1.extname("Byte")
142   - img2.extname("Double")
143   - img3.extname("Float")
144   - img4.extname("Long")
145   - img5.extname("LongLong")
146   - img6.extname("SByte")
147   - img7.extname("Short")
148   - img8.extname("ULong")
149   - img9.extname("UShort")
  354 + img1.extname('Byte')
  355 + img2.extname('Double')
  356 + img3.extname('Float')
  357 + img4.extname('Long')
  358 + img5.extname('LongLong')
  359 + img6.extname('SByte')
  360 + img7.extname('Short')
  361 + img8.extname('ULong')
  362 + img9.extname('UShort')
150 363  
151 364 # Test image types by checking the bitpix values
152 365 self.test_value(img1.bitpix(), 8)
... ... @@ -172,9 +385,9 @@ class Test(gammalib.GPythonTestSuite):
172 385  
173 386 # Set header keywords
174 387 img_byte = fits.image(0)
175   - img_byte.card("test", "test-value", "this is for testing")
176   - img_byte.card("real", 3.1415, "a real value")
177   - img_byte.card("int", 41, "an integer value")
  388 + img_byte.card('test', 'test-value', 'this is for testing')
  389 + img_byte.card('real', 3.1415, 'a real value')
  390 + img_byte.card('int', 41, 'an integer value')
178 391  
179 392 # Save FITS file
180 393 fits.save()
... ... @@ -198,7 +411,7 @@ class Test(gammalib.GPythonTestSuite):
198 411  
199 412 # Get double precision image, take square root of pixel and save in
200 413 # another file
201   - img_double = fits.image("Double")
  414 + img_double = fits.image('Double')
202 415 for x in range(nx):
203 416 for y in range(ny):
204 417 img_double[x, y] = math.sqrt(img_double[x, y])
... ... @@ -232,13 +445,14 @@ class Test(gammalib.GPythonTestSuite):
232 445 # Return
233 446 return
234 447  
235   - def test_fits_table(self):
  448 + # Test GFitsTable class interface
  449 + def _test_fits_table(self):
236 450 """
237   - Test GFitsTable class interface.
  451 + Test GFitsTable class interface
238 452 """
239 453 # Set test file names
240   - file1 = gammalib.GFilename("test_python_fits_table_v1.fits")
241   - file2 = gammalib.GFilename("test_python_fits_table_v2.fits")
  454 + file1 = gammalib.GFilename('test_python_fits_table_v1.fits')
  455 + file2 = gammalib.GFilename('test_python_fits_table_v2.fits')
242 456  
243 457 # Remove test files
244 458 file1.remove()
... ... @@ -249,17 +463,17 @@ class Test(gammalib.GPythonTestSuite):
249 463  
250 464 # Create table columns
251 465 nrows = 10
252   - col1 = gammalib.GFitsTableBitCol("BIT", nrows)
253   - col2 = gammalib.GFitsTableBoolCol("BOOLEAN", nrows)
254   - col3 = gammalib.GFitsTableByteCol("BYTE", nrows)
255   - col4 = gammalib.GFitsTableDoubleCol("DOUBLE", nrows)
256   - col5 = gammalib.GFitsTableFloatCol("FLOAT", nrows)
257   - col6 = gammalib.GFitsTableLongCol("LONG", nrows)
258   - col7 = gammalib.GFitsTableLongLongCol("LONGLONG", nrows)
259   - col8 = gammalib.GFitsTableShortCol("SHORT", nrows)
260   - col9 = gammalib.GFitsTableStringCol("STRING", nrows, 20)
261   - col10 = gammalib.GFitsTableULongCol("ULONG", nrows)
262   - col11 = gammalib.GFitsTableUShortCol("USHORT", nrows)
  466 + col1 = gammalib.GFitsTableBitCol('BIT', nrows)
  467 + col2 = gammalib.GFitsTableBoolCol('BOOLEAN', nrows)
  468 + col3 = gammalib.GFitsTableByteCol('BYTE', nrows)
  469 + col4 = gammalib.GFitsTableDoubleCol('DOUBLE', nrows)
  470 + col5 = gammalib.GFitsTableFloatCol('FLOAT', nrows)
  471 + col6 = gammalib.GFitsTableLongCol('LONG', nrows)
  472 + col7 = gammalib.GFitsTableLongLongCol('LONGLONG', nrows)
  473 + col8 = gammalib.GFitsTableShortCol('SHORT', nrows)
  474 + col9 = gammalib.GFitsTableStringCol('STRING', nrows, 20)
  475 + col10 = gammalib.GFitsTableULongCol('ULONG', nrows)
  476 + col11 = gammalib.GFitsTableUShortCol('USHORT', nrows)
263 477 for i in range(nrows):
264 478 #col1[i] = i % 2 # Old swig version
265 479 #col2[i] = i % 2 # Old swig version
... ... @@ -288,7 +502,7 @@ class Test(gammalib.GPythonTestSuite):
288 502 tbl_ascii.append(col9)
289 503 tbl_ascii.append(col10)
290 504 tbl_ascii.append(col11)
291   - tbl_ascii.extname("ASCII table")
  505 + tbl_ascii.extname('ASCII table')
292 506 fits.append(tbl_ascii)
293 507  
294 508 # Set binary table
... ... @@ -304,7 +518,7 @@ class Test(gammalib.GPythonTestSuite):
304 518 tbl_bin.append(col9)
305 519 tbl_bin.append(col10)
306 520 tbl_bin.append(col11)
307   - tbl_bin.extname("Binary table")
  521 + tbl_bin.extname('Binary table')
308 522 fits.append(tbl_bin)
309 523  
310 524 # Save FITS file
... ... @@ -316,36 +530,37 @@ class Test(gammalib.GPythonTestSuite):
316 530 # Return
317 531 return
318 532  
319   - def test_fits_table_columns(self):
  533 + # Test FITS table columns
  534 + def _test_fits_table_columns(self):
320 535 """
321 536 Test FITS table columns
322 537 """
323 538 # Create table columns
324 539 nrows = 10
325   - col1 = gammalib.GFitsTableBitCol("BIT", nrows)
326   - col2 = gammalib.GFitsTableBoolCol("BOOLEAN", nrows)
327   - col3 = gammalib.GFitsTableByteCol("BYTE", nrows)
328   - col4 = gammalib.GFitsTableDoubleCol("DOUBLE", nrows)
329   - col5 = gammalib.GFitsTableFloatCol("FLOAT", nrows)
330   - col6 = gammalib.GFitsTableLongCol("LONG", nrows)
331   - col7 = gammalib.GFitsTableLongLongCol("LONGLONG", nrows)
332   - col8 = gammalib.GFitsTableShortCol("SHORT", nrows)
333   - col9 = gammalib.GFitsTableStringCol("STRING", nrows, 20)
334   - col10 = gammalib.GFitsTableULongCol("ULONG", nrows)
335   - col11 = gammalib.GFitsTableUShortCol("USHORT", nrows)
  540 + col1 = gammalib.GFitsTableBitCol('BIT', nrows)
  541 + col2 = gammalib.GFitsTableBoolCol('BOOLEAN', nrows)
  542 + col3 = gammalib.GFitsTableByteCol('BYTE', nrows)
  543 + col4 = gammalib.GFitsTableDoubleCol('DOUBLE', nrows)
  544 + col5 = gammalib.GFitsTableFloatCol('FLOAT', nrows)
  545 + col6 = gammalib.GFitsTableLongCol('LONG', nrows)
  546 + col7 = gammalib.GFitsTableLongLongCol('LONGLONG', nrows)
  547 + col8 = gammalib.GFitsTableShortCol('SHORT', nrows)
  548 + col9 = gammalib.GFitsTableStringCol('STRING', nrows, 20)
  549 + col10 = gammalib.GFitsTableULongCol('ULONG', nrows)
  550 + col11 = gammalib.GFitsTableUShortCol('USHORT', nrows)
336 551  
337 552 # Test number of rows
338   - self.test_value(col1.nrows(), nrows, "Check number of rows in Bit column")
339   - self.test_value(col2.nrows(), nrows, "Check number of rows in Boolean column")
340   - self.test_value(col3.nrows(), nrows, "Check number of rows in Byte column")
341   - self.test_value(col4.nrows(), nrows, "Check number of rows in Double column")
342   - self.test_value(col5.nrows(), nrows, "Check number of rows in Float column")
343   - self.test_value(col6.nrows(), nrows, "Check number of rows in Long column")
344   - self.test_value(col7.nrows(), nrows, "Check number of rows in LongLong column")
345   - self.test_value(col8.nrows(), nrows, "Check number of rows in Short column")
346   - self.test_value(col9.nrows(), nrows, "Check number of rows in String column")
347   - self.test_value(col10.nrows(), nrows, "Check number of rows in ULong column")
348   - self.test_value(col11.nrows(), nrows, "Check number of rows in UShort column")
  553 + self.test_value(col1.nrows(), nrows, 'Check number of rows in Bit column')
  554 + self.test_value(col2.nrows(), nrows, 'Check number of rows in Boolean column')
  555 + self.test_value(col3.nrows(), nrows, 'Check number of rows in Byte column')
  556 + self.test_value(col4.nrows(), nrows, 'Check number of rows in Double column')
  557 + self.test_value(col5.nrows(), nrows, 'Check number of rows in Float column')
  558 + self.test_value(col6.nrows(), nrows, 'Check number of rows in Long column')
  559 + self.test_value(col7.nrows(), nrows, 'Check number of rows in LongLong column')
  560 + self.test_value(col8.nrows(), nrows, 'Check number of rows in Short column')
  561 + self.test_value(col9.nrows(), nrows, 'Check number of rows in String column')
  562 + self.test_value(col10.nrows(), nrows, 'Check number of rows in ULong column')
  563 + self.test_value(col11.nrows(), nrows, 'Check number of rows in UShort column')
349 564  
350 565 # Test iterators
351 566 for row in col1:
... ... @@ -373,28 +588,48 @@ class Test(gammalib.GPythonTestSuite):
373 588  
374 589 # Test setting and retrieving of values
375 590 col1[5] = True
376   - self.test_assert(col1[5], "Check Bit column setting and retrieving")
  591 + self.test_assert(col1[5], 'Check Bit column setting and retrieving')
377 592 col2[5] = True
378   - self.test_assert(col2[5], "Check Boolean column setting and retrieving")
  593 + self.test_assert(col2[5], 'Check Boolean column setting and retrieving')
379 594 col3[5] = 5
380   - self.test_value(col3[5], 5, "Check Byte column setting and retrieving")
  595 + self.test_value(col3[5], 5, 'Check Byte column setting and retrieving')
381 596 col4[5] = 3.14
382   - self.test_value(col4[5], 3.14, 1.0e-6, "Check Double column setting and retrieving")
  597 + self.test_value(col4[5], 3.14, 1.0e-6, 'Check Double column setting and retrieving')
383 598 col5[5] = 3.14
384   - self.test_value(col5[5], 3.14, 1.0e-6, "Check Float column setting and retrieving")
  599 + self.test_value(col5[5], 3.14, 1.0e-6, 'Check Float column setting and retrieving')
385 600 col6[5] = 314
386   - self.test_value(col6[5], 314, "Check Long column setting and retrieving")
  601 + self.test_value(col6[5], 314, 'Check Long column setting and retrieving')
387 602 col7[5] = 314
388   - self.test_value(col7[5], 314, "Check LongLong column setting and retrieving")
  603 + self.test_value(col7[5], 314, 'Check LongLong column setting and retrieving')
389 604 col8[5] = 314
390   - self.test_value(col8[5], 314, "Check Short column setting and retrieving")
391   - col9[5] = "Hallo"
392   - self.test_assert(col9[5] == "Hallo", "Check String column setting and retrieving")
  605 + self.test_value(col8[5], 314, 'Check Short column setting and retrieving')
  606 + col9[5] = 'Hallo'
  607 + self.test_assert(col9[5] == 'Hallo', 'Check String column setting and retrieving')
393 608 col10[5] = 314
394   - self.test_value(col10[5], 314, "Check ULong column setting and retrieving")
  609 + self.test_value(col10[5], 314, 'Check ULong column setting and retrieving')
395 610 col11[5] = 314
396   - self.test_value(col11[5], 314, "Check UShort column setting and retrieving")
  611 + self.test_value(col11[5], 314, 'Check UShort column setting and retrieving')
  612 +
  613 + # Return
  614 + return
  615 +
  616 + # Set test functions
  617 + def set(self):
  618 + """
  619 + Set all test functions
  620 + """
  621 + # Set test name
  622 + self.name('fits')
  623 +
  624 + # Append tests
  625 + self.append(self._test_fits, 'Test GFits')
  626 + self.append(self._test_fits_access, 'Test GFits parameter access')
  627 + self.append(self._test_fits_slicing, 'Test GFits slicing')
  628 + self.append(self._test_header_access, 'Test GFitsHeader parameter access')
  629 + self.append(self._test_header_slicing, 'Test GFitsHeader slicing')
  630 + self.append(self._test_fits_image, 'Test GFitsImage')
  631 + self.append(self._test_fits_table, 'Test GFitsTable')
  632 + self.append(self._test_fits_table_columns, 'Test GFitsTableCol')
397 633  
398 634 # Return
399 635 return
400   -
... ...
test/test_GObservation.py
... ... @@ -649,24 +649,8 @@ class Test(gammalib.GPythonTestSuite):
649 649 # Setup photons container
650 650 photons = self._setup_photons()
651 651  
652   - # Loop over all elements using the container iterator and count the
653   - # number of iterations
654   - nphotons = 0
655   - reference = 0.0
656   - for photon in photons:
657   - self.test_value(photon.energy().MeV(), reference)
658   - nphotons += 1
659   - reference += 1.0
660   -
661   - # Check that looping was successful
662   - self.test_value(photons.size(), 10, 'Check container size')
663   - self.test_value(nphotons, 10, 'Check container iterator')
664   -
665   - # Test access from start
666   - self.test_value(photons[3].energy().MeV(), 3.0)
667   -
668   - # Check access from end
669   - self.test_value(photons[-2].energy().MeV(), 8.0)
  652 + # Perform photons access tests
  653 + test_support._energy_container_access_index(self, photons)
670 654  
671 655 # Return
672 656 return
... ... @@ -679,47 +663,8 @@ class Test(gammalib.GPythonTestSuite):
679 663 # Setup photons container
680 664 photons = self._setup_photons()
681 665  
682   - # Test photons[start:end]
683   - self.test_value(len(photons[3:5]), 2)
684   - self.test_value(photons[3:5][0].energy().MeV(), 3.0)
685   - self.test_value(photons[3:5][1].energy().MeV(), 4.0)
686   -
687   - # Test photons[start:]
688   - self.test_value(len(photons[7:]), 3)
689   - self.test_value(photons[7:][0].energy().MeV(), 7.0)
690   - self.test_value(photons[7:][1].energy().MeV(), 8.0)
691   - self.test_value(photons[7:][2].energy().MeV(), 9.0)
692   -
693   - # Test photons[:end]
694   - self.test_value(len(photons[:2]), 2)
695   - self.test_value(photons[:2][0].energy().MeV(), 0.0)
696   - self.test_value(photons[:2][1].energy().MeV(), 1.0)
697   -
698   - # Test photons[:]
699   - self.test_value(len(photons[:]), 10)
700   - for i in range(10):
701   - self.test_value(photons[:][i].energy().MeV(), float(i))
702   -
703   - # Test photons[start:end:step]
704   - self.test_value(len(photons[3:7:2]), 2)
705   - self.test_value(photons[3:7:2][0].energy().MeV(), 3.0)
706   - self.test_value(photons[3:7:2][1].energy().MeV(), 5.0)
707   -
708   - # Test photons[start:end:step]
709   - self.test_value(len(photons[6:3:-2]), 2)
710   - self.test_value(photons[6:3:-2][0].energy().MeV(), 6.0)
711   - self.test_value(photons[6:3:-2][1].energy().MeV(), 4.0)
712   -
713   - # Test photons[-start:]
714   - self.test_value(len(photons[-2:]), 2)
715   - self.test_value(photons[-2:][0].energy().MeV(), 8.0)
716   - self.test_value(photons[-2:][1].energy().MeV(), 9.0)
717   -
718   - # Test photons[:-end]
719   - self.test_value(len(photons[:-7]), 3)
720   - self.test_value(photons[:-7][0].energy().MeV(), 0.0)
721   - self.test_value(photons[:-7][1].energy().MeV(), 1.0)
722   - self.test_value(photons[:-7][2].energy().MeV(), 2.0)
  666 + # Perform slicing tests
  667 + test_support._energy_container_slicing(self, photons)
723 668  
724 669 # Return
725 670 return
... ... @@ -736,16 +681,6 @@ class Test(gammalib.GPythonTestSuite):
736 681 # Perform observation access tests
737 682 test_support._container_access_index(self, obs)
738 683  
739   - # Check observation setting by index from start
740   - run.id('98')
741   - obs[3] = run
742   - self.test_value(obs[3].id(), '98')
743   -
744   - # Check observation setting by index from end
745   - run.id('99')
746   - obs[-2] = run
747   - self.test_value(obs[-2].id(), '99')
748   -
749 684 # Return
750 685 return
751 686  
... ...
test/test_GOptimizer.py
1 1 # ==========================================================================
2 2 # This module performs unit tests for the GammaLib optimizer module.
3 3 #
4   -# Copyright (C) 2012-2015 Juergen Knoedlseder
  4 +# Copyright (C) 2012-2017 Juergen Knoedlseder
5 5 #
6 6 # This program is free software: you can redistribute it and/or modify
7 7 # it under the terms of the GNU General Public License as published by
... ... @@ -18,6 +18,7 @@
18 18 #
19 19 # ==========================================================================
20 20 import gammalib
  21 +import test_support
21 22  
22 23  
23 24 # ======================================== #
... ... @@ -38,24 +39,76 @@ class Test(gammalib.GPythonTestSuite):
38 39 # Return
39 40 return
40 41  
41   - # Set test functions
42   - def set(self):
  42 + # Setup GOptimizerPars container
  43 + def _setup_pars(self):
43 44 """
44   - Set all test functions.
  45 + Setup GOptimizerPars container
  46 +
  47 + Returns
  48 + -------
  49 + pars : `~gammalib.GOptimizerPars`
  50 + GOptimizerPars container
45 51 """
46   - # Set test name
47   - self.name("opt")
  52 + # Setup GOptimizerPars container
  53 + pars = gammalib.GOptimizerPars()
  54 + par = gammalib.GOptimizerPar()
  55 + for i in range(10):
  56 + par.name('%s' % i)
  57 + pars.append(par)
48 58  
49   - # Append tests
50   - self.append(self.test, "Optimizer module dummy test")
  59 + # Return GOptimizerPars container
  60 + return pars
  61 +
  62 + # Test GOptimizerPars class access operators
  63 + def _test_pars_access(self):
  64 + """
  65 + Test GOptimizerPars class parameter access
  66 + """
  67 + # Setup GOptimizerPars container and parameter
  68 + pars = self._setup_pars()
  69 + par = gammalib.GOptimizerPar()
  70 +
  71 + # Perform GOptimizerPars access tests
  72 + test_support._container_access_index(self, pars)
  73 +
  74 + # Check parameter setting by index from start
  75 + par.name('98')
  76 + pars[3] = par
  77 + self.test_value(pars[3].name(), '98')
  78 +
  79 + # Check parameter setting by index from end
  80 + par.name('99')
  81 + pars[-2] = par
  82 + self.test_value(pars[-2].name(), '99')
  83 +
  84 + # Return
  85 + return
  86 +
  87 + # Test GOptimizerPars class slicing
  88 + def _test_pars_slicing(self):
  89 + """
  90 + Test GOptimizerPars class slicing
  91 + """
  92 + # Setup GOptimizerPars container
  93 + pars = self._setup_pars()
  94 +
  95 + # Perform slicing tests
  96 + test_support._container_slicing(self, pars)
51 97  
52 98 # Return
53 99 return
54 100  
55   - # Test function
56   - def test(self):
  101 + # Set test functions
  102 + def set(self):
57 103 """
58   - Test function.
  104 + Set all test functions.
59 105 """
  106 + # Set test name
  107 + self.name('opt')
  108 +
  109 + # Append tests
  110 + self.append(self._test_pars_access, "Test GOptimizerPars parameter access")
  111 + self.append(self._test_pars_slicing, "Test GOptimizerPars slicing")
  112 +
60 113 # Return
61 114 return
... ...
test/test_GSky.py
... ... @@ -20,12 +20,13 @@
20 20 import os
21 21 import math
22 22 import gammalib
  23 +import test_support
23 24  
24 25  
25 26 # =========== #
26 27 # Text parser #
27 28 # =========== #
28   -def loadtxt(filename):
  29 +def _loadtxt(filename):
29 30 """
30 31 Parse text file with columns of floats.
31 32  
... ... @@ -63,40 +64,33 @@ class Test(gammalib.GPythonTestSuite):
63 64 # Return
64 65 return
65 66  
66   - def set(self):
67   - """
68   - Set all test functions.
  67 + # Setup GSkyRegions container
  68 + def _setup_regions(self):
69 69 """
70   - # Set test name
71   - self.name("sky")
  70 + Setup GSkyRegions container
72 71  
73   - # Append tests
74   - self.append(self.test_methods, "Test sky map methods")
75   - self.append(self.test_friend_methods, "Test sky map friend methods")
76   - self.append(self.test_operators, "Test sky map operators")
77   - self.append(self.test_skymap_healpix, "Test HEALPix map")
78   - self.append(self.test_skymap_ait, "Test AIT projection map")
79   - self.append(self.test_skymap_azp, "Test AZP projection map")
80   - self.append(self.test_skymap_car, "Test CAR projection map")
81   - self.append(self.test_skymap_gls, "Test GLS projection map")
82   - self.append(self.test_skymap_mer, "Test MER projection map")
83   - self.append(self.test_skymap_mol, "Test MOL projection map")
84   - self.append(self.test_skymap_sfl, "Test SFL projection map")
85   - self.append(self.test_skymap_sin, "Test SIN projection map")
86   - self.append(self.test_skymap_stg, "Test STG projection map")
87   - self.append(self.test_skymap_tan, "Test TAN projection map")
88   - self.append(self.test_fk5_to_galactic, "Test FK5 to Galactic coordinate conversion")
  72 + Returns
  73 + -------
  74 + regions : `~gammalib.GSkyRegions`
  75 + Sky regions container
  76 + """
  77 + # Setup regions container
  78 + regions = gammalib.GSkyRegions()
  79 + circle = gammalib.GSkyRegionCircle()
  80 + for i in range(10):
  81 + circle.name('%s' % i)
  82 + regions.append(circle)
89 83  
90   - # Return
91   - return
  84 + # Return regions container
  85 + return regions
92 86  
93 87 # Test sky map methods
94   - def test_methods(self):
  88 + def _test_methods(self):
95 89 """
96 90 Test the sky map methods.
97 91 """
98 92 # Setup sky maps
99   - map = gammalib.GSkyMap("CAR", "CEL", 83.63, 22.01, -3.7, 2.6, 10, 8, 12)
  93 + map = gammalib.GSkyMap('CAR', 'CEL', 83.63, 22.01, -3.7, 2.6, 10, 8, 12)
100 94  
101 95 # Set sky map shape
102 96 map.shape(3,4)
... ... @@ -126,7 +120,7 @@ class Test(gammalib.GPythonTestSuite):
126 120 return
127 121  
128 122 # Test sky map friend methods
129   - def test_friend_methods(self):
  123 + def _test_friend_methods(self):
130 124 """
131 125 Test the sky map friend methods
132 126 """
... ... @@ -154,12 +148,12 @@ class Test(gammalib.GPythonTestSuite):
154 148 return
155 149  
156 150 # Test sky map operators
157   - def test_operators(self):
  151 + def _test_operators(self):
158 152 """
159 153 Test the sky map operators.
160 154 """
161 155 # Setup sky maps
162   - map = gammalib.GSkyMap("CAR", "CEL", 83.6331, 22.0145, -3.7, 2.6, 2, 2)
  156 + map = gammalib.GSkyMap('CAR', 'CEL', 83.6331, 22.0145, -3.7, 2.6, 2, 2)
163 157 map[0] = 1.0
164 158 map[1] = 2.0
165 159 map[2] = 3.0
... ... @@ -218,7 +212,7 @@ class Test(gammalib.GPythonTestSuite):
218 212 return
219 213  
220 214 # Generic skymap pixel transformation test
221   - def test_skymap_pixels(self, pixels, map):
  215 + def _test_skymap_pixels(self, pixels, map):
222 216 """
223 217 Control coordinate and pixel transformation methods.
224 218 """
... ... @@ -226,9 +220,9 @@ class Test(gammalib.GPythonTestSuite):
226 220 for i in range(pixels.npix()):
227 221 dir = pixels.inx2dir(i)
228 222 inx = pixels.dir2inx(dir)
229   - msg = map + " inx2dir/dir2inx check for pixel " + str(i)
230   - err = map + " GSkyMap trouble with pixel " + str(i) + " (" + str(inx) + \
231   - "), RA=" + str(dir.ra() * 180 / math.pi) + ", Dec=" + str(dir.dec() * 180 / math.pi)
  223 + msg = map + ' inx2dir/dir2inx check for pixel ' + str(i)
  224 + err = map + ' GSkyMap trouble with pixel ' + str(i) + ' (' + str(inx) + \
  225 + '), RA=' + str(dir.ra() * 180 / math.pi) + ', Dec=' + str(dir.dec() * 180 / math.pi)
232 226 self.test_assert(i == inx, msg, err)
233 227  
234 228 # Control SkyDir coordinate transformation for all pixels
... ... @@ -240,21 +234,21 @@ class Test(gammalib.GPythonTestSuite):
240 234 if (dra >= 5.0):
241 235 dra -= 2.0 * math.pi
242 236 ddec = abs(dir.dec() - dir_new.dec())
243   - msg = map + " dir check for pixel " + str(i)
244   - err = map + " GSkyMap trouble with pixel " + str(i) + " (" + str(dra) + \
245   - "," + str(ddec) + ")"
  237 + msg = map + ' dir check for pixel ' + str(i)
  238 + err = map + ' GSkyMap trouble with pixel ' + str(i) + ' (' + str(dra) + \
  239 + ',' + str(ddec) + ')'
246 240 self.test_assert(not (dra > 1.0e-9 or ddec > 1.0e-9), msg, err)
247 241  
248 242 # Return
249 243 return
250 244  
251 245 # Generic skymap projection test
252   - def test_skymap_proj(self, proj):
  246 + def _test_skymap_proj(self, proj):
253 247 """
254 248 Test skymap projection.
255 249 """
256 250 # Set filename
257   - file = "test_python_skymap_" + proj + ".fits"
  251 + file = 'test_python_skymap_' + proj + '.fits'
258 252  
259 253 # Remove test files
260 254 try:
... ... @@ -263,26 +257,26 @@ class Test(gammalib.GPythonTestSuite):
263 257 pass
264 258  
265 259 # Create skymap
266   - pixels = gammalib.GSkyMap(proj, "CEL", 83.6331, 22.0145, -3.7, 2.6, 5, 5, 20)
  260 + pixels = gammalib.GSkyMap(proj, 'CEL', 83.6331, 22.0145, -3.7, 2.6, 5, 5, 20)
267 261 for map in range(pixels.nmaps()):
268 262 for i in range(pixels.npix()):
269 263 pixels[i, map] = i + map * pixels.npix()
270 264 pixels.save(file)
271 265  
272 266 # Test coordinate and pixel transformations
273   - self.test_skymap_pixels(pixels, proj)
  267 + self._test_skymap_pixels(pixels, proj)
274 268  
275 269 # Return
276 270 return
277 271  
278 272 # Test HEALPix projection
279   - def test_skymap_healpix(self):
  273 + def _test_skymap_healpix(self):
280 274 """
281 275 Test HEALPix interface.
282 276 """
283 277 # Set filenames
284   - file1 = "test_python_skymap_hpx_v1.fits"
285   - file2 = "test_python_skymap_hpx_v2.fits"
  278 + file1 = 'test_python_skymap_hpx_v1.fits'
  279 + file2 = 'test_python_skymap_hpx_v2.fits'
286 280  
287 281 # Remove test files
288 282 try:
... ... @@ -292,7 +286,7 @@ class Test(gammalib.GPythonTestSuite):
292 286 pass
293 287  
294 288 # Create HEALPix skymap
295   - pixels = gammalib.GSkyMap("GAL", 2, "RING", 2)
  289 + pixels = gammalib.GSkyMap('GAL', 2, 'RING', 2)
296 290 for i in range(pixels.npix()):
297 291 pixels[i] = i + 1.0
298 292 pixels[i, 1] = i + 1.0 + 1000.0
... ... @@ -302,7 +296,7 @@ class Test(gammalib.GPythonTestSuite):
302 296 pixels = gammalib.GSkyMap(file1)
303 297  
304 298 # Control coordinate and pixel transformations
305   - self.test_skymap_pixels(pixels, "HEALPix")
  299 + self._test_skymap_pixels(pixels, 'HEALPix')
306 300  
307 301 # Save HEALPix skymap twice. The second saving should fail.
308 302 try:
... ... @@ -311,7 +305,7 @@ class Test(gammalib.GPythonTestSuite):
311 305 except RuntimeError:
312 306 pass
313 307 else:
314   - raise RuntimeError("*** TEST ERROR: FITS file overwritten!")
  308 + raise RuntimeError('*** TEST ERROR: FITS file overwritten!')
315 309 pixels.save(file2, True)
316 310  
317 311 # Load again HEALPix skymap
... ... @@ -321,117 +315,117 @@ class Test(gammalib.GPythonTestSuite):
321 315 return
322 316  
323 317 # Test AIT projection
324   - def test_skymap_ait(self):
  318 + def _test_skymap_ait(self):
325 319 """
326 320 Test AIT projection.
327 321 """
328 322 # Execute generic test
329   - self.test_skymap_proj("AIT")
  323 + self._test_skymap_proj('AIT')
330 324  
331 325 # Return
332 326 return
333 327  
334 328 # Test AZP projection
335   - def test_skymap_azp(self):
  329 + def _test_skymap_azp(self):
336 330 """
337 331 Test AZP projection.
338 332 """
339 333 # Execute generic test
340   - self.test_skymap_proj("AZP")
  334 + self._test_skymap_proj('AZP')
341 335  
342 336 # Return
343 337 return
344 338  
345 339 # Test CAR projection
346   - def test_skymap_car(self):
  340 + def _test_skymap_car(self):
347 341 """
348 342 Test CAR projection.
349 343 """
350 344 # Execute generic test
351   - self.test_skymap_proj("CAR")
  345 + self._test_skymap_proj('CAR')
352 346  
353 347 # Return
354 348 return
355 349  
356 350 # Test GLS projection
357   - def test_skymap_gls(self):
  351 + def _test_skymap_gls(self):
358 352 """
359 353 Test GLS projection.
360 354 """
361 355 # Execute generic test
362   - self.test_skymap_proj("GLS")
  356 + self._test_skymap_proj('GLS')
363 357  
364 358 # Return
365 359 return
366 360  
367 361 # Test MER projection
368   - def test_skymap_mer(self):
  362 + def _test_skymap_mer(self):
369 363 """
370 364 Test MER projection.
371 365 """
372 366 # Execute generic test
373   - self.test_skymap_proj("MER")
  367 + self._test_skymap_proj('MER')
374 368  
375 369 # Return
376 370 return
377 371  
378 372 # Test MOL projection
379   - def test_skymap_mol(self):
  373 + def _test_skymap_mol(self):
380 374 """
381 375 Test MOL projection.
382 376 """
383 377 # Execute generic test
384   - self.test_skymap_proj("MOL")
  378 + self._test_skymap_proj('MOL')
385 379  
386 380 # Return
387 381 return
388 382  
389 383 # Test SIN projection
390   - def test_skymap_sin(self):
  384 + def _test_skymap_sin(self):
391 385 """
392 386 Test SIN projection.
393 387 """
394 388 # Execute generic test
395   - self.test_skymap_proj("SIN")
  389 + self._test_skymap_proj('SIN')
396 390  
397 391 # Return
398 392 return
399 393  
400 394 # Test SFL projection
401   - def test_skymap_sfl(self):
  395 + def _test_skymap_sfl(self):
402 396 """
403 397 Test SFL projection.
404 398 """
405 399 # Execute generic test
406   - self.test_skymap_proj("SFL")
  400 + self._test_skymap_proj('SFL')
407 401  
408 402 # Return
409 403 return
410 404  
411 405 # Test STG projection
412   - def test_skymap_stg(self):
  406 + def _test_skymap_stg(self):
413 407 """
414 408 Test STG projection.
415 409 """
416 410 # Execute generic test
417   - self.test_skymap_proj("STG")
  411 + self._test_skymap_proj('STG')
418 412  
419 413 # Return
420 414 return
421 415  
422 416 # Test TAN projection
423   - def test_skymap_tan(self):
  417 + def _test_skymap_tan(self):
424 418 """
425 419 Test TAN projection.
426 420 """
427 421 # Execute generic test
428   - self.test_skymap_proj("TAN")
  422 + self._test_skymap_proj('TAN')
429 423  
430 424 # Return
431 425 return
432 426  
433 427 # FK5 J2000 to Galactic coordinate tranformations
434   - def test_fk5_to_galactic(self):
  428 + def _test_fk5_to_galactic(self):
435 429 """
436 430 Test precision of FK5 J2000 to Galactic coordinate tranformations
437 431 against pyast (http://dsberry.github.com/starlink/pyast.html)
... ... @@ -446,8 +440,8 @@ class Test(gammalib.GPythonTestSuite):
446 440 # Set parameters
447 441 fk5_filename = datadir + 'initial_coords.txt'
448 442 galactic_filename = datadir + 'fk5_to_galactic.txt'
449   - fk5_coordinates = loadtxt(fk5_filename)
450   - galactic_coordinates = loadtxt(galactic_filename)
  443 + fk5_coordinates = _loadtxt(fk5_filename)
  444 + galactic_coordinates = _loadtxt(galactic_filename)
451 445 coordinates = zip(fk5_coordinates, galactic_coordinates)
452 446 max_dist = 0
453 447  
... ... @@ -483,3 +477,70 @@ class Test(gammalib.GPythonTestSuite):
483 477  
484 478 # Return
485 479 return
  480 +
  481 + # Test GSkyRegions class access operators
  482 + def _test_regions_access(self):
  483 + """
  484 + Test GSkyRegions class observation access
  485 + """
  486 + # Setup regions container
  487 + regions = self._setup_regions()
  488 + circle = gammalib.GSkyRegionCircle()
  489 +
  490 + # Perform regions access tests
  491 + test_support._container_access_index(self, regions)
  492 +
  493 + # Check regions setting by index from start
  494 + circle.name('98')
  495 + regions[3] = circle
  496 + self.test_value(regions[3].name(), '98')
  497 +
  498 + # Check observation setting by index from end
  499 + circle.name('99')
  500 + regions[-2] = circle
  501 + self.test_value(regions[-2].name(), '99')
  502 +
  503 + # Return
  504 + return
  505 +
  506 + # Test GSkyRegions class slicing
  507 + def _test_regions_slicing(self):
  508 + """
  509 + Test GSkyRegions class slicing
  510 + """
  511 + # Setup regions container
  512 + regions = self._setup_regions()
  513 +
  514 + # Perform slicing tests
  515 + test_support._container_slicing(self, regions)
  516 +
  517 + # Return
  518 + return
  519 +
  520 + def set(self):
  521 + """
  522 + Set all test functions.
  523 + """
  524 + # Set test name
  525 + self.name("sky")
  526 +
  527 + # Append tests
  528 + self.append(self._test_methods, "Test sky map methods")
  529 + self.append(self._test_friend_methods, "Test sky map friend methods")
  530 + self.append(self._test_operators, "Test sky map operators")
  531 + self.append(self._test_skymap_healpix, "Test HEALPix map")
  532 + self.append(self._test_skymap_ait, "Test AIT projection map")
  533 + self.append(self._test_skymap_azp, "Test AZP projection map")
  534 + self.append(self._test_skymap_car, "Test CAR projection map")
  535 + self.append(self._test_skymap_gls, "Test GLS projection map")
  536 + self.append(self._test_skymap_mer, "Test MER projection map")
  537 + self.append(self._test_skymap_mol, "Test MOL projection map")
  538 + self.append(self._test_skymap_sfl, "Test SFL projection map")
  539 + self.append(self._test_skymap_sin, "Test SIN projection map")
  540 + self.append(self._test_skymap_stg, "Test STG projection map")
  541 + self.append(self._test_skymap_tan, "Test TAN projection map")
  542 + self.append(self._test_regions_access, "Test GSkyRegions region access")
  543 + self.append(self._test_regions_slicing, "Test GSkyRegions slicing")
  544 +
  545 + # Return
  546 + return
... ...
test/test_GSupport.py
1 1 # ==========================================================================
2 2 # This module performs unit tests for the GammaLib support module.
3 3 #
4   -# Copyright (C) 2012-2016 Juergen Knoedlseder
  4 +# Copyright (C) 2012-2017 Juergen Knoedlseder
5 5 #
6 6 # This program is free software: you can redistribute it and/or modify
7 7 # it under the terms of the GNU General Public License as published by
... ... @@ -39,26 +39,26 @@ class Test(gammalib.GPythonTestSuite):
39 39 # Return
40 40 return
41 41  
42   - # Set all test functions
43   - def set(self):
44   - """
45   - Set all test functions.
  42 + # Setup GNodeArray container
  43 + def _setup_nodes(self):
46 44 """
47   - # Set test name
48   - self.name('support')
  45 + Setup GNodeArray
49 46  
50   - # Append tests
51   - self.append(self.test_node_array, 'Test GNodeArray')
52   - self.append(self.test_url_file, 'Test GUrlFile')
53   - self.append(self.test_url_string, 'Test GUrlString')
54   - self.append(self.test_filename, 'Test GFilename')
55   - self.append(self.test_csv, 'Test GCsv')
  47 + Returns
  48 + -------
  49 + nodes : `~gammalib.GNodeArray`
  50 + Node array
  51 + """
  52 + # Setup time container
  53 + nodes = gammalib.GNodeArray()
  54 + for i in range(10):
  55 + nodes.append(float(i))
56 56  
57   - # Return
58   - return
  57 + # Return GNodeArray
  58 + return nodes
59 59  
60 60 # Test GNodeArray class
61   - def test_node_array(self):
  61 + def _test_node_array(self):
62 62 """
63 63 Test GNodeArray class.
64 64 """
... ... @@ -91,8 +91,91 @@ class Test(gammalib.GPythonTestSuite):
91 91 # Return
92 92 return
93 93  
  94 + # Test GNodeArray access
  95 + def _test_node_array_access(self):
  96 + """
  97 + Test GNodeArray access
  98 + """
  99 + # Setup nodes container
  100 + nodes = self._setup_nodes()
  101 +
  102 + # Loop over all elements using the container iterator and count the
  103 + # number of iterations
  104 + nnodes = 0
  105 + reference = 0.0
  106 + for node in nodes:
  107 + self.test_value(node, reference)
  108 + nnodes += 1
  109 + reference += 1.0
  110 +
  111 + # Check that looping was successful
  112 + self.test_value(nodes.size(), 10, 'Check container size')
  113 + self.test_value(nnodes, 10, 'Check container iterator')
  114 +
  115 + # Test access from start
  116 + self.test_value(nodes[3], 3.0)
  117 +
  118 + # Check access from end
  119 + self.test_value(nodes[-2], 8.0)
  120 +
  121 + # Return
  122 + return
  123 +
  124 + # Test GNodeArray slicing
  125 + def _test_node_array_slicing(self):
  126 + """
  127 + Test GNodeArray slicing
  128 + """
  129 + # Setup nodes container
  130 + nodes = self._setup_nodes()
  131 +
  132 + # Test nodes[start:end]
  133 + self.test_value(len(nodes[3:5]), 2)
  134 + self.test_value(nodes[3:5][0], 3.0)
  135 + self.test_value(nodes[3:5][1], 4.0)
  136 +
  137 + # Test nodes[start:]
  138 + self.test_value(len(nodes[7:]), 3)
  139 + self.test_value(nodes[7:][0], 7.0)
  140 + self.test_value(nodes[7:][1], 8.0)
  141 + self.test_value(nodes[7:][2], 9.0)
  142 +
  143 + # Test nodes[:end]
  144 + self.test_value(len(nodes[:2]), 2)
  145 + self.test_value(nodes[:2][0], 0.0)
  146 + self.test_value(nodes[:2][1], 1.0)
  147 +
  148 + # Test nodes[:]
  149 + self.test_value(len(nodes[:]), 10)
  150 + for i in range(10):
  151 + self.test_value(nodes[:][i], float(i))
  152 +
  153 + # Test nodes[start:end:step]
  154 + self.test_value(len(nodes[3:7:2]), 2)
  155 + self.test_value(nodes[3:7:2][0], 3.0)
  156 + self.test_value(nodes[3:7:2][1], 5.0)
  157 +
  158 + # Test nodes[start:end:step]
  159 + self.test_value(len(nodes[6:3:-2]), 2)
  160 + self.test_value(nodes[6:3:-2][0], 6.0)
  161 + self.test_value(nodes[6:3:-2][1], 4.0)
  162 +
  163 + # Test nodes[-start:]
  164 + self.test_value(len(nodes[-2:]), 2)
  165 + self.test_value(nodes[-2:][0], 8.0)
  166 + self.test_value(nodes[-2:][1], 9.0)
  167 +
  168 + # Test nodes[:-end]
  169 + self.test_value(len(nodes[:-7]), 3)
  170 + self.test_value(nodes[:-7][0], 0.0)
  171 + self.test_value(nodes[:-7][1], 1.0)
  172 + self.test_value(nodes[:-7][2], 2.0)
  173 +
  174 + # Return
  175 + return
  176 +
94 177 # Test GUrlFile class
95   - def test_url_file(self):
  178 + def _test_url_file(self):
96 179 """
97 180 Test GUrlFile class.
98 181 """
... ... @@ -113,7 +196,7 @@ class Test(gammalib.GPythonTestSuite):
113 196 return
114 197  
115 198 # Test GUrlString class
116   - def test_url_string(self):
  199 + def _test_url_string(self):
117 200 """
118 201 Test GUrlString class.
119 202 """
... ... @@ -133,7 +216,7 @@ class Test(gammalib.GPythonTestSuite):
133 216 return
134 217  
135 218 # Test GFilename class
136   - def test_filename(self):
  219 + def _test_filename(self):
137 220 """
138 221 Test GFilename class.
139 222 """
... ... @@ -158,7 +241,7 @@ class Test(gammalib.GPythonTestSuite):
158 241 return
159 242  
160 243 # Test GCsv class
161   - def test_csv(self):
  244 + def _test_csv(self):
162 245 """
163 246 Test GCsv class.
164 247 """
... ... @@ -195,3 +278,24 @@ class Test(gammalib.GPythonTestSuite):
195 278  
196 279 # Return
197 280 return
  281 +
  282 + # Set all test functions
  283 + def set(self):
  284 + """
  285 + Set all test functions.
  286 + """
  287 + # Set test name
  288 + self.name('support')
  289 +
  290 + # Append tests
  291 + self.append(self._test_node_array, 'Test GNodeArray')
  292 + self.append(self._test_node_array_access, 'Test GNodeArray node access')
  293 + self.append(self._test_node_array_slicing, 'Test GNodeArray slicing')
  294 + self.append(self._test_url_file, 'Test GUrlFile')
  295 + self.append(self._test_url_string, 'Test GUrlString')
  296 + self.append(self._test_filename, 'Test GFilename')
  297 + self.append(self._test_csv, 'Test GCsv')
  298 +
  299 + # Return
  300 + return
  301 +
... ...
test/test_GTest.py
1 1 # ==========================================================================
2 2 # This module performs unit tests for the GammaLib test module.
3 3 #
4   -# Copyright (C) 2012-2015 Juergen Knoedlseder
  4 +# Copyright (C) 2012-2017 Juergen Knoedlseder
5 5 #
6 6 # This program is free software: you can redistribute it and/or modify
7 7 # it under the terms of the GNU General Public License as published by
... ... @@ -18,6 +18,7 @@
18 18 #
19 19 # ==========================================================================
20 20 import gammalib
  21 +import test_support
21 22  
22 23  
23 24 # =================================== #
... ... @@ -25,12 +26,12 @@ import gammalib
25 26 # =================================== #
26 27 class Test(gammalib.GPythonTestSuite):
27 28 """
28   - Test class for GammaLib test module.
  29 + Test class for GammaLib test module
29 30 """
30 31 # Constructor
31 32 def __init__(self):
32 33 """
33   - Constructor.
  34 + Constructor
34 35 """
35 36 # Call base class constructor
36 37 gammalib.GPythonTestSuite.__init__(self)
... ... @@ -38,24 +39,76 @@ class Test(gammalib.GPythonTestSuite):
38 39 # Return
39 40 return
40 41  
41   - # Set test functions
42   - def set(self):
  42 + # Setup test suite container
  43 + def _setup_suites(self):
43 44 """
44   - Set all test functions.
  45 + Setup test suite container
  46 +
  47 + Returns
  48 + -------
  49 + suites : `~gammalib.GTestSuites`
  50 + Test suite container
45 51 """
46   - # Set test name
47   - self.name("test")
  52 + # Setup test suite container
  53 + suites = gammalib.GTestSuites()
  54 + suite = gammalib.GPythonTestSuite()
  55 + for i in range(10):
  56 + suite.name('%s' % i)
  57 + suites.append(suite)
48 58  
49   - # Append tests
50   - self.append(self.test, "Test module dummy test")
  59 + # Return test suite container
  60 + return suites
  61 +
  62 + # Test GTestSuites class access operators
  63 + def _test_suites_access(self):
  64 + """
  65 + Test GTestSuites class parameter access
  66 + """
  67 + # Setup test suite container and test suite
  68 + suites = self._setup_suites()
  69 + suite = gammalib.GPythonTestSuite()
  70 +
  71 + # Perform GTestSuites access tests
  72 + test_support._container_access_index(self, suites)
  73 +
  74 + # Check parameter setting by index from start
  75 + suite.name('98')
  76 + suites[3] = suite
  77 + self.test_value(suites[3].name(), '98')
  78 +
  79 + # Check parameter setting by index from end
  80 + suite.name('99')
  81 + suites[-2] = suite
  82 + self.test_value(suites[-2].name(), '99')
  83 +
  84 + # Return
  85 + return
  86 +
  87 + # Test GTestSuites class slicing
  88 + def _test_suites_slicing(self):
  89 + """
  90 + Test GTestSuites class slicing
  91 + """
  92 + # Setup test suite container
  93 + suites = self._setup_suites()
  94 +
  95 + # Perform slicing tests
  96 + test_support._container_slicing(self, suites)
51 97  
52 98 # Return
53 99 return
54 100  
55   - # Test function
56   - def test(self):
  101 + # Set test functions
  102 + def set(self):
57 103 """
58   - Test function.
  104 + Set all test functions.
59 105 """
  106 + # Set test name
  107 + self.name('test')
  108 +
  109 + # Append tests
  110 + self.append(self._test_suites_access, 'Test GTestSuites parameter access')
  111 + self.append(self._test_suites_slicing, 'Test GTestSuites slicing')
  112 +
60 113 # Return
61 114 return
... ...
test/test_GXml.py
1 1 # ==========================================================================
2 2 # This module performs unit tests for the GammaLib xml module.
3 3 #
4   -# Copyright (C) 2012-2015 Juergen Knoedlseder
  4 +# Copyright (C) 2012-2017 Juergen Knoedlseder
5 5 #
6 6 # This program is free software: you can redistribute it and/or modify
7 7 # it under the terms of the GNU General Public License as published by
... ... @@ -18,6 +18,7 @@
18 18 #
19 19 # ==========================================================================
20 20 import gammalib
  21 +import test_support
21 22  
22 23  
23 24 # ================================== #
... ... @@ -25,7 +26,7 @@ import gammalib
25 26 # ================================== #
26 27 class Test(gammalib.GPythonTestSuite):
27 28 """
28   - Test class for GammaLib xml module.
  29 + Test class for GammaLib xml module
29 30 """
30 31 # Constructor
31 32 def __init__(self):
... ... @@ -38,24 +39,137 @@ class Test(gammalib.GPythonTestSuite):
38 39 # Return
39 40 return
40 41  
41   - # Set test functions
42   - def set(self):
  42 + # Setup GXml container
  43 + def _setup_xml(self):
43 44 """
44   - Set all test functions.
  45 + Setup GXml container
  46 +
  47 + Returns
  48 + -------
  49 + xml : `~gammalib.GXml`
  50 + GXml container
45 51 """
46   - # Set test name
47   - self.name("xml")
  52 + # Setup XML container
  53 + xml = gammalib.GXml()
  54 + element = gammalib.GXmlElement()
  55 + for i in range(10):
  56 + element.name('%s' % i)
  57 + xml.append(element)
48 58  
49   - # Append tests
50   - self.append(self.test, "XML module dummy test")
  59 + # Return XML container
  60 + return xml
  61 +
  62 + # Setup GXmlElement container
  63 + def _setup_elements(self):
  64 + """
  65 + Setup GXmlElement container
  66 +
  67 + Returns
  68 + -------
  69 + elements : `~gammalib.GXmlElement`
  70 + GXml container
  71 + """
  72 + # Setup GXmlElement container
  73 + elements = gammalib.GXmlElement()
  74 + element = gammalib.GXmlElement()
  75 + for i in range(10):
  76 + element.name('%s' % i)
  77 + elements.append(element)
  78 +
  79 + # Return GXmlElement container
  80 + return elements
  81 +
  82 + # Test GXml class access operators
  83 + def _test_xml_access(self):
  84 + """
  85 + Test GXml class parameter access
  86 + """
  87 + # Setup XML container and element
  88 + xml = self._setup_xml()
  89 + element = gammalib.GXmlElement()
  90 +
  91 + # Perform GXml access tests
  92 + test_support._container_access_index(self, xml)
  93 +
  94 + # Check parameter setting by index from start
  95 + element.name('98')
  96 + xml[3] = element
  97 + self.test_value(xml[3].name(), '98')
  98 +
  99 + # Check parameter setting by index from end
  100 + element.name('99')
  101 + xml[-2] = element
  102 + self.test_value(xml[-2].name(), '99')
  103 +
  104 + # Return
  105 + return
  106 +
  107 + # Test GXml class slicing
  108 + def _test_xml_slicing(self):
  109 + """
  110 + Test GXml class slicing
  111 + """
  112 + # Setup XML container
  113 + xml = self._setup_xml()
  114 +
  115 + # Perform slicing tests
  116 + test_support._container_slicing(self, xml)
51 117  
52 118 # Return
53 119 return
54 120  
55   - # Test function
56   - def test(self):
  121 + # Test GXmlElement class access operators
  122 + def _test_elements_access(self):
57 123 """
58   - Test function.
  124 + Test GXmlElement class parameter access
59 125 """
  126 + # Setup GXmlElement container and element
  127 + elements = self._setup_elements()
  128 + element = gammalib.GXmlElement()
  129 +
  130 + # Perform GXmlElement access tests
  131 + test_support._container_access_index(self, elements)
  132 +
  133 + # Check parameter setting by index from start
  134 + element.name('98')
  135 + elements[3] = element
  136 + self.test_value(elements[3].name(), '98')
  137 +
  138 + # Check parameter setting by index from end
  139 + element.name('99')
  140 + elements[-2] = element
  141 + self.test_value(elements[-2].name(), '99')
  142 +
  143 + # Return
  144 + return
  145 +
  146 + # Test GXmlElement class slicing
  147 + def _test_elements_slicing(self):
  148 + """
  149 + Test GXmlElement class slicing
  150 + """
  151 + # Setup GXmlElement container
  152 + elements = self._setup_elements()
  153 +
  154 + # Perform slicing tests
  155 + test_support._container_slicing(self, elements)
  156 +
  157 + # Return
  158 + return
  159 +
  160 + # Set test functions
  161 + def set(self):
  162 + """
  163 + Set all test functions.
  164 + """
  165 + # Set test name
  166 + self.name('xml')
  167 +
  168 + # Append tests
  169 + self.append(self._test_xml_access, 'Test GXml parameter access')
  170 + self.append(self._test_xml_slicing, 'Test GXml slicing')
  171 + self.append(self._test_elements_access, 'Test GXmlElement parameter access')
  172 + self.append(self._test_elements_slicing, 'Test GXmlElement slicing')
  173 +
60 174 # Return
61 175 return
... ...
test/test_support.py
... ... @@ -50,6 +50,69 @@ def _container_access_index(testsuite, container):
50 50 # Check access from end
51 51 testsuite.test_value(container[-2].name(), '8')
52 52  
  53 + # Clone first element
  54 + #element = container[0].copy()
  55 +
  56 + # Check setting by index from start
  57 + #element.name('98')
  58 + #container[3] = element
  59 + #self.test_value(container[3].name(), '98')
  60 +
  61 + # Check setting by index from end
  62 + #element.name('99')
  63 + #container[-2] = element
  64 + #self.test_value(container[-2].name(), '99')
  65 +
  66 + # Return
  67 + return
  68 +
  69 +
  70 +# ===================================== #
  71 +# Test energy container access by index #
  72 +# ===================================== #
  73 +def _energy_container_access_index(testsuite, container):
  74 + """
  75 + Test energy container access by index
  76 +
  77 + Parameters
  78 + ----------
  79 + testsuite : `~gammalib.GPythonTestSuite`
  80 + Test suite class
  81 + container : `~gammalib.GContainer`
  82 + Container class
  83 + """
  84 + # Loop over all elements using the container iterator and count the number
  85 + # of iterations
  86 + niter = 0
  87 + reference = 0.0
  88 + for element in container:
  89 + testsuite.test_value(element.energy().MeV(), reference)
  90 + niter += 1
  91 + reference += 1.0
  92 +
  93 + # Check that looping was successful
  94 + testsuite.test_value(container.size(), 10, 'Check container size')
  95 + testsuite.test_value(niter, 10, 'Check container iterator')
  96 +
  97 + # Test access from start
  98 + testsuite.test_value(container[3].energy().MeV(), 3.0)
  99 +
  100 + # Check access from end
  101 + testsuite.test_value(container[-2].energy().MeV(), 8.0)
  102 +
  103 + # Clone first element
  104 + element = container[0].copy()
  105 +
  106 + # Check setting by index from start
  107 + element.energy().MeV(98.0)
  108 + container[3] = element
  109 + testsuite.test_value(container[3].energy().MeV(), 98.0)
  110 +
  111 + # Check setting setting by index from end
  112 + element.energy().MeV(99.0)
  113 + container[-2] = element
  114 + testsuite.test_value(container[-2].energy().MeV(), 99.0)
  115 +
53 116 # Return
54 117 return
55 118  
... ... @@ -112,3 +175,63 @@ def _container_slicing(testsuite, container):
112 175  
113 176 # Return
114 177 return
  178 +
  179 +
  180 +# ============================= #
  181 +# Test energy container slicing #
  182 +# ============================= #
  183 +def _energy_container_slicing(testsuite, container):
  184 + """
  185 + Test energy container slicing
  186 +
  187 + Parameters
  188 + ----------
  189 + testsuite : `~gammalib.GPythonTestSuite`
  190 + Test suite class
  191 + container : `~gammalib.GContainer`
  192 + Container class
  193 + """
  194 + # Test container[start:end]
  195 + testsuite.test_value(len(container[3:5]), 2)
  196 + testsuite.test_value(container[3:5][0].energy().MeV(), 3.0)
  197 + testsuite.test_value(container[3:5][1].energy().MeV(), 4.0)
  198 +
  199 + # Test container[start:]
  200 + testsuite.test_value(len(container[7:]), 3)
  201 + testsuite.test_value(container[7:][0].energy().MeV(), 7.0)
  202 + testsuite.test_value(container[7:][1].energy().MeV(), 8.0)
  203 + testsuite.test_value(container[7:][2].energy().MeV(), 9.0)
  204 +
  205 + # Test container[:end]
  206 + testsuite.test_value(len(container[:2]), 2)
  207 + testsuite.test_value(container[:2][0].energy().MeV(), 0.0)
  208 + testsuite.test_value(container[:2][1].energy().MeV(), 1.0)
  209 +
  210 + # Test container[:]
  211 + testsuite.test_value(len(container[:]), 10)
  212 + for i in range(10):
  213 + testsuite.test_value(container[:][i].energy().MeV(), float(i))
  214 +
  215 + # Test container[start:end:step]
  216 + testsuite.test_value(len(container[3:7:2]), 2)
  217 + testsuite.test_value(container[3:7:2][0].energy().MeV(), 3.0)
  218 + testsuite.test_value(container[3:7:2][1].energy().MeV(), 5.0)
  219 +
  220 + # Test container[start:end:step]
  221 + testsuite.test_value(len(container[6:3:-2]), 2)
  222 + testsuite.test_value(container[6:3:-2][0].energy().MeV(), 6.0)
  223 + testsuite.test_value(container[6:3:-2][1].energy().MeV(), 4.0)
  224 +
  225 + # Test container[-start:]
  226 + testsuite.test_value(len(container[-2:]), 2)
  227 + testsuite.test_value(container[-2:][0].energy().MeV(), 8.0)
  228 + testsuite.test_value(container[-2:][1].energy().MeV(), 9.0)
  229 +
  230 + # Test container[:-end]
  231 + testsuite.test_value(len(container[:-7]), 3)
  232 + testsuite.test_value(container[:-7][0].energy().MeV(), 0.0)
  233 + testsuite.test_value(container[:-7][1].energy().MeV(), 1.0)
  234 + testsuite.test_value(container[:-7][2].energy().MeV(), 2.0)
  235 +
  236 + # Return
  237 + return
... ...