664 lines
24 KiB
C++
664 lines
24 KiB
C++
// Copyright (2019-2023) Paul Scherrer Institute
|
|
|
|
#include <thread>
|
|
|
|
#include "JFJochStateMachine.h"
|
|
|
|
inline DataProcessingSettings Convert(const JFJochProtoBuf::DataProcessingSettings &input) {
|
|
DataProcessingSettings ret;
|
|
ret.signal_to_noise_threshold = input.signal_to_noise_threshold();
|
|
ret.photon_count_threshold = input.photon_count_threshold();
|
|
ret.min_pix_per_spot = input.min_pix_per_spot();
|
|
ret.max_pix_per_spot = input.max_pix_per_spot();
|
|
ret.local_bkg_size = input.local_bkg_size();
|
|
ret.high_resolution_limit = input.high_resolution_limit();
|
|
ret.low_resolution_limit = input.low_resolution_limit();
|
|
ret.bkg_estimate_low_q = input.bkg_estimate_low_q();
|
|
ret.bkg_estimate_high_q = input.bkg_estimate_high_q();
|
|
ret.preview_indexed_only = input.preview_indexed_only();
|
|
return ret;
|
|
}
|
|
|
|
inline JFJochProtoBuf::DataProcessingSettings Convert(const DataProcessingSettings &input) {
|
|
JFJochProtoBuf::DataProcessingSettings ret;
|
|
ret.set_signal_to_noise_threshold(input.signal_to_noise_threshold);
|
|
ret.set_photon_count_threshold(input.photon_count_threshold);
|
|
ret.set_min_pix_per_spot(input.min_pix_per_spot);
|
|
ret.set_max_pix_per_spot(input.max_pix_per_spot);
|
|
ret.set_local_bkg_size(input.local_bkg_size);
|
|
ret.set_high_resolution_limit(input.high_resolution_limit);
|
|
ret.set_low_resolution_limit(input.low_resolution_limit);
|
|
ret.set_bkg_estimate_low_q(input.bkg_estimate_low_q);
|
|
ret.set_bkg_estimate_high_q(input.bkg_estimate_high_q);
|
|
ret.set_preview_indexed_only(input.preview_indexed_only);
|
|
return ret;
|
|
}
|
|
|
|
inline PlotRequest Convert(const JFJochProtoBuf::PlotRequest& request) {
|
|
PlotRequest ret;
|
|
ret.binning = request.binning();
|
|
switch (request.type()) {
|
|
case JFJochProtoBuf::BKG_ESTIMATE:
|
|
ret.type = PlotType::BkgEstimate;
|
|
break;
|
|
case JFJochProtoBuf::RAD_INT:
|
|
ret.type = PlotType::RadInt;
|
|
break;
|
|
case JFJochProtoBuf::SPOT_COUNT:
|
|
ret.type = PlotType::SpotCount;
|
|
break;
|
|
case JFJochProtoBuf::INDEXING_RATE:
|
|
ret.type = PlotType::IndexingRate;
|
|
break;
|
|
case JFJochProtoBuf::INDEXING_RATE_PER_FILE:
|
|
ret.type = PlotType::IndexingRatePerFile;
|
|
break;
|
|
default:
|
|
case JFJochProtoBuf::ADU_HISTOGRAM:
|
|
ret.type = PlotType::ADUHistorgram;
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
inline JFJochProtoBuf::Plot Convert(const Plot& input) {
|
|
JFJochProtoBuf::Plot output;
|
|
if (!input.x.empty())
|
|
*output.mutable_x() = {input.x.begin(), input.x.end()};
|
|
if (!input.y.empty())
|
|
*output.mutable_y() = {input.y.begin(), input.y.end()};
|
|
return output;
|
|
}
|
|
|
|
inline JFJochProtoBuf::RadialIntegrationProfiles Convert(const RadialIntegrationProfiles& input) {
|
|
JFJochProtoBuf::RadialIntegrationProfiles output;
|
|
for (const auto &i: input.profiles) {
|
|
auto tmp = output.add_profiles();
|
|
tmp->set_title(i.title);
|
|
*tmp->mutable_plot() = Convert(i.plot);
|
|
}
|
|
return output;
|
|
}
|
|
|
|
inline JFJochProtoBuf::JFCalibrationStatistics Convert(const std::vector<JFCalibrationModuleStatistics>& input) {
|
|
JFJochProtoBuf::JFCalibrationStatistics output;
|
|
for (const auto& i: input) {
|
|
auto ret = output.add_module_statistics();
|
|
ret->set_module_number(i.module_number);
|
|
ret->set_masked_pixels(i.masked_pixels);
|
|
ret->set_storage_cell_number(i.storage_cell_number);
|
|
ret->set_gain_g0_mean(i.gain_g0_mean);
|
|
ret->set_gain_g1_mean(i.gain_g1_mean);
|
|
ret->set_gain_g2_mean(i.gain_g2_mean);
|
|
ret->set_pedestal_g0_mean(i.pedestal_g0_mean);
|
|
ret->set_pedestal_g1_mean(i.pedestal_g1_mean);
|
|
ret->set_pedestal_g2_mean(i.pedestal_g2_mean);
|
|
}
|
|
return output;
|
|
}
|
|
|
|
JFJochStateMachine::JFJochStateMachine(JFJochServices &in_services, Logger &in_logger)
|
|
: services(in_services), logger(in_logger),
|
|
data_processing_settings(DiffractionExperiment::DefaultDataProcessingSettings()) {
|
|
|
|
}
|
|
|
|
void JFJochStateMachine::ImportPedestalG0(const JFJochReceiverOutput &receiver_output) {
|
|
if (receiver_output.pedestal_result.size() != experiment.GetModulesNum() * experiment.GetStorageCellNumber())
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Mismatch in pedestal output");
|
|
|
|
for (int s = 0; s < experiment.GetStorageCellNumber(); s++) {
|
|
for (int module = 0; module < experiment.GetModulesNum(); module++)
|
|
calibration->Pedestal(module, 0, s)
|
|
= receiver_output.pedestal_result[module + s * experiment.GetModulesNum()];
|
|
}
|
|
SetCalibrationStatistics(Convert(calibration->GetModuleStatistics()));
|
|
}
|
|
|
|
void JFJochStateMachine::ImportPedestal(const JFJochReceiverOutput &receiver_output, size_t gain_level,
|
|
size_t storage_cell) {
|
|
for (int i = 0; i < receiver_output.pedestal_result.size(); i++)
|
|
calibration->Pedestal(i, gain_level, storage_cell) = receiver_output.pedestal_result[i];
|
|
SetCalibrationStatistics(Convert(calibration->GetModuleStatistics()));
|
|
}
|
|
|
|
void JFJochStateMachine::TakePedestalInternalAll(std::unique_lock<std::mutex> &ul) {
|
|
calibration = std::make_unique<JFCalibration>(experiment);
|
|
|
|
if (!gain_calibration.empty()) {
|
|
if (gain_calibration.size() != experiment.GetModulesNum())
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Mismatch in gain files number");
|
|
for (int i = 0; i < gain_calibration.size(); i++)
|
|
calibration->GainCalibration(i) = gain_calibration[i];
|
|
}
|
|
|
|
cancel_sequence = false;
|
|
|
|
logger.Info("Pedestal sequence started");
|
|
|
|
try {
|
|
TakePedestalInternalG0(ul);
|
|
|
|
for (int i = 0; i < experiment.GetStorageCellNumber(); i++) {
|
|
TakePedestalInternalG1(ul, i);
|
|
TakePedestalInternalG2(ul, i);
|
|
}
|
|
} catch (...) {
|
|
logger.Info("Pedestal sequence error");
|
|
state = JFJochState::Error;
|
|
throw;
|
|
}
|
|
logger.Info("Pedestal sequence done");
|
|
}
|
|
|
|
void JFJochStateMachine::TakePedestalInternalG0(std::unique_lock<std::mutex> &ul) {
|
|
state = JFJochState::Pedestal;
|
|
DiffractionExperiment local_experiment(experiment);
|
|
local_experiment.Mode(DetectorMode::PedestalG0);
|
|
|
|
if (local_experiment.GetStorageCellNumber() == 1)
|
|
local_experiment.StorageCellStart(15);
|
|
else
|
|
local_experiment.StorageCellStart(0);
|
|
|
|
if (!cancel_sequence && (local_experiment.GetPedestalG0Frames() > 0)) {
|
|
services.Start(local_experiment, *calibration);
|
|
services.Trigger();
|
|
ul.unlock();
|
|
// Allow to cancel/abort during the pedestal data collection
|
|
// Must ensure that while state is Pedestal, nothing can take lock for longer time, to avoid deadlock
|
|
auto pedestal_output = services.Stop(*calibration);
|
|
ul.lock();
|
|
|
|
// SetFullMeasurementOutput(pedestal_output);
|
|
ImportPedestalG0(pedestal_output.receiver_output);
|
|
}
|
|
state = JFJochState::Idle;
|
|
}
|
|
|
|
void JFJochStateMachine::TakePedestalInternalG1(std::unique_lock<std::mutex> &ul, int32_t storage_cell) {
|
|
state = JFJochState::Pedestal;
|
|
DiffractionExperiment local_experiment(experiment);
|
|
local_experiment.Mode(DetectorMode::PedestalG1);
|
|
|
|
if (local_experiment.GetStorageCellNumber() == 2)
|
|
local_experiment.StorageCellStart((storage_cell + 15) % 16); // one previous
|
|
else
|
|
local_experiment.StorageCellStart(15);
|
|
|
|
if (!cancel_sequence && (local_experiment.GetPedestalG1Frames() > 0)) {
|
|
services.Start(local_experiment, *calibration);
|
|
services.Trigger();
|
|
ul.unlock();
|
|
// Allow to cancel/abort during the pedestal data collection
|
|
// Must ensure that while state is Pedestal, nothing can take lock for longer time, to avoid deadlock
|
|
auto pedestal_output = services.Stop(*calibration);
|
|
ul.lock();
|
|
|
|
// SetFullMeasurementOutput(pedestal_output);
|
|
ImportPedestal(pedestal_output.receiver_output, 1, storage_cell);
|
|
}
|
|
state = JFJochState::Idle;
|
|
}
|
|
|
|
void JFJochStateMachine::TakePedestalInternalG2(std::unique_lock<std::mutex> &ul, int32_t storage_cell) {
|
|
state = JFJochState::Pedestal;
|
|
DiffractionExperiment local_experiment(experiment);
|
|
local_experiment.Mode(DetectorMode::PedestalG2);
|
|
|
|
if (local_experiment.GetStorageCellNumber() == 2)
|
|
local_experiment.StorageCellStart((storage_cell + 15) % 16); // one previous
|
|
else
|
|
local_experiment.StorageCellStart(15);
|
|
|
|
if (!cancel_sequence && (local_experiment.GetPedestalG2Frames() > 0)) {
|
|
services.Start(local_experiment, *calibration);
|
|
services.Trigger();
|
|
ul.unlock();
|
|
// Allow to cancel/abort during the pedestal data collection
|
|
// Must ensure that while state is Pedestal, nothing can take lock for longer time, to avoid deadlock
|
|
auto pedestal_output = services.Stop(*calibration);
|
|
ul.lock();
|
|
|
|
// SetFullMeasurementOutput(pedestal_output);
|
|
ImportPedestal(pedestal_output.receiver_output, 2, storage_cell);
|
|
}
|
|
state = JFJochState::Idle;
|
|
}
|
|
|
|
void JFJochStateMachine::Initialize() {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
|
|
if ((state == JFJochState::Measuring) || (state == JFJochState::Pedestal))
|
|
throw JFJochException(JFJochExceptionCategory::WrongDAQState, "Cannot initialize during measurement");
|
|
|
|
if (detector_setup.empty())
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Detector information not provided");
|
|
|
|
logger.Info("Initialize");
|
|
|
|
state = JFJochState::Busy;
|
|
ClearMeasurementStatistics();
|
|
try {
|
|
services.On(experiment);
|
|
} catch (...) {
|
|
state = JFJochState::Error;
|
|
throw;
|
|
}
|
|
TakePedestalInternalAll(ul);
|
|
}
|
|
|
|
void JFJochStateMachine::Pedestal() {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
|
|
if (state != JFJochState::Idle)
|
|
throw JFJochException(JFJochExceptionCategory::WrongDAQState,"Must be idle to take pedestal");
|
|
TakePedestalInternalAll(ul);
|
|
}
|
|
|
|
void JFJochStateMachine::Trigger() {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
if (state == JFJochState::Measuring)
|
|
services.Trigger();
|
|
}
|
|
|
|
void JFJochStateMachine::Start(const JFJochProtoBuf::DatasetSettings& settings) {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
|
|
if (state != JFJochState::Idle)
|
|
throw JFJochException(JFJochExceptionCategory::WrongDAQState,
|
|
"Must be idle to start measurement");
|
|
|
|
if (measurement.valid())
|
|
measurement.get(); // In case measurement was running - clear thread
|
|
|
|
auto mod_settings = settings;
|
|
SetDatasetDefaults(mod_settings);
|
|
experiment.LoadDatasetSettings(mod_settings);
|
|
|
|
ClearAndSetMeasurementStatistics();
|
|
|
|
cancel_sequence = false;
|
|
if (experiment.GetStorageCellNumber() == 1)
|
|
experiment.StorageCellStart(15);
|
|
else
|
|
experiment.StorageCellStart(0);
|
|
|
|
try {
|
|
state = JFJochState::Busy;
|
|
services.SetDataProcessingSettings(GetDataAnalysisSettings());
|
|
services.Start(experiment, *calibration);
|
|
|
|
state = JFJochState::Measuring;
|
|
measurement = std::async(std::launch::async, &JFJochStateMachine::WaitTillMeasurementDone, this);
|
|
} catch (...) {
|
|
state = JFJochState::Error;
|
|
services.Abort();
|
|
throw;
|
|
}
|
|
}
|
|
|
|
void JFJochStateMachine::SetDatasetDefaults(JFJochProtoBuf::DatasetSettings &settings) {
|
|
if (settings.detector_distance_mm() <= 0)
|
|
settings.set_detector_distance_mm(100);
|
|
if (settings.ntrigger() <= 0)
|
|
settings.set_ntrigger(1);
|
|
}
|
|
|
|
void JFJochStateMachine::Stop() {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
|
|
if (state == JFJochState::Pedestal)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Cannot use the function during pedestal collection");
|
|
|
|
c.wait(ul, [&] { return state != JFJochState::Measuring; });
|
|
|
|
if (!measurement.valid())
|
|
return; // This is for unlikely condition of two parallel stops
|
|
else
|
|
measurement.get();
|
|
|
|
switch (state) {
|
|
case JFJochState::Inactive:
|
|
throw JFJochException(JFJochExceptionCategory::WrongDAQState,"Not initialized");
|
|
case JFJochState::Error:
|
|
throw JFJochException(JFJochExceptionCategory::WrongDAQState,"Detector in error state");
|
|
case JFJochState::Measuring:
|
|
case JFJochState::Busy:
|
|
case JFJochState::Pedestal:
|
|
throw JFJochException(JFJochExceptionCategory::WrongDAQState,"Detector in not expected state to end measurment");
|
|
case JFJochState::Idle:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void JFJochStateMachine::WaitTillMeasurementDone() {
|
|
try {
|
|
auto tmp_output = services.Stop(*calibration);
|
|
SetFullMeasurementOutput(tmp_output);
|
|
{
|
|
std::unique_lock<std::mutex> ul(m);
|
|
state = JFJochState::Idle;
|
|
}
|
|
} catch (...) {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
state = JFJochState::Error;
|
|
}
|
|
c.notify_all();
|
|
}
|
|
|
|
void JFJochStateMachine::Abort() {
|
|
// This is inconsistency in naming - need to solve later
|
|
std::unique_lock<std::mutex> ul(m);
|
|
if ((state == JFJochState::Pedestal) || (state == JFJochState::Measuring)) {
|
|
services.Abort();
|
|
cancel_sequence = true;
|
|
}
|
|
}
|
|
|
|
void JFJochStateMachine::Cancel() {
|
|
// This is inconsistency in naming - need to solve later
|
|
std::unique_lock<std::mutex> ul(m);
|
|
if ((state == JFJochState::Pedestal) || (state == JFJochState::Measuring)) {
|
|
services.Cancel();
|
|
cancel_sequence = true;
|
|
}
|
|
}
|
|
|
|
void JFJochStateMachine::DebugOnly_SetState(JFJochState in_state) {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
state = in_state;
|
|
}
|
|
|
|
void JFJochStateMachine::Deactivate() {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
try {
|
|
if (measurement.valid())
|
|
measurement.get();
|
|
services.Off();
|
|
state = JFJochState::Inactive;
|
|
} catch (...) {
|
|
state = JFJochState::Error;
|
|
throw;
|
|
}
|
|
}
|
|
|
|
JFJochStateMachine::~JFJochStateMachine() {
|
|
try {
|
|
if (measurement.valid())
|
|
measurement.get();
|
|
} catch (...) {}
|
|
}
|
|
|
|
void JFJochStateMachine::SetFullMeasurementOutput(const JFJochServicesOutput &output) {
|
|
std::unique_lock<std::mutex> ul(last_receiver_output_mutex);
|
|
|
|
auto tmp = JFJochProtoBuf::MeasurementStatistics(); // reset last measurement statistics
|
|
|
|
tmp.set_file_prefix(experiment.GetFilePrefix());
|
|
tmp.set_detector_width(experiment.GetXPixelsNum());
|
|
tmp.set_detector_height(experiment.GetYPixelsNum());
|
|
tmp.set_detector_pixel_depth(experiment.GetPixelDepth());
|
|
|
|
tmp.set_compression_ratio(output.receiver_output.compressed_ratio);
|
|
tmp.set_collection_efficiency(output.receiver_output.efficiency);
|
|
tmp.set_images_collected(output.receiver_output.images_sent);
|
|
tmp.set_cancelled(output.receiver_output.cancelled);
|
|
tmp.set_max_image_number_sent(output.receiver_output.max_image_number_sent);
|
|
tmp.set_max_receive_delay(output.receiver_output.max_receive_delay);
|
|
tmp.set_indexing_rate(output.receiver_output.indexing_rate);
|
|
tmp.set_bkg_estimate(output.receiver_output.bkg_estimate);
|
|
|
|
measurement_statistics = tmp;
|
|
}
|
|
|
|
void JFJochStateMachine::ClearAndSetMeasurementStatistics() {
|
|
std::unique_lock<std::mutex> ul(last_receiver_output_mutex);
|
|
measurement_statistics = JFJochProtoBuf::MeasurementStatistics();
|
|
|
|
measurement_statistics->set_file_prefix(experiment.GetFilePrefix());
|
|
measurement_statistics->set_detector_height(experiment.GetXPixelsNum());
|
|
measurement_statistics->set_detector_width(experiment.GetYPixelsNum());
|
|
measurement_statistics->set_detector_pixel_depth(experiment.GetPixelDepth());
|
|
}
|
|
|
|
void JFJochStateMachine::ClearMeasurementStatistics() {
|
|
std::unique_lock<std::mutex> ul(last_receiver_output_mutex);
|
|
measurement_statistics.reset();
|
|
}
|
|
|
|
std::optional<JFJochProtoBuf::MeasurementStatistics> JFJochStateMachine::GetMeasurementStatistics() const {
|
|
std::unique_lock<std::mutex> ul(last_receiver_output_mutex);
|
|
return measurement_statistics;
|
|
}
|
|
|
|
void JFJochStateMachine::LoadMask(const std::vector<uint32_t> &vec, uint32_t bit) {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
if (state == JFJochState::Inactive)
|
|
throw JFJochException(JFJochExceptionCategory::WrongDAQState,
|
|
"Detector not calibrated");
|
|
if (state != JFJochState::Idle)
|
|
throw JFJochException(JFJochExceptionCategory::WrongDAQState,
|
|
"Cannot load mask if detector is not idle");
|
|
calibration->LoadMask(experiment, vec, bit);
|
|
}
|
|
|
|
JFJochProtoBuf::JFCalibrationStatistics JFJochStateMachine::GetCalibrationStatistics() const {
|
|
std::unique_lock<std::mutex> ul(calibration_statistics_mutex);
|
|
return calibration_statistics;
|
|
}
|
|
|
|
void JFJochStateMachine::SetCalibrationStatistics(const JFJochProtoBuf::JFCalibrationStatistics &input) {
|
|
std::unique_lock<std::mutex> ul(calibration_statistics_mutex);
|
|
calibration_statistics = input;
|
|
}
|
|
|
|
JFJochProtoBuf::DetectorSettings JFJochStateMachine::GetDetectorSettings() const {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
return experiment.GetDetectorSettings();
|
|
}
|
|
|
|
void JFJochStateMachine::SetDetectorSettings(const JFJochProtoBuf::DetectorSettings &settings) {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
switch (state) {
|
|
case JFJochState::Inactive:
|
|
case JFJochState::Error:
|
|
experiment.LoadDetectorSettings(settings);
|
|
break;
|
|
case JFJochState::Idle:
|
|
experiment.LoadDetectorSettings(settings);
|
|
TakePedestalInternalAll(ul);
|
|
break;
|
|
case JFJochState::Measuring:
|
|
case JFJochState::Busy:
|
|
case JFJochState::Pedestal:
|
|
throw JFJochException(JFJochExceptionCategory::WrongDAQState,
|
|
"Cannot change detector set during data collection");
|
|
}
|
|
}
|
|
|
|
DiffractionExperiment &JFJochStateMachine::NotThreadSafe_Experiment() {
|
|
return experiment;
|
|
}
|
|
|
|
|
|
JFJochProtoBuf::Image JFJochStateMachine::GetNeXusMask() const {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
if (state == JFJochState::Inactive)
|
|
throw JFJochException(JFJochExceptionCategory::WrongDAQState, "Detector not calibrated");
|
|
|
|
JFJochProtoBuf::Image ret;
|
|
auto mask = calibration->CalculateNexusMask(experiment);
|
|
|
|
ret.set_width(experiment.GetXPixelsNum());
|
|
ret.set_height(experiment.GetYPixelsNum());
|
|
ret.set_pixel_depth(4);
|
|
*ret.mutable_data() = {mask.begin(), mask.end()};
|
|
return ret;
|
|
}
|
|
|
|
JFJochProtoBuf::Image JFJochStateMachine::GetPedestalG0() const {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
if (state == JFJochState::Inactive)
|
|
throw JFJochException(JFJochExceptionCategory::WrongDAQState, "Detector not calibrated");
|
|
|
|
JFJochProtoBuf::Image ret;
|
|
auto pedestal = calibration->GetPedestal(0);
|
|
|
|
ret.set_width(experiment.GetXPixelsNum());
|
|
ret.set_height(experiment.GetYPixelsNum());
|
|
ret.set_pixel_depth(2);
|
|
*ret.mutable_data() = {pedestal.begin(), pedestal.end()};
|
|
return ret;
|
|
}
|
|
|
|
JFJochProtoBuf::Image JFJochStateMachine::GetPedestalG1() const {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
if (state == JFJochState::Inactive)
|
|
throw JFJochException(JFJochExceptionCategory::WrongDAQState, "Detector not calibrated");
|
|
|
|
JFJochProtoBuf::Image ret;
|
|
auto pedestal = calibration->GetPedestal(1);
|
|
|
|
ret.set_width(experiment.GetXPixelsNum());
|
|
ret.set_height(experiment.GetYPixelsNum());
|
|
ret.set_pixel_depth(2);
|
|
*ret.mutable_data() = {pedestal.begin(), pedestal.end()};
|
|
return ret;
|
|
}
|
|
|
|
JFJochProtoBuf::Image JFJochStateMachine::GetPedestalG2() const {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
if (state == JFJochState::Inactive)
|
|
throw JFJochException(JFJochExceptionCategory::WrongDAQState, "Detector not calibrated");
|
|
|
|
JFJochProtoBuf::Image ret;
|
|
auto pedestal = calibration->GetPedestal(2);
|
|
|
|
ret.set_width(experiment.GetXPixelsNum());
|
|
ret.set_height(experiment.GetYPixelsNum());
|
|
ret.set_pixel_depth(2);
|
|
*ret.mutable_data() = {pedestal.begin(), pedestal.end()};
|
|
return ret;
|
|
}
|
|
|
|
JFJochProtoBuf::BrokerStatus JFJochStateMachine::GetStatus() const {
|
|
JFJochProtoBuf::BrokerStatus ret;
|
|
|
|
switch (state) {
|
|
case JFJochState::Inactive:
|
|
ret.set_broker_state(JFJochProtoBuf::NOT_INITIALIZED);
|
|
break;
|
|
case JFJochState::Idle:
|
|
ret.set_broker_state(JFJochProtoBuf::IDLE);
|
|
break;
|
|
case JFJochState::Measuring:
|
|
ret.set_broker_state(JFJochProtoBuf::DATA_COLLECTION);
|
|
break;
|
|
case JFJochState::Error:
|
|
ret.set_broker_state(JFJochProtoBuf::ERROR);
|
|
break;
|
|
case JFJochState::Busy:
|
|
ret.set_broker_state(JFJochProtoBuf::BUSY);
|
|
break;
|
|
case JFJochState::Pedestal:
|
|
ret.set_broker_state(JFJochProtoBuf::PEDESTAL);
|
|
break;
|
|
}
|
|
|
|
try {
|
|
auto rcv_status = services.GetReceiverStatus();
|
|
ret.set_progress(rcv_status.progress);
|
|
ret.set_indexing_rate(rcv_status.indexing_rate);
|
|
ret.set_receiver_send_buffers_avail(rcv_status.send_buffers_avail);
|
|
} catch (JFJochException &e) {} // ignore exception in getting receiver status (don't really care, e.g. if receiver is down)
|
|
|
|
return ret;
|
|
}
|
|
|
|
JFJochProtoBuf::Plot JFJochStateMachine::GetPlots(const JFJochProtoBuf::PlotRequest &request) const {
|
|
return Convert(services.GetPlots(Convert(request)));
|
|
}
|
|
|
|
JFJochProtoBuf::RadialIntegrationProfiles JFJochStateMachine::GetRadialIntegrationProfiles() const {
|
|
return Convert(services.GetRadialIntegrationProfiles());
|
|
}
|
|
|
|
void JFJochStateMachine::SetDataProcessingSettings(const JFJochProtoBuf::DataProcessingSettings &settings) {
|
|
std::unique_lock<std::mutex> ul(data_processing_settings_mutex);
|
|
auto tmp = Convert(settings);
|
|
DiffractionExperiment::CheckDataProcessingSettings(tmp);
|
|
data_processing_settings = tmp;
|
|
services.SetDataProcessingSettings(tmp);
|
|
}
|
|
|
|
JFJochProtoBuf::DataProcessingSettings JFJochStateMachine::GetDataProcessingSettings() const {
|
|
std::unique_lock<std::mutex> ul(data_processing_settings_mutex);
|
|
return Convert(data_processing_settings);
|
|
}
|
|
|
|
DataProcessingSettings JFJochStateMachine::GetDataAnalysisSettings() const {
|
|
std::unique_lock<std::mutex> ul(data_processing_settings_mutex);
|
|
return data_processing_settings;
|
|
}
|
|
|
|
JFJochState JFJochStateMachine::GetState() const {
|
|
return state;
|
|
}
|
|
|
|
void JFJochStateMachine::AddDetectorSetup(const DetectorSetup &setup) {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
|
|
if (detector_setup.empty()) {
|
|
experiment.Detector(setup);
|
|
gain_calibration = setup.GetGainCalibration();
|
|
current_detector_setup = 0;
|
|
}
|
|
detector_setup.emplace_back(setup);
|
|
}
|
|
|
|
JFJochProtoBuf::DetectorList JFJochStateMachine::GetDetectorsList() {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
JFJochProtoBuf::DetectorList ret;
|
|
|
|
for (int i = 0; i < detector_setup.size(); i++) {
|
|
auto tmp = ret.add_detector();
|
|
tmp->set_description(detector_setup[i].GetDescription());
|
|
tmp->set_nmodules(detector_setup[i].GetModulesNum());
|
|
tmp->set_id(i);
|
|
}
|
|
|
|
ret.set_current_id(current_detector_setup);
|
|
ret.set_current_description(experiment.GetDetectorDescription());
|
|
return ret;
|
|
}
|
|
|
|
void JFJochStateMachine::SelectDetector(int64_t id) {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
|
|
if ((id < 0) || (id >= detector_setup.size()))
|
|
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Detector doesn't exist");
|
|
|
|
switch (state) {
|
|
case JFJochState::Inactive:
|
|
case JFJochState::Error:
|
|
case JFJochState::Idle:
|
|
try {
|
|
experiment.Detector(detector_setup[id]);
|
|
gain_calibration = detector_setup[id].GetGainCalibration();
|
|
state = JFJochState::Inactive;
|
|
current_detector_setup = id;
|
|
} catch (JFJochException &e) {
|
|
logger.ErrorException(e);
|
|
state = JFJochState::Inactive;
|
|
}
|
|
break;
|
|
case JFJochState::Measuring:
|
|
case JFJochState::Busy:
|
|
case JFJochState::Pedestal:
|
|
throw JFJochException(JFJochExceptionCategory::WrongDAQState,
|
|
"Cannot change detector during data collection");
|
|
}
|
|
}
|