Feature #2128
Implement slicing in the Python interface of container classes
Status: | Closed | Start date: | 06/21/2017 | |
---|---|---|---|---|
Priority: | Normal | Due date: | ||
Assigned To: | Knödlseder Jürgen | % Done: | 100% | |
Category: | - | |||
Target version: | 1.4.0 | |||
Duration: |
Description
The following should work:
>>> import gammalib >>> obs=gammalib.GObservations('obs.xml') >>> print(obs[0:1])
This apparently needs a special version of the
__getitem__
method that takes a PyObject
as argument (see https://stackoverflow.com/questions/23206796/how-to-get-python-slicing-to-work-with-my-c-array-class-using-swig):%extend Array1D { Array1D* __getitem__(PyObject *param) { if (PySlice_Check(param)) { /* Py_ssize_t might be needed here instead of ints */ int len = 0, start = 0, stop = 0, step = 0, slicelength = 0; len = this->size(); /* Or however you get the size of a vector */ PySlice_GetIndicesEx((PySliceObject*)param, len, &start, &stop, &step, &slicelength); /* Here do stuff in order to return an Array1D that is the proper slice given the start/stop/step defined above */ } /* Unexpected parameter, probably should throw an exception here */ } }
Recurrence
No recurrence.
Related issues
History
#1 Updated by Knödlseder Jürgen over 7 years ago
Here the code that allows slicing of the GObservations
container and that also allows to return elements from the back of the container:
GObservation* __getitem__(const int& index) {
if (index >= 0 && index < self->size()) { // counting from start
return (*self)[index];
}
else if (index < 0 && self->size()+index >= 0) { // counting from end
return (*self)[self->size()+index];
}
else {
throw GException::out_of_range("__getitem__(int)", index, self->size());
}
}
GObservations* __getitem__(PyObject *param) {
if (PySlice_Check(param)) {
Py_ssize_t start = 0;
Py_ssize_t stop = 0;
Py_ssize_t step = 0;
Py_ssize_t len = self->size();
if (PySlice_GetIndices((PySliceObject*)param, len, &start, &stop, &step) == 0) {
GObservations* obs = new GObservations;
if (step > 0) {
for (int i = (int)start; i < (int)stop; i += (int)step) {
obs->append(*(*self)[i]);
}
}
else {
for (int i = (int)start; i > (int)stop; i += (int)step) {
obs->append(*(*self)[i]);
}
}
return obs;
}
else {
throw GException::invalid_argument("__getitem__(PyObject)","Invalid slice indices");
}
}
else {
throw GException::invalid_argument("__getitem__(PyObject)","");
}
}
#2 Updated by Knödlseder Jürgen over 7 years ago
- Status changed from New to In Progress
- Assigned To set to Knödlseder Jürgen
- % Done changed from 0 to 10
Implemented slicing for
GObservations
container. Missing classes are:
GApplicationPars
GEnergies
GModels
GOptimizerPars
GPhotons
GSkyRegions
GTimes
GFits
GFitsHeader
GFitsTable
GGti
GNodeArray
GPhases
GXml
GXmlNode
GCTAEventList
GLATEventList
#3 Updated by Knödlseder Jürgen over 7 years ago
- % Done changed from 10 to 60
Here the progress I made:
GApplicationPars.hpp done GEbounds.hpp done (no [] operator) GEnergies.hpp done GGti.hpp done (no [] operator) GObservations.hpp done GPhases.hpp done (no [] operator) GPhotons.hpp done GTimes.hpp done GModels.hpp done GNodeArray.hpp done GSkyRegions.hpp done GOptimizerPars.hpp GFits.hpp GFitsHeader.hpp GXml.hpp GXmlNode.hpp GTestSuites.hppUnit tests are added for all classes that are
done
.#4 Updated by Knödlseder Jürgen over 7 years ago
- Status changed from In Progress to Closed
- % Done changed from 60 to 100
Now have done all:
GApplicationPars.hpp done GEbounds.hpp done (no [] operator) GEnergies.hpp done GGti.hpp done (no [] operator) GObservations.hpp done GPhases.hpp done (no [] operator) GPhotons.hpp done GTimes.hpp done GModels.hpp done GNodeArray.hpp done GSkyRegions.hpp done GOptimizerPars.hpp done (but may lead to memory leak) GXml.hpp done GXmlNode.hpp done GTestSuites.hpp done GFits.hpp done GFitsHeader.hpp done GCTAEventList done GLATEventList done
Merged into
devel
.#5 Updated by Knödlseder Jürgen over 7 years ago
- Related to Action #1582: Add Python unit tests for all iterators added