chrono_batch_render/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
88 / 92
95.7%
Branches:
60 / 68
88.2%
Functions:
7 / 7
100.0%

python/src/sensor_pipeline.cpp
Line Branch Exec Source
1 // SPDX-License-Identifier: BSD-3-Clause
2 #include <cstdint>
3 #include <map>
4 #include <optional>
5 #include <string>
6 #include <string_view>
7
8 #include <nanobind/nanobind.h>
9 #include <nanobind/stl/map.h>
10 #include <nanobind/stl/optional.h>
11 #include <nanobind/stl/string.h>
12 #include <nanobind/stl/string_view.h>
13 #include <nanobind/stl/vector.h>
14
15 #include "bindings.h"
16
17 namespace nb = nanobind;
18
19 namespace chrono::batch_render::python {
20
21 namespace {
22
23 2 DetectorPattern FindPattern(std::string_view name) {
24
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 time.
12 for (uint32_t pattern = 0; pattern < std::size(kDetectorPatternTokens); ++pattern) {
25
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 10 times.
11 if (kDetectorPatternTokens[pattern] == name) {
26 1 return DetectorPattern(pattern);
27 }
28 }
29
2/3
✓ Branch 2 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
3 throw nb::value_error((std::string(name) + " isn't a detector pattern").c_str());
30 2 }
31
32 66 nb::dict Ports(const std::vector<SensorPipelineNodePort>& ports) {
33 66 nb::dict found;
34
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 66 times.
129 for (const SensorPipelineNodePort& port : ports) {
35
2/2
✓ Branch 1 taken 63 times.
✓ Branch 4 taken 63 times.
126 found[port.name.c_str()] = nb::make_tuple(port.type, port.optional);
36 }
37 66 return found;
38 ✗ }
39
40 4 SensorPipelineRunDesc RunDesc(const SensorPipelineRunner& pipeline, HeldTensors& held,
41 const nb::dict& inputs, const std::optional<DetectorDesc>& detector,
42 float exposureTime, float iso, uint32_t capture, uint32_t identity,
43 std::optional<uintptr_t> stream) {
44 8 SensorPipelineRunDesc desc{.detector = detector.value_or(DetectorDesc{}),
45 .exposureTime = exposureTime,
46 .iso = iso,
47 .capture = capture,
48
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 .identity = identity};
49
4/4
✓ Branch 1 taken 4 times.
✓ Branch 4 taken 3 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 4 times.
7 for (auto [key, value] : inputs) {
50
1/1
✓ Branch 1 taken 3 times.
3 const std::string name = nb::cast<std::string>(key);
51 3 desc.inputs[name] = nb::isinstance<device::Tensor>(value)
52
6/10
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 3 taken 3 times.
✓ Branch 6 taken 3 times.
✓ Branch 9 taken 3 times.
✓ Branch 12 taken 3 times.
✓ Branch 15 taken 3 times.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
9 ? nb::cast<device::Tensor>(value)
53 3 : held.Import(pipeline.GetDevice(), value, stream, name);
54 3 }
55 4 return desc;
56 ✗ }
57
58 }
59
60 2 void BindSensorPipeline(nb::module_& module) {
61 2 module.def(
62 "sensor_pipeline_node",
63 36 [](std::string_view id) -> std::optional<nb::dict> {
64 34 const std::optional<SensorPipelineNodeInfo> info = FindSensorPipelineNode(id);
65
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 33 times.
34 if (!info) {
66 1 return std::nullopt;
67 }
68
1/1
✓ Branch 1 taken 33 times.
33 nb::dict found;
69
1/1
✓ Branch 1 taken 33 times.
33 found["id"] = info->id;
70
1/1
✓ Branch 1 taken 33 times.
33 found["kind"] = info->kind;
71
2/2
✓ Branch 1 taken 33 times.
✓ Branch 4 taken 33 times.
66 found["inputs"] = Ports(info->inputs);
72
2/2
✓ Branch 1 taken 33 times.
✓ Branch 4 taken 33 times.
66 found["outputs"] = Ports(info->outputs);
73 33 return found;
74 67 },
75 2 nb::arg("id"));
76
77 2 nb::class_<DetectorDesc>(module, "DetectorDesc")
78 2 .def(
79 "__init__",
80 2 [](DetectorDesc* desc, std::string_view pattern, float fullWell, float readNoise,
81 float darkCurrent, float darkCurrentDoubling, float temperature, float prnu,
82 float dsnu, float systemGain, uint32_t bitDepth, float blackLevel, uint32_t seed) {
83 2 new (desc) DetectorDesc{.pattern = FindPattern(pattern),
84 .fullWell = fullWell,
85 .readNoise = readNoise,
86 .darkCurrent = darkCurrent,
87 .darkCurrentDoubling = darkCurrentDoubling,
88 .temperature = temperature,
89 .prnu = prnu,
90 .dsnu = dsnu,
91 .systemGain = systemGain,
92 .bitDepth = bitDepth,
93 .blackLevel = blackLevel,
94 1 .seed = seed};
95 },
96
1/1
✓ Branch 1 taken 2 times.
6 nb::kw_only(), nb::arg("pattern") = "rgb", nb::arg("full_well") = 10000.0f,
97
2/2
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
6 nb::arg("read_noise") = 2.0f, nb::arg("dark_current") = 1.0f,
98
2/2
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
6 nb::arg("dark_current_doubling") = 7.0f, nb::arg("temperature") = 293.15f,
99
3/3
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 7 taken 2 times.
8 nb::arg("prnu") = 0.005f, nb::arg("dsnu") = 0.5f, nb::arg("system_gain") = 0.25f,
100
4/4
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 7 taken 2 times.
✓ Branch 10 taken 2 times.
10 nb::arg("bit_depth") = 12u, nb::arg("black_level") = 0.0f, nb::arg("seed") = 0u)
101 2 .def_prop_ro("pattern",
102 ✗ [](const DetectorDesc& desc) {
103 ✗ return std::string(kDetectorPatternTokens[uint32_t(desc.pattern)]);
104 })
105 2 .def_rw("full_well", &DetectorDesc::fullWell)
106 2 .def_rw("read_noise", &DetectorDesc::readNoise)
107 2 .def_rw("dark_current", &DetectorDesc::darkCurrent)
108 2 .def_rw("dark_current_doubling", &DetectorDesc::darkCurrentDoubling)
109 2 .def_rw("temperature", &DetectorDesc::temperature)
110 2 .def_rw("prnu", &DetectorDesc::prnu)
111 2 .def_rw("dsnu", &DetectorDesc::dsnu)
112 2 .def_rw("system_gain", &DetectorDesc::systemGain)
113 2 .def_rw("bit_depth", &DetectorDesc::bitDepth)
114 2 .def_rw("black_level", &DetectorDesc::blackLevel)
115 2 .def_rw("seed", &DetectorDesc::seed);
116
117 2 nb::class_<SensorPipelineSession>(module, "SensorPipelineSession")
118
1/1
✓ Branch 2 taken 2 times.
4 .def_prop_ro("captures", &SensorPipelineSession::Captures)
119 2 .def(
120 "run",
121 2 [](SensorPipelineSession& session, const nb::dict& inputs,
122 std::optional<DetectorDesc> detector, float exposureTime, float iso,
123 uint32_t identity, std::optional<uintptr_t> stream) {
124 2 HeldTensors held;
125
1/1
✓ Branch 1 taken 2 times.
2 SensorPipelineRunDesc desc = RunDesc(session.GetRunner(), held, inputs, detector,
126
1/1
✓ Branch 1 taken 2 times.
2 exposureTime, iso, 0, identity, stream);
127 2 const nb::gil_scoped_release release;
128
1/1
✓ Branch 2 taken 2 times.
4 return session.Run(std::move(desc));
129
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 },
130 4 nb::arg("inputs"), nb::kw_only(), nb::arg("detector") = nb::none(),
131
3/3
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 7 taken 2 times.
10 nb::arg("exposure_time") = 1.0f, nb::arg("iso") = 100.0f, nb::arg("identity") = 0u,
132
1/1
✓ Branch 1 taken 2 times.
4 nb::arg("stream") = nb::none());
133
134 2 nb::class_<SensorPipelineRunner>(module, "SensorPipelineRunner")
135 4 .def(nb::init<const Ref<Scene>&, std::string_view>(), nb::arg("scene"), nb::arg("path"))
136 2 .def_prop_ro("sources", &SensorPipelineRunner::Sources)
137
1/1
✓ Branch 2 taken 2 times.
4 .def_prop_ro("outputs", &SensorPipelineRunner::Outputs)
138 2 .def(
139 "run",
140 2 [](const SensorPipelineRunner& pipeline, const nb::dict& inputs,
141 std::optional<DetectorDesc> detector, float exposureTime, float iso,
142 uint32_t capture, uint32_t identity, std::optional<uintptr_t> stream) {
143 2 HeldTensors held;
144 2 const SensorPipelineRunDesc desc = RunDesc(
145
1/1
✓ Branch 1 taken 2 times.
2 pipeline, held, inputs, detector, exposureTime, iso, capture, identity, stream);
146 2 const nb::gil_scoped_release release;
147
1/1
✓ Branch 1 taken 1 time.
2 return pipeline.Run(desc);
148
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
4 },
149 4 nb::arg("inputs"), nb::kw_only(), nb::arg("detector") = nb::none(),
150
2/2
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
8 nb::arg("exposure_time") = 1.0f, nb::arg("iso") = 100.0f, nb::arg("capture") = 0u,
151
2/2
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
6 nb::arg("identity") = 0u, nb::arg("stream") = nb::none())
152 2 .def(
153 "session",
154 1 [](const SensorPipelineRunner& pipeline) { return SensorPipelineSession(pipeline); },
155 nb::keep_alive<0, 1>());
156 2 }
157
158 }
159