Skip to content

Commit

Permalink
Merge pull request #284 from ax3l/topic-pythonParticleRecord
Browse files Browse the repository at this point in the history
Python: Particle Record Components
  • Loading branch information
ax3l authored Jul 7, 2018
2 parents 0a29f35 + 71fdba0 commit 2bb8900
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 16 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ Features
- include internally shipped pybind11 v2.2.3 #281
- ADIOS1: enable serial API usage even if MPI is present #252 #254
- introduce detection and specification ``%0\d+T`` of iteration padding #270
- Python:

- add unit tests #249
- expose record components for particles #284

Bug Fixes
"""""""""
Expand All @@ -39,7 +43,7 @@ Other

- docs:

- improve "Install from source" section #274
- improve "Install from source" section #274 #285
- Spack python 3 install command #278


Expand Down
8 changes: 8 additions & 0 deletions include/openPMD/backend/BaseRecordComponent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ class BaseRecordComponent : public Attributable
friend
class BaseRecord;

template<
typename T,
typename T_key,
typename T_container
>
friend
class Container;

public:
virtual ~BaseRecordComponent()
{ }
Expand Down
3 changes: 3 additions & 0 deletions src/binding/python/BaseRecord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "openPMD/backend/BaseRecord.hpp"
#include "openPMD/backend/Container.hpp"
#include "openPMD/backend/MeshRecordComponent.hpp"
#include "openPMD/backend/BaseRecordComponent.hpp"

#include <string>

Expand All @@ -33,6 +34,8 @@ using namespace openPMD;

void init_BaseRecord(py::module &m) {
py::class_<BaseRecord< MeshRecordComponent >, Container< MeshRecordComponent > >(m, "Mesh_Base_Record");
py::class_<BaseRecord< BaseRecordComponent >, Container< BaseRecordComponent > >(m, "Particle_Base_Record");
py::class_<BaseRecord< RecordComponent >, Container< RecordComponent > >(m, "Base_Record");

py::enum_<UnitDimension>(m, "Unit_Dimension")
.value("L", UnitDimension::L)
Expand Down
15 changes: 14 additions & 1 deletion src/binding/python/Container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@
#include <pybind11/stl.h>

#include "openPMD/backend/Container.hpp"
#include "openPMD/backend/BaseRecord.hpp"
#include "openPMD/backend/MeshRecordComponent.hpp"
#include "openPMD/Iteration.hpp"
#include "openPMD/Mesh.hpp"
#include "openPMD/ParticleSpecies.hpp"
#include "openPMD/Record.hpp"
#include "openPMD/backend/MeshRecordComponent.hpp"

#include <string>
#include <memory>
Expand Down Expand Up @@ -202,12 +203,16 @@ using PyIterationContainer = Container<
using PyMeshContainer = Container< Mesh >;
using PyPartContainer = Container< ParticleSpecies >;
using PyRecordContainer = Container< Record >;
using PyRecordComponentContainer = Container< RecordComponent >;
using PyMeshRecordComponentContainer = Container< MeshRecordComponent >;
using PyBaseRecordComponentContainer = Container< BaseRecordComponent >;
PYBIND11_MAKE_OPAQUE(PyIterationContainer)
PYBIND11_MAKE_OPAQUE(PyMeshContainer)
PYBIND11_MAKE_OPAQUE(PyPartContainer)
PYBIND11_MAKE_OPAQUE(PyRecordContainer)
PYBIND11_MAKE_OPAQUE(PyRecordComponentContainer)
PYBIND11_MAKE_OPAQUE(PyMeshRecordComponentContainer)
PYBIND11_MAKE_OPAQUE(PyBaseRecordComponentContainer)

void init_Container( py::module & m ) {
detail::bind_container< PyIterationContainer >(
Expand All @@ -226,8 +231,16 @@ void init_Container( py::module & m ) {
m,
"Record_Container"
);
detail::bind_container< PyRecordComponentContainer >(
m,
"Record_Component_Container"
);
detail::bind_container< PyMeshRecordComponentContainer >(
m,
"Mesh_Record_Component_Container"
);
detail::bind_container< PyBaseRecordComponentContainer >(
m,
"Base_Record_Component_Container"
);
}
4 changes: 3 additions & 1 deletion src/binding/python/Record.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@
#include <pybind11/stl.h>

#include "openPMD/Record.hpp"
#include "openPMD/backend/BaseRecord.hpp"
#include "openPMD/RecordComponent.hpp"

namespace py = pybind11;
using namespace openPMD;


void init_Record(py::module &m) {
py::class_<Record>(m, "Record")
py::class_<Record, BaseRecord< RecordComponent > >(m, "Record")
.def(py::init<Record const &>())

.def("__repr__",
Expand Down
57 changes: 44 additions & 13 deletions test/python/unittest/API/APITest.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ def testData(self):
self.assertTrue(i in [100, 200, 300, 400, 500])

# Check type.
self.assertTrue(100 in series.iterations)
i = series.iterations[100]
self.assertTrue(400 in series.iterations)
i = series.iterations[400]
self.assertIsInstance(i, openPMD.Iteration)
with self.assertRaises(TypeError):
series.iterations[-1]
Expand All @@ -146,12 +146,38 @@ def testData(self):
# Get a particle species.
electrons = i.particles["electrons"]
self.assertIsInstance(electrons, openPMD.ParticleSpecies)
pos_y = electrons["position"]["y"]
w = electrons["weighting"][openPMD.Record_Component.SCALAR]

self.assertSequenceEqual(pos_y.shape, [270625, ])
self.assertSequenceEqual(w.shape, [270625, ])
if found_numpy:
self.assertEqual(pos_y.dtype, np.float64)
self.assertEqual(w.dtype, np.float64)
y_data = pos_y.load_chunk([200000, ], [10, ])
w_data = w.load_chunk([200000, ], [10, ])
series.flush()
self.assertSequenceEqual(y_data.shape, [10, ])
self.assertSequenceEqual(w_data.shape, [10, ])
if found_numpy:
self.assertEqual(y_data.dtype, np.float64)
self.assertEqual(w_data.dtype, np.float64)

np.testing.assert_allclose(
y_data,
[-9.60001131e-06, -8.80004967e-06, -8.00007455e-06,
-7.20008487e-06, -6.40007232e-06, -5.60002710e-06,
-4.79993871e-06, -3.99980648e-06, -3.19964406e-06,
-2.39947455e-06]
)
np.testing.assert_allclose(
w_data,
np.ones((10,)) * 1600000.
)

E_x = i.meshes["E"]["x"]
E_x = E["x"]
shape = E_x.shape

print("Field E.x has shape {0} and datatype {1}".format(
shape, E_x.dtype))
self.assertSequenceEqual(shape, [26, 26, 201])
if found_numpy:
self.assertEqual(E_x.dtype, np.float64)
Expand All @@ -164,16 +190,16 @@ def testData(self):
self.assertSequenceEqual(chunk_data.shape, extent)
if found_numpy:
self.assertEqual(chunk_data.dtype, np.float64)
np.testing.assert_almost_equal(
np.testing.assert_allclose(
chunk_data,
[
[
[-75874183.04159331],
[-75956606.50847568]
[6.26273197e7],
[2.70402498e8]
],
[
[-84234548.15893488],
[-48105850.2088511]
[-1.89238617e8],
[-1.66413019e8]
]
]
)
Expand Down Expand Up @@ -306,15 +332,20 @@ def testRecord(self):
self.assertRaises(TypeError, openPMD.Record)

# Get a record.
electrons = self.__series.iterations[100].particles['electrons']
position = electrons['position'] # ['x']
electrons = self.__series.iterations[400].particles['electrons']
position = electrons['position']
self.assertIsInstance(position, openPMD.Record)
x = position['x']
self.assertIsInstance(x, openPMD.Record_Component)

# Copy.
# copy_record = openPMD.Record(record)
# copy_record = openPMD.Record(position)
# copy_record_component = openPMD.Record(x)

# Check.
# self.assertIsInstance(copy_record, openPMD.Record)
# self.assertIsInstance(copy_record_component,
# openPMD.Record_Component)

def testRecord_Component(self):
""" Test openPMD.Record_Component. """
Expand Down

0 comments on commit 2bb8900

Please sign in to comment.