9#include "arg_wrappers.hpp"
12#include "data_types.hpp"
13#include "histogram_events.hpp"
14#include "int_arith.hpp"
15#include "int_types.hpp"
16#include "introspect.hpp"
17#include "processor.hpp"
36template <
typename Event,
typename DataTypes,
typename DataMapper,
38class map_to_datapoints {
39 static_assert(std::is_same_v<std::invoke_result_t<DataMapper, Event>,
40 typename DataTypes::datapoint_type>);
42 static_assert(processor<Downstream, datapoint_event<DataTypes>>);
46 Downstream downstream;
49 explicit map_to_datapoints(DataMapper mapper, Downstream downstream)
50 : mapper(std::move(mapper)), downstream(std::move(downstream)) {}
52 [[nodiscard]]
auto introspect_node() const -> processor_info {
53 return processor_info(
this,
"map_to_datapoints");
56 [[nodiscard]]
auto introspect_graph() const -> processor_graph {
57 return downstream.introspect_graph().push_entry_point(
this);
60 void handle(Event
const &event) {
62 datapoint_event<DataTypes>{std::invoke(mapper, event)});
66 void handle(Event &&event) { handle(
static_cast<Event
const &
>(event)); }
68 template <
typename OtherEvent>
69 requires handler_for<Downstream, std::remove_cvref_t<OtherEvent>>
70 void handle(OtherEvent &&event) {
71 downstream.handle(std::forward<OtherEvent>(event));
74 void flush() { downstream.flush(); }
111 typename DataMapper,
typename Downstream>
113 return internal::map_to_datapoints<Event, DataTypes, DataMapper,
114 Downstream>(std::move(mapper),
115 std::move(downstream));
130 template <
typename Event>
132 typename DataTypes::datapoint_type {
134 internal::representable_in<
decltype(
event.difftime),
135 typename DataTypes::datapoint_type>,
136 "difftime_data_mapper does not allow narrowing conversion");
137 return event.difftime;
153 template <
typename Event>
155 typename DataTypes::datapoint_type {
157 internal::representable_in<
decltype(
event.count),
158 typename DataTypes::datapoint_type>,
159 "count_data_mapper does not allow narrowing conversion");
176 template <
typename Event>
178 typename DataTypes::datapoint_type {
180 internal::representable_in<
decltype(
event.channel),
181 typename DataTypes::datapoint_type>,
182 "channel_data_mapper does not allow narrowing conversion");
183 return event.channel;
189template <
typename DataTypes,
typename BinMapper,
typename Downstream>
191 static_assert(processor<Downstream, bin_increment_event<DataTypes>>);
194 std::is_same_v<std::invoke_result_t<
195 BinMapper,
typename DataTypes::datapoint_type>,
196 std::optional<typename DataTypes::bin_index_type>>);
198 BinMapper bin_mapper;
199 Downstream downstream;
201 static_assert(std::is_unsigned_v<typename DataTypes::bin_index_type>,
202 "The bin_index_type must be an unsigned integer type");
205 explicit map_to_bins(BinMapper bin_mapper, Downstream downstream)
206 : bin_mapper(std::move(bin_mapper)),
207 downstream(std::move(downstream)) {}
209 [[nodiscard]]
auto introspect_node() const -> processor_info {
210 return processor_info(
this,
"map_to_bins");
213 [[nodiscard]]
auto introspect_graph() const -> processor_graph {
214 return downstream.introspect_graph().push_entry_point(
this);
217 template <
typename DT>
void handle(datapoint_event<DT>
const &event) {
218 static_assert(std::is_same_v<
typename DT::datapoint_type,
219 typename DataTypes::datapoint_type>);
220 auto bin = std::invoke(bin_mapper, event.value);
222 downstream.handle(bin_increment_event<DataTypes>{bin.value()});
226 template <
typename DT>
void handle(datapoint_event<DT> &&event) {
227 handle(
static_cast<datapoint_event<DT>
const &
>(event));
230 template <
typename OtherEvent>
231 requires handler_for<Downstream, std::remove_cvref_t<OtherEvent>>
232 void handle(OtherEvent &&event) {
233 downstream.handle(std::forward<OtherEvent>(event));
236 void flush() { downstream.flush(); }
274 return internal::map_to_bins<DataTypes, BinMapper, Downstream>(
275 std::move(bin_mapper), std::move(downstream));
303template <
unsigned NDataBits,
unsigned NHistoBits,
bool Flip =
false,
304 typename DataTypes = default_data_types>
306 static_assert(NHistoBits <= 64);
307 static_assert(NDataBits >= NHistoBits);
308 static_assert(NDataBits <= 8 *
sizeof(
typename DataTypes::datapoint_type));
309 static_assert(NHistoBits <=
310 8 *
sizeof(
typename DataTypes::bin_index_type));
312 static_assert(std::is_unsigned_v<typename DataTypes::bin_index_type> ||
313 NHistoBits < 8 *
sizeof(
typename DataTypes::bin_index_type));
316 [[nodiscard]]
auto n_bins() const -> std::
size_t {
317 return std::size_t{1} << NHistoBits;
321 auto operator()(
typename DataTypes::datapoint_type datapoint)
const
322 -> std::optional<typename DataTypes::bin_index_type> {
323 using datapoint_type =
typename DataTypes::datapoint_type;
324 using bin_index_type =
typename DataTypes::bin_index_type;
326 static constexpr int shift = NDataBits - NHistoBits;
327 static_assert(shift <= 8 *
sizeof(datapoint_type));
328 if constexpr (shift == 8 *
sizeof(datapoint_type))
329 return bin_index_type{0};
333 auto const shifted = internal::ensure_unsigned(datapoint >> shift);
334 static constexpr auto max_bin_index =
static_cast<bin_index_type
>(
335 NHistoBits == 64 ? std::numeric_limits<u64>::max()
336 : (
u64(1) << NHistoBits) - 1);
337 if (shifted > max_bin_index)
340 auto const bin_index =
static_cast<bin_index_type
>(shifted);
342 return static_cast<bin_index_type
>(max_bin_index - bin_index);
357 typename DataTypes::datapoint_type off;
358 typename DataTypes::datapoint_type bwidth;
359 typename DataTypes::bin_index_type max_index;
362 static_assert(std::is_integral_v<typename DataTypes::datapoint_type>,
363 "datapoint_type must be an integer type");
364 static_assert(std::is_integral_v<typename DataTypes::bin_index_type>,
365 "bin_index_type must be an integer type");
368 static_assert(
sizeof(
typename DataTypes::datapoint_type) <=
sizeof(
u64));
369 static_assert(
sizeof(
typename DataTypes::bin_index_type) <=
sizeof(
u64));
395 : off(offset.value), bwidth(bin_width.value),
396 max_index(max_bin_index.value), clamp(clamp.value) {
398 throw std::invalid_argument(
399 "linear_bin_mapper bin_width must not be zero");
401 throw std::invalid_argument(
402 "linear_bin_mapper max_bin_index must not be negative");
406 [[nodiscard]]
auto n_bins() const -> std::
size_t {
407 return std::size_t(max_index) + 1;
411 auto operator()(
typename DataTypes::datapoint_type datapoint)
const
412 -> std::optional<typename DataTypes::bin_index_type> {
413 using bin_index_type =
typename DataTypes::bin_index_type;
415 if (bwidth < 0 ? datapoint > off : datapoint < off)
416 return clamp ? std::make_optional(bin_index_type{0})
420 auto const scaled = (datapoint - off) / bwidth;
422 if (
u64(scaled) >
u64(max_index))
423 return clamp ? std::make_optional(max_index) : std::nullopt;
424 return static_cast<bin_index_type
>(scaled);
433template <
typename T>
class unique_bin_mapper_access {
434 std::function<std::vector<T>()> values_fn;
438 template <
typename Func>
439 explicit unique_bin_mapper_access(Func values_func)
440 : values_fn(values_func) {}
445 auto values() -> std::vector<T> {
return values_fn(); }
466 using datapoint_type =
typename DataTypes::datapoint_type;
467 using bin_index_type =
typename DataTypes::bin_index_type;
468 bin_index_type max_index;
469 std::vector<datapoint_type> values;
485 : max_index(max_bin_index.value), trk(std::move(tracker)) {
487 throw std::invalid_argument(
488 "unique_bin_mapper max_bin_index must not be negative");
489 trk.register_access_factory([](
auto &tracker) {
493 [self] {
return self->values; });
498 [[nodiscard]]
auto n_bins() const -> std::
size_t {
499 return std::size_t(max_index) + 1;
503 auto operator()(
typename DataTypes::datapoint_type datapoint)
504 -> std::optional<typename DataTypes::bin_index_type> {
505 auto it = std::find(values.begin(), values.end(), datapoint);
506 if (it == values.end()) {
507 values.push_back(datapoint);
508 it = std::prev(values.end());
510 auto idx = std::distance(values.begin(), it);
511 return u64(idx) <=
u64(max_index)
512 ? std::make_optional(bin_index_type(idx))
519template <
typename StartEvent,
typename StopEvent,
typename DataTypes,
523 processor<Downstream, bin_increment_cluster_event<DataTypes>>);
525 bool in_cluster =
false;
526 std::vector<typename DataTypes::bin_index_type> cur_cluster;
528 Downstream downstream;
531 explicit cluster_bin_increments(Downstream downstream)
532 : downstream(std::move(downstream)) {}
534 [[nodiscard]]
auto introspect_node() const -> processor_info {
535 return processor_info(
this,
"cluster_bin_increments");
538 [[nodiscard]]
auto introspect_graph() const -> processor_graph {
539 return downstream.introspect_graph().push_entry_point(
this);
542 template <
typename DT>
void handle(bin_increment_event<DT>
const &event) {
543 static_assert(std::is_same_v<
typename DT::bin_index_type,
544 typename DataTypes::bin_index_type>);
546 cur_cluster.push_back(event.bin_index);
549 void handle(StartEvent
const & ) {
554 void handle(StopEvent
const & ) {
556 auto const e = bin_increment_cluster_event<DataTypes>{
558 downstream.handle(e);
564 template <
typename DT>
void handle(bin_increment_event<DT> &&event) {
565 handle(
static_cast<bin_increment_event<DT>
const &
>(event));
569 void handle(StartEvent &&event) {
570 handle(
static_cast<StartEvent
const &
>(event));
574 void handle(StopEvent &&event) {
575 handle(
static_cast<StopEvent
const &
>(event));
578 template <
typename OtherEvent>
579 requires handler_for<Downstream, std::remove_cvref_t<OtherEvent>>
580 void handle(OtherEvent &&event) {
581 downstream.handle(std::forward<OtherEvent>(event));
584 void flush() { downstream.flush(); }
615template <
typename StartEvent,
typename StopEvent,
618 return internal::cluster_bin_increments<StartEvent, StopEvent, DataTypes,
619 Downstream>(std::move(downstream));
Tracker that mediates access to objects via a tcspc::context.
Definition context.hpp:39
Data mapper mapping channel to the data value.
Definition binning.hpp:173
auto operator()(Event const &event) const -> typename DataTypes::datapoint_type
Implements data mapper requirement.
Definition binning.hpp:177
Data mapper mapping count to the data value.
Definition binning.hpp:150
auto operator()(Event const &event) const -> typename DataTypes::datapoint_type
Implements data mapper requirement.
Definition binning.hpp:154
Data mapper mapping difference time to the data value.
Definition binning.hpp:127
auto operator()(Event const &event) const -> typename DataTypes::datapoint_type
Implements data mapper requirement.
Definition binning.hpp:131
linear_bin_mapper(arg::offset< typename DataTypes::datapoint_type > offset, arg::bin_width< typename DataTypes::datapoint_type > bin_width, arg::max_bin_index< typename DataTypes::bin_index_type > max_bin_index, arg::clamp< bool > clamp=arg::clamp{false})
Construct with parameters.
Definition binning.hpp:390
auto n_bins() const -> std::size_t
Implements bin mapper requirement.
Definition binning.hpp:406
auto operator()(typename DataTypes::datapoint_type datapoint) const -> std::optional< typename DataTypes::bin_index_type >
Implements bin mapper requirement.
Definition binning.hpp:411
Access for tcspc::unique_bin_mapper data.
Definition binning.hpp:433
auto values() -> std::vector< T >
Return the datapoint values assigned to bin indices.
Definition binning.hpp:445
auto n_bins() const -> std::size_t
Implements bin mapper requirement.
Definition binning.hpp:498
auto operator()(typename DataTypes::datapoint_type datapoint) -> std::optional< typename DataTypes::bin_index_type >
Implements bin mapper requirement.
Definition binning.hpp:503
unique_bin_mapper(access_tracker< unique_bin_mapper_access< typename DataTypes::datapoint_type > > &&tracker, arg::max_bin_index< typename DataTypes::bin_index_type > max_bin_index)
Construct with context and parameter.
Definition binning.hpp:480
auto ad_hoc_bucket(std::span< T > s) -> bucket< T >
Create a tcspc::bucket referencing a span.
Definition bucket.hpp:489
#define LIBTCSPC_OBJECT_FROM_TRACKER(obj_type, tracker_field_name, tracker)
Recover the object address from a tcspc::access_tracker embedded in the object.
Definition context.hpp:253
auto map_to_datapoints(DataMapper mapper, Downstream downstream)
Create a processor that maps arbitrary time-tagged events to datapoint events.
Definition binning.hpp:112
auto map_to_bins(BinMapper bin_mapper, Downstream downstream)
Create a processor that maps datapoints to histogram bin indices.
Definition binning.hpp:273
auto cluster_bin_increments(Downstream downstream)
Create a processor collecting binned data into clusters.
Definition binning.hpp:617
std::uint64_t u64
Short name for uint64_t.
Definition int_types.hpp:33
libtcspc namespace.
Definition acquire.hpp:29
Function argument wrapper for bin width parameter.
Definition arg_wrappers.hpp:57
Function argument wrapper for clamp parameter.
Definition arg_wrappers.hpp:87
Function argument wrapper for maximum bin index parameter.
Definition arg_wrappers.hpp:217
Function argument wrapper for offset parameter.
Definition arg_wrappers.hpp:347
The default data type set.
Definition data_types.hpp:24
Bin mapper that discards the least significant bits.
Definition binning.hpp:305
auto operator()(typename DataTypes::datapoint_type datapoint) const -> std::optional< typename DataTypes::bin_index_type >
Implements bin mapper requirement.
Definition binning.hpp:321
auto n_bins() const -> std::size_t
Implements bin mapper requirement.
Definition binning.hpp:316