EventLoaderEUDAQ2.cpp 7.53 KB
Newer Older
1
2
/**
 * @file
3
 * @brief Implementation of EventLoaderEUDAQ2 module
4
 * @copyright Copyright (c) 2019 CERN and the Corryvreckan authors.
5
6
7
8
9
10
 * 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
 * Intergovernmental Organization or submit itself to any jurisdiction.
 */

#include "EventLoaderEUDAQ2.h"
11
#include "eudaq/FileReader.hh"
12
13
14

using namespace corryvreckan;

15
16
EventLoaderEUDAQ2::EventLoaderEUDAQ2(Configuration config, std::shared_ptr<Detector> detector)
    : Module(std::move(config), detector), m_detector(detector) {
17

18
19
    m_filename = m_config.getPath("file_name", true);
}
20

21
void EventLoaderEUDAQ2::initialise() {
22

23
24
25
26
27
28
29
30
    // open the input file with the eudaq reader
    try {
        reader_ = eudaq::Factory<eudaq::FileReader>::MakeUnique(eudaq::str2hash("native"), m_filename);
    } catch(...) {
        LOG(ERROR) << "eudaq::FileReader could not read the input file ' " << m_filename
                   << " '. Please verify that the path and file name are correct.";
        throw InvalidValueError(m_config, "file_path", "Parsing error!");
    }
31
32
}

33
34
35
36
37
38
39
40
41
42
43
44
45
std::shared_ptr<eudaq::StandardEvent> EventLoaderEUDAQ2::get_next_event() {
    auto stdevt = eudaq::StandardEvent::MakeShared();
    bool decoding_failed = true;

    do {
        // Check if we need a new full event or if we still have some in the cache:
        if(events_.empty()) {
            LOG(TRACE) << "Reading new EUDAQ event from file";
            auto new_event = reader_->GetNextEvent();
            if(!new_event) {
                LOG(DEBUG) << "Reached EOF";
                throw EndOfFile();
            }
46
            // Build buffer from all sub-events:
47
            events_ = new_event->GetSubEvents();
48
49
            // The main event might also contain data, so add it to the buffer:
            events_.push_back(new_event);
50

51
            // FIXME get TLU events with trigger IDs before Ni - sort by name, reversed
52
53
54
55
56
            sort(events_.begin(), events_.end(), [](const eudaq::EventSPC& a, const eudaq::EventSPC& b) -> bool {
                return a->GetDescription() > b->GetDescription();
            });
        }
        LOG(TRACE) << "Buffer contains " << events_.size() << " (sub-) events";
57

58
59
60
61
62
        auto event = events_.front();
        events_.erase(events_.begin());
        decoding_failed = !eudaq::StdEventConverter::Convert(event, stdevt, nullptr);
        LOG(DEBUG) << "Decoding of " << event->GetDescription() << (decoding_failed ? " failed" : " succeeded");
    } while(decoding_failed);
63

64
65
66
    LOG(DEBUG) << "Returning StandardEvent";
    return stdevt;
}
67

