Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Hierarchies #1432

Open
wants to merge 26 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c3522f0
JSON backend: Fail when trying to open non-existing groups
franzpoeschel May 30, 2023
506363f
Insert CustomHierarchy class to Iteration
franzpoeschel Apr 12, 2023
a57bf26
Help older compilers deal with this
franzpoeschel May 25, 2023
56363a5
Add vector variants of meshes/particlesPath
franzpoeschel Jul 28, 2023
83d2e12
Move meshes and particles over to CustomHierarchies class
franzpoeschel Jul 28, 2023
0ee50f4
Move dirtyRecursive to CustomHierarchy
franzpoeschel May 30, 2023
10b6b9e
Move Iteration reading logic to CustomHierarchy
franzpoeschel Jul 28, 2023
0b3bb43
Move Iteration flushing logic to CustomHierarchy class
franzpoeschel Jul 31, 2023
90cd659
Support for custom datasets
franzpoeschel Jul 31, 2023
b321772
Treat "meshes"/"particles" as normal subgroups
franzpoeschel Jul 31, 2023
9335e13
Regex-based list of meshes/particlesPaths
franzpoeschel Jul 31, 2023
1415e90
More extended testing
franzpoeschel Jul 31, 2023
6303b14
Fix Python bindings without adding new functionality yet
franzpoeschel Aug 1, 2023
9468600
Add simple Python bindings and an example
franzpoeschel Aug 1, 2023
1876759
Replace Regexes with Globbing
franzpoeschel Oct 13, 2023
01e59a7
Move .meshes and .particles back to Iteration class
franzpoeschel Oct 24, 2023
3849c74
Some fixes in read error handling
franzpoeschel Oct 26, 2023
4acd1f8
More symmetric design for container types
franzpoeschel Oct 26, 2023
0637683
Don't write unitSI in custom datasets
franzpoeschel Nov 13, 2023
a869c3d
Discouraged support for custom datasets inside the particlesPath
franzpoeschel Dec 21, 2023
8dbe1c2
Fix after rebase: dirtyRecursive
franzpoeschel Mar 26, 2024
a4512d7
Fixes to the dirty/dirtyRecursive logic
franzpoeschel May 24, 2024
59a4a1c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 7, 2024
583ec1b
Some cleanup in CustomHierarchies class
franzpoeschel Aug 14, 2024
317cc0f
Use polymorphism for meshes/particlesPath in Python
franzpoeschel Nov 6, 2024
1032573
Remove hasMeshes / hasParticles logic
franzpoeschel Nov 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add simple Python bindings and an example
  • Loading branch information
franzpoeschel committed Dec 17, 2024
commit 946860036223c27fdf3e95161ac8d6605d7f474b
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,7 @@ if(openPMD_HAVE_PYTHON)
src/binding/python/Attributable.cpp
src/binding/python/BaseRecordComponent.cpp
src/binding/python/ChunkInfo.cpp
src/binding/python/CustomHierarchy.cpp
src/binding/python/Dataset.cpp
src/binding/python/Datatype.cpp
src/binding/python/Error.cpp
Expand Down Expand Up @@ -721,6 +722,7 @@ set(openPMD_PYTHON_EXAMPLE_NAMES
11_particle_dataframe
12_span_write
13_write_dynamic_configuration
14_custom_hierarchy
)

if(openPMD_USE_INVASIVE_TESTS)
Expand Down
48 changes: 48 additions & 0 deletions examples/14_custom_hierarchy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import numpy as np
import openpmd_api as io


def main():
if "bp" in io.file_extensions:
filename = "../samples/custom_hierarchy.bp"
else:
filename = "../samples/custom_hierarchy.json"
s = io.Series(filename, io.Access.create)
it = s.write_iterations()[100]

# write openPMD part
temp = it.meshes["temperature"]
temp.axis_labels = ["x", "y"]
temp.unit_dimension = {io.Unit_Dimension.T: 1}
temp.position = [0.5, 0.5]
temp.grid_spacing = [1, 1]
temp.grid_global_offset = [0, 0]
temp.reset_dataset(io.Dataset(np.dtype("double"), [5, 5]))
temp[()] = np.zeros((5, 5))

