12#include <nanobind/nanobind.h>
13#include <nanobind/ndarray.h>
14#include <nanobind/operators.h>
15#include <nanobind/stl/list.h>
16#include <nanobind/stl/string.h>
17#include <nanobind/stl/vector.h>
18#include <nanobind/stl/pair.h>
19#include <nanobind/stl/map.h>
24namespace nb = nanobind;
26using namespace nb::literals;
32 std::snprintf(buffer,
sizeof(buffer),
"0x%llx",
reinterpret_cast<unsigned long long>(&obj));
33 return std::string(buffer);
38 if (type_info ==
typeid(
int)) {
40 }
else if (type_info ==
typeid(
unsigned int)) {
42 }
else if (type_info ==
typeid(
short)) {
44 }
else if (type_info ==
typeid(
unsigned short)) {
46 }
else if (type_info ==
typeid(
char)) {
49 }
else if (type_info ==
typeid(
unsigned char)) {
51 }
else if (type_info ==
typeid(
float)) {
53 }
else if (type_info ==
typeid(
double)) {
55 }
else if (type_info ==
typeid(
long)) {
57 }
else if (type_info ==
typeid(
unsigned long)) {
59 }
else if (type_info ==
typeid(
bool)) {
63 return std::string(
"unknown ('") + type_info.name() +
"')";
68 if (nb::isinstance<nb::str>(value)) {
69 self.
setProperty(key, nb::cast<std::string>(value));
70 }
else if (nb::isinstance<nb::int_>(value)) {
72 }
else if (nb::isinstance<nb::float_>(value)) {
75 throw std::runtime_error(
"Unsupported property type. Must be str, int, or float.");
83 const std::type_info* type_info =
nullptr;
84 const nb::dlpack::dtype dtype = column.dtype();
85 switch ((nb::dlpack::dtype_code) dtype.code) {
86 case nb::dlpack::dtype_code::Int:
91 case 8: type_info = &
typeid(char);
break;
92 case 16: type_info = &
typeid(std::int16_t);
break;
93 case 32: type_info = &
typeid(std::int32_t);
break;
94 case 64: type_info = &
typeid(std::int64_t);
break;
98 case nb::dlpack::dtype_code::UInt:
100 case 8: type_info = &
typeid(std::uint8_t);
break;
101 case 16: type_info = &
typeid(std::uint16_t);
break;
102 case 32: type_info = &
typeid(std::uint32_t);
break;
103 case 64: type_info = &
typeid(std::uint64_t);
break;
107 case nb::dlpack::dtype_code::Float:
108 switch (dtype.bits) {
109 case 32: type_info = &
typeid(float);
break;
110 case 64: type_info = &
typeid(double);
break;
118 if (type_info ==
nullptr)
throw std::runtime_error (
"unsupported column type passed in");
119 self.
setColumnVoid(key, column.shape(0), column.data(), *type_info, is_const);
128 module.doc() = "Nanobind bindings for PythonToolHandle";
131 throw nb::import_error(
"This module can only be used in columnar access mode. Try setting up a ColumnarAnalysis release instead.");
133 module.attr("numberOfEventsName") = &columnar::numberOfEventsName;
136 nb::enum_<columnar::ColumnAccessMode>(module,
"ColumnAccessMode")
143 return "<ColumnAccessMode input>";
145 return "<ColumnAccessMode output>";
147 return "<ColumnAccessMode update>";
149 return "<ColumnAccessMode update value=" + std::to_string(
static_cast<int>(mode)) +
">";
154 nb::class_<columnar::ColumnInfo>(module,
"ColumnInfo")
170 std::string access_mode;
173 access_mode =
"input";
176 access_mode =
"output";
179 access_mode =
"update";
183 access_mode =
"unknown";
185 return "<ColumnInfo name='" + self.
name +
"'" +
187 ", access_mode='" + access_mode +
"'" +
194 d[
"name"] = self.
name;
195 d[
"index"] = self.
index;
197 d[
"access_mode"] =
static_cast<int>(self.
accessMode);
208 nb::class_<columnar::PythonToolHandle>(module,
"PythonToolHandle")
216 std::cerr <<
"Warning: PythonToolHandle.type is empty."
217 <<
" Set with PythonToolHandle.set_type_and_name." << std::endl;
224 const std::string& name =
config.name();
226 std::cerr <<
"Warning: PythonToolHandle.name is empty."
227 <<
" Set with PythonToolHandle.set_type_and_name." << std::endl;
233 .def(
"set_type_and_name",
235 self.setTypeAndName(type_and_name);
238 "Set the type and name of the tool.")
242 "Set a property on the tool.")
246 "Set a property on the tool.")
248 .def(
"preinitialize",
250 "Preinitialize the tool.")
253 .def(
"rename_containers",
256 "Rename the columns the tool uses.")
259 .def(
"rename_containers",
261 std::vector<std::pair<std::string, std::string>> vectorized;
262 for (
const auto&
pair : renames)
263 vectorized.emplace_back(
pair);
265 return self.renameContainers(vectorized);
268 "Rename the columns the tool uses.")
272 "Initialize the tool.")
274 .def(
"apply_systematic_variation",
276 self.applySystematicVariation(sys_name);
279 "Apply a systematic variation to the tool.")
283 self.setColumn<
float>(key, column.shape(0), column.data());
286 "Set a float column pointer.")
290 self.setColumn<
char>(key, column.shape(0), column.data());
293 "Set a char column pointer.")
297 self.setColumn<
int>(key, column.shape(0), column.data());
300 "Set an int column pointer.")
304 self.setColumn<uint8_t>(key, column.shape(0), column.data());
307 "Set a uint8_t column pointer.")
311 self.setColumn<uint16_t>(key, column.shape(0), column.data());
314 "Set a uint16_t column pointer.")
318 self.setColumn<uint32_t>(key, column.shape(0), column.data());
321 "Set a uint32_t column pointer.")
325 self.setColumn<uint64_t>(key, column.shape(0), column.data());
328 "Set a uint64_t column pointer.")
332 "key"_a,
"column"_a,
"is_const"_a =
true,
333 "Set a void column pointer (nanobind version).")
337 "Set a void immutable column pointer (nanobind version).")
341 "Call the tool and reset the columns.")
346 "Get the expected column information."
349 .def(
"get_recommended_systematics",
351 "Get the recommended systematics.")
NB_MODULE(python_tool_handle, module)
std::string get_type_name(const std::type_info &type_info)
void setColumnVoid(columnar::PythonToolHandle &self, const std::string &key, nb::ndarray<> column, bool is_const=true)
void setProperty(columnar::PythonToolHandle &self, const std::string &key, nb::object value)
void setImmutableColumnVoid(columnar::PythonToolHandle &self, const std::string &key, nb::ndarray<> column)
std::string getAddressString(const columnar::PythonToolHandle &obj)
constexpr unsigned columnarAccessMode
ColumnAccessMode
an enum for the different access modes for a column
@ update
an updateable column
a struct that contains meta-information about each column that's needed to interface the column with ...
std::string offsetName
the name of the offset column used for this column (or empty string for none)
std::vector< unsigned > fixedDimensions
the fixed dimensions this column has (if any)
bool isOptional
whether this column is optional
std::string variantLinkKeyColumn
if this is a variant link column, this is the name of the column with the container keys
std::string name
the name of the column
std::vector< std::string > linkTargetNames
for link columns: the name(s) of the container(s) we link to
bool isOffset
whether this is an offset column
ColumnAccessMode accessMode
the access mode for the column
std::string replacesColumn
whether this replaces another column
unsigned index
the index of the column in the data array
const std::type_info * type
the type of the individual entries in the column