ATLAS Offline Software
Functions
NanobindBindings.cxx File Reference
#include <ColumnarToolWrapperPython/PythonToolHandle.h>
#include <ColumnarCore/ColumnarDef.h>
#include <nanobind/nanobind.h>
#include <nanobind/ndarray.h>
#include <nanobind/operators.h>
#include <nanobind/stl/list.h>
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
#include <nanobind/stl/pair.h>
#include <nanobind/stl/map.h>
#include <cstdio>
#include <string>

Go to the source code of this file.

Functions

std::string getAddressString (const columnar::PythonToolHandle &obj)
 
std::string get_type_name (const std::type_info &type_info)
 
void setProperty (columnar::PythonToolHandle &self, const std::string &key, nb::object value)
 
void setColumnVoid (columnar::PythonToolHandle &self, const std::string &key, nb::ndarray<> column, bool is_const=true)
 
void setImmutableColumnVoid (columnar::PythonToolHandle &self, const std::string &key, nb::ndarray<> column)
 
 NB_MODULE (python_tool_handle, module)
 

Function Documentation

◆ get_type_name()

std::string get_type_name ( const std::type_info &  type_info)

escape hatch for char

Definition at line 37 of file NanobindBindings.cxx.

37  {
38  if (type_info == typeid(int)) {
39  return "int32";
40  } else if (type_info == typeid(unsigned int)) {
41  return "uint32";
42  } else if (type_info == typeid(short)) {
43  return "int16";
44  } else if (type_info == typeid(unsigned short)) {
45  return "uint16";
46  } else if (type_info == typeid(char)) {
48  return "int8";
49  } else if (type_info == typeid(unsigned char)) {
50  return "uint8";
51  } else if (type_info == typeid(float)) {
52  return "float32";
53  } else if (type_info == typeid(double)) {
54  return "float64";
55  } else if (type_info == typeid(long)) {
56  return "int64";
57  } else if (type_info == typeid(unsigned long)) {
58  return "uint64";
59  } else if (type_info == typeid(bool)) {
60  return "bool";
61  } else {
62  // If the type is unknown, you can return the mangled name or a default message
63  return std::string("unknown ('") + type_info.name() + "')";
64  }
65 }

◆ getAddressString()

std::string getAddressString ( const columnar::PythonToolHandle obj)

Definition at line 30 of file NanobindBindings.cxx.

30  {
31  char buffer[32]; // Ensure the buffer is large enough for the hex representation
32  std::snprintf(buffer, sizeof(buffer), "0x%llx", reinterpret_cast<unsigned long long>(&obj));
33  return std::string(buffer);
34 }

◆ NB_MODULE()

NB_MODULE ( python_tool_handle  ,
module   
)

load in the ColumnAccessMode enum

Definition at line 127 of file NanobindBindings.cxx.

