Files
slsDetectorPackage/slsDetectorSoftware/tests/acquire/ExpectedState.cpp
T
maliakal_d eff61ec624
Run Simulator Tests on local RHEL9 / build (push) Failing after 56s
Build on RHEL9 docker image / build (push) Failing after 1m53s
Build on RHEL8 docker image / build (push) Failing after 2m5s
Run Simulator Tests on local RHEL8 / build (push) Failing after 2m29s
wip, at ctbexpectedstate
2026-05-28 01:22:24 +02:00

321 lines
12 KiB
C++

// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#include "ExpectedState.h"
#include "Caller/test-Caller-global.h"
#include "receiver_defs.h"
namespace {
using sls::defs;
using sls::Detector;
using ns = std::chrono::nanoseconds;
namespace acq = sls::test::acquire;
defs::detectorType get_detector_type(const Detector &det) {
return det.getDetectorType().tsquash("Inconsistent detector type");
}
defs::xy get_geometry (const Detector& det) {
auto modGeometry = det.getModuleGeometry();
auto portperModGeometry = det.getPortPerModuleGeometry();
return defs::xy{modGeometry.x * portperModGeometry.x,
modGeometry.y * portperModGeometry.y};
}
int get_dynamic_range(const Detector &det) {
return det.getDynamicRange().tsquash("Inconsistent dynamic range");
}
int get_image_size(const Detector &det) {
auto det_type = get_detector_type(det);
auto dynamic_range = get_dynamic_range(det);
int bytes_per_pixel = dynamic_range / 8;
int image_size = 0;
detParameters par(det_type);
switch (det_type) {
case defs::EIGER: {
int num_chips = (par.nChipX / 2);
image_size = par.nChanX * par.nChanY * num_chips * bytes_per_pixel;
} break;
case defs::JUNGFRAU:
case defs::MOENCH: {
auto num_udp_interfaces = det.getNumberofUDPInterfaces().tsquash(
"inconsistent number of udp interfaces");
image_size = (par.nChanX * par.nChanY * par.nChipX * par.nChipY *
bytes_per_pixel) /
num_udp_interfaces;
} break;
case defs::MYTHEN3: {
int counter_mask = det.getCounterMask().squash();
int num_counters = __builtin_popcount(counter_mask);
int num_channels_per_counter = par.nChanX / MAX_NUM_COUNTERS;
image_size = num_channels_per_counter * num_counters * par.nChipX *
bytes_per_pixel;
} break;
case defs::GOTTHARD2: {
image_size = par.nChanX * par.nChipX * bytes_per_pixel;
} break;
case defs::CHIPTESTBOARD:
case defs::XILINX_CHIPTESTBOARD: {
acq::CTBState test_info = acq::default_ctb_state();
image_size = sls::calculate_ctb_image_size(
test_info, (det_type == defs::XILINX_CHIPTESTBOARD))
.first;
} break;
default:
throw sls::RuntimeError("Unsupported detector type for this test");
}
}
defs::xy get_port_shape(const Detector &det) {
auto det_type = get_detector_type(det);
auto portSize = det.getPortSize()[0];
// m3 assumes all counters enabled when getting num channels from client
// TODO: in future, remove assumption
if (det_type == defs::MYTHEN3) {
int nchan = portSize.x / MAX_NUM_COUNTERS;
auto counter_mask = det.getCounterMask().tsquash(
"Inconsistent counter mask for Mythen3 detector");
int num_counters = __builtin_popcount(counter_mask);
portSize.x = nchan * num_counters;
} else if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) {
acq::CTBState test_info = acq::default_ctb_state();
portSize.x = sls::calculate_ctb_image_size(
test_info, det_type == defs::XILINX_CHIPTESTBOARD)
.second;
portSize.y = 1;
}
return portSize;
}
uint64_t get_total_frames(const Detector &det) {
uint64_t repeats =
det.getNumberOfTriggers().tsquash("Inconsistent number of triggers");
uint64_t numFrames =
det.getNumberOfFrames().tsquash("Inconsistent number of frames");
int numAdditionalStorageCells = 0;
auto det_type = get_detector_type(det);
if (det_type == defs::GOTTHARD2) {
auto timing_mode =
det.getTimingMode().tsquash("Inconsistent timing mode");
auto burst_mode = det.getBurstMode().tsquash("Inconsistent burst mode");
auto numBursts =
det.getNumberOfBursts().tsquash("Inconsistent number of bursts");
if (timing_mode == defs::AUTO_TIMING) {
// burst mode, repeats = #bursts
if (burst_mode == defs::BURST_INTERNAL ||
burst_mode == defs::BURST_EXTERNAL) {
repeats = numBursts;
}
// continuous, repeats = 1 (no trigger as well)
else {
repeats = 1;
}
} else {
// trigger
// continuous, numFrames is limited
if (burst_mode == defs::CONTINUOUS_INTERNAL ||
burst_mode == defs::CONTINUOUS_EXTERNAL) {
numFrames = 1;
}
}
} else if (det_type == defs::JUNGFRAU) {
numAdditionalStorageCells =
det.getNumberOfAdditionalStorageCells().tsquash(
"Inconsistent number of additional storage cells");
}
uint64_t total_frames =
numFrames * repeats * (int64_t)(numAdditionalStorageCells + 1);
return total_frames;
}
std::vector<defs::ROI> get_rois(const Detector &det) {
auto rois = det.getRxROI();
auto detsize = det.getDetectorSize();
auto det_type = get_detector_type(det);
// compensate for m3 channel size and counter mask mess
if (det_type == defs::MYTHEN3) {
int nchan = detsize.x / MAX_NUM_COUNTERS;
auto counter_mask = det.getCounterMask().tsquash(
"Inconsistent counter mask for Mythen3 detector");
int num_counters = __builtin_popcount(counter_mask);
detsize.x = nchan * num_counters;
}
// replace -1 for complete ROI
bool is2D = (detsize.y > 1);
for (auto &roi : rois) {
if (roi.completeRoi()) {
roi.xmin = 0;
roi.xmax = detsize.x - 1;
if (is2D) {
roi.ymin = 0;
roi.ymax = detsize.y - 1;
}
}
}
return rois;
}
ns get_exptime(const Detector &det) {
return ns(det.getExptime().tsquash("Inconsistent exposure time"));
}
ns get_period(const Detector &det) {
return ns(det.getPeriod().tsquash("Inconsistent exposure time"));
}
int get_num_udp_interfaces(const Detector &det) {
return det.getNumberofUDPInterfaces().tsquash("Inconsistent number of UDP interfaces");
}
int get_read_n_rows(const Detector &det) {
return det.getReadNRows().tsquash("Inconsistent number of read rows");
}
defs::speedLevel get_readout_speed(const Detector &det) {
return det.getReadoutSpeed().tsquash("Inconsistent readout speed");
}
bool ten_giga(const Detector &det) {
return det.getTenGiga().tsquash("Inconsistent 10Giga setting");
}
std::pair<ns, ns> get_sub_exptime_and_sub_period(const Detector& det) {
auto exptime = det.getSubExptime().tsquash("Inconsistent sub exptime");
auto deadtime = det.getSubDeadTime().tsquash("Inconsistent sub deadtime");
auto sub_period = exptime + deadtime;
return std::make_pair(ns(exptime), ns(sub_period));
}
acq::CommonExpectedState build_common_state(const Detector& det) {
acq::CommonExpectedState e;
e.det_type = get_detector_type(det);
e.timing_mode = det.getTimingMode().tsquash("Inconsistent timing mode");
e.geometry = get_geometry(det);
e.image_size = get_image_size(det);
e.port_shape = get_port_shape(det);
e.max_frames_per_file =
det.getFramesPerFile().tsquash("Inconsistent frames per file");
e.frame_discard_policy = det.getRxFrameDiscardPolicy().tsquash("Inconsistent frame discard policy");
e.partial_frames_padding = static_cast<int>(
det.getPartialFramesPadding().tsquash("Inconsistent frame padding"));
e.scan_parameters = det.getScan().tsquash("Inconsistent scan parameters");
e.total_frames = get_total_frames(det);
e.frames_in_file = det.getFramesCaught()[0][0];
e.additional_json_header = det.getAdditionalJsonHeader().tsquash("Inconsistent JSON header");
return e;
}
acq::JungfrauExpectedState build_jungfrau_specific_state(const Detector& det) {
acq::JungfrauExpectedState e;
e.rois = get_rois(det);
e.exptime = get_exptime(det);
e.period = get_period(det);
e.num_udp_interfaces = get_num_udp_interfaces(det);
e.read_n_rows = get_read_n_rows(det);
e.readout_speed = get_readout_speed(det);
return e;
}
acq::MoenchExpectedState build_moench_specific_state(const Detector& det) {
acq::MoenchExpectedState e;
e.rois = get_rois(det);
e.exptime = get_exptime(det);
e.period = get_period(det);
e.num_udp_interfaces = get_num_udp_interfaces(det);
e.read_n_rows = get_read_n_rows(det);
e.readout_speed = get_readout_speed(det);
return e;
}
acq::EigerExpectedState build_eiger_specific_state(const Detector& det) {
acq::EigerExpectedState e;
e.rois = get_rois(det);
e.dynamic_range = get_dynamic_range(det);
e.ten_giga = ten_giga(det);
e.exptime = get_exptime(det);
e.period = get_period(det);
e.threshold_energy = det.getThresholdEnergy().tsquash("Inconsistent threshold energy");
auto [sub_exptime, sub_period] = get_sub_exptime_and_sub_period(det);
e.sub_exptime = sub_exptime;
e.sub_period = sub_period;
e.quad = det.getQuad().tsquash("Inconsistent quad setting");
e.read_n_rows = get_read_n_rows(det);
{
for (auto item : det.getRateCorrection())
e.rate_corrections.push_back(item.count());
}
e.readout_speed = get_readout_speed(det);
return e;
}
acq::Mythen3ExpectedState build_mythen3_specific_state(const Detector& det) {
acq::Mythen3ExpectedState e;
e.rois = get_rois(det);
e.dynamic_range = get_dynamic_range(det);
e.ten_giga = ten_giga(det);
e.period = get_period(det);
e.counter_mask = det.getCounterMask().tsquash("Inconsistent counter mask for Mythen3 detector");
e.exp_times = det.getExptimeForAllGates().tsquash("Inconsistent exposure times for all gates");
e.gate_delays = det.getGateDelayForAllGates().tsquash("Inconsistent gate delays");
e.num_gates = det.getNumberOfGates().tsquash("Inconsistent number of gates for Mythen3 detector");
e.threshold_energies = det.getAllThresholdEnergy().tsquash("Inconsistent threshold energies");
e.readout_speed = get_readout_speed(det);
return e;
}
acq::Gotthard2ExpectedState build_gotthard2_specific_state(const Detector& det) {
acq::Gotthard2ExpectedState e;
e.rois = get_rois(det);
e.exptime = get_exptime(det);
e.period = get_period(det);
e.burst_mode = det.getBurstMode().tsquash("Inconsistent burst mode");
e.readout_speed = get_readout_speed(det);
return e;
}
acq::CTBExpectedState build_ctb_specific_state(const Detector& det, const acq::CTBState& ctb_state) {
acq::CTBExpectedState e;
e.exptime = get_exptime(det);
e.period = get_period(det);
e.ctb_acq_state = ctb_state;
return e;
}
acq::DetectorSpecificState build_detector_specific_state(const Detector& det, const acq::CTBState& ctb_state) {
switch (det.getDetectorType().tsquash("bad type")) {
case defs::JUNGFRAU:
return build_jungfrau_specific_state(det);
case defs::MOENCH:
return build_moench_specific_state(det);
case defs::EIGER:
return build_eiger_specific_state(det);
case defs::MYTHEN3:
return build_mythen3_specific_state(det);
case defs::GOTTHARD2:
return build_gotthard2_specific_state(det);
case defs::CHIPTESTBOARD:
case defs::XILINX_CHIPTESTBOARD:
return build_ctb_specific_state(det, ctb_state);
}
throw sls::RuntimeError("Unsupported detector type");
}
} // anonymous namespace
namespace sls::test::acquire {
ExpectedState build_expected_state(const Detector& det, const AcquisitionState &acq_state, const FileState &file_state, const CTBState &ctb_state) {
ExpectedState e;
e.common_state = build_common_state(det);
e.file_state = file_state;
e.acquisition_state = acq_state;
e.detector_specific_state = build_detector_specific_state(det, ctb_state);
return e;
}
} // namespace sls::test::acquire