diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt index 489eba06c8480655ea7876aea66b9013f3e42fe7..69f1657da64d48125dda6e99f2a9316de6ce2cf5 100644 --- a/algo/CMakeLists.txt +++ b/algo/CMakeLists.txt @@ -1 +1,26 @@ add_subdirectory (data) + + + +# Create a library libCbmAlgo + +set(SRCS + evbuild/EventBuilder.cxx + ) + +add_library(Algo SHARED ${SRCS}) + +target_include_directories(Algo + PUBLIC ${CMAKE_SOURCE_DIR}/core/data + PUBLIC ${CMAKE_SOURCE_DIR}/core/data/base + PUBLIC ${CMAKE_SOURCE_DIR}/core/data/global + PUBLIC ${CMAKE_SOURCE_DIR}/core/data/sts + PUBLIC ${CMAKE_SOURCE_DIR}/external/ipc/ipc/lib/fles_ipc +) + +target_include_directories(Algo SYSTEM + PUBLIC ${Boost_INCLUDE_DIR} +) + +target_compile_definitions(Algo PUBLIC NO_ROOT) + diff --git a/algo/evbuild/EventBuilder.cxx b/algo/evbuild/EventBuilder.cxx new file mode 100644 index 0000000000000000000000000000000000000000..baac61a175db8984043321015173730b8cdfa706 --- /dev/null +++ b/algo/evbuild/EventBuilder.cxx @@ -0,0 +1,44 @@ +/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +#include "EventBuilder.h" + +#include <algorithm> +#include <cassert> +#include <vector> + +using std::is_sorted; +using std::vector; + +namespace cbm +{ + namespace algo + { + + // --- Execution + std::vector<CbmDigiEvent> EventBuilder::operator()(const CbmDigiTimeslice& ts, const vector<double> triggers) const + { + assert(is_sorted(triggers.begin(), triggers.end())); + vector<CbmDigiEvent> eventVec(triggers.size()); + std::transform(triggers.begin(), triggers.end(), eventVec.begin(), + [&ts, this](const double& trigger) { return BuildEvent(ts, trigger); }); + return eventVec; + } + + + // --- Build a single event + CbmDigiEvent EventBuilder::BuildEvent(const CbmDigiTimeslice& ts, double trigger) const + { + CbmDigiEvent event; + event.fTime = trigger; + double tMin = trigger + fTriggerWindows.find(ECbmModuleId::kSts)->second.first; + double tMax = trigger + fTriggerWindows.find(ECbmModuleId::kSts)->second.second; + assert(is_sorted(ts.fData.fSts.fDigis.begin(), ts.fData.fSts.fDigis.end(), IsBefore<CbmStsDigi, CbmStsDigi>)); + event.fData.fSts.fDigis = CopyRange(ts.fData.fSts.fDigis, tMin, tMax); + return event; + } + + + } // namespace algo +} // namespace cbm diff --git a/algo/evbuild/EventBuilder.h b/algo/evbuild/EventBuilder.h new file mode 100644 index 0000000000000000000000000000000000000000..948956f3aaa3105c754eb7353dcd527b24575138 --- /dev/null +++ b/algo/evbuild/EventBuilder.h @@ -0,0 +1,119 @@ +/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Volker Friese [committer] */ + +#ifndef CBM_ALGO_EVENTBUILDER_H +#define CBM_ALGO_EVENTBUILDER_H 1 + + +#include "CbmDefs.h" +#include "CbmDigiEvent.h" +#include "CbmDigiTimeslice.h" + +#include <algorithm> +#include <map> +#include <vector> + +namespace cbm +{ + namespace algo + { + + /** @brief Time comparison of two objects with time stamps (class implementing GetTime()) **/ + template<typename Data1, typename Data2> + bool IsBefore(const Data1& obj1, const Data2& obj2) + { + return obj1.GetTime() < obj2.GetTime(); + } + + + /** @class EventBuilder + ** @author Volker Friese <v.friese@gsi.de> + ** @since 2021 + ** @brief Constructs CbmDigiEvents out of CbmDigiTimeslices + ** + ** Events are constructed by copying digi data from the source (CbmDigiTimeslice). + ** Digis are selected in trigger windows, the sizes of which relative to a trigger time are configurable. + ** For each trigger time, an event is generated. The time intervals may overlap, resulting in digis + ** being attributed to multiple events. + ** + ** The source digi vectors (in CbmDigiTimeslice) must be sorted w.r.t. time, otherwise the behaviour is + ** undefined. + ** + ** The trigger vector must be sorted. + **/ + class EventBuilder { + + public: + /** @brief Constructor **/ + EventBuilder() {}; + + + /** @brief Destructor **/ + virtual ~EventBuilder() {}; + + + /** @brief Execution + ** @param ts Digi source (timeslice) + ** @param triggers List of trigger times + ** @return Vector of constructed events + **/ + std::vector<CbmDigiEvent> operator()(const CbmDigiTimeslice& ts, const std::vector<double> triggers) const; + + + /** @brief Build a single event from a trigger time + ** @param ts Digi source (timeslice) + ** @param trigger Trigger time + ** @return Digi event + **/ + CbmDigiEvent BuildEvent(const CbmDigiTimeslice& ts, double trigger) const; + + + /** @brief Configure the trigger windows + ** @param system Detector system identifier + ** @param tMin Trigger window start time w.r.t. trigger time + ** @param tMax Trigger window end time w.r.t. trigger time + **/ + void SetTriggerWindow(ECbmModuleId system, double tMin, double tMax) + { + fTriggerWindows[system] = std::make_pair(tMin, tMax); + } + + + private: // methods + /** @brief Copy data objects in a given time interval from the source to the target vector + ** @param source Source data vector + ** @param tMin Minimal time + ** @param tMax Maximal time + ** @return Target data vector + ** + ** The Data class specialisation must implement the method double GetTime(), which is used to + ** check whether the Data object falls into the specified time interval. + ** + ** The source vector must be ordered w.r.t. GetTime(), otherwise the behaviour is undefined. + ** + ** TODO: The current implementation searches, for each trigger, the entire source vector. This + ** can surely be optimised when the contract that the trigger vector be sorted is properly exploited, + ** e.g., by starting the search for the first digi in the trigger window from the start of the + ** previous trigger window. This, however, requires bookkeeping hardly to be realised without + ** changing the state of the class. I leave this for the future and for bright specialists. + **/ + template<typename Data> + static typename std::vector<Data> CopyRange(const std::vector<Data>& source, double tMin, double tMax) + { + auto comp = [](const Data& obj, double value) { return obj.GetTime() < value; }; + auto lower = std::lower_bound(source.begin(), source.end(), tMin, comp); + auto upper = std::lower_bound(lower, source.end(), tMax, comp); + return std::vector<Data>(lower, upper); + } + + + private: // data members + std::map<ECbmModuleId, std::pair<double, double>> fTriggerWindows; + }; + + + } // namespace algo +} // namespace cbm + +#endif /* CBM_ALGO_EVENTBUILDER_H */ diff --git a/reco/CMakeLists.txt b/reco/CMakeLists.txt index c31e7d8f51a63f8f8254872194ba42ed57bfb2af..68dcb85e80b53185df1137bf70a409656ca720b6 100644 --- a/reco/CMakeLists.txt +++ b/reco/CMakeLists.txt @@ -12,4 +12,3 @@ add_subdirectory(littrack) add_subdirectory(steer) add_subdirectory(tracking) add_subdirectory(qa) -