Skip to content

Commit

Permalink
Merge branch 'section_load'
Browse files Browse the repository at this point in the history
  • Loading branch information
Alessandro Bacchini committed Jun 11, 2015
2 parents 1b02d4e + 8e487b5 commit e224c4e
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 24 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
data/*
build/*
*.user
5 changes: 5 additions & 0 deletions Changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
0.5.0
- Fixed bugs in `erg::Reader::read()` function
- Add ability to read only a portion of a quantity from both C++ and Python
- Improved pyerg.read() function: now it create a erg.Reader Python object

0.4.1
- Improved documentation

Expand Down
49 changes: 35 additions & 14 deletions pyerg/pyerg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,21 @@ static size_t indexFromPyObject(erg::Reader* parser, PyObject* arg)

PyFUNC py_read(PyObject* self, PyObject* filename)
{
PyObject* args = PyTuple_New(0);
Reader* pyReader = (Reader*)PyObject_CallObject((PyObject*)&pyerg_ReaderType, args);
Py_DecRef(args);

PyObject* ret = Parser_open(pyReader, filename);
if(ret==nullptr)
return nullptr;

Py_DecRef(ret);

PyObject* data = Parser_readAll(pyReader);
Py_DecRef((PyObject*)pyReader);
return data;

/*
// self is unused.
if(PyString_Check(filename)==false) {
PyErr_SetString(PyExc_NameError, "The input arguments must be a string");
Expand Down Expand Up @@ -174,6 +189,7 @@ PyFUNC py_read(PyObject* self, PyObject* filename)
}
return map;
*/
}

PyFUNC py_can_read(PyObject* self, PyObject* filename)
Expand All @@ -190,7 +206,6 @@ PyFUNC py_can_read(PyObject* self, PyObject* filename)

