Commit c1a5f0da authored by Jens Kroeger's avatar Jens Kroeger
Browse files

Merge branch 'clipboard' into 'master'

Rewritten Clipboard & FileReader/Writer Modules

See merge request !155
parents 6ac7cc81 f4da748b
Pipeline #1088083 passed with stages
in 16 minutes and 24 seconds
...@@ -145,13 +145,14 @@ INCLUDE("cmake/clang-cpp-checks.cmake") ...@@ -145,13 +145,14 @@ INCLUDE("cmake/clang-cpp-checks.cmake")
# Always include sources from top directory # Always include sources from top directory
INCLUDE_DIRECTORIES(src) INCLUDE_DIRECTORIES(src)
# Build objects library
ADD_SUBDIRECTORY(src/objects)
SET(CORRYVRECKAN_LIBRARIES ${CORRYVRECKAN_LIBRARIES} CorryvreckanObjects)
# Build core Corryvreckan library # Build core Corryvreckan library
ADD_SUBDIRECTORY(src/core) ADD_SUBDIRECTORY(src/core)
SET(CORRYVRECKAN_LIBRARIES ${CORRYVRECKAN_LIBRARIES} CorryvreckanCore) SET(CORRYVRECKAN_LIBRARIES ${CORRYVRECKAN_LIBRARIES} CorryvreckanCore)
# Build objects library
ADD_SUBDIRECTORY(src/objects)
SET(CORRYVRECKAN_LIBRARIES ${CORRYVRECKAN_LIBRARIES} CorryvreckanObjects)
# Build required modules # Build required modules
ADD_SUBDIRECTORY(src/modules) ADD_SUBDIRECTORY(src/modules)
......
...@@ -70,4 +70,6 @@ This software is distributed under the terms of the MIT license. A copy of this ...@@ -70,4 +70,6 @@ This software is distributed under the terms of the MIT license. A copy of this
The documentation is distributed under the terms of the CC-BY-4.0 license. This license can be found in [doc/COPYING.md](doc/COPYING.md). The documentation is distributed under the terms of the CC-BY-4.0 license. This license can be found in [doc/COPYING.md](doc/COPYING.md).
This project strongly profits from the developments done for the [Allpix Squared project](https://cern.ch/allpix-squared) which is released under the MIT license. Especially the configuration class, the module instantiation logic and the file reader and writer modules have profited heavily by their corresponding framework components in Allpix Squared.
The LaTeX and Pandoc CMake modules used by Corryvreckan are licensed under the BSD 3-Clause License. The LaTeX and Pandoc CMake modules used by Corryvreckan are licensed under the BSD 3-Clause License.
#include "Clipboard.hpp" #include "Clipboard.hpp"
#include "core/utils/log.h"
#include "exceptions.h" #include "exceptions.h"
#include "objects/Object.hpp" #include "objects/Object.hpp"
using namespace corryvreckan; using namespace corryvreckan;
void Clipboard::put(std::string name, Objects* objects) { void Clipboard::putPersistentData(std::string name, double value) {
m_data.insert(ClipboardData::value_type(name, objects));
}
void Clipboard::put(std::string name, std::string type, Objects* objects) {
m_data.insert(ClipboardData::value_type(name + type, objects));
}
void Clipboard::put_persistent(std::string name, double value) {
m_persistent_data[name] = value; m_persistent_data[name] = value;
} }
Objects* Clipboard::get(std::string name, std::string type) { double Clipboard::getPersistentData(std::string name) const {
if(m_data.count(name + type) == 0) {
return nullptr;
}
return m_data[name + type];
}
double Clipboard::get_persistent(std::string name) const {
try { try {
return m_persistent_data.at(name); return m_persistent_data.at(name);
} catch(std::out_of_range&) { } catch(std::out_of_range&) {
...@@ -32,11 +16,15 @@ double Clipboard::get_persistent(std::string name) const { ...@@ -32,11 +16,15 @@ double Clipboard::get_persistent(std::string name) const {
} }
} }
bool Clipboard::event_defined() const { bool Clipboard::hasPersistentData(std::string name) const {
return m_persistent_data.find(name) != m_persistent_data.end();
}
bool Clipboard::isEventDefined() const {
return (m_event != nullptr); return (m_event != nullptr);
} }
void Clipboard::put_event(std::shared_ptr<Event> event) { void Clipboard::putEvent(std::shared_ptr<Event> event) {
// Already defined: // Already defined:
if(m_event) { if(m_event) {
throw InvalidDataError("Event already defined. Only one module can place an event definition"); throw InvalidDataError("Event already defined. Only one module can place an event definition");
...@@ -45,25 +33,33 @@ void Clipboard::put_event(std::shared_ptr<Event> event) { ...@@ -45,25 +33,33 @@ void Clipboard::put_event(std::shared_ptr<Event> event) {
} }
} }
std::shared_ptr<Event> Clipboard::get_event() const { std::shared_ptr<Event> Clipboard::getEvent() const {
if(!m_event) { if(!m_event) {
throw InvalidDataError("Event not defined. Add Metronome module or Event reader defining the event"); throw InvalidDataError("Event not defined. Add Metronome module or Event reader defining the event");
} }
return m_event; return m_event;
} }
bool Clipboard::has_persistent(std::string name) const {
return m_persistent_data.find(name) != m_persistent_data.end();
}
void Clipboard::clear() { void Clipboard::clear() {
for(auto set = m_data.cbegin(); set != m_data.cend();) { // Loop over all data types
Objects* collection = set->second; for(auto block = m_data.cbegin(); block != m_data.cend();) {
for(Objects::iterator it = collection->begin(); it != collection->end(); ++it) { auto collections = block->second;
delete(*it);
// Loop over all stored collections of this type
for(auto set = collections.cbegin(); set != collections.cend();) {
std::shared_ptr<ObjectVector> collection = std::static_pointer_cast<ObjectVector>(set->second);
// Loop over all objects and delete them
for(ObjectVector::iterator it = collection->begin(); it != collection->end(); ++it) {
// All objects are destroyed together in this clear function at the end of the event. To avoid costly
// reverse-iterations through the TRef dependency hash lists, we just tell ROOT not to care about possible
// TRef-dependants and to just destroy the object directly by resetting the `kMustCleanup` bit.
(*it)->ResetBit(kMustCleanup);
// Delete the object itself:
delete(*it);
}
set = collections.erase(set);
} }
delete collection; block = m_data.erase(block);
set = m_data.erase(set);
} }
// Resetting the event definition: // Resetting the event definition:
...@@ -72,8 +68,20 @@ void Clipboard::clear() { ...@@ -72,8 +68,20 @@ void Clipboard::clear() {
std::vector<std::string> Clipboard::listCollections() const { std::vector<std::string> Clipboard::listCollections() const {
std::vector<std::string> collections; std::vector<std::string> collections;
for(auto& dataset : m_data) {
collections.push_back(dataset.first); for(const auto& block : m_data) {
std::string line(corryvreckan::demangle(block.first.name()));
line += ": ";
for(const auto& set : block.second) {
std::shared_ptr<ObjectVector> collection = std::static_pointer_cast<ObjectVector>(set.second);
line += set.first + " (" + collection->size() + ") ";
}
line += "\n";
collections.push_back(line);
} }
return collections; return collections;
} }
const ClipboardData& Clipboard::getAll() const {
return m_data;
}
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <string> #include <string>
#include <typeindex>
#include <unordered_map> #include <unordered_map>
#include "core/utils/log.h" #include "core/utils/log.h"
...@@ -20,6 +21,7 @@ ...@@ -20,6 +21,7 @@
#include "objects/Object.hpp" #include "objects/Object.hpp"
namespace corryvreckan { namespace corryvreckan {
typedef std::map<std::type_index, std::map<std::string, std::shared_ptr<void>>> ClipboardData;
/** /**
* @brief Class for temporary data storage for exachange between modules * @brief Class for temporary data storage for exachange between modules
...@@ -32,6 +34,7 @@ namespace corryvreckan { ...@@ -32,6 +34,7 @@ namespace corryvreckan {
* information which should outlast a single event. This is dubbed the "persistent storage" * information which should outlast a single event. This is dubbed the "persistent storage"
*/ */
class Clipboard { class Clipboard {
friend class ModuleManager;
public: public:
/** /**
...@@ -44,54 +47,44 @@ namespace corryvreckan { ...@@ -44,54 +47,44 @@ namespace corryvreckan {
virtual ~Clipboard() {} virtual ~Clipboard() {}
/** /**
* @brief Add object to the clipboard * @brief Method to add a vector of objects to the clipboard
* @param name Name of the collection to be stored * @param objects Shared pointer to vector of objects to be stored
* @param objects vector of Objects to store * @param key Identifying key for this set of objects. Defaults to empty key
*/ */
void put(std::string name, Objects* objects); template <typename T> void putData(std::shared_ptr<std::vector<T*>> objects, const std::string& key = "");
/** /**
* @brief Add object to the clipboard * @brief Method to retrieve objects from the clipboard
* @param name Name of the collection to be stored * @param key Identifying key of objects to be fetched. Defaults to empty key
* @param type Type of the object collection to be stored
* @param Objects vector of Objects to store
*/ */
void put(std::string name, std::string type, Objects* objects); template <typename T> std::shared_ptr<std::vector<T*>> getData(const std::string& key = "") const;
/**
* @brief Retrieve objects from the clipboard
* @param name Name of the object collection to fetch
* @param type Type of objects to be retrieved
* @return Vector of Object pointers
*/
Objects* get(std::string name, std::string type = "");
/** /**
* @brief Check whether an event has been defined * @brief Check whether an event has been defined
* @return true if an event has been defined, false otherwise * @return true if an event has been defined, false otherwise
*/ */
bool event_defined() const; bool isEventDefined() const;
/** /**
* @brief Store the event object * @brief Store the event object
* @param event The event object to be stored * @param event The event object to be stored
* @thorws InvalidDataError in case an event exist already * @thorws InvalidDataError in case an event exist already
*/ */
void put_event(std::shared_ptr<Event> event); void putEvent(std::shared_ptr<Event> event);
/** /**
* @brief Retrieve the event object * @brief Retrieve the event object
* @returnShared pointer to the event * @returnShared pointer to the event
* @throws MissingDataError in case no event is available. * @throws MissingDataError in case no event is available.
*/ */
std::shared_ptr<Event> get_event() const; std::shared_ptr<Event> getEvent() const;
/** /**
* @brief Store or update variable on the persistent clipboard storage * @brief Store or update variable on the persistent clipboard storage
* @param name Name of the variable * @param name Name of the variable
* @param value Value to be stored * @param value Value to be stored
*/ */
void put_persistent(std::string name, double value); void putPersistentData(std::string name, double value);
/** /**
* @brief Retrieve variable from the persistent clipboard storage * @brief Retrieve variable from the persistent clipboard storage
...@@ -99,19 +92,14 @@ namespace corryvreckan { ...@@ -99,19 +92,14 @@ namespace corryvreckan {
* @return Stored value from the persistent clipboard storage * @return Stored value from the persistent clipboard storage
* @throws MissingDataError in case the key is not found. * @throws MissingDataError in case the key is not found.
*/ */
double get_persistent(std::string name) const; double getPersistentData(std::string name) const;
/** /**
* @brief Check if variable exists on the persistent clipboard storage * @brief Check if variable exists on the persistent clipboard storage
* @param name Name of the variable * @param name Name of the variable
* @return True if value exists, false if it does not exist. * @return True if value exists, false if it does not exist.
*/ */
bool has_persistent(std::string name) const; bool hasPersistentData(std::string name) const;
/**
* @brief Clear the event storage of the clipboard
*/
void clear();
/** /**
* @brief Get a list of currently held collections on the clipboard event storage * @brief Get a list of currently held collections on the clipboard event storage
...@@ -119,8 +107,17 @@ namespace corryvreckan { ...@@ -119,8 +107,17 @@ namespace corryvreckan {
*/ */
std::vector<std::string> listCollections() const; std::vector<std::string> listCollections() const;
/**
* @brief Retrieve all currently stored clipboard data
* @return All clipboard data
*/
const ClipboardData& getAll() const;
private: private:
typedef std::map<std::string, Objects*> ClipboardData; /**
* @brief Clear the event storage of the clipboard
*/
void clear();
// Container for data, list of all data held // Container for data, list of all data held
ClipboardData m_data; ClipboardData m_data;
...@@ -133,4 +130,7 @@ namespace corryvreckan { ...@@ -133,4 +130,7 @@ namespace corryvreckan {
}; };
} // namespace corryvreckan } // namespace corryvreckan
// Include template members
#include "Clipboard.tpp"
#endif // CORRYVRECKAN_CLIPBOARD_H #endif // CORRYVRECKAN_CLIPBOARD_H
namespace corryvreckan {
template <typename T> void Clipboard::putData(std::shared_ptr<std::vector<T*>> objects, const std::string& key) {
// Do not insert empty sets:
if(objects->empty()) {
return;
}
// Iterator for data type:
ClipboardData::iterator type = m_data.begin();
/* If data type exists, returns iterator to offending key, if data type does not exist yet, creates new entry and
* returns iterator to the newly created element
*/
type = m_data.insert(type, ClipboardData::value_type(typeid(T), std::map<std::string, std::shared_ptr<void>>()));
// Insert data into data type element, silently fail if it exists already
auto test = type->second.insert(std::make_pair(key, std::static_pointer_cast<void>(objects)));
if(!test.second) {
LOG(WARNING) << "Not inserted for " << key;
}
}
template <typename T> std::shared_ptr<std::vector<T*>> Clipboard::getData(const std::string& key) const {
if(m_data.count(typeid(T)) == 0 || m_data.at(typeid(T)).count(key) == 0) {
return nullptr;
}
return std::static_pointer_cast<std::vector<T*>>(m_data.at(typeid(T)).at(key));
}
} // namespace corryvreckan
...@@ -380,7 +380,7 @@ bool Detector::isWithinROI(Cluster* cluster) const { ...@@ -380,7 +380,7 @@ bool Detector::isWithinROI(Cluster* cluster) const {
} }
// Loop over all pixels of the cluster // Loop over all pixels of the cluster
for(auto& pixel : (*cluster->pixels())) { for(auto& pixel : cluster->pixels()) {
if(winding_number(pixel->coordinates(), m_roi) == 0) { if(winding_number(pixel->coordinates(), m_roi) == 0) {
return false; return false;
} }
......
...@@ -564,7 +564,7 @@ void ModuleManager::run() { ...@@ -564,7 +564,7 @@ void ModuleManager::run() {
break; break;
} }
if(m_clipboard->event_defined() && run_time > 0.0 && m_clipboard->get_event()->start() >= run_time) { if(m_clipboard->isEventDefined() && run_time > 0.0 && m_clipboard->getEvent()->start() >= run_time) {
break; break;
} }
...@@ -574,7 +574,7 @@ void ModuleManager::run() { ...@@ -574,7 +574,7 @@ void ModuleManager::run() {
} }
// Print statistics: // Print statistics:
Tracks* tracks = reinterpret_cast<Tracks*>(m_clipboard->get("tracks")); auto tracks = m_clipboard->getData<Track>();
m_tracks += (tracks == nullptr ? 0 : static_cast<int>(tracks->size())); m_tracks += (tracks == nullptr ? 0 : static_cast<int>(tracks->size()));
if(m_events % 100 == 0) { if(m_events % 100 == 0) {
...@@ -590,8 +590,8 @@ void ModuleManager::run() { ...@@ -590,8 +590,8 @@ void ModuleManager::run() {
LOG_PROGRESS(STATUS, "event_loop") LOG_PROGRESS(STATUS, "event_loop")
<< "Ev: " << kilo_or_mega(m_events) << " Tr: " << kilo_or_mega(m_tracks) << " (" << std::setprecision(3) << "Ev: " << kilo_or_mega(m_events) << " Tr: " << kilo_or_mega(m_tracks) << " (" << std::setprecision(3)
<< (static_cast<double>(m_tracks) / m_events) << "/ev)" << (static_cast<double>(m_tracks) / m_events) << "/ev)"
<< (m_clipboard->event_defined() << (m_clipboard->isEventDefined()
? " t = " + Units::display(m_clipboard->get_event()->start(), {"ns", "us", "ms", "s"}) ? " t = " + Units::display(m_clipboard->getEvent()->start(), {"ns", "us", "ms", "s"})
: ""); : "");
} }
......
/** /**
* @file * @file
* @brief Collection of simple file system utilities * @brief Collection of simple file system utilities
* @copyright Copyright (c) 2017-2018 CERN and the Allpix Squared authors.
* @copyright Copyright (c) 2017 CERN and the Corryvreckan authors. * @copyright Copyright (c) 2017 CERN and the Corryvreckan authors.
* This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md". * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
* In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an
......
...@@ -39,7 +39,7 @@ namespace corryvreckan { ...@@ -39,7 +39,7 @@ namespace corryvreckan {
// Remove corryvreckan tag if necessary // Remove corryvreckan tag if necessary
std::string str = res.get(); std::string str = res.get();
if(!keep_corryvreckan && str.find("corryvreckan::") == 0) { if(!keep_corryvreckan && str.find("corryvreckan::") == 0) {
return str.substr(8); return str.substr(14);
} }
return str; return str;
} }
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
using namespace corryvreckan; using namespace corryvreckan;
// Global container declarations // Global container declarations
Tracks globalTracks; TrackVector globalTracks;
std::shared_ptr<Detector> globalDetector; std::shared_ptr<Detector> globalDetector;
AlignmentDUTResidual::AlignmentDUTResidual(Configuration config, std::shared_ptr<Detector> detector) AlignmentDUTResidual::AlignmentDUTResidual(Configuration config, std::shared_ptr<Detector> detector)
...@@ -58,7 +58,7 @@ void AlignmentDUTResidual::initialise() { ...@@ -58,7 +58,7 @@ void AlignmentDUTResidual::initialise() {
StatusCode AlignmentDUTResidual::run(std::shared_ptr<Clipboard> clipboard) { StatusCode AlignmentDUTResidual::run(std::shared_ptr<Clipboard> clipboard) {
// Get the tracks // Get the tracks
Tracks* tracks = reinterpret_cast<Tracks*>(clipboard->get("tracks")); auto tracks = clipboard->getData<Track>();
if(tracks == nullptr) { if(tracks == nullptr) {
return StatusCode::Success; return StatusCode::Success;
} }
...@@ -83,7 +83,7 @@ StatusCode AlignmentDUTResidual::run(std::shared_ptr<Clipboard> clipboard) { ...@@ -83,7 +83,7 @@ StatusCode AlignmentDUTResidual::run(std::shared_ptr<Clipboard> clipboard) {
} }
} }
Track* alignmentTrack = new Track(track); Track* alignmentTrack = new Track(*track);
m_alignmenttracks.push_back(alignmentTrack); m_alignmenttracks.push_back(alignmentTrack);
// Find the cluster that needs to have its position recalculated // Find the cluster that needs to have its position recalculated
...@@ -214,7 +214,7 @@ void AlignmentDUTResidual::finalise() { ...@@ -214,7 +214,7 @@ void AlignmentDUTResidual::finalise() {
size_t n_associatedClusters = 0; size_t n_associatedClusters = 0;
// count associated clusters: // count associated clusters:
for(auto& track : globalTracks) { for(auto& track : globalTracks) {
Clusters associatedClusters = track->associatedClusters(); ClusterVector associatedClusters = track->associatedClusters();
for(auto& associatedCluster : associatedClusters) { for(auto& associatedCluster : associatedClusters) {
std::string detectorID = associatedCluster->detectorID(); std::string detectorID = associatedCluster->detectorID();
if(detectorID != name) { if(detectorID != name) {
......
...@@ -55,7 +55,7 @@ namespace corryvreckan { ...@@ -55,7 +55,7 @@ namespace corryvreckan {
static void MinimiseResiduals(Int_t& npar, Double_t* grad, Double_t& result, Double_t* par, Int_t flag); static void MinimiseResiduals(Int_t& npar, Double_t* grad, Double_t& result, Double_t* par, Int_t flag);
std::shared_ptr<Detector> m_detector; std::shared_ptr<Detector> m_detector;
Tracks m_alignmenttracks; TrackVector m_alignmenttracks;
int m_discardedtracks{}; int m_discardedtracks{};
size_t nIterations; size_t nIterations;
......
...@@ -69,14 +69,14 @@ void AlignmentMillepede::initialise() { ...@@ -69,14 +69,14 @@ void AlignmentMillepede::initialise() {
StatusCode AlignmentMillepede::run(std::shared_ptr<Clipboard> clipboard) { StatusCode AlignmentMillepede::run(std::shared_ptr<Clipboard> clipboard) {
// Get the tracks // Get the tracks
Tracks* tracks = reinterpret_cast<Tracks*>(clipboard->get("tracks")); auto tracks = clipboard->getData<Track>();
if(tracks == nullptr) { if(tracks == nullptr) {
return StatusCode::Success; return StatusCode::Success;
} }
// Make a local copy and store it // Make a local copy and store it
for(auto& track : (*tracks)) { for(auto& track : (*tracks)) {
Track* alignmentTrack = new Track(track); Track* alignmentTrack = new Track(*track);
m_alignmenttracks.push_back(alignmentTrack); m_alignmenttracks.push_back(alignmentTrack);
} }
return StatusCode::Success; return StatusCode::Success;
......
...@@ -94,7 +94,7 @@ namespace corryvreckan { ...@@ -94,7 +94,7 @@ namespace corryvreckan {
const unsigned int n,