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")
# Always include sources from top directory
INCLUDE_DIRECTORIES(src)
# Build objects library
ADD_SUBDIRECTORY(src/objects)
SET(CORRYVRECKAN_LIBRARIES ${CORRYVRECKAN_LIBRARIES} CorryvreckanObjects)
# Build core Corryvreckan library
ADD_SUBDIRECTORY(src/core)
SET(CORRYVRECKAN_LIBRARIES ${CORRYVRECKAN_LIBRARIES} CorryvreckanCore)
# Build objects library
ADD_SUBDIRECTORY(src/objects)
SET(CORRYVRECKAN_LIBRARIES ${CORRYVRECKAN_LIBRARIES} CorryvreckanObjects)
# Build required modules
ADD_SUBDIRECTORY(src/modules)
......
......@@ -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).
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.
#include "Clipboard.hpp"
#include "core/utils/log.h"
#include "exceptions.h"
#include "objects/Object.hpp"
using namespace corryvreckan;
void Clipboard::put(std::string name, Objects* objects) {
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) {
void Clipboard::putPersistentData(std::string name, double value) {
m_persistent_data[name] = value;
}
Objects* Clipboard::get(std::string name, std::string type) {
if(m_data.count(name + type) == 0) {
return nullptr;
}
return m_data[name + type];
}
double Clipboard::get_persistent(std::string name) const {
double Clipboard::getPersistentData(std::string name) const {
try {
return m_persistent_data.at(name);
} catch(std::out_of_range&) {
......@@ -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);
}
void Clipboard::put_event(std::shared_ptr<Event> event) {
void Clipboard::putEvent(std::shared_ptr<Event> event) {
// Already defined:
if(m_event) {
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) {
}
}
std::shared_ptr<Event> Clipboard::get_event() const {
std::shared_ptr<Event> Clipboard::getEvent() const {
if(!m_event) {
throw InvalidDataError("Event not defined. Add Metronome module or Event reader defining the 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() {
for(auto set = m_data.cbegin(); set != m_data.cend();) {
Objects* collection = set->second;
for(Objects::iterator it = collection->begin(); it != collection->end(); ++it) {
delete(*it);
// Loop over all data types
for(auto block = m_data.cbegin(); block != m_data.cend();) {
auto collections = block->second;
// 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;
set = m_data.erase(set);
block = m_data.erase(block);
}
// Resetting the event definition:
......@@ -72,8 +68,20 @@ void Clipboard::clear() {
std::vector<std::string> Clipboard::listCollections() const {
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;
}
const ClipboardData& Clipboard::getAll() const {
return m_data;
}
......@@ -13,6 +13,7 @@
#include <iostream>
#include <memory>
#include <string>
#include <typeindex>
#include <unordered_map>
#include "core/utils/log.h"
......@@ -20,6 +21,7 @@
#include "objects/Object.hpp"
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
......@@ -32,6 +34,7 @@ namespace corryvreckan {
* information which should outlast a single event. This is dubbed the "persistent storage"
*/
class Clipboard {
friend class ModuleManager;
public:
/**
......@@ -44,54 +47,44 @@ namespace corryvreckan {
virtual ~Clipboard() {}
/**
* @brief Add object to the clipboard
* @param name Name of the collection to be stored
* @param objects vector of Objects to store
* @brief Method to add a vector of objects to the clipboard
* @param objects Shared pointer to vector of objects to be stored
* @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
* @param name Name of the collection to be stored
* @param type Type of the object collection to be stored
* @param Objects vector of Objects to store
* @brief Method to retrieve objects from the clipboard
* @param key Identifying key of objects to be fetched. Defaults to empty key
*/
void put(std::string name, std::string type, Objects* objects);
/**
* @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 = "");
template <typename T> std::shared_ptr<std::vector<T*>> getData(const std::string& key = "") const;
/**
* @brief Check whether an event has been defined
* @return true if an event has been defined, false otherwise
*/
bool event_defined() const;
bool isEventDefined() const;
/**
* @brief Store the event object
* @param event The event object to be stored
* @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
* @returnShared pointer to the event
* @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
* @param name Name of the variable
* @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
......@@ -99,19 +92,14 @@ namespace corryvreckan {
* @return Stored value from the persistent clipboard storage
* @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
* @param name Name of the variable
* @return True if value exists, false if it does not exist.
*/
bool has_persistent(std::string name) const;
/**
* @brief Clear the event storage of the clipboard
*/
void clear();
bool hasPersistentData(std::string name) const;
/**
* @brief Get a list of currently held collections on the clipboard event storage
......@@ -119,8 +107,17 @@ namespace corryvreckan {
*/
std::vector<std::string> listCollections() const;
/**
* @brief Retrieve all currently stored clipboard data
* @return All clipboard data
*/
const ClipboardData& getAll() const;
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
ClipboardData m_data;
......@@ -133,4 +130,7 @@ namespace corryvreckan {
};
} // namespace corryvreckan
// Include template members
#include "Clipboard.tpp"
#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 {
}
// 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) {
return false;
}
......
......@@ -564,7 +564,7 @@ void ModuleManager::run() {
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;
}
......@@ -574,7 +574,7 @@ void ModuleManager::run() {
}
// 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()));
if(m_events % 100 == 0) {
......@@ -590,8 +590,8 @@ void ModuleManager::run() {
LOG_PROGRESS(STATUS, "event_loop")
<< "Ev: " << kilo_or_mega(m_events) << " Tr: " << kilo_or_mega(m_tracks) << " (" << std::setprecision(3)
<< (static_cast<double>(m_tracks) / m_events) << "/ev)"
<< (m_clipboard->event_defined()
? " t = " + Units::display(m_clipboard->get_event()->start(), {"ns", "us", "ms", "s"})
<< (m_clipboard->isEventDefined()
? " t = " + Units::display(m_clipboard->getEvent()->start(), {"ns", "us", "ms", "s"})
: "");
}
......
/**
* @file
* @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.
* 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
......
......@@ -39,7 +39,7 @@ namespace corryvreckan {
// Remove corryvreckan tag if necessary
std::string str = res.get();
if(!keep_corryvreckan && str.find("corryvreckan::") == 0) {
return str.substr(8);
return str.substr(14);
}
return str;
}
......
......@@ -15,7 +15,7 @@
using namespace corryvreckan;
// Global container declarations
Tracks globalTracks;
TrackVector globalTracks;
std::shared_ptr<Detector> globalDetector;
AlignmentDUTResidual::AlignmentDUTResidual(Configuration config, std::shared_ptr<Detector> detector)
......@@ -58,7 +58,7 @@ void AlignmentDUTResidual::initialise() {
StatusCode AlignmentDUTResidual::run(std::shared_ptr<Clipboard> clipboard) {
// Get the tracks
Tracks* tracks = reinterpret_cast<Tracks*>(clipboard->get("tracks"));
auto tracks = clipboard->getData<Track>();
if(tracks == nullptr) {
return StatusCode::Success;
}
......@@ -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);
// Find the cluster that needs to have its position recalculated
......@@ -214,7 +214,7 @@ void AlignmentDUTResidual::finalise() {
size_t n_associatedClusters = 0;
// count associated clusters:
for(auto& track : globalTracks) {
Clusters associatedClusters = track->associatedClusters();
ClusterVector associatedClusters = track->associatedClusters();
for(auto& associatedCluster : associatedClusters) {
std::string detectorID = associatedCluster->detectorID();
if(detectorID != name) {
......
......@@ -55,7 +55,7 @@ namespace corryvreckan {
static void MinimiseResiduals(Int_t& npar, Double_t* grad, Double_t& result, Double_t* par, Int_t flag);
std::shared_ptr<Detector> m_detector;
Tracks m_alignmenttracks;
TrackVector m_alignmenttracks;
int m_discardedtracks{};
size_t nIterations;
......
......@@ -69,14 +69,14 @@ void AlignmentMillepede::initialise() {
StatusCode AlignmentMillepede::run(std::shared_ptr<Clipboard> clipboard) {
// Get the tracks
Tracks* tracks = reinterpret_cast<Tracks*>(clipboard->get("tracks"));
auto tracks = clipboard->getData<Track>();
if(tracks == nullptr) {
return StatusCode::Success;
}
// Make a local copy and store it
for(auto& track : (*tracks)) {
Track* alignmentTrack = new Track(track);
Track* alignmentTrack = new Track(*track);
m_alignmenttracks.push_back(alignmentTrack);
}
return StatusCode::Success;
......
......@@ -94,7 +94,7 @@ namespace corryvreckan {
const unsigned int n,
const unsigned int m);
Tracks m_alignmenttracks;
TrackVector m_alignmenttracks;
/// Number of global derivatives
unsigned int m_nagb;
......
......@@ -7,7 +7,7 @@ using namespace corryvreckan;
using namespace std;
// Global container declarations
Tracks globalTracks;
TrackVector globalTracks;
std::shared_ptr<Detector> globalDetector;
int detNum;
......@@ -33,7 +33,7 @@ AlignmentTrackChi2::AlignmentTrackChi2(Configuration config, std::vector<std::sh
StatusCode AlignmentTrackChi2::run(std::shared_ptr<Clipboard> clipboard) {
// Get the tracks
Tracks* tracks = reinterpret_cast<Tracks*>(clipboard->get("tracks"));
auto tracks = clipboard->getData<Track>();
if(tracks == nullptr) {
return StatusCode::Success;
}
......@@ -58,7 +58,7 @@ StatusCode AlignmentTrackChi2::run(std::shared_ptr<Clipboard> clipboard) {
}
}
Track* alignmentTrack = new Track(track);
Track* alignmentTrack = new Track(*track);
m_alignmenttracks.push_back(alignmentTrack);
}
......@@ -92,7 +92,7 @@ void AlignmentTrackChi2::MinimiseTrackChi2(Int_t&, Double_t*, Double_t& result,
// Get the track
Track* track = globalTracks[iTrack];
// Get all clusters on the track
Clusters trackClusters = track->clusters();
auto trackClusters = track->clusters();
// Find the cluster that needs to have its position recalculated
for(size_t iTrackCluster = 0; iTrackCluster < trackClusters.size(); iTrackCluster++) {
Cluster* trackCluster = trackClusters[iTrackCluster];
......
......@@ -32,7 +32,7 @@ namespace corryvreckan {
static void MinimiseTrackChi2(Int_t& npar, Double_t* grad, Double_t& result, Double_t* par, Int_t flag);
// Member variables
Tracks m_alignmenttracks;
TrackVector m_alignmenttracks;
int m_discardedtracks{};
size_t nIterations;
......
......@@ -219,7 +219,7 @@ void AnalysisCLICpix::initialise() {
StatusCode AnalysisCLICpix::run(std::shared_ptr<Clipboard> clipboard) {
// Get the clicpix clusters in this event
Clusters* clusters = reinterpret_cast<Clusters*>(clipboard->get(m_detector->name(), "clusters"));
auto clusters = clipboard->getData<Cluster>(m_detector->name());
if(clusters == nullptr) {
LOG(DEBUG) << "No clusters for " << m_detector->name() << " on the clipboard";
return StatusCode::Success;
......@@ -236,7 +236,7 @@ StatusCode AnalysisCLICpix::run(std::shared_ptr<Clipboard> clipboard) {
fillClusterHistos(clusters);
// Get the tracks in this event
Tracks* tracks = reinterpret_cast<Tracks*>(clipboard->get("tracks"));
auto tracks = clipboard->getData<Track>();
if(tracks == nullptr) {
LOG(DEBUG) << "No tracks on the clipboard";
return StatusCode::Success;
......@@ -264,7 +264,7 @@ StatusCode AnalysisCLICpix::run(std::shared_ptr<Clipboard> clipboard) {
// Plot the difference between track intercepts and all clicpix clusters
// Also record which cluster is the closest
bool matched = false;
Clusters trackclusters = track->clusters();
auto trackclusters = track->clusters();
Cluster* bestCluster = nullptr;
double xresidualBest = 10000.;
double yresidualBest = 10000.;
......@@ -388,8 +388,8 @@ StatusCode AnalysisCLICpix::run(std::shared_ptr<Clipboard> clipboard) {
hClusterChargeAssociated4pix->Fill((bestCluster)->charge());
hInterceptClusterSize4->Fill(pixelInterceptX, pixelInterceptY);
}
Pixels* pixels = bestCluster->pixels();
for(auto& pixel : (*pixels)) {
auto pixels = bestCluster->pixels();
for(auto& pixel : pixels) {
hPixelToTMap->Fill(pixel->column(), pixel->row(), pixel->raw());
}
......@@ -403,7 +403,7 @@ StatusCode AnalysisCLICpix::run(std::shared_ptr<Clipboard> clipboard) {
/* for (itCorrelate = clusters->begin(); itCorrelate != clusters->end(); ++itCorrelate) {
if(pixelMatch) break;
// Loop over pixels
Pixels::const_iterator itPixel;
PixelVector::const_iterator itPixel;
for (itPixel = (*itCorrelate)->pixels().begin(); itPixel != (*itCorrelate)->pixels().end(); itPixel++) {
// Get the pixel global position
......@@ -502,7 +502,7 @@ bool AnalysisCLICpix::checkMasked(double chipInterceptRow, double chipInterceptC
// Check if there is another track close to the selected track.
// "Close" is defined as the intercept at the clicpix
bool AnalysisCLICpix::checkProximity(Track* track, Tracks* tracks) {
bool AnalysisCLICpix::checkProximity(Track* track, std::shared_ptr<TrackVector> tracks) {
// Get the intercept of the interested track at the dut
bool close = false;
......@@ -510,7 +510,7 @@ bool AnalysisCLICpix::checkProximity(Track* track, Tracks* tracks) {
// Loop over all other tracks and check if they intercept close to the track
// we are considering
Tracks::iterator itTrack;
TrackVector::iterator itTrack;
for(itTrack = tracks->begin(); itTrack != tracks->end(); itTrack++) {
// Get the track
......@@ -528,11 +528,11 @@ bool AnalysisCLICpix::checkProximity(Track* track, Tracks* tracks) {
}
// Small sub-routine to fill histograms that only need clusters
void AnalysisCLICpix::fillClusterHistos(Clusters* clusters) {
void AnalysisCLICpix::fillClusterHistos(std::shared_ptr<ClusterVector> clusters) {
// Pick up column to generate unique pixel id
int nCols = m_detector->nPixels().X();
Clusters::iterator itc;
ClusterVector::iterator itc;
// Check if this is a new clicpix frame (each frame may be in several events)
// and
......@@ -541,23 +541,22 @@ void AnalysisCLICpix::fillClusterHistos(Clusters* clusters) {
for(itc = clusters->begin(); itc != clusters->end(); ++itc) {
// Loop over pixels and check if there are pixels not known
Pixels* pixels = (*itc)->pixels();
Pixels::iterator itp;
for(itp = pixels->begin(); itp != pixels->end(); itp++) {
auto pixels = (*itc)->pixels();
for(auto& itp : pixels) {
// Check if this clicpix frame is still the current
int pixelID = (*itp)->column() + nCols * (*itp)->row();
if(m_hitPixels[pixelID] != (*itp)->raw()) {
int pixelID = itp->column() + nCols * itp->row();
if(m_hitPixels[pixelID] != itp->raw()) {
// New frame! Reset the stored pixels and trigger number
if(!newFrame) {
m_hitPixels.clear();
newFrame = true;
}
m_hitPixels[pixelID] = (*itp)->raw();
m_hitPixels[pixelID] = itp->raw();
m_triggerNumber = 0;
}
hHitPixels->Fill((*itp)->column(), (*itp)->row());