68
69
EventLoaderEUDAQ2::EventPosition EventLoaderEUDAQ2::is_within_event(std::shared_ptr<Clipboard> clipboard,
                                                                    std::shared_ptr<eudaq::StandardEvent> evt) {
70

71
    // Check if this event has timestamps available:
72
73
    if(evt->GetTimeBegin() == 0) {
        LOG(DEBUG) << "Event " << evt->GetDescription() << " has no timestamp, comparing trigger number";
74

75
76
77
78
79
        // If there is no event defined yet or the trigger number is unkown, there is little we can do:
        if(!clipboard->event_defined() || !clipboard->get_event()->hasTriggerID(evt->GetTriggerN())) {
            LOG(DEBUG) << "Trigger ID not found in current event.";
            return EventPosition::UNKNOWN;
        }
80

81
82
83
84
85
86
        // Store trigger timestamp in event:
        auto trigger_time = clipboard->get_event()->getTriggerTime(evt->GetTriggerN());
        LOG(DEBUG) << "Assigning trigger time " << Units::display(trigger_time, {"us", "ns"}) << " to event with trigger ID "
                   << evt->GetTriggerN();
        evt->SetTimeBegin(trigger_time);
        evt->SetTimeEnd(trigger_time);
87
    }
88

89
90
    double event_start = evt->GetTimeBegin();
    double event_end = evt->GetTimeEnd();
Jens Kroeger's avatar
Jens Kroeger committed
91

92
    if(!clipboard->event_defined()) {
93
94
95
        LOG(DEBUG) << "Defining Corryvreckan event: " << Units::display(event_start, {"us", "ns"}) << " - "
                   << Units::display(event_end, {"us", "ns"});
        clipboard->put_event(std::make_shared<Event>(event_start, event_end));
96
    }
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

    double clipboard_start = clipboard->get_event()->start();
    double clipboard_end = clipboard->get_event()->end();

    if(event_start < clipboard_start) {
        LOG(DEBUG) << "Event start before Corryvreckan event: " << Units::display(event_start, {"us", "ns"}) << " < "
                   << Units::display(clipboard_start, {"us", "ns"});
        return EventPosition::BEFORE;
    } else if(clipboard_end < event_end) {
        LOG(DEBUG) << "Event end after Corryvreckan event: " << Units::display(event_end, {"us", "ns"}) << " > "
                   << Units::display(clipboard_end, {"us", "ns"});
        return EventPosition::AFTER;
    } else {
        // Store potential trigger numbers, assign to center of event:
        clipboard->get_event()->addTrigger(evt->GetTriggerN(), (event_start + event_start) / 2);
        LOG(DEBUG) << "Stored trigger ID " << evt->GetTriggerN() << " at "
                   << Units::display((event_start + event_start) / 2, {"us", "ns"});
        return EventPosition::DURING;
115
    }
116
}
117

118
void EventLoaderEUDAQ2::store_data(std::shared_ptr<Clipboard> clipboard, std::shared_ptr<eudaq::StandardEvent> evt) {
119

120
121
    Pixels* pixels = new Pixels();

122
123
124
    // Loop over all planes, select the relevant detector:
    for(size_t i_plane = 0; i_plane < evt->NumPlanes(); i_plane++) {
        auto plane = evt->GetPlane(i_plane);
125

126
        // Concatenate plane name according to naming convention: sensor_type + "_" + int
127
128
129
130
        auto plane_name = plane.Sensor() + "_" + std::to_string(i_plane);
        if(m_detector->name() != plane_name) {
            continue;
        }
Jens Kroeger's avatar
Jens Kroeger committed
131

132
        // Loop over all hits and add to pixels vector:
133
        for(unsigned int i = 0; i < plane.GetPixels<int>().size(); i++) {
134
135
            auto col = static_cast<int>(plane.GetX(i));
            auto row = static_cast<int>(plane.GetY(i));
136
137
138
            if(m_detector->masked(col, row)) {
                continue;
            }
139

140
141
            Pixel* pixel =
                new Pixel(m_detector->name(), row, col, static_cast<int>(plane.GetPixel(i)), plane.GetTimestamp(i));
142
            pixels->push_back(pixel);
143
144
        }
    }
145

146
    if(!pixels->empty()) {
147
        LOG(DEBUG) << "Detector " << m_detector->name() << " has " << pixels->size() << " pixels";
148
149
150
        clipboard->put(m_detector->name(), "pixels", reinterpret_cast<Objects*>(pixels));
    } else {
        delete pixels;
151
152
153
154
155
    }
}

StatusCode EventLoaderEUDAQ2::run(std::shared_ptr<Clipboard> clipboard) {

156
    EventPosition current_position = EventPosition::UNKNOWN;
157
    while(1) {
158
159
160
161
162
163
        // Retrieve next event from file/buffer:
        if(!event_) {
            try {
                event_ = get_next_event();
            } catch(EndOfFile&) {
                return StatusCode::EndRun;
164
            }
165
        }
166

167
168
169
170
171
172
173
        // Check if this event is within the currently defined Corryvreckan event:
        current_position = is_within_event(clipboard, event_);
        if(current_position == EventPosition::DURING) {
            LOG(DEBUG) << "Is withing current event, storing data";
            // Store data on the clipboard
            store_data(clipboard, event_);
        }
174

175
176
177
178
        // If this event was after the current event, stop reading:
        if(current_position == EventPosition::AFTER) {
            break;
        }
179

180
181
        // Reset this event to get a new one:
        event_.reset();
182
    }
183
184
185

    LOG(INFO) << "Finished Corryvreckan event";
    return StatusCode::Success;
186
}