Commit 45a41171 authored by Lennart Huth's avatar Lennart Huth
Browse files

Merge branch 'fix_eventdefinitionm26' into 'master'

Fixes to EventDefinitionM26

See merge request !369
parents 4792df3a b8160e24
Pipeline #2024864 passed with stages
in 36 minutes and 9 seconds
/**
* @file
* @brief Implementation of module EventCreatorEUDAQ2
* @brief Implementation of module EventDefinitionM26
*
* @copyright Copyright (c) 2020 CERN and the Corryvreckan authors.
* This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
......@@ -14,17 +14,41 @@ using namespace corryvreckan;
EventDefinitionM26::EventDefinitionM26(Configuration& config, std::vector<std::shared_ptr<Detector>> detectors)
: Module(config, std::move(detectors)) {
config_.setDefault<int>("time_shift", 0);
config_.setDefault<int>("shift_triggers", 0);
config_.setDefault<std::string>("eudaq_loglevel", "ERROR");
config_.setDefault<double>("response_time_m26", Units::get<double>(0, "us"));
config_.setDefault<double>("skip_time", 0.);
detector_time_ = config_.get<std::string>("detector_event_time");
detector_duration_ = config_.get<std::string>("detector_event_duration");
duration_ = config_.get<std::string>("file_duration");
timestamp_ = config_.get<std::string>("file_timestamp");
timeshift_ = config_.get<double>("time_shift");
shift_triggers_ = config_.get<int>("shift_triggers");
skip_time_ = config_.get<double>("skip_time");
config_.setDefault<std::string>("eudaq_loglevel", "ERROR");
// Set EUDAQ log level to desired value:
EUDAQ_LOG_LEVEL(config_.get<std::string>("eudaq_loglevel"));
LOG(INFO) << "Setting EUDAQ2 log level to \"" << config_.get<std::string>("eudaq_loglevel") << "\"";
// Prepare EUDAQ2 config object
eudaq::Configuration cfg;
// Forward all settings to EUDAQ
// WARNING: the EUDAQ Configuration class is not very flexible and e.g. booleans have to be passed as 1 and 0.
auto configs = config_.getAll();
for(const auto& key : configs) {
LOG(DEBUG) << "Forwarding key \"" << key.first << " = " << key.second << "\" to EUDAQ converter";
cfg.Set(key.first, key.second);
}
// Converting the newly built configuration to a shared pointer of a const configuration object
// Unfortunately, EUDAQ does not provide appropriate member functions for their configuration class to avoid this dance
const eudaq::Configuration eu_cfg = cfg;
eudaq_config_ = std::make_shared<const eudaq::Configuration>(eu_cfg);
}
void EventDefinitionM26::initialize() {
......@@ -33,6 +57,15 @@ void EventDefinitionM26::initialize() {
timebetweenTLUEvents_ =
new TH1F("htimebetweenTrigger", "time between two triggers frames; time /us; #entries", 1000, -0.5, 995.5);
timeBeforeTrigger_ = new TH1F("timeBeforeTrigger", "time in frame before trigger; time /us; #entries", 2320, -231, 1);
timeAfterTrigger_ = new TH1F("timeAfterTrigger", "time in frame after trigger; time /us; #entries", 2320, -1, 231);
std::string title = "Corryvreckan event start times (placed on clipboard); Corryvreckan event start time [ms];# entries";
hClipboardEventStart = new TH1D("clipboardEventStart", title.c_str(), 3e6, 0, 3e3);
title = "Corryvreckan event start times (placed on clipboard); Corryvreckan event start time [s];# entries";
hClipboardEventStart_long = new TH1D("clipboardEventStart_long", title.c_str(), 3e6, 0, 3e3);
// open the input file with the eudaq reader
try {
readerDuration_ = eudaq::Factory<eudaq::FileReader>::MakeUnique(eudaq::str2hash("native"), duration_);
......@@ -48,40 +81,47 @@ void EventDefinitionM26::initialize() {
<< " '. Please verify that the path and file name are correct.";
throw InvalidValueError(config_, "file_path", "Parsing error!");
}
// get the first event each
timestampTrig_ = get_next_event_with_det(readerTime_, detector_time_, time_trig_start_, time_trig_stop_);
while((int(timestampTrig_) + shift_triggers_) < 0) {
timestampTrig_ = get_next_event_with_det(readerTime_, detector_time_, time_trig_start_, time_trig_stop_);
}
timestampTrig_ = static_cast<unsigned>(static_cast<int>(timestampTrig_) + shift_triggers_);
durationTrig_ = get_next_event_with_det(readerDuration_, detector_duration_, time_before_, time_after_);
}
unsigned EventDefinitionM26::get_next_event_with_det(eudaq::FileReaderUP& filereader,
std::string& det,
unsigned EventDefinitionM26::get_next_event_with_det(const eudaq::FileReaderUP& filereader,
const std::string& det,
long double& begin,
long double& end) {
do {
LOG(DEBUG) << "Get next event.";
auto evt = filereader->GetNextEvent();
if(!evt) {
LOG(DEBUG) << "Reached end-of-file.";
throw EndOfFile();
}
LOG(DEBUG) << "Get subevents.";
std::vector<eudaq::EventSPC> events_ = evt->GetSubEvents();
if(events_.empty()) {
events_.push_back(evt);
}
for(const auto& e : events_) {
auto stdevt = eudaq::StandardEvent::MakeShared();
if(!eudaq::StdEventConverter::Convert(e, stdevt, eudaq_config_)) {
continue;
}
auto detector = stdevt->GetDetectorType();
LOG(DEBUG) << "det = " << det << ", detector = " << detector;
if(det == detector) {
begin = Units::get(static_cast<double>(stdevt->GetTimeBegin()), "ps");
end = Units::get(static_cast<double>(stdevt->GetTimeEnd()), "ps");
LOG(DEBUG) << "Set begin/end, begin: " << Units::display(begin, {"ns", "us"})
<< ", end: " << Units::display(end, {"ns", "us"});
// MIMOSA
if(det == "MIMOSA26") {
// pivot magic - see readme
double piv = stdevt->GetPlane(0).PivotPixel() / 16.;
begin = Units::get(piv * (115.2 / 576), "us") + timeshift_;
end = Units::get(230.4, "us") - begin;
LOG(DEBUG) << "Pivot magic, begin: " << Units::display(begin, {"ns", "us", "ms"})
<< ", end: " << Units::display(end, {"ns", "us", "ms"})
<< ", duration = " << Units::display(begin + end, {"ns", "us"});
}
return e->GetTriggerN();
}
......@@ -93,56 +133,77 @@ StatusCode EventDefinitionM26::run(const std::shared_ptr<Clipboard>& clipboard)
// Loop over all detectors
if(clipboard->isEventDefined()) {
throw ModuleError(
"Event already defined - cannot crate a new event. This module needs to be placed before the first EventLoader");
throw ModuleError("Event already defined - cannot create a new event. This module needs to be placed before the "
"first EventLoader");
}
// read events until we have a common tag:
try {
triggerTLU_ = static_cast<unsigned>(
static_cast<int>(get_next_event_with_det(readerTime_, detector_time_, time_trig_start_, time_trig_stop_)) +
shift_triggers_);
timebetweenTLUEvents_->Fill(static_cast<double>(Units::convert(time_trig_start_ - trig_prev_, "us")));
trig_prev_ = time_trig_start_;
triggerM26_ = get_next_event_with_det(readerDuration_, "MIMOSA26", time_before_, time_after_);
} catch(EndOfFile&) {
return StatusCode::EndRun;
}
do {
LOG(DEBUG) << "Trigger of timestamp defining event: " << timestampTrig_ << std::endl
<< " Trigger of duration defining event: " << durationTrig_;
try {
if(timestampTrig_ < durationTrig_) {
timestampTrig_ = static_cast<unsigned>(static_cast<int>(get_next_event_with_det(
readerTime_, detector_time_, time_trig_start_, time_trig_stop_)) +
shift_triggers_);
if(triggerTLU_ < triggerM26_) {
LOG(DEBUG) << "TLU trigger smaller than Mimosa26 trigger, get next TLU trigger";
triggerTLU_ = static_cast<unsigned>(static_cast<int>(get_next_event_with_det(
readerTime_, detector_time_, time_trig_start_, time_trig_stop_)) +
shift_triggers_);
timebetweenTLUEvents_->Fill(static_cast<double>(Units::convert(time_trig_start_ - trig_prev_, "us")));
trig_prev_ = time_trig_start_;
} else if(timestampTrig_ > durationTrig_) {
durationTrig_ = get_next_event_with_det(readerDuration_, detector_duration_, time_before_, time_after_);
} else if(triggerTLU_ > triggerM26_) {
LOG(DEBUG) << "Mimosa26 trigger smaller than TLU trigger, get next Mimosa26 trigger";
triggerM26_ = get_next_event_with_det(readerDuration_, "MIMOSA26", time_before_, time_after_);
}
} catch(EndOfFile&) {
return StatusCode::EndRun;
}
if(timestampTrig_ == durationTrig_) {
auto time_trig = (time_trig_start_ + time_trig_stop_) / 2.;
LOG(DEBUG) << "TLU trigger defining event: " << triggerTLU_ << std::endl
<< "Mimosa26 trigger defining event: " << triggerM26_;
if(triggerTLU_ == triggerM26_) {
auto time_trig = time_trig_start_;
if(time_trig - time_prev_ > 0) {
timebetweenMimosaEvents_->Fill(static_cast<double>(Units::convert(time_trig - time_prev_, "us")));
time_prev_ = time_trig;
long double evtstart = time_trig - time_before_;
timeBeforeTrigger_->Fill(static_cast<double>(Units::convert(-1.0 * time_before_, "us")));
timeAfterTrigger_->Fill(static_cast<double>(Units::convert(time_after_, "us")));
long double evtStart = time_trig - time_before_;
long double evtEnd = time_trig + time_after_;
clipboard->putEvent(std::make_shared<Event>(evtstart, evtEnd));
LOG(DEBUG) << "Defining Corryvreckan event: " << Units::display(evtstart, {"us", "ns"}) << " - "
if(evtStart < skip_time_) {
LOG(DEBUG) << "Event start before requested skip time: " << Units::display(evtStart, {"us", "ns"})
<< " < " << Units::display(skip_time_, {"us", "ns"});
continue;
}
LOG(DEBUG) << "time to previous trigger = " << Units::display(time_trig - time_prev_, "us");
time_prev_ = time_trig;
LOG(DEBUG) << "before/after/duration = " << Units::display(time_before_, "us") << ", "
<< Units::display(time_after_, "us") << ", " << Units::display(time_after_ + time_before_, "us");
LOG(DEBUG) << "evtStart/evtEnd/duration = " << Units::display(evtStart, "us") << ", "
<< Units::display(evtEnd, "us") << ", " << Units::display(evtEnd - evtStart, "us");
clipboard->putEvent(std::make_shared<Event>(evtStart, evtEnd));
LOG(DEBUG) << "Defining Corryvreckan event: " << Units::display(evtStart, {"us", "ns"}) << " - "
<< Units::display(evtEnd, {"us", "ns"}) << ", length "
<< Units::display(evtEnd - evtstart, {"us", "ns"});
<< Units::display(evtEnd - evtStart, {"us", "ns"});
hClipboardEventStart->Fill(static_cast<double>(Units::convert(evtStart, "ms")));
hClipboardEventStart_long->Fill(static_cast<double>(Units::convert(evtStart, "s")));
} else {
LOG(WARNING) << "Current trigger time smaller than previous: " << time_trig << " vs " << time_prev_;
}
try {
timestampTrig_ = static_cast<unsigned>(static_cast<int>(get_next_event_with_det(
readerTime_, detector_time_, time_trig_start_, time_trig_stop_)) +
shift_triggers_);
timebetweenTLUEvents_->Fill(static_cast<double>(Units::convert(time_trig_start_ - trig_prev_, "us")));
trig_prev_ = time_trig_start_;
durationTrig_ = get_next_event_with_det(readerDuration_, detector_duration_, time_before_, time_after_);
} catch(EndOfFile&) {
return StatusCode::EndRun;
}
} else if(timestampTrig_ > durationTrig_) {
LOG(DEBUG) << "No TLU time stamp for trigger ID " << timestampTrig_;
} else if(timestampTrig_ < durationTrig_) {
LOG(DEBUG) << "No Mimosa data for trigger ID " << durationTrig_;
} else if(triggerTLU_ > triggerM26_) {
LOG(DEBUG) << "No TLU time stamp for trigger ID " << triggerTLU_;
} else if(triggerTLU_ < triggerM26_) {
LOG(DEBUG) << "No Mimosa data for trigger ID " << triggerM26_;
}
} while(!clipboard->isEventDefined());
......
/**
* @file
* @brief Definition of module EventCreatorEUDAQ2
* @brief Definition of module EventDefinitionM26
*
* @copyright Copyright (c) 2020 CERN and the Corryvreckan authors.
* This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
......@@ -52,33 +52,43 @@ namespace corryvreckan {
std::vector<uint32_t> triggerIDs_{};
long double timeshift_{};
int shift_triggers_{};
double skip_time_{};
// EUDAQ2 readers for all required files
eudaq::FileReaderUP readerTime_;
eudaq::FileReaderUP readerDuration_;
// Detector defining the event time
// Note: detector defining duration of event is always "MIMOSA26"
std::string detector_time_;
// Detector defining the event duration
std::string detector_duration_;
// input data files
std::string timestamp_, duration_;
TH1F* timebetweenMimosaEvents_;
TH1F* timebetweenTLUEvents_;
TH1F* timeBeforeTrigger_;
TH1F* timeAfterTrigger_;
TH1D* hClipboardEventStart;
TH1D* hClipboardEventStart_long;
unsigned timestampTrig_{}, durationTrig_{};
unsigned triggerTLU_{}, triggerM26_{};
long double time_prev_{}, trig_prev_{}, time_trig_start_{}, time_trig_stop_{}, time_before_{}, time_after_{};
long double time_trig_stop_prev_{};
/**
* @brief get_next_event_with_det
* @param filereader: eudaq::FileReader
* @param det: detetcor name to search for in data
* @param det: detector name to search for in data
* @param begin: timestamp of begin of event
* @param end: timestamp of end of event
* @return
*/
unsigned
get_next_event_with_det(eudaq::FileReaderUP& filereader, std::string& det, long double& begin, long double& end);
unsigned get_next_event_with_det(const eudaq::FileReaderUP& filereader,
const std::string& det,
long double& begin,
long double& end);
// EUDAQ configuration to be passed to the decoder instance
eudaq::ConfigurationSPC eudaq_config_;
};
} // namespace corryvreckan
# EventDefinitionM26
**Maintainer**: Lennart Huth (lennart.huth@desy.de)
**Maintainer**: Lennart Huth (lennart.huth@desy.de), Jens Kroeger (jens.kroeger@cern.ch)
**Module Type**: *GLOBAL*
**Status**: Functional
**Status**: Functional
### Description
This global module allows to fully utilize the PIVOT pixel behaviour of the
EUDET type telescopes based on the NI MIMOSA26 readout. The event begin and
end are defined based on the pivot pixel provided in the MIMOSA data
stream. Currently the module assumes that the full two data frames are read
stream. Currently, the module assumes that the full two data frames are read
out, which is not the case in the standard converter.
However, the converter only returns all pixels after the pivot pixel of the
first frame and those before the pivot pixel of the second frame.
Event definition example:
If a triggerID has a TLU event from 425.000us to 425.025us (default
25 ns events) and the pivot pixel-row is 512 the event will be defined as:
```
It should be noted that in about 1 permille of the cases, zero triggers per event are
observed, which should in principle not be possible.
Presumably, the reason is a delay between an incoming trigger signal and the
moment when the pivot pixel is defined.
This causes that in about 1 permille of the cases, the "time before" and
"time after" a trigger spanning the event is not set correctly when the
pivot pixel is close to its roll-over.
```math
begin = 125.012.5us - (512 * (115.2 / 576)) us
end = begin + 230us
```
### Parameters
* `detector_event_time`: Specify the detector used to define the event timestamp
* `detector_event_duration`: Specify detector used to define the begin and end of the event relative to the timestamp provided by `detector_event_time`
* `detector_event_time`: Specify the detector type used to define the event timestamp.
* `file_timestamp`: Data file containing the `detector_event_time` data
* `file_duration`: Data file containing the `detector_event_duration` data
* `file_m26`: Data file containing the `MIMOSA26` data used to define the extend of the event.
* `time_shift`: Optional shift of the event begin/end point. Defaults to `0`
* `shift_triggers`: Shift the trigger ID of the `detector_event_time`. Defaults to `0`
* `eudaq_loglevel`: Verbosity level of the EUDAQ logger instance of the converter module. Possible options are, in decreasing severity, `USER`, `ERROR`, `WARN`, `INFO`, `EXTRA` and `DEBUG`. The default level is `ERROR`.
* `shift_triggers`: Shift the trigger ID of the `detector_event_time`. This allows to correct trigger ID offsets between different devices such as the TLU and MIMOSA26. Note that if using the module `EventLoaderEUDAQ2` the same value for `shift_triggers` needs to be passed in both cases. Defaults to `0`.
* `skip_time`: Time that can be skipped at the start of a run. All events with earlier timestamps are discarded. Default is `0ms`.
* `eudaq_loglevel`: Verbosity level of the EUDAQ logger instance of the converter module. Possible options are, in decreasing severity, `USER`, `ERROR`, `WARN`, `INFO`, `EXTRA` and `DEBUG`. The default level is `ERROR`. Please note that the EUDAQ verbosity can only be changed globally, i.e. when using instances of `EventLoaderEUDAQ2` below this module, the last occurrence will determine the (global) value of this parameter.
In addition, parameters can be forwarded to the EUDAQ2 event converters.
Please refer to the README of the `EventLoaderEUDAQ2` for more details.
### Plots produced
* 1D histogram of time between trigger timestamps
......@@ -35,11 +49,9 @@ end = begin + 230us
### Usage
```toml
[EventDefinitionM26]
detector_event_time = TLU
detector_event_duration = MIMOSA
file_timestamp = tlu_data.raw
file_duration = mimosa_data.raw
time_shift = 0
shift_triggers = 0
shift_triggers = -1
```
......@@ -80,13 +80,13 @@ void EventLoaderEUDAQ2::initialize() {
title = ";EUDAQ event start time[s];# entries";
hEudaqEventStart_long = new TH1D("eudaqEventStart_long", title.c_str(), 3e6, 0, 3e3);
title = "Corryvreckan event start times (on clipboard); Corryvreckan event start time [ms];# entries";
title = "Corryvreckan event start times (placed on clipboard); Corryvreckan event start time [ms];# entries";
hClipboardEventStart = new TH1D("clipboardEventStart", title.c_str(), 3e6, 0, 3e3);
title = "Corryvreckan event start times (on clipboard); Corryvreckan event start time [s];# entries";
title = "Corryvreckan event start times (placed on clipboard); Corryvreckan event start time [s];# entries";
hClipboardEventStart_long = new TH1D("clipboardEventStart_long", title.c_str(), 3e6, 0, 3e3);
title = "Corryvreckan event end times (on clipboard); Corryvreckan event end time [ms];# entries";
title = "Corryvreckan event end times (placed on clipboard); Corryvreckan event end time [ms];# entries";
hClipboardEventEnd = new TH1D("clipboardEventEnd", title.c_str(), 3e6, 0, 3e3);
title = "Corryvreckan event end times (on clipboard); Corryvreckan event duration [ms];# entries";
......@@ -346,8 +346,16 @@ Event::Position EventLoaderEUDAQ2::is_within_event(const std::shared_ptr<Clipboa
<< Units::display(event_end, {"us", "ns"}) << ", length "
<< Units::display(event_end - event_start, {"us", "ns"});
clipboard->putEvent(std::make_shared<Event>(event_start, event_end));
hClipboardEventStart->Fill(static_cast<double>(Units::convert(event_start, "ms")));
hClipboardEventStart_long->Fill(static_cast<double>(Units::convert(event_start, "s")));
hClipboardEventEnd->Fill(static_cast<double>(Units::convert(event_end, "ms")));
hClipboardEventDuration->Fill(
static_cast<double>(Units::convert(clipboard->getEvent()->end() - clipboard->getEvent()->start(), "ms")));
} else {
LOG(DEBUG) << "Corryvreckan event found on clipboard.";
LOG(DEBUG) << "Corryvreckan event found on clipboard: "
<< Units::display(clipboard->getEvent()->start(), {"us", "ns"}) << " - "
<< Units::display(clipboard->getEvent()->end(), {"us", "ns"})
<< ", length: " << Units::display(clipboard->getEvent()->duration(), {"us", "ns"});
}
// Get position of this time frame with respect to the defined event:
......@@ -365,8 +373,7 @@ Event::Position EventLoaderEUDAQ2::is_within_event(const std::shared_ptr<Clipboa
auto trigger_id = static_cast<uint32_t>(static_cast<int>(evt->GetTriggerN()) + shift_triggers_);
// Store potential trigger numbers, assign to center of event:
clipboard->getEvent()->addTrigger(trigger_id, event_timestamp);
LOG(DEBUG) << "Stored trigger ID " << evt->GetTriggerN() << " at "
<< Units::display(event_timestamp, {"us", "ns"});
LOG(DEBUG) << "Stored trigger ID " << trigger_id << " at " << Units::display(event_timestamp, {"us", "ns"});
}
}
......@@ -544,13 +551,6 @@ StatusCode EventLoaderEUDAQ2::run(const std::shared_ptr<Clipboard>& clipboard) {
// Converting EUDAQ2 picoseconds into Corryvreckan nanoseconds:
hEudaqEventStart->Fill(static_cast<double>(event_->GetTimeBegin()) / 1e9); // here convert from ps to ms
hEudaqEventStart_long->Fill(static_cast<double>(event_->GetTimeBegin()) / 1e12); // here convert from ps to seconds
if(clipboard->isEventDefined()) {
hClipboardEventStart->Fill(static_cast<double>(Units::convert(clipboard->getEvent()->start(), "ms")));
hClipboardEventStart_long->Fill(static_cast<double>(Units::convert(clipboard->getEvent()->start(), "s")));
hClipboardEventEnd->Fill(static_cast<double>(Units::convert(clipboard->getEvent()->end(), "ms")));
hClipboardEventDuration->Fill(
static_cast<double>(Units::convert(clipboard->getEvent()->end() - clipboard->getEvent()->start(), "ms")));
}
// Reset this shared event pointer to get a new event from the stack:
event_.reset();
......
......@@ -91,7 +91,7 @@ In addition, the calibration file of the detector specified in the geometry conf
* `ignore_bore`: Boolean to completely ignore the Begin-of-Run event (BORE) from EUDAQ2. Default value is `true`.
* `adjust_event_times`: Matrix that allows the user to shift the event start/end of all different types of EUDAQ events before comparison to any other Corryvreckan data. The first entry of each row specifies the data type, the second is the offset which is added to the event start and the third entry is the offset added to the event end. A usage example is shown below, double brackets are required if only one entry is provided.
* `buffer_depth`: Depth of buffer in which EUDAQ2 `StandardEvents` are timesorted. This algorithm only works for `StandardEvents` with well-defined timestamps. Setting it to `0` disables timesorting. Default is `0`.
* `shift_triggers`: Shift the trigger ID up or down when assigning it to the Corryvreckan event. This allows to correct trigger ID offsets between different devices such as the TLU and MIMOSA26.
* `shift_triggers`: Shift the trigger ID up or down when assigning it to the Corryvreckan event. This allows to correct trigger ID offsets between different devices such as the TLU and MIMOSA26. Note that if using the module `EventDefinitionM26` the same value for `shift_triggers` needs to be passed in both cases. Defaults to `0`.
* `eudaq_loglevel`: Verbosity level of the EUDAQ logger instance of the converter module. Possible options are, in decreasing severity, `USER`, `ERROR`, `WARN`, `INFO`, `EXTRA` and `DEBUG`. The default level is `ERROR`. Please note that the verbosity can only be changed globally, i.e. when using multiple instances of `EventLoaderEUDAQ2`, the last occurrence will determine the (global) value of this parameter.
### Plots produced
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment