Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 30 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import tempfile
import shutil
import subprocess as subp
from multiprocessing.pool import ThreadPool


compile_flags = {
Expand All @@ -20,8 +21,17 @@
}


# override class method to inject platform-specific compiler flags
def patched_compile(self, sources, **kwargs):
# override class method to inject platform-specific compiler flags, build in parallel and
# skip already compiled object files if they are newer than the source files
def patched_compile(self, sources, output_dir=None, macros=None,
include_dirs=None, debug=0, extra_preargs=None,
extra_postargs=None, depends=None):

macros, objects, extra_postargs, pp_opts, build = \
self._setup_compile(output_dir, macros, include_dirs, sources,
depends, extra_postargs)
cc_args = self._get_cc_args(pp_opts, debug, extra_preargs)

if not hasattr(self, "my_extra_flags"):
self.my_extra_flags = []
cmd = self.compiler[0]
Expand All @@ -38,8 +48,22 @@ def patched_compile(self, sources, **kwargs):
self.my_extra_flags.append(flag)
finally:
shutil.rmtree(tmpdir)
kwargs['extra_preargs'] = kwargs.get('extra_preargs', []) + self.my_extra_flags
return self.original_compile(sources, **kwargs)

cc_args += self.my_extra_flags

jobs = []
for obj in objects:
try:
src, ext = build[obj]
except KeyError:
continue
if not os.path.exists(obj) or os.stat(obj).st_mtime < os.stat(src).st_mtime:
jobs.append((obj, src))

p = ThreadPool(4)
p.map(lambda args: self._compile(args[0], args[1], ext, cc_args, extra_postargs, pp_opts), jobs)

return objects

import distutils.ccompiler
distutils.ccompiler.CCompiler.original_compile = distutils.ccompiler.CCompiler.compile
Expand Down Expand Up @@ -106,13 +130,13 @@ def get_description():
},
ext_modules=[
Extension('pyhepmc_ng._bindings',
['src/bindings.cpp']
['src/bindings.cpp', 'src/io.cpp']
+ glob.glob('extern/HepMC3/src/*.cc')
+ glob.glob('extern/HepMC3/src/Search/*.cc'),
include_dirs=[
'src',
'extern/HepMC3/include',
'extern/pybind11/include',
'src',
],
language='c++')
],
Expand Down
101 changes: 7 additions & 94 deletions src/bindings.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include <pybind11/pybind11.h>
#include <pybind11/operators.h>
#include <pybind11/stl.h>
#include "pybind.h"

#include "HepMC3/FourVector.h"
#include "HepMC3/GenHeavyIon.h"
#include "HepMC3/GenPdfInfo.h"
Expand All @@ -11,10 +10,8 @@
#include "HepMC3/GenVertex.h"
#include "HepMC3/Units.h"
#include "HepMC3/Print.h"
#include "HepMC3/WriterAscii.h"
#include "HepMC3/ReaderAscii.h"
#include "HepMC3/ReaderAsciiHepMC2.h"
#include "HepMC3/HEPEVT_Wrapper.h"

#include <memory>
#include <vector>
#include <algorithm>
Expand All @@ -27,6 +24,8 @@
#include "hepevt_wrapper.h"
// #include "GzReaderAscii.h"

void register_io(py::module& m);

template <class Iterator, class Streamer>
std::ostream& ostream_range(std::ostream& os,
Iterator begin, Iterator end, Streamer streamer,
Expand Down Expand Up @@ -279,17 +278,6 @@ inline std::ostream& repr(std::ostream& os, const HepMC3::GenEvent& x) {
}
} // namespace HepMC3

namespace py = pybind11;
using namespace py::literals;

#define FUNC(name) m.def(#name, name)
#define PROP_RO(name, cls) .def_property_readonly(#name, &cls::name)
#define PROP_RO_OL(name, cls, rval) .def_property_readonly(#name, (rval (cls::*)() const) &cls::name)
#define PROP(name, cls) .def_property(#name, &cls::name, &cls::set_##name)
#define PROP_OL(name, cls, rval) .def_property(#name, (rval (cls::*)() const) &cls::name, &cls::set_##name)
#define METH(name, cls) .def(#name, &cls::name)
#define METH_OL(name, cls, rval, args) .def(#name, (rval (cls::*)(args)) &cls::name)

PYBIND11_MODULE(_bindings, m) {
using namespace HepMC3;

Expand Down Expand Up @@ -631,83 +619,6 @@ PYBIND11_MODULE(_bindings, m) {
.def_property_readonly_static("max_size", [](py::object){ return NMXHEP; } )
;

// this class is here to simplify unit testing of Reader- and WriterAscii
py::class_<std::stringstream>(m, "stringstream")
.def(py::init<>())
.def(py::init<std::string>())
.def("__str__", (std::string (std::stringstream::*)() const) &std::stringstream::str)
METH(flush, std::stringstream)
METH(write, std::stringstream)
METH(read, std::stringstream)
;

py::class_<ReaderAscii>(m, "ReaderAscii")
.def(py::init<const std::string>(), "filename"_a)
.def(py::init<std::stringstream&>())
METH(read_event, ReaderAscii)
METH(failed, ReaderAscii)
METH(close, ReaderAscii)
.def("read", [](ReaderAscii& self) {
py::object obj = py::cast(GenEvent());
bool ok = self.read_event(py::cast<GenEvent&>(obj));
if (!ok) {
PyErr_SetString(PyExc_IOError, "error reading event");
throw py::error_already_set();
}
return obj;
})
// support contextmanager protocoll
.def("__enter__", [](py::object self) { return self; })
.def("__exit__", [](ReaderAscii& self, py::object type, py::object value, py::object tb) {
self.close();
return false;
})
;

py::class_<ReaderAsciiHepMC2>(m, "ReaderAsciiHepMC2")
.def(py::init<const std::string>(), "filename"_a)
METH(read_event, ReaderAsciiHepMC2)
METH(failed, ReaderAsciiHepMC2)
METH(close, ReaderAsciiHepMC2)
.def("read", [](ReaderAsciiHepMC2& self) {
py::object obj = py::cast(GenEvent());
bool ok = self.read_event(py::cast<GenEvent&>(obj));
if (!ok) {
PyErr_SetString(PyExc_IOError, "error reading event");
throw py::error_already_set();
}
return obj;
})
// support contextmanager protocoll
.def("__enter__", [](py::object self) { return self; })
.def("__exit__", [](ReaderAsciiHepMC2& self, py::object type, py::object value, py::object tb) {
self.close();
return false;
})
;

py::class_<WriterAscii>(m, "WriterAscii")
.def(py::init<const std::string&, GenRunInfoPtr>(),
"filename"_a, "run"_a = nullptr)
.def(py::init<std::stringstream&, GenRunInfoPtr>(),
"ostringstream"_a, "run"_a = nullptr,
py::keep_alive<1, 2>())
METH(write_event, WriterAscii)
METH(write_run_info, WriterAscii)
.def("write", [](WriterAscii& self, const GenEvent& evt) {
self.write_event(evt);
})
METH(failed, WriterAscii)
METH(close, WriterAscii)
PROP(precision, WriterAscii)
// support contextmanager protocoll
.def("__enter__", [](py::object self) { return self; })
.def("__exit__", [](WriterAscii& self, py::object type, py::object value, py::object tb) {
self.close();
return false;
})
;

m.def("fill_genevent_from_hepevt", fill_genevent_from_hepevt<double>,
"evt"_a, "event_number"_a, "p"_a, "m"_a, "v"_a, "pid"_a, "parents"_a,
"children"_a, "particle_status"_a, "vertex_status"_a,
Expand All @@ -724,4 +635,6 @@ PYBIND11_MODULE(_bindings, m) {
HepMC3::Print::listing(os, event, precision);
return os.str();
});

register_io(m);
}
131 changes: 131 additions & 0 deletions src/io.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#include "pybind.h"

#include "HepMC3/GenRunInfo.h"
#include "HepMC3/WriterAscii.h"
#include "HepMC3/WriterAsciiHepMC2.h"
#include "HepMC3/WriterHEPEVT.h"
#include "HepMC3/ReaderAscii.h"
#include "HepMC3/ReaderAsciiHepMC2.h"
#include "HepMC3/ReaderLHEF.h"
#include "HepMC3/ReaderHEPEVT.h"

#ifdef HEPMC3_ROOTIO
#include "HepMC3/ReaderRootTree.h"
#include "HepMC3/ReaderRoot.h"
#endif

#include <string>
#include <sstream>
#include <memory>

using namespace HepMC3;

using GenRunInfoPtr = std::shared_ptr<GenRunInfo>;
using ReaderAsciiPtr = std::shared_ptr<ReaderAscii>;
using ReaderAsciiHepMC2Ptr = std::shared_ptr<ReaderAsciiHepMC2>;
using ReaderLHEFPtr = std::shared_ptr<ReaderLHEF>;
using ReaderHEPEVTPtr = std::shared_ptr<ReaderHEPEVT>;

#ifdef HEPMC3_ROOTIO
using ReaderRootTreePtr = std::shared_ptr<ReaderRootTree>;
using ReaderRootPtr = std::shared_ptr<ReaderRoot>;
#endif

void register_io(py::module& m) {

// this class is here to simplify unit testing of Readers and Writers
py::class_<std::stringstream>(m, "stringstream")
.def(py::init<>())
.def(py::init<std::string>())
.def("__str__", (std::string (std::stringstream::*)() const) &std::stringstream::str)
METH(flush, std::stringstream)
METH(write, std::stringstream)
METH(read, std::stringstream)
;

py::class_<ReaderAscii, ReaderAsciiPtr>(m, "ReaderAscii")
.def(py::init<const std::string>(), "filename"_a)
.def(py::init<std::stringstream&>())
METH(read_event, ReaderAscii)
METH(failed, ReaderAscii)
METH(close, ReaderAscii)
;

py::class_<ReaderAsciiHepMC2, ReaderAsciiHepMC2Ptr>(m, "ReaderAsciiHepMC2")
.def(py::init<const std::string>(), "filename"_a)
.def(py::init<std::stringstream&>())
METH(read_event, ReaderAsciiHepMC2)
METH(failed, ReaderAsciiHepMC2)
METH(close, ReaderAsciiHepMC2)
;

py::class_<ReaderLHEF, ReaderLHEFPtr>(m, "ReaderLHEF")
.def(py::init<const std::string>(), "filename"_a)
//This will be enabled a bit later: .def(py::init<std::stringstream&>())
METH(read_event, ReaderLHEF)
METH(failed, ReaderLHEF)
METH(close, ReaderLHEF)
;

py::class_<ReaderHEPEVT, ReaderHEPEVTPtr>(m, "ReaderHEPEVT")
.def(py::init<const std::string>(), "filename"_a)
.def(py::init<std::stringstream&>())
.def("read_event", (bool (ReaderHEPEVT::*)(GenEvent&)) &ReaderHEPEVT::read_event)
.def("read_event", (bool (ReaderHEPEVT::*)(GenEvent&, bool)) &ReaderHEPEVT::read_event)
METH(failed, ReaderHEPEVT)
METH(close, ReaderHEPEVT)
;

py::class_<WriterAscii>(m, "WriterAscii")
.def(py::init<const std::string&, GenRunInfoPtr>(),
"filename"_a, "run"_a = nullptr)
.def(py::init<std::stringstream&, GenRunInfoPtr>(),
"ostringstream"_a, "run"_a = nullptr,
py::keep_alive<1, 2>())
METH(write_event, WriterAscii)
METH(write_run_info, WriterAscii)
METH(failed, WriterAscii)
METH(close, WriterAscii)
PROP(precision, WriterAscii)
;

py::class_<WriterAsciiHepMC2>(m, "WriterAsciiHepMC2")
.def(py::init<const std::string&, GenRunInfoPtr>(),
"filename"_a, "run"_a = nullptr)
.def(py::init<std::stringstream&, GenRunInfoPtr>(),
"ostringstream"_a, "run"_a = nullptr,
py::keep_alive<1, 2>())
METH(write_event, WriterAsciiHepMC2)
METH(write_run_info, WriterAsciiHepMC2)
METH(failed, WriterAsciiHepMC2)
METH(close, WriterAsciiHepMC2)
PROP(precision, WriterAsciiHepMC2)
;

py::class_<WriterHEPEVT>(m, "WriterHEPEVT")
.def(py::init<const std::string&>(),"filename"_a)
METH(write_event, WriterHEPEVT)
METH(failed, WriterHEPEVT)
METH(close, WriterHEPEVT)
;

#ifdef HEPMC3_ROOTIO

py::class_<ReaderRootTree, ReaderRootTreePtr>(m, "ReaderRootTree")
.def(py::init<const std::string>(), "filename"_a)
.def(py::init<const std::string, const std::string, const std::string>(), "filename"_a,"treename"_a,"branchname"_a)
METH(read_event, ReaderRootTree)
METH(failed, ReaderRootTree)
METH(close, ReaderRootTree)
;

py::class_<ReaderRoot, ReaderRootPtr>(m, "ReaderRoot")
.def(py::init<const std::string>(), "filename"_a)
METH(read_event, ReaderRoot)
METH(failed, ReaderRoot)
METH(close, ReaderRoot)
;

#endif

}
19 changes: 19 additions & 0 deletions src/pybind.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef PYHEPMC_PYBIND_HEADER
#define PYHEPMC_PYBIND_HEADER

#include <pybind11/pybind11.h>
#include <pybind11/operators.h>
#include <pybind11/stl.h>

namespace py = pybind11;
using namespace py::literals;

#define FUNC(name) m.def(#name, name)
#define PROP_RO(name, cls) .def_property_readonly(#name, &cls::name)
#define PROP_RO_OL(name, cls, rval) .def_property_readonly(#name, (rval (cls::*)() const) &cls::name)
#define PROP(name, cls) .def_property(#name, &cls::name, &cls::set_##name)
#define PROP_OL(name, cls, rval) .def_property(#name, (rval (cls::*)() const) &cls::name, &cls::set_##name)
#define METH(name, cls) .def(#name, &cls::name)
#define METH_OL(name, cls, rval, args) .def(#name, (rval (cls::*)(args)) &cls::name)

#endif
Loading