Files
Jungfraujoch/common/DiffractionExperiment.cpp
2024-10-07 11:56:40 +02:00

1136 lines
36 KiB
C++

// Copyright (2019-2023) Paul Scherrer Institute
#include <cmath>
#include <utility>
#include "NetworkAddressConvert.h"
#include "JFJochCompressor.h" // For ZSTD_USE_JFJOCH_RLE
#include "DiffractionExperiment.h"
#include "JFJochException.h"
#include "RawToConvertedGeometry.h"
#include "../fpga/pcie_driver/jfjoch_fpga.h"
#include "../include/spdlog/fmt/fmt.h"
#include "GitInfo.h"
using namespace std::literals::chrono_literals;
#define check_max(param, val, max) if ((val) > (max)) throw JFJochException(JFJochExceptionCategory::InputParameterAboveMax, param)
#define check_min(param, val, min) if ((val) < (min)) throw JFJochException(JFJochExceptionCategory::InputParameterBelowMin, param)
#define check_finite(param, val) if (!std::isfinite(val)) throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, param)
DiffractionExperiment::DiffractionExperiment() : DiffractionExperiment(DetectorGeometry(8, 2)) {}
DiffractionExperiment::DiffractionExperiment(const DetectorSetup& det_setup)
: detector(det_setup), roi_mask(det_setup) {
ndatastreams = 1;
frame_time_pedestalG1G2 = std::chrono::microseconds(FRAME_TIME_PEDE_G1G2_IN_US);
preview_period = std::chrono::microseconds(1000*1000); // 1s / 1 Hz
series_id = 0;
mode = DetectorMode::Conversion;
image_format_settings.Conv();
max_spot_count = MAX_SPOT_COUNT;
summation = 1;
}
// setter functions
DiffractionExperiment &DiffractionExperiment::Detector(const DetectorSetup &input) {
detector = input;
roi_mask = ROIMap(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::Mode(DetectorMode input) {
mode = input;
if (input == DetectorMode::Conversion)
Conversion();
if (input == DetectorMode::Raw)
Raw();
return *this;
}
DiffractionExperiment &DiffractionExperiment::DataStreams(int64_t input) {
check_max("Number of data streams", input, 16);
check_min("Number of data streams", input, 1);
ndatastreams = input;
return *this;
}
DiffractionExperiment &DiffractionExperiment::ImagesPerTrigger(int64_t input) {
dataset.ImagesPerTrigger(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::NumTriggers(int64_t input) {
dataset.NumTriggers(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::FrameTime(std::chrono::microseconds in_frame_time,
std::chrono::microseconds in_count_time) {
if (in_count_time.count() == 0)
detector_settings.FrameTime(in_frame_time);
else
detector_settings.FrameTime(in_frame_time, in_count_time);
return *this;
}
DiffractionExperiment &DiffractionExperiment::PedestalG1G2FrameTime(std::chrono::microseconds input) {
check_min("Pedestal G1G2 frame time (us) ", input.count(), MIN_FRAME_TIME_FULL_SPEED_IN_US);
frame_time_pedestalG1G2 = input;
return *this;
}
DiffractionExperiment &DiffractionExperiment::PedestalG0Frames(int64_t input) {
detector_settings.PedestalG0Frames(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::PedestalG1Frames(int64_t input) {
detector_settings.PedestalG1Frames(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::PedestalG2Frames(int64_t input) {
detector_settings.PedestalG2Frames(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::PhotonEnergy_keV(float input) {
dataset.PhotonEnergy_keV(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::BeamX_pxl(float input) {
dataset.BeamX_pxl(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::BeamY_pxl(float input) {
dataset.BeamY_pxl(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::DetectorDistance_mm(float input) {
dataset.DetectorDistance_mm(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::FilePrefix(std::string input) {
dataset.FilePrefix(std::move(input));
return *this;
}
DiffractionExperiment &DiffractionExperiment::UseInternalPacketGenerator(bool input) {
detector_settings.InternalGeneratorEnable(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::MaskModuleEdges(bool input) {
image_format_settings.MaskModuleEdges(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::Compression(CompressionAlgorithm input) {
dataset.Compression(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::MaskChipEdges(bool input) {
image_format_settings.MaskChipEdges(input);
return *this;
}
DiffractionExperiment& DiffractionExperiment::LowResForAzimInt_A(float input) {
radial_integration_settings.LowQ_recipA(2 * static_cast<float>(M_PI) / input);
return *this;
}
DiffractionExperiment& DiffractionExperiment::HighResForAzimInt_A(float input) {
radial_integration_settings.HighQ_recipA(2 * static_cast<float>(M_PI) / input);
return *this;
}
DiffractionExperiment& DiffractionExperiment::LowQForAzimInt_recipA(float input) {
radial_integration_settings.LowQ_recipA(input);
return *this;
}
DiffractionExperiment& DiffractionExperiment::HighQForAzimInt_recipA(float input) {
radial_integration_settings.HighQ_recipA(input);
return *this;
}
DiffractionExperiment& DiffractionExperiment::QSpacingForAzimInt_recipA(float input) {
radial_integration_settings.QSpacing_recipA(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::SetUnitCell(const std::optional<UnitCell> &cell) {
dataset.SetUnitCell(cell);
return *this;
}
DiffractionExperiment &DiffractionExperiment::PreviewPeriod(std::chrono::microseconds input) {
check_min("Preview image generation period", input.count(), 0);
preview_period = input;
return *this;
}
DiffractionExperiment &DiffractionExperiment::SpaceGroupNumber(int64_t input) {
dataset.SpaceGroupNumber(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::StorageCells(int64_t input) {
detector_settings.StorageCells(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::StorageCellStart(int64_t input) {
detector_settings.StorageCellStart(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::SampleName(const std::string &input) {
dataset.SampleName(input);
return *this;
}
// getter functions
int64_t DiffractionExperiment::GetNumTriggers() const {
if (IsPedestalRun())
return 1;
else if (IsPulsedSource())
// For pulsed source summation happens over multiple triggers
return dataset.GetNumTriggers() * GetSummation();
else
return dataset.GetNumTriggers();
}
DetectorMode DiffractionExperiment::GetDetectorMode() const {
return mode;
}
std::chrono::microseconds DiffractionExperiment::GetFrameTime() const {
switch (GetDetectorMode()) {
case DetectorMode::PedestalG1:
case DetectorMode::PedestalG2:
return frame_time_pedestalG1G2;
default:
return detector_settings.GetFrameTime();
}
}
std::chrono::microseconds DiffractionExperiment::GetDetectorPeriod() const {
// Without storage cells - this is just frame time
if (GetStorageCellNumber() == 1)
return GetFrameTime();
// With storage cells
// Do 100 Hz repetition for pedestal G1/G2
// Do 2 kHz repetition for conversion/raw/pedestal G0
switch (GetDetectorMode()) {
case DetectorMode::PedestalG1:
case DetectorMode::PedestalG2:
return frame_time_pedestalG1G2;
default:
return std::chrono::microseconds(MIN_FRAME_TIME_FULL_SPEED_IN_US) * GetStorageCellNumber();
}
}
std::chrono::microseconds DiffractionExperiment::GetImageTime() const {
switch (GetDetectorMode()) {
case DetectorMode::PedestalG1:
case DetectorMode::PedestalG2:
return frame_time_pedestalG1G2;
default:
return GetFrameTime() * GetSummation();
}
}
int64_t DiffractionExperiment::GetImageNum() const {
return IsPedestalRun() ? 0 : (GetFrameNum() / GetSummation());
}
int64_t DiffractionExperiment::GetFrameNum() const {
return GetFrameNumPerTrigger() * GetNumTriggers();
}
int64_t DiffractionExperiment::GetFrameNumPerTrigger() const {
switch (GetDetectorMode()) {
case DetectorMode::PedestalG0:
return GetPedestalG0Frames() * GetStorageCellNumber();
case DetectorMode::PedestalG1:
return GetPedestalG1Frames() * GetStorageCellNumber();
case DetectorMode::PedestalG2:
return GetPedestalG2Frames()* GetStorageCellNumber();
default:
if (GetStorageCellNumber() > 1)
return GetStorageCellNumber();
else if (IsPulsedSource())
return 1;
else
return dataset.GetImageNumPerTrigger() * GetSummation();
}
}
std::chrono::microseconds DiffractionExperiment::GetFrameCountTime() const {
if (detector_settings.GetCountTime().has_value())
return detector_settings.GetCountTime().value();
else
return GetFrameTime() - std::chrono::microseconds(READOUT_TIME_IN_US);
}
std::chrono::microseconds DiffractionExperiment::GetImageCountTime() const {
return GetFrameCountTime() * GetSummation();
}
int64_t DiffractionExperiment::GetPedestalG0Frames() const {
if (detector.GetDetectorType() == DetectorType::EIGER)
return 0;
return detector_settings.GetPedestalG0Frames();
}
int64_t DiffractionExperiment::GetPedestalG1Frames() const {
if (detector.GetDetectorType() == DetectorType::EIGER)
return 0;
return detector_settings.GetPedestalG1Frames();
}
int64_t DiffractionExperiment::GetPedestalG2Frames() const {
if (detector.GetDetectorType() == DetectorType::EIGER)
return 0;
return detector_settings.GetPedestalG2Frames();
}
float DiffractionExperiment::GetPhotonEnergy_keV() const {
return dataset.GetPhotonEnergy_keV();
}
float DiffractionExperiment::GetWavelength_A() const {
return WVL_1A_IN_KEV / dataset.GetPhotonEnergy_keV();
}
float DiffractionExperiment::GetBeamX_pxl() const {
return dataset.GetBeamX_pxl();
}
float DiffractionExperiment::GetBeamY_pxl() const {
return dataset.GetBeamY_pxl();
}
float DiffractionExperiment::GetDetectorDistance_mm() const {
return dataset.GetDetectorDistance_mm();
}
Coord DiffractionExperiment::GetScatteringVector() const {
return dataset.GetScatteringVector();
}
std::string DiffractionExperiment::GetFilePrefix() const {
return dataset.GetFilePrefix();
}
CompressionAlgorithm DiffractionExperiment::GetCompressionAlgorithm() const {
return dataset.GetCompressionAlgorithm();
}
int64_t DiffractionExperiment::GetByteDepthImage() const {
auto bit_depth_image = image_format_settings.GetBitDepthImage();
if (!bit_depth_image.has_value())
return (GetSummation() > 2) ? 4 : 2;
else
return bit_depth_image.value() / 8;
}
bool DiffractionExperiment::IsPixelSigned() const {
auto pixel_signed = image_format_settings.IsPixelSigned();
if (!pixel_signed.has_value())
return IsJungfrauConvPhotonCnt() && (detector.GetDetectorType() == DetectorType::JUNGFRAU);
else
return pixel_signed.value();
}
int64_t DiffractionExperiment::GetDataStreamsNum() const {
return std::min<int64_t>(ndatastreams, detector.GetModulesNum());
}
int64_t DiffractionExperiment::GetModulesNum(uint16_t data_stream) const {
if (data_stream >= GetDataStreamsNum())
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Non existing data stream");
return (detector.GetModulesNum() + (GetDataStreamsNum() - 1) - data_stream) / GetDataStreamsNum();
}
int64_t DiffractionExperiment::GetModulesNum() const {
return detector.GetModulesNum();
}
int64_t DiffractionExperiment::GetFirstModuleOfDataStream(uint16_t data_stream) const {
if (data_stream >= GetDataStreamsNum())
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Non exisiting data stream");
int64_t val = 0;
for (int i = 0; i < data_stream; i++) val += GetModulesNum(i);
return val;
}
int64_t DiffractionExperiment::GetMaxCompressedSize() const {
return MaxCompressedSize(GetCompressionAlgorithm(), GetPixelsNum(), GetByteDepthImage());
}
int64_t DiffractionExperiment::GetPixelsNum() const {
return GetXPixelsNum() * GetYPixelsNum();
}
int64_t DiffractionExperiment::GetXPixelsNum() const {
if (IsGeometryTransformed())
return detector.GetGeometry().GetWidth();
else
return RAW_MODULE_COLS;
}
int64_t DiffractionExperiment::GetYPixelsNum() const {
if (IsGeometryTransformed())
return detector.GetGeometry().GetHeight();
else
return RAW_MODULE_LINES * GetModulesNum();
}
int64_t DiffractionExperiment::GetPixel0OfModule(uint16_t module_number) const {
if (module_number >= GetModulesNum())
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Module number out of bounds");
if (IsGeometryTransformed())
return detector.GetGeometry().GetPixel0(module_number);
else
return RAW_MODULE_SIZE * module_number;
}
int64_t DiffractionExperiment::GetOverflow() const {
if (GetByteDepthImage() == 2)
return IsPixelSigned() ? INT16_MAX : UINT16_MAX;
else
return IsPixelSigned() ? INT32_MAX : UINT32_MAX;
}
int64_t DiffractionExperiment::GetUnderflow() const {
if (!IsPixelSigned())
return -1;
if (GetByteDepthImage() == 2)
return INT16_MIN;
else
return INT32_MIN;
}
std::chrono::microseconds DiffractionExperiment::GetPreviewPeriod() const {
if (IsPedestalRun())
return std::chrono::microseconds(0);
else
return preview_period;
}
int64_t DiffractionExperiment::GetDefaultPlotBinning() const {
auto tmp = 500ms / GetImageTime();
if (GetImageNum() / tmp >= 10)
return tmp; // 1 bin == 500 ms
else
return 1; // no binning if less than 10 bins with 200 ms
}
bool DiffractionExperiment::IsUsingInternalPacketGen() const {
return detector_settings.IsInternalGeneratorEnable();
}
uint32_t DiffractionExperiment::GetSrcIPv4Address(uint32_t data_stream, uint32_t half_module) const {
uint32_t host = half_module + detector.GetUDPInterfaceCount() * GetFirstModuleOfDataStream(data_stream);
return detector.GetSrcIPv4Addr(host);
}
bool DiffractionExperiment::GetMaskModuleEdges() const {
return image_format_settings.IsMaskModuleEdges();
}
bool DiffractionExperiment::GetMaskChipEdges() const {
return image_format_settings.IsMaskChipEdges();
}
std::optional<UnitCell> DiffractionExperiment::GetUnitCell() const {
return dataset.GetUnitCell();
}
std::string DiffractionExperiment::GetUnitCellString() const {
auto uc = dataset.GetUnitCell();
if (uc.has_value()) {
return fmt::format("{:.1f}, {:.1f}, {:.1f}, {:.1f}, {:.1f} {:.1f}",
uc.value().a,
uc.value().b,
uc.value().c,
uc.value().alpha,
uc.value().beta,
uc.value().gamma);
} else
return "-";
}
Coord DiffractionExperiment::LabCoord(float detector_x, float detector_y) const {
// Assumes planar detector, 90 deg towards beam
return {(detector_x - GetBeamX_pxl()) * GetPixelSize_mm() ,
(detector_y - GetBeamY_pxl()) * GetPixelSize_mm() ,
GetDetectorDistance_mm()};
}
int64_t DiffractionExperiment::GetSpaceGroupNumber() const {
return dataset.GetSpaceGroupNumber();
}
int64_t DiffractionExperiment::GetStorageCellNumber() const {
auto storage_cells = detector_settings.GetStorageCells();
switch (GetDetectorMode()) {
case DetectorMode::PedestalG1:
if (IsFixedGainG1())
return storage_cells;
case DetectorMode::PedestalG2:
if (storage_cells > 1)
return 2;
else
return 1;
default:
return storage_cells;
}
}
int64_t DiffractionExperiment::GetStorageCellStart() const {
return detector_settings.GetStorageCellStart();
}
float DiffractionExperiment::GetLowQForAzimInt_recipA() const {
return radial_integration_settings.GetLowQ_recipA();
}
float DiffractionExperiment::GetHighQForAzimInt_recipA() const {
return radial_integration_settings.GetHighQ_recipA();
}
float DiffractionExperiment::GetQSpacingForAzimInt_recipA() const {
return radial_integration_settings.GetQSpacing_recipA();
}
DiffractionExperiment &DiffractionExperiment::MaxSpotCount(int64_t input) {
check_min("Max spot count", input, 10);
check_max("Max spot count", input, MAX_SPOT_COUNT);
max_spot_count = input;
return *this;
}
int64_t DiffractionExperiment::GetMaxSpotCount() const {
return max_spot_count;
}
std::string DiffractionExperiment::GetSampleName() const {
return dataset.GetSampleName();
}
void DiffractionExperiment::CheckDataProcessingSettings(const SpotFindingSettings &settings) {
check_min("Signal to noise threshold", settings.signal_to_noise_threshold, 1);
check_min("Photon count threshold", settings.photon_count_threshold, 0);
check_min("Minimum pixels per spot", settings.min_pix_per_spot, 1);
check_min("Maximum pixels per spot", settings.max_pix_per_spot, settings.min_pix_per_spot + 1);
if (settings.high_resolution_limit > 0) {
check_min("Spot finding high resolution limit", settings.high_resolution_limit, 0.5);
check_max("Spot finding high resolution limit", settings.high_resolution_limit, 50.0);
if (settings.low_resolution_limit > 0) {
check_min("Spot finding low resolution limit", settings.low_resolution_limit,
settings.high_resolution_limit);
}
} else if (settings.low_resolution_limit > 0) {
check_min("Spot finding low resolution limit", settings.low_resolution_limit, 1.0);
check_max("Spot finding low resolution limit", settings.low_resolution_limit, 50.0);
}
check_min("min spot count for powder ring detection", settings.min_spot_count_powder_ring, 5);
check_min("indexing tolerance", settings.indexing_tolerance, 0.0);
check_max("indexing tolerance", settings.indexing_tolerance, 1.0);
}
SpotFindingSettings DiffractionExperiment::DefaultDataProcessingSettings() {
return {};
}
void DiffractionExperiment::FillMessage(StartMessage &message) const {
message.images_per_file = GetImagesPerFile();
message.beam_center_x = GetBeamX_pxl();
message.beam_center_y = GetBeamY_pxl();
message.detector_distance = GetDetectorDistance_mm() * 1e-3f;
message.incident_wavelength = GetWavelength_A();
message.incident_energy = GetPhotonEnergy_keV() * 1e3f;
message.image_size_x = GetXPixelsNum();
message.image_size_y = GetYPixelsNum();
message.saturation_value = GetOverflow() - 1;
message.error_value = GetUnderflow();
message.frame_time = GetImageTime().count() * 1e-6f;
message.count_time = GetImageCountTime().count() * 1e-6f;
message.number_of_images = GetImageNum();
message.pixel_size_x = GetPixelSize_mm() * 1e-3f;
message.pixel_size_y = GetPixelSize_mm() * 1e-3f;
message.sensor_material = detector.GetSensorMaterial();
message.sensor_thickness = detector.GetSensorThickness_um() * 1e-6f;
message.bit_depth_image = GetByteDepthImage() * 8;
message.bit_depth_readout = GetByteDepthReadout() * 8;
message.storage_cell_number = GetStorageCellNumber();
message.storage_cell_delay_ns = GetStorageCellDelay().count();
message.file_prefix = GetFilePrefix();
message.pixel_signed = IsPixelSigned();
message.sample_name = GetSampleName();
message.max_spot_count = GetMaxSpotCount();
message.pixel_mask_enabled = false;
message.detector_description = GetDetectorDescription();
message.space_group_number = GetSpaceGroupNumber();
message.unit_cell = GetUnitCell();
message.total_flux = GetTotalFlux();
message.attenuator_transmission = GetAttenuatorTransmission();
message.detector_translation[0] = 0.0f;
message.detector_translation[1] = 0.0f;
message.detector_translation[2] = GetDetectorDistance_mm() * 1e-3f;
message.source_name = GetSourceName();
message.source_type = GetSourceType();
message.instrument_name = GetInstrumentName();
message.summation = GetSummation();
message.user_data = GetHeaderAppendix();
message.countrate_correction_enabled = false;
message.flatfield_enabled = false;
auto goniometer = dataset.GetGoniometer();
if (goniometer) {
message.goniometer = goniometer;
message.rotation_axis[0] = GetRotationAxis().x;
message.rotation_axis[1] = GetRotationAxis().y;
message.rotation_axis[2] = GetRotationAxis().z;
}
message.run_number = GetRunNumber();
message.run_name = GetRunName();
message.gain_file_names = detector.GetGainFileNames();
for (const auto &[x, y]: roi_mask.GetROINameMap())
message.roi_names.emplace_back(x);
message.data_reduction_factor_serialmx = GetLossyCompressionSerialMX();
message.experiment_group = dataset.GetExperimentGroup();
message.jfjoch_release = jfjoch_version();
message.detector_serial_number = detector.GetSerialNumber();
message.write_master_file = dataset.IsWriteNXmxHDF5Master();
}
float DiffractionExperiment::GetPixelSize_mm() const {
return detector.GetPixelSize_mm();
}
std::string DiffractionExperiment::GetSourceName() const {
return instrument.GetSourceName();
}
std::string DiffractionExperiment::GetSourceType() const {
return instrument.GetSourceType();
}
std::string DiffractionExperiment::GetInstrumentName() const {
return instrument.GetInstrumentName();
}
int64_t DiffractionExperiment::GetModuleFastDirectionStep(uint16_t module_number) const {
if (module_number >= GetModulesNum())
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Module number out of bounds");
return detector.GetGeometry().GetFastDirectionStep(module_number);
}
int64_t DiffractionExperiment::GetModuleSlowDirectionStep(uint16_t module_number) const {
if (module_number >= GetModulesNum())
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Module number out of bounds");
return detector.GetGeometry().GetSlowDirectionStep(module_number);
}
std::vector<std::string> DiffractionExperiment::GetDetectorModuleHostname() const {
return detector.GetDetectorModuleHostname();
}
std::string DiffractionExperiment::GetDetectorDescription() const {
return detector.GetDescription();
}
DiffractionExperiment &DiffractionExperiment::ApplySolidAngleCorr(bool input) {
radial_integration_settings.SolidAngleCorrection(input);
return *this;
}
bool DiffractionExperiment::GetApplySolidAngleCorr() const {
return radial_integration_settings.IsSolidAngleCorrection();
}
bool DiffractionExperiment::GetSaveCalibration() const {
auto val = dataset.IsSaveCalibration();
if (val.has_value())
return val.value();
// By default calibration is saved if more than 4 images
// to limit cases were size of the file is determined by the calibration
return (GetImageNum() > 4) && (detector.GetDetectorType() == DetectorType::JUNGFRAU);
}
DiffractionExperiment &DiffractionExperiment::StorageCellDelay(std::chrono::nanoseconds input) {
detector_settings.StorageCellDelay(input);
return *this;
}
std::chrono::nanoseconds DiffractionExperiment::GetStorageCellDelay() const {
return detector_settings.GetStorageCellDelay();
}
DiffractionExperiment &DiffractionExperiment::Summation(int64_t input) {
check_min("Summation factor", input, 1);
check_max("Summation factor", input, MAX_FPGA_SUMMATION);
summation = input;
return *this;
}
int64_t DiffractionExperiment::GetSummation() const {
if (GetAutoSummation())
return summation;
else
return 1;
}
int64_t DiffractionExperiment::GetUDPInterfaceCount() const {
return detector.GetUDPInterfaceCount();
}
std::vector<DetectorModuleConfig>
DiffractionExperiment::GetDetectorModuleConfig(const std::vector<AcquisitionDeviceNetConfig> &net_config) const{
std::vector<DetectorModuleConfig> ret;
for (int d = 0; d < GetDataStreamsNum(); d++) {
for (int m = 0; m < GetModulesNum(d); m++) {
DetectorModuleConfig mod_cfg;
mod_cfg.udp_dest_port_1 = net_config[d].udp_port;
mod_cfg.udp_dest_port_2 = net_config[d].udp_port;
if (detector.GetUDPInterfaceCount() == 2) {
mod_cfg.ipv4_src_addr_1 = IPv4AddressToStr(GetSrcIPv4Address(d, 2 * m));
mod_cfg.ipv4_src_addr_2 = IPv4AddressToStr(GetSrcIPv4Address(d, 2 * m + 1));
} else {
mod_cfg.ipv4_src_addr_1 = IPv4AddressToStr(GetSrcIPv4Address(d, m));
mod_cfg.ipv4_src_addr_2 = IPv4AddressToStr(GetSrcIPv4Address(d, m)); // not used, settings just in case
}
mod_cfg.ipv4_dest_addr_1 = net_config[d].ipv4_addr;
mod_cfg.ipv4_dest_addr_2 = net_config[d].ipv4_addr;
mod_cfg.mac_addr_dest_1 = net_config[d].mac_addr;
mod_cfg.mac_addr_dest_2 = net_config[d].mac_addr;
mod_cfg.module_id_in_data_stream = m;
ret.emplace_back(std::move(mod_cfg));
}
}
return ret;
}
float DiffractionExperiment::GetLowQForBkgEstimate_recipA() const {
return 2 * static_cast<float>(M_PI) / 5.0;
}
float DiffractionExperiment::GetHighQForBkgEstimate_recipA() const {
return 2 * static_cast<float>(M_PI) / 3.0;
}
DiffractionExperiment &DiffractionExperiment::AttenuatorTransmission(const std::optional<float> &input) {
dataset.AttenuatorTransmission(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::TotalFlux(const std::optional<float> &input) {
dataset.TotalFlux(input);
return *this;
}
std::optional<float> DiffractionExperiment::GetAttenuatorTransmission() const {
return dataset.GetAttenuatorTransmission();
}
std::optional<float> DiffractionExperiment::GetTotalFlux() const {
return dataset.GetTotalFlux();
}
DiffractionExperiment &DiffractionExperiment::Goniometer(const std::optional<GoniometerAxis> &input) {
dataset.Goniometer(input);
return *this;
}
std::optional<GoniometerAxis> DiffractionExperiment::GetGoniometer() const {
return dataset.GetGoniometer();
}
DiffractionExperiment &DiffractionExperiment::UsingGainHG0(bool input) {
detector_settings.UseGainHG0(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::FixedGainG1(bool input) {
detector_settings.FixGainG1(input);
return *this;
}
bool DiffractionExperiment::IsFixedGainG1() const {
return detector_settings.IsFixGainG1();
}
bool DiffractionExperiment::IsUsingGainHG0() const {
return detector_settings.IsUseGainHG0();
}
DiffractionExperiment &DiffractionExperiment::HeaderAppendix(const nlohmann::json &input) {
dataset.HeaderAppendix(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::ImageAppendix(const nlohmann::json &input) {
dataset.ImageAppendix(input);
return *this;
}
const nlohmann::json& DiffractionExperiment::GetHeaderAppendix() const {
return dataset.GetHeaderAppendix();
}
const nlohmann::json& DiffractionExperiment::GetImageAppendix() const {
return dataset.GetImageAppendix();
}
DiffractionExperiment &DiffractionExperiment::RotationAxis(const Coord &c) {
dataset.RotationAxis(c);
return *this;
}
Coord DiffractionExperiment::GetRotationAxis() const {
return dataset.GetRotationAxis();
}
uint64_t DiffractionExperiment::GetRunNumber() const {
if (dataset.GetRunNumber())
return dataset.GetRunNumber().value();
return series_id;
}
std::string DiffractionExperiment::GetRunName() const {
auto run_name = dataset.GetRunName();
if (run_name)
return run_name.value();
else
return std::to_string(series_id) + ":" + dataset.GetFilePrefix();
}
DiffractionExperiment &DiffractionExperiment::IncrementRunNumber() {
series_id++;
return *this;
}
Coord DiffractionExperiment::GetModuleFastDirection(uint16_t module_number) const {
return detector.GetGeometry().GetFastDirection(module_number);
}
Coord DiffractionExperiment::GetModuleSlowDirection(uint16_t module_number) const {
return detector.GetGeometry().GetSlowDirection(module_number);
}
DiffractionExperiment &DiffractionExperiment::JungfrauConvPhotonCnt(bool input) {
image_format_settings.JungfrauConversion(input);
return *this;
}
bool DiffractionExperiment::IsJungfrauConvPhotonCnt() const {
if (!IsPedestalRun() && (detector.GetDetectorType() == DetectorType::JUNGFRAU))
return image_format_settings.IsJungfrauConversion();
else
return false;
}
DiffractionExperiment &DiffractionExperiment::DetectorDelay(std::chrono::nanoseconds input) {
detector_settings.DetectorDelay(input);
return *this;
}
std::chrono::nanoseconds DiffractionExperiment::GetDetectorDelay() const {
return detector_settings.GetDetectorDelay();
}
const DetectorSetup &DiffractionExperiment::GetDetectorSetup() const {
return detector;
}
DiffractionExperiment &DiffractionExperiment::PulsedSource(bool input) {
instrument.PulsedSource(input);
return *this;
}
bool DiffractionExperiment::IsPulsedSource() const {
return instrument.IsPulsedSource();
}
bool DiffractionExperiment::IsSpotFindingEnabled() const {
return !IsPedestalRun();
}
float DiffractionExperiment::GetPhotonEnergyForConversion_keV() const {
auto val = GetJungfrauConversionFactor_keV();
if (val.has_value())
return val.value();
else
return GetPhotonEnergy_keV();
}
DiffractionExperiment &DiffractionExperiment::InternalPacketGeneratorImages(int64_t input) {
detector_settings.InternalGeneratorImages(input);
return *this;
}
int64_t DiffractionExperiment::GetInternalPacketGeneratorImages() const {
return detector_settings.GetInternalGeneratorImages();
}
DiffractionExperiment &DiffractionExperiment::ImportDatasetSettings(const DatasetSettings &input) {
auto tmp = dataset;
dataset = input;
auto image_time = input.GetImageTime();
if (image_time) {
if (image_time->count() % GetFrameTime().count() != 0) {
dataset = tmp;
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Image time must be multiple of frame time");
}
if (GetFrameTime().count() == 0) {
dataset = tmp;
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Frame time cannot be zero");
}
this->Summation(image_time.value() / GetFrameTime());
} else
summation = 1;
if (GetFrameNum() >= MAX_FRAMES) {
dataset = tmp;
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Frame number (summation * images_per_trigger * ntrigger) cannot exceed "
+ std::to_string(MAX_FRAMES));
}
return *this;
}
DatasetSettings DiffractionExperiment::GetDatasetSettings() const {
return dataset;
}
ROIMap &DiffractionExperiment::ROI() {
return roi_mask;
}
const ROIMap &DiffractionExperiment::ROI() const {
return roi_mask;
}
void DiffractionExperiment::ExportROIMap(uint16_t *v, size_t module_number) const {
ConvertedToRawGeometry(*this, module_number, v, roi_mask.GetROIMap().data());
}
DiffractionExperiment &DiffractionExperiment::ImagesPerFile(int64_t input) {
dataset.ImagesPerFile(input);
return *this;
}
int64_t DiffractionExperiment::GetImagesPerFile() const {
auto tmp = dataset.GetImagesPerFile();
if (tmp == 0)
return GetImageNum();
else
return tmp;
}
int64_t DiffractionExperiment::GetSendBufferLocationSize() const {
return GetMaxCompressedSize() + 1024 * 1024;
}
float DiffractionExperiment::GetLossyCompressionSerialMX() const {
return dataset.GetLossyCompressionSerialMX();
}
DiffractionExperiment &DiffractionExperiment::LossyCompressionSerialMX(float input) {
dataset.LossyCompressionSerialMX(input);
return *this;
}
std::optional<int64_t> DiffractionExperiment::GetLossyCompressionPoisson() const {
return dataset.GetLossyCompressionPoisson();
}
DiffractionExperiment &DiffractionExperiment::LossyCompressionPoisson(const std::optional<int64_t> &input) {
dataset.LossyCompressionPoisson(input);
return *this;
}
std::string DiffractionExperiment::GetExperimentGroup() const {
return dataset.GetExperimentGroup();
}
std::optional<int64_t> DiffractionExperiment::GetPixelValueLowThreshold() const {
return dataset.GetPixelValueLowThreshold();
}
DiffractionExperiment &DiffractionExperiment::PixelValueLowThreshold(const std::optional<int64_t> &input) {
dataset.PixelValueLowThreshold(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::ImportInstrumentMetadata(const InstrumentMetadata &input) {
instrument = input;
return *this;
}
InstrumentMetadata DiffractionExperiment::GetInstrumentMetadata() const {
return instrument;
}
bool DiffractionExperiment::IsGeometryTransformed() const {
return image_format_settings.IsGeometryTransformed();
}
DiffractionExperiment &DiffractionExperiment::GeometryTransformation(bool input) {
image_format_settings.GeometryTransformed(input);
return *this;
}
int64_t DiffractionExperiment::GetImageFillValue() const {
switch (GetByteDepthImage()) {
case 2:
return IsPixelSigned() ? INT16_MIN : UINT16_MAX;
case 4:
return IsPixelSigned() ? INT32_MIN : UINT32_MAX;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Pixel depth unsupported");
}
}
int64_t DiffractionExperiment::GetByteDepthReadout() const {
return 2;
}
bool DiffractionExperiment::IsPedestalRun() const {
switch (GetDetectorMode()) {
case DetectorMode::PedestalG0:
case DetectorMode::PedestalG1:
case DetectorMode::PedestalG2:
return true;
default:
return false;
}
}
bool DiffractionExperiment::GetAutoSummation() const {
if (IsPedestalRun() || (GetStorageCellNumber() > 1))
return false; // for pedestal and more than 1 storage cell summation doesn't make sense and should be always turned off
else
return image_format_settings.IsAutoSummation();
}
DiffractionExperiment &DiffractionExperiment::AutoSummation(bool input) {
image_format_settings.AutoSummation(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::BitDepthImage(const std::optional<int64_t> &input) {
image_format_settings.BitDepthImage(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::PixelSigned(const std::optional<bool> &input) {
image_format_settings.PixelSigned(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::JungfrauConversionFactor_keV(const std::optional<float> &input) {
image_format_settings.JungfrauConvFactor_keV(input);
return *this;
}
std::optional<float> DiffractionExperiment::GetJungfrauConversionFactor_keV() const {
return image_format_settings.GetJungfrauConvFactor_keV();
}
void DiffractionExperiment::Conversion() {
image_format_settings.Conv();
}
void DiffractionExperiment::Raw() {
image_format_settings.Raw();
}
DiffractionExperiment &DiffractionExperiment::ImportDetectorSettings(const DetectorSettings &input) {
detector_settings = input;
return *this;
}
DetectorSettings DiffractionExperiment::GetDetectorSettings() const {
return detector_settings;
}
DiffractionExperiment &DiffractionExperiment::ImportImageFormatSettings(const ImageFormatSettings &input) {
image_format_settings = input;
return *this;
}
ImageFormatSettings DiffractionExperiment::GetImageFormatSettings() const {
return image_format_settings;
}
DiffractionExperiment &DiffractionExperiment::ImportRadialIntegrationSettings(const AzimuthalIntegrationSettings &input) {
radial_integration_settings = input;
return *this;
}
AzimuthalIntegrationSettings DiffractionExperiment::GetRadialIntegrationSettings() const {
return radial_integration_settings;
}
DiffractionExperiment &DiffractionExperiment::PolarizationFactor(const std::optional<float> &input) {
radial_integration_settings.PolarizationFactor(input);
return *this;
}
std::optional<float> DiffractionExperiment::GetPolarizationFactor() const {
return radial_integration_settings.GetPolarizationFactor();
}
DiffractionExperiment &DiffractionExperiment::SaveCalibration(const std::optional<bool> &input) {
dataset.SaveCalibration(input);
return *this;
}
float DiffractionExperiment::GetPedestalG0RMSLimit() const {
return detector_settings.GetPedestalG0RMSLimit();
}
uint32_t DiffractionExperiment::GetPedestalMinImageCount() const {
return detector_settings.GetPedestalMinImageCount();
}