openPMD-api
 
Loading...
Searching...
No Matches
Pickle.hpp
1/* Copyright 2018-2025 Axel Huebl, Franz Poeschel
2 *
3 * This file is part of openPMD-api.
4 *
5 * openPMD-api is free software: you can redistribute it and/or modify
6 * it under the terms of of either the GNU General Public License or
7 * the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * openPMD-api is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License and the GNU Lesser General Public License
15 * for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * and the GNU Lesser General Public License along with openPMD-api.
19 * If not, see <http://www.gnu.org/licenses/>.
20 */
21#pragma once
22
23#include "openPMD/IO/Access.hpp"
24#include "openPMD/Series.hpp"
25#include "openPMD/auxiliary/StringManip.hpp"
26#include "openPMD/backend/Attributable.hpp"
27
28#include "Common.hpp"
29
30#include <exception>
31#include <string>
32#include <tuple>
33#include <vector>
34
35namespace openPMD
36{
45template <typename... T_Args, typename T_SeriesAccessor>
46inline void
47add_pickle(pybind11::class_<T_Args...> &cl, T_SeriesAccessor &&seriesAccessor)
48{
49 // helper: get first class in py::class_ - that's the type we pickle
50 using PickledClass =
51 typename std::tuple_element<0, std::tuple<T_Args...> >::type;
52
53 cl.def(
54 py::pickle(
55 // __getstate__
56 [](const PickledClass &a) {
57 // Return a tuple that fully encodes the state of the object
58 Attributable::MyPath const myPath = a.myPath();
59 return py::make_tuple(myPath.filePath(), myPath.group);
60 },
61
62 // __setstate__
63 [&seriesAccessor](py::tuple const &t) {
64 // our tuple has exactly two elements: filePath & group
65 if (t.size() != 2)
66 throw std::runtime_error("Invalid state!");
67
68 std::string const filename = t[0].cast<std::string>();
69 std::vector<std::string> const group =
70 t[1].cast<std::vector<std::string> >();
71
72 /*
73 * Cache the Series per thread.
74 */
75 thread_local std::optional<openPMD::Series> series;
76 bool re_initialize = [&]() {
77 try
78 {
79 return !series.has_value() ||
80 !series->operator bool() ||
81 auxiliary::replace_all(
82 series->myPath().filePath(), "\\", "/") !=
83 auxiliary::replace_all(filename, "\\", "/");
84 }
85 /*
86 * Better safe than sorry, if anything goes wrong because
87 * the Series is in a weird state, just reinitialize it.
88 */
89 catch (...)
90 {
91 return true;
92 }
93 }();
94 if (re_initialize)
95 {
96 /*
97 * Do NOT close the old Series, it might still be active in
98 * terms of handed-out handles.
99 */
100 series = std::make_optional<Series>(
101 filename,
102 Access::READ_ONLY,
103 "defer_iteration_parsing = true");
104 }
105
106 return seriesAccessor(*series, group);
107 }));
108}
109} // namespace openPMD
Public definitions of openPMD-api.
Definition Date.cpp:29
void add_pickle(pybind11::class_< T_Args... > &cl, T_SeriesAccessor &&seriesAccessor)
Helper to Pickle Attributable Classes.
Definition Pickle.hpp:47
String serialization to describe an Attributable.
Definition Attributable.hpp:367
std::string filePath() const
Reconstructs a path that can be passed to a Series constructor.
Definition Attributable.cpp:214
std::vector< std::string > group
e.g., .bp, .h5, .json, ...
Definition Attributable.hpp:379