127  {
128  module.doc() = "Nanobind bindings for PythonToolHandle";
129 
131  throw nb::import_error("This module can only be used in columnar access mode. Try setting up a ColumnarAnalysis release instead.");
132 
133  module.attr("numberOfEventsName") = &columnar::numberOfEventsName;
134 
136  nb::enum_<columnar::ColumnAccessMode>(module, "ColumnAccessMode")
137  .value("input", columnar::ColumnAccessMode::input)
138  .value("output", columnar::ColumnAccessMode::output)
139  .value("update", columnar::ColumnAccessMode::update)
140  .def("__repr__", [](const columnar::ColumnAccessMode &mode) -> std::string {
141  switch (mode) {
143  return "<ColumnAccessMode input>";
145  return "<ColumnAccessMode output>";
147  return "<ColumnAccessMode update>";
148  default:
149  return "<ColumnAccessMode update value=" + std::to_string(static_cast<int>(mode)) + ">";
150  }
151  })
152  .export_values(); // Makes the enum values accessible without namespace in Python
153 
154  nb::class_<columnar::ColumnInfo>(module, "ColumnInfo")
155  .def(nb::init<>()) // Default constructor
156  .def_ro("name", &columnar::ColumnInfo::name)
157  .def_ro("index", &columnar::ColumnInfo::index)
158  .def_prop_ro("dtype", [](const columnar::ColumnInfo &self){
159  return get_type_name(*self.type);
160  })
161  .def_ro("access_mode", &columnar::ColumnInfo::accessMode)
162  .def_ro("offset_name", &columnar::ColumnInfo::offsetName)
163  .def_ro("fixed_dimensions", &columnar::ColumnInfo::fixedDimensions)
164  .def_ro("link_target_names", &columnar::ColumnInfo::linkTargetNames)
165  .def_ro("variant_link_key_column", &columnar::ColumnInfo::variantLinkKeyColumn)
166  .def_ro("is_offset", &columnar::ColumnInfo::isOffset)
167  .def_ro("replaces_column", &columnar::ColumnInfo::replacesColumn)
168  .def_ro("is_optional", &columnar::ColumnInfo::isOptional)
169  .def("__repr__", [](const columnar::ColumnInfo &self) {
170  std::string access_mode;
171  switch (self.accessMode) {
173  access_mode = "input";
174  break;
176  access_mode = "output";
177  break;
179  access_mode = "update";
180  break;
181  default:
182  // For unknown values, return the integer value
183  access_mode = "unknown";
184  }
185  return "<ColumnInfo name='" + self.name + "'" +
186  (self.isOffset ? "" : ", offset='" + self.offsetName + "'") +
187  ", access_mode='" + access_mode + "'" +
188  ", dtype='" + (self.type ? get_type_name(*self.type) : "" ) + "'" +
189  (self.isOptional ? ", optional": "") +
190  ">";
191  })
192  .def("to_dict", [](const columnar::ColumnInfo& self) {
193  nb::dict d;
194  d["name"] = self.name;
195  d["index"] = self.index;
196  d["dtype"] = self.type ? get_type_name(*self.type) : "";
197  d["access_mode"] = static_cast<int>(self.accessMode);
198  d["offset_name"] = self.offsetName;
199  d["fixed_dimensions"] = self.fixedDimensions;
200  d["link_target_names"] = self.linkTargetNames;
201  d["variant_link_key_column"] = self.variantLinkKeyColumn;
202  d["is_offset"] = self.isOffset;
203  d["replaces_column"] = self.replacesColumn;
204  d["is_optional"] = self.isOptional;
205  return d;
206  });
207 
208  nb::class_<columnar::PythonToolHandle>(module, "PythonToolHandle")
209  .def(nb::init())
210 
211  // Properties
212  .def_prop_ro("type", [](const columnar::PythonToolHandle &self) {
213  const asg::AsgToolConfig& config = self.getConfig();
214  const std::string& type = config.type();
215  if (type.empty()) {
216  std::cerr << "Warning: PythonToolHandle.type is empty."
217  << " Set with PythonToolHandle.set_type_and_name." << std::endl;
218  }
219  return type;
220  })
221 
222  .def_prop_ro("name", [](const columnar::PythonToolHandle &self) {
223  const asg::AsgToolConfig& config = self.getConfig();
224  const std::string& name = config.name();
225  if (name.empty()) {
226  std::cerr << "Warning: PythonToolHandle.name is empty."
227  << " Set with PythonToolHandle.set_type_and_name." << std::endl;
228  }
229  return name;
230  })
231 
232  // Methods
233  .def("set_type_and_name",
234  [](columnar::PythonToolHandle &self, const std::string& type_and_name) {
235  self.setTypeAndName(type_and_name);
236  },
237  "type_and_name"_a,
238  "Set the type and name of the tool.")
239 
240  .def("set_property", &setProperty,
241  "key"_a, "value"_a,
242  "Set a property on the tool.")
243 
244  .def("__setattr__", &setProperty,
245  "key"_a, "value"_a,
246  "Set a property on the tool.")
247 
248  .def("preinitialize",
250  "Preinitialize the tool.")
251 
252  // rename_containers([("from", "to"), ...])
253  .def("rename_containers",
255  "renames"_a,
256  "Rename the columns the tool uses.")
257 
258  // rename_containers({"from": "to"}, ...})
259  .def("rename_containers",
260  [](columnar::PythonToolHandle &self, const std::map<std::string,std::string>& renames){
261  std::vector<std::pair<std::string, std::string>> vectorized;
262  for (const auto& pair : renames)
263  vectorized.emplace_back(pair);
264 
265  return self.renameContainers(vectorized);
266  },
267  "renames"_a,
268  "Rename the columns the tool uses.")
269 
270  .def("initialize",
272  "Initialize the tool.")
273 
274  .def("apply_systematic_variation",
275  [](columnar::PythonToolHandle &self, const std::string& sys_name) {
276  self.applySystematicVariation(sys_name);
277  },
278  "sys_name"_a,
279  "Apply a systematic variation to the tool.")
280 
281  .def("set_column",
282  [](columnar::PythonToolHandle &self, const std::string& key, nb::ndarray<float> column) {
283  self.setColumn<float>(key, column.shape(0), column.data());
284  },
285  "key"_a, "column"_a,
286  "Set a float column pointer.")
287 
288  .def("set_column",
289  [](columnar::PythonToolHandle &self, const std::string& key, nb::ndarray<char> column) {
290  self.setColumn<char>(key, column.shape(0), column.data());
291  },
292  "key"_a, "column"_a,
293  "Set a char column pointer.")
294 
295  .def("set_column",
296  [](columnar::PythonToolHandle &self, const std::string& key, nb::ndarray<int> column) {
297  self.setColumn<int>(key, column.shape(0), column.data());
298  },
299  "key"_a, "column"_a,
300  "Set an int column pointer.")
301 
302  .def("set_column",
303  [](columnar::PythonToolHandle &self, const std::string& key, nb::ndarray<std::uint8_t> column) {
304  self.setColumn<uint8_t>(key, column.shape(0), column.data());
305  },
306  "key"_a, "column"_a,
307  "Set a uint8_t column pointer.")
308 
309  .def("set_column",
310  [](columnar::PythonToolHandle &self, const std::string& key, nb::ndarray<std::uint16_t> column) {
311  self.setColumn<uint16_t>(key, column.shape(0), column.data());
312  },
313  "key"_a, "column"_a,
314  "Set a uint16_t column pointer.")
315 
316  .def("set_column",
317  [](columnar::PythonToolHandle &self, const std::string& key, nb::ndarray<std::uint32_t> column) {
318  self.setColumn<uint32_t>(key, column.shape(0), column.data());
319  },
320  "key"_a, "column"_a,
321  "Set a uint32_t column pointer.")
322 
323  .def("set_column",
324  [](columnar::PythonToolHandle &self, const std::string& key, nb::ndarray<std::uint64_t> column) {
325  self.setColumn<uint64_t>(key, column.shape(0), column.data());
326  },
327  "key"_a, "column"_a,
328  "Set a uint64_t column pointer.")
329 
330  .def("set_column_void", &setColumnVoid,
331  // cppcheck-suppress assignBoolToPointer
332  "key"_a, "column"_a, "is_const"_a = true,
333  "Set a void column pointer (nanobind version).")
334 
335  .def("__setitem__", &setImmutableColumnVoid,
336  "key"_a, "column"_a,
337  "Set a void immutable column pointer (nanobind version).")
338 
339  .def("call",
341  "Call the tool and reset the columns.")
342 
343  .def_prop_ro(
344  "columns",
346  "Get the expected column information."
347  )
348 
349  .def("get_recommended_systematics",
351  "Get the recommended systematics.")
352 
353  // Make this more fancy in the future
354  // <PythonToolHandle(CP::MuonEfficiencyScaleFactors/unique0) object at 0x7f2943b07568>
355  .def("__repr__", [](const columnar::PythonToolHandle &self) {
356  const asg::AsgToolConfig& config = self.getConfig();
357  return "<PythonToolHandle(" + config.type() + "/" + config.name() + ") object at " + getAddressString(self) + ">";
358  });
359 }

