Files
Jungfraujoch/common/DiffractionExperiment.cpp
Filip Leonarski 4dbbf0e365
Some checks failed
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 8m11s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 9m9s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 9m18s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 10m14s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 10m3s
Build Packages / Generate python client (push) Successful in 15s
Build Packages / Build documentation (push) Successful in 50s
Build Packages / Create release (push) Has been skipped
Build Packages / build:rpm (rocky8) (push) Successful in 8m31s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 8m21s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 7m42s
Build Packages / build:rpm (rocky9) (push) Successful in 9m11s
Build Packages / Unit tests (push) Failing after 1h13m19s
v1.0.0-rc.97
This is an UNSTABLE release and not recommended for production use (please use rc.96 instead).

* jfjoch_broker: For DECTRIS detectors add dark data collection during initialization for bad pixel mask
* jfjoch_broker: Refactor of calibration logic for more clear code (likely to introduce problems)
* jfjoch_viewer: Add option to handle user pixel mask (experimental)
* jfjoch_viewer: More options for ROI
* jfjoch_viewer: Add window to display calibration

Reviewed-on: #2
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
Co-committed-by: Filip Leonarski <filip.leonarski@psi.ch>
2025-11-09 12:42:27 +01:00

1644 lines
54 KiB
C++

// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include <cmath>
#include <utility>
#include "NetworkAddressConvert.h"
#include "JFJochCompressor.h" // For ZSTD_USE_JFJOCH_RLE
#include "DiffractionExperiment.h"
#include "CUDAWrapper.h"
#include "JFJochException.h"
#include "RawToConvertedGeometry.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(DetJF4M()) {}
DiffractionExperiment::DiffractionExperiment(const DetectorSetup& det_setup)
: detector(det_setup) {
ndatastreams = 1;
series_id = 0;
mode = DetectorMode::Standard;
image_format_settings.Conv();
summation = 1;
cpu_summation = false;
}
// setter functions
DiffractionExperiment &DiffractionExperiment::Detector(const DetectorSetup &input) {
detector = input;
// Conversion is always default mode after switching detectors
mode = DetectorMode::Standard;
auto settings = detector.GetDefaultSettings();
if (settings)
detector_settings = *settings;
return *this;
}
DiffractionExperiment &DiffractionExperiment::Mode(DetectorMode input) {
// Handle allowed mode settings
switch (GetDetectorType()) {
case DetectorType::JUNGFRAU:
if (input == DetectorMode::DarkMask)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Dark mask is not supported for PSI JUNGFRAU detector");
break;
case DetectorType::DECTRIS:
if ((input == DetectorMode::PedestalG0) || (input == DetectorMode::PedestalG1) || (input == DetectorMode::PedestalG2))
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Pedestal data collection is not supported for DECTRIS detector");
break;
case DetectorType::EIGER:
if ((input == DetectorMode::PedestalG0) || (input == DetectorMode::PedestalG1) || (input == DetectorMode::PedestalG2) || (input == DetectorMode::DarkMask))
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Pedestal or dark mask data collection is not supported for PSI EIGER detector");
break;
}
mode = input;
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) {
DetectorSettings tmp = detector_settings;
if (in_count_time.count() == 0)
tmp.FrameTime(in_frame_time);
else
tmp.FrameTime(in_frame_time, in_count_time);
ImportDetectorSettings(tmp);
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::IncidentEnergy_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::QRangeForAzimInt_recipA(float low, float high) {
az_integration_settings.QRange_recipA(low, high);
return *this;
}
DiffractionExperiment& DiffractionExperiment::BkgEstimateQRange_recipA(float low, float high) {
az_integration_settings.BkgEstimateQRange_recipA(low, high);
return *this;
}
DiffractionExperiment& DiffractionExperiment::QSpacingForAzimInt_recipA(float input) {
az_integration_settings.QSpacing_recipA(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::SetUnitCell(const std::optional<UnitCell> &cell) {
dataset.SetUnitCell(cell);
return *this;
}
DiffractionExperiment &DiffractionExperiment::ZMQPreviewPeriod(const std::optional<std::chrono::microseconds> &input) {
if (input.has_value()) {
check_min("Preview image generation period", input.value().count(), 0);
}
zmq_preview_period = input;
return *this;
}
DiffractionExperiment &DiffractionExperiment::SpaceGroupNumber(std::optional<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;
}
DiffractionExperiment &DiffractionExperiment::OverwriteExistingFiles(bool input) {
file_writer.OverwriteExistingFiles(input);
return *this;
}
// getter functions
int64_t DiffractionExperiment::GetNumTriggers() const {
if (GetDetectorMode() != DetectorMode::Standard)
// For pedestal and dark mask modes
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::DarkMask:
return GetDarkMaskSettings().GetFrameTime();
case DetectorMode::PedestalG1:
case DetectorMode::PedestalG2:
return detector_settings.GetFrameTimePedestalG1G2();
default:
if ((GetDetectorType() != DetectorType::JUNGFRAU) && dataset.GetImageTime().has_value())
return dataset.GetImageTime().value();
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 detector_settings.GetFrameTimePedestalG1G2();
default:
return std::chrono::microseconds(MIN_FRAME_TIME_JUNGFRAU_FULL_SPEED_IN_US) * GetStorageCellNumber();
}
}
std::chrono::microseconds DiffractionExperiment::GetImageTime() const {
switch (GetDetectorMode()) {
case DetectorMode::PedestalG1:
case DetectorMode::PedestalG2:
return detector_settings.GetFrameTimePedestalG1G2();
default:
return GetFrameTime() * GetSummation();
}
}
int64_t DiffractionExperiment::GetImageNum() const {
if (GetDetectorMode() == DetectorMode::Standard)
return GetFrameNum() / GetSummation();
return 0;
}
int64_t DiffractionExperiment::GetFrameNum() const {
return GetFrameNumPerTrigger() * GetNumTriggers();
}
int64_t DiffractionExperiment::GetFrameNumPerTrigger() const {
switch (GetDetectorMode()) {
case DetectorMode::DarkMask:
return GetDarkMaskSettings().GetNumberOfFrames();
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 ((GetDetectorType() != DetectorType::JUNGFRAU)
&& dataset.GetImageTime().has_value()
&& !detector_settings.GetCountTime().has_value())
return dataset.GetImageTime().value() - detector.GetReadOutTime();
return detector_settings.GetCountTime()
.value_or(detector_settings.GetFrameTime() - detector.GetReadOutTime());
}
bool DiffractionExperiment::GetFrameCountTimeAuto() const {
return detector_settings.GetCountTime().has_value();
}
std::chrono::microseconds DiffractionExperiment::GetImageCountTime() const {
return GetFrameCountTime() * GetSummation();
}
int64_t DiffractionExperiment::GetPedestalG0Frames() const {
if (GetDetectorType() != DetectorType::JUNGFRAU)
return 0;
return detector_settings.GetPedestalG0Frames();
}
int64_t DiffractionExperiment::GetPedestalG1Frames() const {
if (GetDetectorType() != DetectorType::JUNGFRAU)
return 0;
return detector_settings.GetPedestalG1Frames();
}
int64_t DiffractionExperiment::GetPedestalG2Frames() const {
if (GetDetectorType() != DetectorType::JUNGFRAU)
return 0;
return detector_settings.GetPedestalG2Frames();
}
float DiffractionExperiment::GetIncidentEnergy_keV() const {
return dataset.GetPhotonEnergy_keV();
}
float DiffractionExperiment::GetWavelength_A() const {
if (instrument.IsElectronSource()) {
const double hc = WVL_1A_IN_KEV;
const double me_c2 = 511; // in keV
return static_cast<float>(hc / sqrt(dataset.GetPhotonEnergy_keV() * (dataset.GetPhotonEnergy_keV() + 2 * me_c2)));
}
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 {
if (detector.GetBitDepthImage())
return detector.GetBitDepthImage().value() / 8;
if (IsCPUSummation())
return 4;
auto bit_depth_image = image_format_settings.GetBitDepthImage();
if (!bit_depth_image.has_value()) {
if (GetBitDepthReadout() == 32)
return 4;
if (GetBitDepthReadout() == 8)
return 1;
return (GetSummation() > 2) ? 4 : 2;
}
return bit_depth_image.value() / 8;
}
bool DiffractionExperiment::IsPixelSigned() const {
auto pixel_signed = image_format_settings.IsPixelSigned();
if (!pixel_signed.has_value())
return IsJungfrauConvPhotonCnt() && (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 {
return detector.GetGeometry().GetWidth(IsGeometryTransformed());
}
int64_t DiffractionExperiment::GetYPixelsNum() const {
return detector.GetGeometry().GetHeight(IsGeometryTransformed());
}
int64_t DiffractionExperiment::GetPixelsNumConv() const {
return GetXPixelsNumConv() * GetYPixelsNumConv();
}
int64_t DiffractionExperiment::GetXPixelsNumConv() const {
return detector.GetGeometry().GetWidth(true);
}
int64_t DiffractionExperiment::GetYPixelsNumConv() const {
return detector.GetGeometry().GetHeight(true);
}
int64_t DiffractionExperiment::GetPixel0OfModuleConv(uint16_t module_number) const {
return detector.GetGeometry().GetPixel0(module_number, true);
}
int64_t DiffractionExperiment::GetOverflow() const {
switch (GetByteDepthImage()) {
case 4:
return IsPixelSigned() ? static_cast<int64_t>(INT32_MAX) : static_cast<int64_t>(UINT32_MAX);
case 2:
return IsPixelSigned() ? INT16_MAX : UINT16_MAX;
case 1:
return IsPixelSigned() ? INT8_MAX : UINT8_MAX;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Pixel depth unsupported");
}
}
int64_t DiffractionExperiment::GetSaturationLimit() const {
auto sat = detector.GetSaturationLimit();
auto overflow = GetOverflow();
if (!sat)
return overflow;
return std::min(sat.value(), overflow);
}
int64_t DiffractionExperiment::GetUnderflow() const {
if (!IsPixelSigned())
return -1;
switch (GetByteDepthImage()) {
case 1:
return INT8_MIN;
case 2:
return INT16_MIN;
case 4:
return INT32_MIN;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Pixel depth unsupported");
}
}
std::optional<std::chrono::microseconds> DiffractionExperiment::GetZMQPreviewPeriod() const {
if (IsPedestalRun())
return {};
else
return zmq_preview_period;
}
int64_t DiffractionExperiment::GetDefaultPlotBinning() const {
// If images are equal longer than 100 ms, don't bin images
// If data collection is shorter than 5s, don't bin
if ((GetImageTime() >= 100ms) || (GetImageNum() * GetImageTime() < 5s))
return 1;
return 500ms / GetImageTime(); // 1 bin == 500 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 "-";
}
std::optional<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 az_integration_settings.GetLowQ_recipA();
}
float DiffractionExperiment::GetHighQForAzimInt_recipA() const {
return az_integration_settings.GetHighQ_recipA();
}
float DiffractionExperiment::GetQSpacingForAzimInt_recipA() const {
return az_integration_settings.GetQSpacing_recipA();
}
DiffractionExperiment &DiffractionExperiment::MaxSpotCount(int64_t input) {
dataset.MaxSpotCount(input);
return *this;
}
int64_t DiffractionExperiment::GetMaxSpotCount() const {
if (!IsSpotFindingEnabled())
return 0;
return dataset.GetMaxSpotCount();
}
std::string DiffractionExperiment::GetSampleName() const {
return dataset.GetSampleName();
}
void DiffractionExperiment::CheckDataProcessingSettings(const SpotFindingSettings &settings) {
check_finite("Signal to noise threshold", settings.signal_to_noise_threshold);
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);
check_finite("Spot finding high resolution limit", settings.high_resolution_limit);
check_finite("Spot finding low resolution limit", settings.low_resolution_limit);
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("Ice ring width in Q-space (A^-1)", settings.ice_ring_width_Q_recipA, 0.0);
check_max("Ice ring width in Q-space (A^-1)", settings.ice_ring_width_Q_recipA, 1.0);
check_finite("Ice ring width in Q-space (A^-1)", settings.ice_ring_width_Q_recipA);
if (settings.high_res_gap_Q_recipA.has_value()) {
check_min("High resolution gap (A^-1)", settings.high_res_gap_Q_recipA.value(), 0.1);
check_max("High resolution gap (A^-1)", settings.high_res_gap_Q_recipA.value(), 5.0);
check_finite("High resolution gap (A^-1)", settings.high_res_gap_Q_recipA.value());
}
}
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 = GetIncidentEnergy_keV() * 1e3f;
message.image_size_x = GetXPixelsNum();
message.image_size_y = GetYPixelsNum();
message.saturation_value = GetSaturationLimit() - 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 = GetBitDepthReadout();
message.indexing_algorithm = GetIndexingAlgorithm();
message.images_per_trigger = dataset.GetImageNumPerTrigger();
if (GetDetectorType() == DetectorType::JUNGFRAU) {
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 = IsApplyPixelMask();
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;
message.goniometer = dataset.GetGoniometer();
message.grid_scan = dataset.GetGridScan();
message.run_number = GetRunNumber();
message.run_name = GetRunName();
message.gain_file_names = detector.GetGainFileNames();
message.rois = roi_mask.ExportMetadata();
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();
message.overwrite = file_writer.IsOverwriteExistingFiles();
message.file_format = file_writer.GetHDF5MasterFormatVersion();
message.ring_current_mA = dataset.GetRingCurrent_mA();
message.sample_temperature_K = dataset.GetSampleTemperature_K();
message.fluorescence_spectrum = dataset.GetFluorescenceSpectrum();
message.poni_rot1 = dataset.GetPoniRot1_rad();
message.poni_rot2 = dataset.GetPoniRot2_rad();
message.poni_rot3 = dataset.GetPoniRot3_rad();
message.detect_ice_rings = dataset.IsDetectIceRings();
message.channels = {"default"};
switch (GetDetectorType()) {
case DetectorType::JUNGFRAU:
message.jungfrau_conversion_enabled = IsJungfrauConvPhotonCnt();
if (IsJungfrauConvPhotonCnt())
message.jungfrau_conversion_factor = GetPhotonEnergyForConversion_keV() * 1000;
break;
case DetectorType::EIGER:
case DetectorType::DECTRIS:
message.threshold_energy["default"] = GetEigerThreshold_keV() * 1000.0f; // threshold in CBOR is in eV
break;
}
message.geometry_transformation_enabled = IsGeometryTransformed();
if (GetSummation() == 1)
message.summation_mode = "none";
else {
if (IsCPUSummation())
message.summation_mode = "cpu";
else
message.summation_mode = "fpga";
}
}
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 {
return detector.GetGeometry().GetFastDirectionStep(module_number);
}
int64_t DiffractionExperiment::GetModuleSlowDirectionStep(uint16_t module_number) const {
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) {
az_integration_settings.SolidAngleCorrection(input);
return *this;
}
bool DiffractionExperiment::GetApplySolidAngleCorr() const {
return az_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) && (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);
summation = input;
return *this;
}
int64_t DiffractionExperiment::GetSummation() const {
if (GetAutoSummation())
return summation;
return 1;
}
int64_t DiffractionExperiment::GetFPGASummation() const {
if (IsCPUSummation())
return 1;
return GetSummation();
}
int64_t DiffractionExperiment::GetByteDepthFPGA() const {
if (IsCPUSummation())
return 2;
return GetByteDepthImage();
}
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.data_stream = d;
mod_cfg.udp_dest_port_1 = 1024 + m;
mod_cfg.udp_dest_port_2 = 1024 + m;
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 az_integration_settings.GetBkgEstimateLowQ_recipA();
}
float DiffractionExperiment::GetHighQForBkgEstimate_recipA() const {
return az_integration_settings.GetBkgEstimateHighQ_recipA();
}
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();
}
std::optional<GridScanSettings> DiffractionExperiment::GetGridScan() const {
return dataset.GetGridScan();
}
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();
}
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() && (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;
}
DetectorSetup &DiffractionExperiment::Detector() {
return detector;
}
DiffractionExperiment &DiffractionExperiment::PulsedSource(bool input) {
instrument.PulsedSource(input);
return *this;
}
bool DiffractionExperiment::IsPulsedSource() const {
return instrument.IsPulsedSource();
}
bool DiffractionExperiment::IsSpotFindingEnabled() const {
return dataset.IsSpotFindingEnabled() && !IsPedestalRun();
}
float DiffractionExperiment::GetPhotonEnergyForConversion_keV() const {
auto val = GetJungfrauConversionFactor_keV();
if (val.has_value())
return val.value();
else
return GetIncidentEnergy_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) {
switch (GetDetectorType()) {
case DetectorType::EIGER:
case DetectorType::DECTRIS:
check_min("Image time [us]", image_time.value().count(), detector.GetMinFrameTime().count());
summation = 1;
break;
case DetectorType::JUNGFRAU:
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");
}
if (image_time < GetFrameTime()) {
dataset = tmp;
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Image time cannot be less than base frame time");
}
this->Summation(image_time.value() / GetFrameTime());
break;
}
} else
summation = 1;
if (dataset.GridScan())
dataset.GridScan()->ImageNum(GetImageNum());
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;
}
std::vector<uint16_t> DiffractionExperiment::ExportROIMap() const {
return roi_mask.GetROIMap(GetDiffractionGeometry(), GetXPixelsNumConv(), GetYPixelsNumConv());
}
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::GetImageBufferLocationSize() 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;
}
std::optional<int64_t> DiffractionExperiment::GetPixelValueHighThreshold() const {
return dataset.GetPixelValueHighThreshold();
}
DiffractionExperiment &DiffractionExperiment::PixelValueHighThreshold(const std::optional<int64_t> &input) {
dataset.PixelValueHighThreshold(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::ImportInstrumentMetadata(const InstrumentMetadata &input) {
instrument = input;
return *this;
}
InstrumentMetadata DiffractionExperiment::GetInstrumentMetadata() const {
return instrument;
}
DiffractionExperiment &DiffractionExperiment::ImportFileWriterSettings(const FileWriterSettings &input) {
file_writer = input;
return *this;
}
FileWriterSettings DiffractionExperiment::GetFileWriterSettings() const {
return file_writer;
}
bool DiffractionExperiment::IsGeometryTransformed() const {
// For DECTRIS detectors always operate in transformed geometry
return (GetDetectorType() == DetectorType::DECTRIS) || image_format_settings.IsGeometryTransformed();
}
DiffractionExperiment &DiffractionExperiment::GeometryTransformation(bool input) {
image_format_settings.GeometryTransformed(input);
return *this;
}
int64_t DiffractionExperiment::GetImageFillValue() const {
switch (GetByteDepthImage()) {
case 1:
if (IsPixelSigned())
return INT8_MIN;
return UINT8_MAX;
case 2:
if (IsPixelSigned())
return INT16_MIN;
return UINT16_MAX;
case 4:
if (IsPixelSigned())
return INT32_MIN;
return UINT32_MAX;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Pixel depth unsupported");
}
}
int64_t DiffractionExperiment::GetBitDepthReadout() const {
if (GetDetectorType() == DetectorType::EIGER) {
if (detector_settings.GetEigerBitDepth().has_value())
return detector_settings.GetEigerBitDepth().value();
if (GetFrameTime().count() > 1000)
return 32;
if (GetFrameTime().count() < 450)
return 8;
return 16;
}
auto det_value = detector.GetBitDepthReadout();
if (det_value)
return det_value.value();
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Bit depth readout not configured");
}
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 or 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();
}
DiffractionExperiment & DiffractionExperiment::Conversion() {
image_format_settings.Conv();
return *this;
}
DiffractionExperiment & DiffractionExperiment::Raw() {
image_format_settings.Raw();
return *this;
}
DiffractionExperiment &DiffractionExperiment::ImportDetectorSettings(const DetectorSettings &input) {
check_min("Frame time [us]", input.GetFrameTime().count(), detector.GetMinFrameTime().count());
if (GetDetectorType() == DetectorType::JUNGFRAU) {
if (!input.GetCountTime().has_value()) {
// implicit count time
check_max("Frame time [us]", input.GetFrameTime().count(),
MAX_COUNT_TIME_JUNGFRAU_IN_US + detector.GetReadOutTime().count());
} else {
// explicit count time
check_max("Count time [us]", input.GetCountTime().value().count(),
MAX_COUNT_TIME_JUNGFRAU_IN_US);
}
if ((input.GetTiming() == DetectorTiming::Burst) ||
(input.GetTiming() == DetectorTiming::Gated))
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Burst and gated timing modes not supported in JUNGFRAU");
}
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::ImportAzimuthalIntegrationSettings(const AzimuthalIntegrationSettings &input) {
az_integration_settings = input;
return *this;
}
AzimuthalIntegrationSettings DiffractionExperiment::GetAzimuthalIntegrationSettings() const {
return az_integration_settings;
}
DiffractionExperiment &DiffractionExperiment::PolarizationFactor(const std::optional<float> &input) {
dataset.PolarizationFactor(input);
return *this;
}
std::optional<float> DiffractionExperiment::GetPolarizationFactor() const {
return dataset.GetPolarizationFactor();
}
DiffractionExperiment &DiffractionExperiment::SaveCalibration(const std::optional<bool> &input) {
dataset.SaveCalibration(input);
return *this;
}
float DiffractionExperiment::GetPedestalG0RMSLimit() const {
return image_format_settings.GetPedestalG0RMSLimit();
}
uint32_t DiffractionExperiment::GetPedestalMinImageCount() const {
return detector_settings.GetPedestalMinImageCount();
}
float DiffractionExperiment::GetEigerThreshold_keV() const {
float thr;
if (GetDetectorMode() == DetectorMode::DarkMask)
thr = GetDarkMaskSettings().GetThreshold_keV();
else {
auto val = detector_settings.GetEigerThreshold_keV();
if (val)
thr = val.value();
else
thr = GetIncidentEnergy_keV() / 2.0f;
}
if (thr < detector.GetMinThreshold_keV())
thr = detector.GetMinThreshold_keV();
return thr;
}
DetectorTiming DiffractionExperiment::GetDetectorTiming() const {
return detector_settings.GetTiming();
}
bool DiffractionExperiment::IsDetectorModuleSync() const {
return detector.IsModuleSync();
}
int64_t DiffractionExperiment::GetEigerBitDepth() const {
auto tmp = detector_settings.GetEigerBitDepth();
if (tmp.has_value())
return tmp.value();
else
return 16;
}
DiffractionExperiment &DiffractionExperiment::EigerBitDepth(const std::optional<int64_t> &input) {
detector_settings.EigerBitDepth(input);
return *this;
}
DetectorType DiffractionExperiment::GetDetectorType() const {
return detector.GetDetectorType();
}
bool DiffractionExperiment::IsMaskPixelsWithoutG0() const {
if (GetDetectorType() == DetectorType::JUNGFRAU)
return image_format_settings.IsMaskPixelsWithoutG0();
return false;
}
bool DiffractionExperiment::IsApplyPixelMask() const {
return image_format_settings.IsApplyPixelMask() && !IsPedestalRun();
}
DiffractionExperiment &DiffractionExperiment::CPUSummation(bool input) {
cpu_summation = input;
return *this;
}
DiffractionExperiment &DiffractionExperiment::ApplyPixelMask(bool input) {
image_format_settings.ApplyPixelMask(input);
return *this;
}
bool DiffractionExperiment::IsCPUSummation() const {
if (summation == 1)
return false;
if (summation >= MAX_FPGA_SUMMATION)
return true;
return cpu_summation;
}
DiffractionExperiment & DiffractionExperiment::ElectronSource(bool input) {
instrument.ElectronSource(input);
return *this;
}
bool DiffractionExperiment::IsElectronSource() const {
return instrument.IsElectronSource();
}
DiffractionExperiment &DiffractionExperiment::SetFileWriterFormat(FileWriterFormat input) {
file_writer.HDF5MasterFormatVersion(input);
return *this;
}
FileWriterFormat DiffractionExperiment::GetFileWriterFormat() const {
return file_writer.GetHDF5MasterFormatVersion();
}
DiffractionGeometry DiffractionExperiment::GetDiffractionGeometry() const {
DiffractionGeometry g;
g.Wavelength_A(GetWavelength_A())
.PixelSize_mm(GetPixelSize_mm())
.BeamX_pxl(dataset.GetBeamX_pxl())
.BeamY_pxl(dataset.GetBeamY_pxl())
.DetectorDistance_mm(dataset.GetDetectorDistance_mm())
.PoniRot1_rad(dataset.GetPoniRot1_rad())
.PoniRot2_rad(dataset.GetPoniRot2_rad())
.PoniRot3_rad(dataset.GetPoniRot3_rad());
return g;
}
void DiffractionExperiment::CalcAzIntCorrRawCoord(float *output, size_t module_number) const {
if (module_number >= GetModulesNum())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Wrong module number");
auto geom = GetDiffractionGeometry();
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
auto [x,y] = RawToConvertedCoordinate(*this, module_number, i);
if (GetApplySolidAngleCorr())
output[i] /= geom.CalcAzIntSolidAngleCorr(static_cast<float>(x), static_cast<float>(y));
auto p = GetPolarizationFactor();
if (p.has_value())
output[i] /= geom.CalcAzIntPolarizationCorr(static_cast<float>(x), static_cast<float>(y), p.value());
}
}
void DiffractionExperiment::CalcSpotFinderResolutionMap(float *data, size_t module_number) const {
if (module_number >= GetModulesNum())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Wrong module number");
auto geom = GetDiffractionGeometry();
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
auto [x,y] = RawToConvertedCoordinate(*this, module_number, i);
data[i] = geom.PxlToRes(static_cast<float>(x), static_cast<float>(y));
}
}
CompressedImageMode DiffractionExperiment::GetImageMode() const {
switch (GetByteDepthImage()) {
case 1:
return (IsPixelSigned() ? CompressedImageMode::Int8 : CompressedImageMode::Uint8);
case 2:
return (IsPixelSigned() ? CompressedImageMode::Int16 : CompressedImageMode::Uint16);
case 4:
return (IsPixelSigned() ? CompressedImageMode::Int32 : CompressedImageMode::Uint32);
default:
throw (JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Bit depth not supported"));
}
}
DiffractionExperiment &DiffractionExperiment::IndexingAlgorithm(IndexingAlgorithmEnum input) {
indexing.Algorithm(input);
return *this;
}
IndexingAlgorithmEnum DiffractionExperiment::GetIndexingAlgorithm() const {
auto cell = GetUnitCell().has_value();
switch (indexing.GetAlgorithm()) {
case IndexingAlgorithmEnum::FFBIDX:
if (!cell)
return IndexingAlgorithmEnum::None;
return IndexingAlgorithmEnum::FFBIDX;
case IndexingAlgorithmEnum::Auto:
if (get_gpu_count() == 0)
return IndexingAlgorithmEnum::FFTW;
if (!cell)
return IndexingAlgorithmEnum::FFT;
return IndexingAlgorithmEnum::FFBIDX;
case IndexingAlgorithmEnum::FFT:
return IndexingAlgorithmEnum::FFT;
case IndexingAlgorithmEnum::FFTW:
return IndexingAlgorithmEnum::FFTW;
default:
return IndexingAlgorithmEnum::None;
}
}
IndexingSettings DiffractionExperiment::GetIndexingSettings() const {
return indexing;
}
DiffractionExperiment &DiffractionExperiment::ImportIndexingSettings(const IndexingSettings &input) {
indexing = input;
return *this;
}
float DiffractionExperiment::GetIndexingTolerance() const {
return indexing.GetTolerance();
}
DiffractionExperiment &DiffractionExperiment::IndexingTolerance(float input) {
indexing.Tolerance(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::GridScan(const std::optional<GridScanSettings> &input) {
dataset.GridScan(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::SampleTemperature_K(const std::optional<float> &input) {
dataset.SampleTemperature_K(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::RingCurrent_mA(const std::optional<float> &input) {
dataset.RingCurrent_mA(input);
return *this;
}
std::optional<float> DiffractionExperiment::GetSampleTemperature_K() const {
return dataset.GetSampleTemperature_K();
}
std::optional<float> DiffractionExperiment::GetRingCurrent_mA() const {
return dataset.GetRingCurrent_mA();
}
DiffractionExperiment &DiffractionExperiment::ImportBraggIntegrationSettings(const BraggIntegrationSettings &input) {
bragg_integration_settings = input;
return *this;
}
BraggIntegrationSettings DiffractionExperiment::GetBraggIntegrationSettings() const {
return bragg_integration_settings;
}
DiffractionExperiment &DiffractionExperiment::PoniRot1_rad(float input) {
dataset.PoniRot1_rad(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::PoniRot2_rad(float input) {
dataset.PoniRot2_rad(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::PoniRot3_rad(float input) {
dataset.PoniRot3_rad(input);
return *this;
}
float DiffractionExperiment::GetPoniRot1_rad() const {
return dataset.GetPoniRot1_rad();
}
float DiffractionExperiment::GetPoniRot2_rad() const {
return dataset.GetPoniRot2_rad();
}
float DiffractionExperiment::GetPoniRot3_rad() const {
return dataset.GetPoniRot3_rad();
}
GeomRefinementAlgorithmEnum DiffractionExperiment::GetGeomRefinementAlgorithm() const {
return indexing.GetGeomRefinementAlgorithm();
}
DiffractionExperiment &DiffractionExperiment::GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum input) {
indexing.GeomRefinementAlgorithm(input);
return *this;
}
gemmi::CrystalSystem DiffractionExperiment::GetCrystalSystem() const {
auto sg = GetGemmiSpaceGroup();
if (!sg)
return gemmi::CrystalSystem::Monoclinic;
return sg->crystal_system();
}
std::string DiffractionExperiment::GetSpaceGroupName() const {
auto sg = GetGemmiSpaceGroup();
if (!sg)
return "";
return sg->short_name();
}
std::optional<gemmi::SpaceGroup> DiffractionExperiment::GetGemmiSpaceGroup() const {
auto sg = GetSpaceGroupNumber();
if (!sg)
return std::nullopt;
const gemmi::SpaceGroup *g = gemmi::find_spacegroup_by_number(sg.value());
if (g == nullptr)
return std::nullopt;
return *g;
}
char DiffractionExperiment::GetCentering() const {
auto sg = GetGemmiSpaceGroup();
if (!sg)
return 'P';
return sg->centring_type();
}
DiffractionExperiment &DiffractionExperiment::FluorescenceSpectrum(const XrayFluorescenceSpectrum &input) {
dataset.FluorescenceSpectrum(input);
return *this;
}
DiffractionExperiment &DiffractionExperiment::DetectIceRings(bool input) {
dataset.DetectIceRings(input);
return *this;
}
bool DiffractionExperiment::IsDetectIceRings() const {
return dataset.IsDetectIceRings();
}
const XrayFluorescenceSpectrum &DiffractionExperiment::GetFluorescenceSpectrum() const {
return dataset.GetFluorescenceSpectrum();
}
DarkMaskSettings DiffractionExperiment::GetDarkMaskSettings() const {
return dark_mask_settings;
}
DiffractionExperiment &DiffractionExperiment::ImportDarkMaskSettings(const DarkMaskSettings &input) {
dark_mask_settings = input;
return *this;
}
int64_t DiffractionExperiment::GetDarkMaskNumberOfFrames() const {
if (GetDetectorType() == DetectorType::DECTRIS)
return GetDarkMaskSettings().GetNumberOfFrames();
return 0;
}