// Release the GIL because the open function is an I/O
// operation that read a file.
PyThreadState *_save; // The GIL save state
Py_BEGIN_ALLOW_THREADS;
try {
// Try to read the file: if the file is valid,
Expand Down Expand Up @@ -229,7 +244,7 @@ PyFUNC Parser_new(PyTypeObject* type, PyObject *args, PyObject *kwds)

extern "C" int Parser_init(Reader* self, PyObject *args, PyObject *kwds)
{
if(PyTuple_Size(args)==1) {
if(args!=nullptr && PyTuple_Size(args)==1) {
// Initialize with a filename: open the file
PyObject* filename = PyTuple_GetItem(args, 0);

Expand Down Expand Up @@ -340,35 +355,42 @@ PyFUNC Parser_readAll(Reader* self)
return map;
}

PyFUNC Parser_read(Reader* self, PyObject* arg)
PyFUNC Parser_read(Reader* self, PyObject* args, PyObject* keywds)
{
size_t qindex = indexFromPyObject(self->parser, arg);
PyObject* objIndex = nullptr;
size_t from = 0;
size_t count = self->parser->records();
static char* kwlist[] = {"name", "start", "count", NULL};
if(!PyArg_ParseTupleAndKeywords(args, keywds, "O|ii", kwlist, &objIndex, &from, &count))
return nullptr;

const size_t qindex = indexFromPyObject(self->parser, objIndex);
if(PyErr_Occurred()!=nullptr)
return nullptr;

// Numpy array creation
npy_intp rows = self->parser->records();
npy_intp rows = count;
int type = ergType2npyType(self->parser->quantityType(qindex));
PyObject* array = PyArray_SimpleNew(1, &rows, type);
uint8_t* outData = (uint8_t*)PyArray_DATA((PyArrayObject*)array);
npy_intp size = PyArray_NBYTES((PyArrayObject*)array);
PyArrayObject* array = (PyArrayObject*)PyArray_SimpleNew(1, &rows, type);
uint8_t* outData = (uint8_t*)PyArray_DATA(array);
const npy_intp size = PyArray_NBYTES(array);

std::string error;
Py_BEGIN_ALLOW_THREADS;
try {
self->parser->read(qindex, outData, size);
self->parser->read(qindex, from, count, outData, size);
} catch(std::runtime_error e) {
error = e.what();
}
Py_END_ALLOW_THREADS;

if(error.length()>0) {
Py_DecRef(array);
Py_DecRef((PyObject*)array);
PyErr_SetString(PyExc_NameError, error.c_str());
return nullptr;
}

return array;
return (PyObject*)array;
}

PyFUNC Parser_quantitySize(Reader* self, PyObject* arg)
Expand Down Expand Up @@ -492,12 +514,11 @@ PyMODINIT_FUNC initpyerg(void)
if (PyType_Ready(&pyerg_ReaderType) < 0)
return;

pyergModule = Py_InitModule3("pyerg", pyerg_methods,
"Module for loading CarMaker .erg files.");
pyergModule = Py_InitModule3("pyerg", pyerg_methods, "Module for loading CarMaker .erg files.");

Py_INCREF(&pyerg_ReaderType);
PyModule_AddObject(pyergModule, "Reader", (PyObject*)&pyerg_ReaderType);
PyModule_AddStringConstant(pyergModule, "__version__", "0.4.1");
PyModule_AddStringConstant(pyergModule, "__version__", "0.5.0");

import_array();
}
4 changes: 2 additions & 2 deletions pyerg/pyerg.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ PyFUNC Parser_records(Reader* self);
PyFUNC Parser_recordSize(Reader* self);
PyFUNC Parser_numQuanities(Reader* self);
PyFUNC Parser_readAll(Reader* self);
PyFUNC Parser_read(Reader* self, PyObject* arg);
PyFUNC Parser_read(Reader* self, PyObject *args, PyObject *keywds);
PyFUNC Parser_quantitySize(Reader* self, PyObject* arg);
PyFUNC Parser_quantityName(Reader* self, PyObject* arg);
PyFUNC Parser_quantityType(Reader* self, PyObject* arg);
Expand Down Expand Up @@ -92,7 +92,7 @@ static PyMethodDef parser_methods[] = {
PYERG_PARSER_READALL_DOC
},
{
"read", (PyCFunction)Parser_read, METH_O,
"read", (PyCFunction)Parser_read, METH_VARARGS|METH_KEYWORDS,
PYERG_PARSER_READ_DOC
},
{
Expand Down
16 changes: 9 additions & 7 deletions pyerg/pyerg_docstrings.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
" Dict of numpy ndarray with the datasets in the file. The names of the datasets are " \
"the keys of the Dict.\n" \
"Raises:\n" \
" Exception if the file can't be read or is not an ERG file."
" Exception if the file can't be read or is not an ERG file."

#define PYERG_CAN_READ_DOC \
"ok = can_read(filename)\n" \
Expand All @@ -81,7 +81,7 @@
"Args:\n" \
" filename: Pathname of the erg file.\n" \
"Raises:\n" \
" Exception if the file can't be read or is not an ERG file."
" Exception if the file can't be read or is not an ERG file."

#define PYERG_PARSER_RECORDS_DOC \
"Number of records/rows in th `.erg` file.\n\n" \
Expand All @@ -98,20 +98,22 @@
"The number of quantities is the number of columns that contains data in each record:\n" \
"the padding columns are ignored.\n\n" \
"Returns:\n" \
" The number of quantities.\n"
" The number of quantities.\n"

#define PYERG_PARSER_READALL_DOC \
"Read all the datasets from the file.\n\n" \
"Returns:\n" \
" Dict with all the datasets as numpy ndarray with the quantity names as keys." \
"See:\n" \
" quantitySize() to know the size of each dataset to known in advice the quantity of memory " \
"that will be used."
"that will be used."

#define PYERG_PARSER_READ_DOC \
"Read a single dataset from the file.\n\n" \
"Args:\n" \
" qindex: Index or name of the dataset to read.\n" \
" name: Index or name of the dataset to read.\n" \
" start: Index of the row from which to start reading.\n" \
" count: Number of rows to read.\n" \
"Returns:\n" \
" Numpy ndarray with the data.\n" \
"Raises:\n" \
Expand Down Expand Up @@ -170,14 +172,14 @@
#define PYERG_PARSER_ISFORTRAN_DOC \
"Version of th ERG file.\n\n" \
"Returns:\n" \
" True if the format of the file is Fortran binary (`FORTRAN_Binary_Data`)."
" True if the format of the file is Fortran binary (`FORTRAN_Binary_Data`)."

#define PYERG_PARSER_HAS_DOC \
"Test if the quantity is present in the file.\n" \
"Args:\n" \
" name: Name of the quantity.\n" \
"Returns:\n" \
" True if the quantity is present inside the file, False otherwise."
" True if the quantity is present inside the file, False otherwise."

#define PYERG_PARSER_CLOSE_DOC \
"Close the current file and clear the data." \
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
language='c++')

setup(name='pyerg',
version='0.4',
version='0.5.0',
description='Python C extension for reading IPG CarMaker ERG files.',
author='Alessandro Bacchini',
author_email='alessandro.bacchini@henesis.eu',
Expand Down
4 changes: 4 additions & 0 deletions test/test_pyerg.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@ def test_Read(self):
t = parser.read('Data_8')
self.assertEquals(len(t), parser.records())

t2 = parser.read('Data_8', start=10, count=90)
self.assertEquals(len(t2), 90)
self.assertTrue(np.all(t2 == t[10:100]))


class TestPyerg(unittest.TestCase):

Expand Down

0 comments on commit e224c4e

Please sign in to comment.