◆ setColumnVoid()

void setColumnVoid ( columnar::PythonToolHandle self,
const std::string &  key,
nb::ndarray<>  column,
bool  is_const = true 
)

Definition at line 79 of file NanobindBindings.cxx.

79  {
80  // TODO: figure out how to get type_info from handle instead...
81  // nb::handle handle = column.handle();
82 
83  const std::type_info* type_info = nullptr;
84  const nb::dlpack::dtype dtype = column.dtype();
85  switch ((nb::dlpack::dtype_code) dtype.code) {
87  switch (dtype.bits) {
88  // escape hatch to handle char for now
89  // we should rely on signed/unsigned and nbits, instead of std::type_info
90  // case 8: type_info = &typeid(std::int8_t); break;
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;
95  }
96  break;
97 
98  case nb::dlpack::dtype_code::UInt:
99  switch (dtype.bits) {
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;
104  }
105  break;
106 
108  switch (dtype.bits) {
109  case 32: type_info = &typeid(float); break;
110  case 64: type_info = &typeid(double); break;
111  }
112  break;
113 
114  default:
115  break;
116  }
117 
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);
120 }

◆ setImmutableColumnVoid()

void setImmutableColumnVoid ( columnar::PythonToolHandle self,
const std::string &  key,
nb::ndarray<>  column 
)