# write NeXus part
nxentry = it["Scan"]
nxentry.set_attribute("NX_class", "NXentry")
nxentry.set_attribute("default", "data")

data = nxentry["data"]
data.set_attribute("NX_class", "NXdata")
data.set_attribute("signal", "counts")
data.set_attribute("axes", ["two_theta"])
data.set_attribute("two_theta_indices", [0])

counts = data.as_container_of_datasets()["counts"]
counts.set_attribute("units", "counts")
counts.set_attribute("long_name", "photodiode counts")
counts.reset_dataset(io.Dataset(np.dtype("int"), [15]))
counts[()] = np.zeros(15, dtype=np.dtype("int"))

two_theta = data.as_container_of_datasets()["two_theta"]
two_theta.set_attribute("units", "degrees")
two_theta.set_attribute("long_name", "two_theta (degrees)")
two_theta.reset_dataset(io.Dataset(np.dtype("double"), [15]))
two_theta[()] = np.zeros(15)


if __name__ == "__main__":
main()
3 changes: 3 additions & 0 deletions include/openPMD/binding/python/Common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/
#pragma once

#include "openPMD/CustomHierarchy.hpp"
#include "openPMD/Iteration.hpp"
#include "openPMD/Mesh.hpp"
#include "openPMD/ParticlePatches.hpp"
Expand Down Expand Up @@ -46,6 +47,7 @@ using PyPatchRecordComponentContainer = Container<PatchRecordComponent>;
using PyBaseRecordRecordComponent = BaseRecord<RecordComponent>;
using PyBaseRecordMeshRecordComponent = BaseRecord<MeshRecordComponent>;
using PyBaseRecordPatchRecordComponent = BaseRecord<PatchRecordComponent>;
using PyCustomHierarchyContainer = Container<CustomHierarchy>;
PYBIND11_MAKE_OPAQUE(PyIterationContainer)
PYBIND11_MAKE_OPAQUE(PyMeshContainer)
PYBIND11_MAKE_OPAQUE(PyPartContainer)
Expand All @@ -57,3 +59,4 @@ PYBIND11_MAKE_OPAQUE(PyMeshRecordComponentContainer)
PYBIND11_MAKE_OPAQUE(PyPatchRecordComponentContainer)
PYBIND11_MAKE_OPAQUE(PyBaseRecordRecordComponent)
PYBIND11_MAKE_OPAQUE(PyBaseRecordPatchRecordComponent)
PYBIND11_MAKE_OPAQUE(PyCustomHierarchyContainer)
71 changes: 71 additions & 0 deletions src/binding/python/Container.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* Copyright 2018-2021 Axel Huebl
*
* This file is part of openPMD-api.
*
* openPMD-api is free software: you can redistribute it and/or modify
* it under the terms of of either the GNU General Public License or
* the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* openPMD-api is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with openPMD-api.
* If not, see <http://www.gnu.org/licenses/>.
*
* The function `bind_container` is based on std_bind.h in pybind11
* Copyright (c) 2016 Sergey Lyskov and Wenzel Jakob
*
* BSD-style license, see pybind11 LICENSE file.
*/

#include <pybind11/pybind11.h>

#include "openPMD/Iteration.hpp"
#include "openPMD/Mesh.hpp"
#include "openPMD/ParticlePatches.hpp"
#include "openPMD/ParticleSpecies.hpp"
#include "openPMD/Record.hpp"
#include "openPMD/Series.hpp"
#include "openPMD/backend/BaseRecord.hpp"
#include "openPMD/backend/BaseRecordComponent.hpp"
#include "openPMD/backend/Container.hpp"
#include "openPMD/backend/MeshRecordComponent.hpp"
#include "openPMD/backend/PatchRecord.hpp"
#include "openPMD/backend/PatchRecordComponent.hpp"
#include "openPMD/binding/python/Container.hpp"

#include "openPMD/binding/python/Common.hpp"

