Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions app/econd_decoder.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,7 @@ int main(int argc, char* argv[]) {
r >> ep;
pflib_log(debug) << "r.eof(): " << std::boolalpha << r.eof()
<< " and bool(r): " << bool(r);
for (const auto& sample : ep.samples) {
sample.to_csv(o);
}
ep.to_csv(o);
count++;
if (nevents > 0 and count >= nevents) {
break;
Expand Down
36 changes: 33 additions & 3 deletions app/tool/algorithm/get_toa_efficiencies.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,33 @@

namespace pflib::algorithm {

template <class EventPacket>
std::array<double, 72> get_toa_efficiencies(
const std::vector<pflib::packing::SingleROCEventPacket>& data) {
const std::vector<EventPacket>& data) {
std::array<double, 72> efficiencies;
/// reserve a vector of the appropriate size to avoid repeating allocation
/// time for all 72 channels
std::vector<int> toas(data.size());
int i_ch = 0; // 0–35
int i_link = 0;

for (int ch{0}; ch < 72; ch++) {
i_link = (ch / 36);
i_ch = ch % 36;
for (std::size_t i{0}; i < toas.size(); i++) {
toas[i] = data[i].channel(ch).toa();
if constexpr (std::is_same_v<
EventPacket,
pflib::packing::MultiSampleECONDEventPacket>) {
toas[i] = data[i].samples[data[i].i_soi].channel(i_link, i_ch).toa();
} else if constexpr (std::is_same_v<
EventPacket,
pflib::packing::SingleROCEventPacket>) {
toas[i] = data[i].channel(ch).toa();
} else {
PFEXCEPTION_RAISE("BadConf",
"Unable to do all_channels_to_csv for the "
"currently configured format.");
}
}
/// we assume that the data provided is not empty otherwise the efficiency
/// calculation is meaningless
Expand All @@ -21,4 +39,16 @@ std::array<double, 72> get_toa_efficiencies(
return efficiencies;
}

} // namespace pflib::algorithm
// -----------------------------------------------------------------------------
// Explicit template instantiations
// -----------------------------------------------------------------------------

// get toa efficiencies
template std::array<double, 72>
pflib::algorithm::get_toa_efficiencies<pflib::packing::SingleROCEventPacket>(
const std::vector<pflib::packing::SingleROCEventPacket>& data);
template std::array<double, 72> pflib::algorithm::get_toa_efficiencies<
pflib::packing::MultiSampleECONDEventPacket>(
const std::vector<pflib::packing::MultiSampleECONDEventPacket>& data);

} // namespace pflib::algorithm
10 changes: 9 additions & 1 deletion app/tool/algorithm/get_toa_efficiencies.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <array>

#include "../pftool.h"
#include "pflib/packing/MultiSampleECONDEventPacket.h"
#include "pflib/packing/SingleROCEventPacket.h"

namespace pflib::algorithm {
Expand All @@ -10,7 +12,13 @@ namespace pflib::algorithm {
* calculate the highest TOA_VREF value for each link, for which there is a
* non-zero TOA efficiency
*/

// templated to match any event packet type
template <class EventPacket>
std::array<double, 72> get_toa_efficiencies(
const std::vector<pflib::packing::SingleROCEventPacket>& data);
const std::vector<EventPacket>& data);

// std::array<double, 72> get_toa_efficiencies(
// const std::vector<pflib::packing::SingleROCEventPacket>& data);

} // namespace pflib::algorithm
155 changes: 105 additions & 50 deletions app/tool/algorithm/level_pedestals.cxx
Original file line number Diff line number Diff line change
@@ -1,59 +1,25 @@
#include "level_pedestals.h"

#include "../daq_run.h"
#include "../tasks/level_pedestals.h"
#include "pflib/utility/median.h"
#include "pflib/utility/string_format.h"

/**
* get the medians of the channel ADC values
*
* This may be helpful in some other contexts, but since it depends on the
* packing library it cannot go into utility. Just keeping it here for now,
* maybe move it into its own header/impl in algorithm.
*
* @param[in] data buffer of single-roc packet data
* @return array of channel ADC values
*
* @note We assume the caller knows what they are doing.
* Calib and Common Mode channels are ignored.
* TOT/TOA and the sample Tp/Tc flags are ignored.
*/
static std::array<int, 72> get_adc_medians(
const std::vector<pflib::packing::SingleROCEventPacket>& data) {
std::array<int, 72> medians;
/// reserve a vector of the appropriate size to avoid repeating allocation
/// time for all 72 channels
std::vector<int> adcs(data.size());
for (int ch{0}; ch < 72; ch++) {
for (std::size_t i{0}; i < adcs.size(); i++) {
adcs[i] = data[i].channel(ch).adc();
}
medians[ch] = pflib::utility::median(adcs);
}
return medians;
}

namespace pflib::algorithm {

std::map<std::string, std::map<std::string, uint64_t>> level_pedestals(
Target* tgt, ROC roc) {
// Helper function to pull the 3 runs
template <class EventPacket> // any use of <EventPacket> is a placeholder for
// what the function gets called with.
static void pedestal_runs(Target* tgt, ROC& roc, std::array<int, 72>& baseline,
std::array<int, 72>& highend,
std::array<int, 72>& lowend,
std::array<int, 2>& target, size_t n_events) {
/// TODO for multi-ROC set ups, we could dynamically determine the number
// of ROCs and the number of channels from the Target
DecodeAndBuffer<EventPacket> buffer{n_events, 2};
static auto the_log_{::pflib::logging::get("level_pedestals")};

/// do three runs of 100 samples each to have well defined pedestals
static const std::size_t n_events = 100;

tgt->setup_run(1, Target::DaqFormat::SIMPLEROC, 1);

std::array<int, 2> target;
std::array<int, 72> baseline, highend, lowend;
DecodeAndBuffer buffer{n_events};

// for future devs:
// I do this weird extra brackets to limit the scope
// of the test_handle object and force it to destruct
// after the run is over (unsetting the parameters).

{ // baseline run
{ // baseline run scope
pflib_log(info) << "100 event baseline run";
auto test_handle = roc.testParameters()
.add_all_channels("SIGN_DAC", 0)
Expand All @@ -62,7 +28,7 @@ std::map<std::string, std::map<std::string, uint64_t>> level_pedestals(
.apply();
daq_run(tgt, "PEDESTAL", buffer, n_events, 100);
pflib_log(trace) << "baseline run done, getting channel medians";
auto medians = get_adc_medians(buffer.get_buffer());
auto medians = get_adc_medians<EventPacket>(buffer.get_buffer());
baseline = medians;
pflib_log(trace) << "got channel medians, getting link medians";
for (int i_link{0}; i_link < 2; i_link++) {
Expand All @@ -75,15 +41,15 @@ std::map<std::string, std::map<std::string, uint64_t>> level_pedestals(
pflib_log(trace) << "got link medians";
}

{ // highend run
{ // highend run scope
pflib_log(info) << "100 event highend run";
auto test_handle = roc.testParameters()
.add_all_channels("SIGN_DAC", 0)
.add_all_channels("DACB", 0)
.add_all_channels("TRIM_INV", 63)
.apply();
daq_run(tgt, "PEDESTAL", buffer, n_events, 100);
highend = get_adc_medians(buffer.get_buffer());
highend = get_adc_medians<EventPacket>(buffer.get_buffer());
}

{ // lowend run
Expand All @@ -94,7 +60,96 @@ std::map<std::string, std::map<std::string, uint64_t>> level_pedestals(
.add_all_channels("TRIM_INV", 0)
.apply();
daq_run(tgt, "PEDESTAL", buffer, n_events, 100);
lowend = get_adc_medians(buffer.get_buffer());
lowend = get_adc_medians<EventPacket>(buffer.get_buffer());
}
}

template <class EventPacket>
static int get_adc(const EventPacket& p, int ch) {
if constexpr (std::is_same_v<EventPacket,
pflib::packing::SingleROCEventPacket>) {
return p.channel(ch).adc();
} else if constexpr (std::is_same_v<
EventPacket,
pflib::packing::MultiSampleECONDEventPacket>) {
// Use link specific channel calculation, this is done in
// singleROCEventPacket.cxx for the other case
// Use the "Sample Of Interest" inside the EventPacket
// TODO this is only true if we only have one ROC's channels enabled
// in the ECON-D. In the more realistic case, we should get the
// link indices depending on which ROC we are aligning
int i_link = ch / 36; // 0 or 1
int i_ch = ch % 36; // 0 - 35

// ECONDEventPacket.h defines channel differently to SingleROCEventPacket.h
// because it can have more than 2 links readout
return p.samples[p.i_soi].channel(i_link, i_ch).adc();
} else {
static_assert(sizeof(EventPacket) == 0,
"Unsupported packet type in get_adc()");
}
}

/**
* get the medians of the channel ADC values
*
* This may be helpful in some other contexts, but since it depends on the
* packing library it cannot go into utility. Just keeping it here for now,
* maybe move it into its own header/impl in algorithm.
*
* @param[in] data buffer of single-roc packet data
* @return array of channel ADC values
*
* @note We assume the caller knows what they are doing.
* Calib and Common Mode channels are ignored.
* TOT/TOA and the sample Tp/Tc flags are ignored.
*/
template <class EventPacket>
static std::array<int, 72> get_adc_medians(
const std::vector<EventPacket>& data) {
std::array<int, 72> medians;
/// reserve a vector of the appropriate size to avoid repeating allocation
/// time for all 72 channels
std::vector<int> adcs(data.size());
for (int ch{0}; ch < 72; ch++) {
for (std::size_t i{0}; i < adcs.size(); i++) {
adcs[i] = get_adc(data[i], ch);
}
medians[ch] = pflib::utility::median(adcs);
}
return medians;
}

std::map<std::string, std::map<std::string, uint64_t>> level_pedestals(
Target* tgt, ROC roc) {
static auto the_log_{::pflib::logging::get("level_pedestals")};

/// do three runs of 100 samples each to have well defined pedestals
static const std::size_t n_events = 100;

// tgt->setup_run(1, Target::DaqFormat::SIMPLEROC, 1);
// Use the DAQ format selected in the pftool DAQ->FORMAT menu so the
// format mode can be chosen interactively by the user.
tgt->setup_run(1, pftool::state.daq_format_mode, 1);
pflib_log(info) << "Using DAQ format mode: "
<< static_cast<int>(pftool::state.daq_format_mode);

std::array<int, 2> target;
std::array<int, 72> baseline, highend, lowend;

if (pftool::state.daq_format_mode == Target::DaqFormat::SIMPLEROC) {
pedestal_runs<pflib::packing::SingleROCEventPacket>(
tgt, roc, baseline, highend, lowend, target, n_events);

} else if (pftool::state.daq_format_mode ==
Target::DaqFormat::ECOND_SW_HEADERS) {
pedestal_runs<pflib::packing::MultiSampleECONDEventPacket>(
tgt, roc, baseline, highend, lowend, target, n_events);

} else {
pflib_log(warn) << "Unsupported DAQ format ("
<< static_cast<int>(pftool::state.daq_format_mode)
<< ") in level_pedestals. Skipping pedestal leveling...";
}

pflib_log(info) << "sample collections done, deducing settings";
Expand Down
50 changes: 34 additions & 16 deletions app/tool/algorithm/toa_vref_scan.cxx
Original file line number Diff line number Diff line change
@@ -1,32 +1,22 @@
#include "toa_vref_scan.h"

#include "../daq_run.h"
#include "../tasks/toa_vref_scan.h"
#include "get_toa_efficiencies.h"
#include "pflib/utility/efficiency.h"
#include "pflib/utility/string_format.h"

namespace pflib::algorithm {

std::map<std::string, std::map<std::string, uint64_t>> toa_vref_scan(
Target* tgt, ROC roc) {
// Templated helpder function
template <class EventPacket>
static void toa_vref_runs(Target* tgt, ROC& roc, size_t n_events,
std::array<int, 2>& target) {
static auto the_log_{::pflib::logging::get("toa_vref_scan")};

/// do a run of 100 samples per toa_vref to measure the TOA
/// efficiency when looking at pedestal data

static const std::size_t n_events = 100;

tgt->setup_run(1, Target::DaqFormat::SIMPLEROC, 1);

std::array<int, 2>
target; // toa_vref is a global parameter (1 value per link)

// there is probably a better way to do the next line
std::array<std::array<double, 256>, 2> final_effs;
DecodeAndBuffer buffer{n_events}; // working in buffer, not in writer
DecodeAndBuffer<EventPacket> buffer{n_events, 2};

// loop over runs, from toa_vref = 0 to = 255

for (int toa_vref{0}; toa_vref < 256; toa_vref++) {
pflib_log(info) << "testing toa_vref = " << toa_vref;
auto test_handle = roc.testParameters()
Expand Down Expand Up @@ -64,6 +54,34 @@ std::map<std::string, std::map<std::string, uint64_t>> toa_vref_scan(
}
target[i_link] = highest_non_zero_eff; // store value
}
}

std::map<std::string, std::map<std::string, uint64_t>> toa_vref_scan(
Target* tgt, ROC roc) {
static auto the_log_{::pflib::logging::get("toa_vref_scan")};

/// do a run of 100 samples per toa_vref to measure the TOA
/// efficiency when looking at pedestal data

static const std::size_t n_events = 100;

tgt->setup_run(1, pftool::state.daq_format_mode, 1);

std::array<int, 2> target;
// toa_vref is a global parameter (1 value per link)

if (pftool::state.daq_format_mode == Target::DaqFormat::SIMPLEROC) {
toa_vref_runs<pflib::packing::SingleROCEventPacket>(tgt, roc, n_events,
target);
} else if (pftool::state.daq_format_mode ==
Target::DaqFormat::ECOND_SW_HEADERS) {
toa_vref_runs<pflib::packing::MultiSampleECONDEventPacket>(
tgt, roc, n_events, target);
} else {
pflib_log(warn) << "Unsupported DAQ format ("
<< static_cast<int>(pftool::state.daq_format_mode)
<< ") in level_pedestals. Skipping pedestal leveling...";
}

std::map<std::string, std::map<std::string, uint64_t>> settings;
for (int i_link{0}; i_link < 2; i_link++) {
Expand Down
Loading