Definition at line 122 of file NanobindBindings.cxx.

122  {
123  setColumnVoid(self, key, column, true);
124 };

◆ setProperty()

void setProperty ( columnar::PythonToolHandle self,
const std::string &  key,
nb::object  value 
)

Definition at line 67 of file NanobindBindings.cxx.

67  {
68  if (nb::isinstance<nb::str>(value)) {
69  self.setProperty(key, nb::cast<std::string>(value));
70  } else if (nb::isinstance<nb::int_>(value)) {
71  self.setProperty(key, nb::cast<int>(value));
72  } else if (nb::isinstance<nb::float_>(value)) {
73  self.setProperty(key, nb::cast<double>(value));
74  } else {
75  throw std::runtime_error("Unsupported property type. Must be str, int, or float.");
76  }
77 }
columnar::PythonToolHandle::getRecommendedSystematics
std::vector< std::string > getRecommendedSystematics() const
get the recommended systematics
Definition: PythonToolHandle.h:179
columnar::ColumnAccessMode::input
@ input
an input column
columnar::numberOfEventsName
const std::string numberOfEventsName
the name used for the column containing the number of events
Definition: IColumnarTool.h:38
columnar::ColumnInfo::accessMode
ColumnAccessMode accessMode
the access mode for the column
Definition: ColumnInfo.h:58
defaults::Int
constexpr int Int
Definition: MSVtxValidationAlg.h:44
columnar::ColumnInfo::name
std::string name
the name of the column
Definition: ColumnInfo.h:42
columnar::ColumnInfo::offsetName
std::string offsetName
the name of the offset column used for this column (or empty string for none)
Definition: ColumnInfo.h:74
get_type_name
std::string get_type_name(const std::type_info &type_info)
Definition: NanobindBindings.cxx:37
xAOD::uint8_t
uint8_t
Definition: Muon_v1.cxx:558
columnar::ColumnInfo::variantLinkKeyColumn
std::string variantLinkKeyColumn
if this is a variant link column, this is the name of the column with the container keys
Definition: ColumnInfo.h:169
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
PlotCalibFromCool.dtype
dtype
Definition: PlotCalibFromCool.py:495
hist_file_dump.d
d
Definition: hist_file_dump.py:142
xAOD::char
char
Definition: TrigDecision_v1.cxx:38
columnar::ColumnInfo::replacesColumn
std::string replacesColumn
whether this replaces another column
Definition: ColumnInfo.h:102
DeMoUpdate.column
dictionary column
Definition: DeMoUpdate.py:1110
athena.value
value
Definition: athena.py:124
defaults::Float
constexpr float Float
Definition: MSVtxValidationAlg.h:45
columnar::PythonToolHandle::initialize
void initialize()
initialize the tool
Definition: PythonToolHandle.h:114
columnar::ColumnInfo::isOffset
bool isOffset
whether this is an offset column
Definition: ColumnInfo.h:92
xAOD::int16_t
setScaleOne setStatusOne setSaturated int16_t
Definition: gFexGlobalRoI_v1.cxx:55
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
columnar::ColumnAccessMode::output
@ output
an output column
config
Definition: PhysicsAnalysis/AnalysisCommon/AssociationUtils/python/config.py:1
columnar::PythonToolHandle
a handle to a python tool for use via nanobind
Definition: PythonToolHandle.h:39
setImmutableColumnVoid
void setImmutableColumnVoid(columnar::PythonToolHandle &self, const std::string &key, nb::ndarray<> column)
Definition: NanobindBindings.cxx:122
python.PyAthena.module
module
Definition: PyAthena.py:131
columnar::columnarAccessMode
constexpr unsigned columnarAccessMode
Definition: ColumnarDef.h:15
setProperty
void setProperty(columnar::PythonToolHandle &self, const std::string &key, nb::object value)
Definition: NanobindBindings.cxx:67
columnar::ColumnInfo
a struct that contains meta-information about each column that's needed to interface the column with ...
Definition: ColumnInfo.h:35
createCoolChannelIdFile.buffer
buffer
Definition: createCoolChannelIdFile.py:11
asg::AsgToolConfig
an object that can create a AsgTool
Definition: AsgToolConfig.h:22
xAOD::uint16_t
setWord1 uint16_t
Definition: eFexEMRoI_v1.cxx:93
columnar::ColumnInfo::isOptional
bool isOptional
whether this column is optional
Definition: ColumnInfo.h:121
getAddressString
std::string getAddressString(const columnar::PythonToolHandle &obj)
Definition: NanobindBindings.cxx:30
xAOD::uint64_t
uint64_t
Definition: EventInfo_v1.cxx:123
Preparation.mode
mode
Definition: Preparation.py:107
columnar::PythonToolHandle::call
void call()
call the tool and reset the columns
Definition: PythonToolHandle.h:153
columnar::ColumnAccessMode::update
@ update
an updateable column
columnar::ColumnAccessMode
ColumnAccessMode
an enum for the different access modes for a column
Definition: ColumnInfo.h:19
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
columnar::PythonToolHandle::renameContainers
void renameContainers(const std::vector< std::pair< std::string, std::string >> &renames)
rename the columns the tool uses
Definition: PythonToolHandle.h:86
columnar::ColumnInfo::linkTargetNames
std::vector< std::string > linkTargetNames
for link columns: the name(s) of the container(s) we link to
Definition: ColumnInfo.h:154
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
columnar::PythonToolHandle::preinitialize
void preinitialize()
preinitialize the tool
Definition: PythonToolHandle.h:69
python.PyKernel.init
def init(v_theApp, v_rootStream=None)
Definition: PyKernel.py:45
columnar::ColumnInfo::index
unsigned index
the index of the column in the data array
Definition: ColumnInfo.h:46
pool::accessMode
const char * accessMode(pool::DbAccessMode access_mode)
Translate access mode to string.
columnar::PythonToolHandle::getColumnInfo
std::vector< ColumnInfo > getColumnInfo() const
get the expected column info
Definition: PythonToolHandle.h:163
setColumnVoid
void setColumnVoid(columnar::PythonToolHandle &self, const std::string &key, nb::ndarray<> column, bool is_const=true)
Definition: NanobindBindings.cxx:79
python.PyAthena.obj
obj
Definition: PyAthena.py:132
python.difftuple.renames
dictionary renames
Definition: difftuple.py:22
columnar::ColumnInfo::fixedDimensions
std::vector< unsigned > fixedDimensions
the fixed dimensions this column has (if any)
Definition: ColumnInfo.h:82
python.LArMinBiasAlgConfig.float
float
Definition: LArMinBiasAlgConfig.py:65
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37