void init_Container(py::module &m)
{
::detail::create_and_bind_container<PyIterationContainer, Attributable>(
m, "Iteration_Container");
::detail::create_and_bind_container<PyMeshContainer, Attributable>(
m, "Mesh_Container");
::detail::create_and_bind_container<PyPartContainer, Attributable>(
m, "Particle_Container");
::detail::create_and_bind_container<PyPatchContainer, Attributable>(
m, "Particle_Patches_Container");
::detail::create_and_bind_container<PyRecordContainer, Attributable>(
m, "Record_Container");
::detail::create_and_bind_container<PyPatchRecordContainer, Attributable>(
m, "Patch_Record_Container");
::detail::
create_and_bind_container<PyRecordComponentContainer, Attributable>(
m, "Record_Component_Container");
::detail::
create_and_bind_container<PyMeshRecordComponentContainer, Attributable>(
m, "Mesh_Record_Component_Container");
::detail::create_and_bind_container<
PyPatchRecordComponentContainer,
Attributable>(m, "Patch_Record_Component_Container");
::detail::
create_and_bind_container<PyCustomHierarchyContainer, Attributable>(
m, "Custom_Hierarchy_Container");
}
42 changes: 42 additions & 0 deletions src/binding/python/CustomHierarchy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@


#include "openPMD/CustomHierarchy.hpp"
#include "openPMD/ParticleSpecies.hpp"
#include "openPMD/RecordComponent.hpp"
#include "openPMD/backend/Attributable.hpp"
#include "openPMD/binding/python/Common.hpp"
#include "openPMD/binding/python/Container.H"
#include <pybind11/pybind11.h>

namespace py = pybind11;
using namespace openPMD;

void init_CustomHierarchy(py::module &m)
{
auto py_ch_cont = declare_container<PyCustomHierarchyContainer, Attributable>(m, "Container_CustomHierarchy");

py::class_<CustomHierarchy, Container<CustomHierarchy>, Attributable>(
m, "CustomHierarchy")
.def(
"as_container_of_datasets",
&CustomHierarchy::asContainerOf<RecordComponent>)
.def("as_container_of_meshes", &CustomHierarchy::asContainerOf<Mesh>)
.def(
"as_container_of_particles",
&CustomHierarchy::asContainerOf<ParticleSpecies>)

.def_readwrite(
"meshes",
&CustomHierarchy::meshes,
py::return_value_policy::copy,
// garbage collection: return value must be freed before Iteration
py::keep_alive<1, 0>())
.def_readwrite(
"particles",
&CustomHierarchy::particles,
py::return_value_policy::copy,
// garbage collection: return value must be freed before Iteration
py::keep_alive<1, 0>());

finalize_container<PyCustomHierarchyContainer>(py_ch_cont);
}
8 changes: 6 additions & 2 deletions src/binding/python/Iteration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "openPMD/Iteration.hpp"
#include "openPMD/CustomHierarchy.hpp"

#include "openPMD/backend/Attributable.hpp"
#include "openPMD/binding/python/Common.hpp"
Expand All @@ -40,8 +41,11 @@ void init_Iteration(py::module &m)
#define OPENPMD_AVOID_CLANG_FORMAT auto cl =
OPENPMD_AVOID_CLANG_FORMAT
#undef OPENPMD_AVOID_CLANG_FORMAT

py::class_<Iteration, Attributable>(m, "Iteration")
py::class_<
Iteration,
CustomHierarchy,
PyCustomHierarchyContainer,
Attributable>(m, "Iteration")
.def(py::init<Iteration const &>())

.def(
Expand Down
2 changes: 2 additions & 0 deletions src/binding/python/openPMD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ void init_Dataset(py::module &);
void init_Datatype(py::module &);
void init_Error(py::module &);
void init_Helper(py::module &);
void init_CustomHierarchy(py::module &);
void init_Iteration(py::module &);
void init_IterationEncoding(py::module &);
void init_Mesh(py::module &);
Expand Down Expand Up @@ -90,6 +91,7 @@ PYBIND11_MODULE(openpmd_api_cxx, m)
init_Datatype(m);
init_Dataset(m);

init_CustomHierarchy(m);
init_BaseRecordComponent(m);
init_RecordComponent(m);
init_MeshRecordComponent(m);
Expand Down