Files
Jungfraujoch/receiver/JFJochReceiverPlots.cpp

509 lines
18 KiB
C++

// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "JFJochReceiverPlots.h"
#include <algorithm>
MultiLinePlot JFJochReceiverPlots::GetROIPlot(PlotType type, int64_t nbins, float start, float incr,
const std::optional<float> &fill_value) const {
MultiLinePlot ret;
std::shared_lock sl(roi_m);
for (const auto &[key, roi] : roi_status) {
MultiLinePlotStruct plot;
switch (type) {
case PlotType::ROISum:
plot = roi.sum.GetMeanPerBin(nbins, start, incr, fill_value);
break;
case PlotType::ROIMaxCount:
plot = roi.max_count.GetMeanPerBin(nbins, start, incr, fill_value);
break;
case PlotType::ROIPixels:
plot = roi.pixels.GetMeanPerBin(nbins, start, incr, fill_value);
break;
case PlotType::ROIMean:
plot = roi.mean.GetMeanPerBin(nbins, start, incr, fill_value);
break;
case PlotType::ROIWeightedX:
plot = roi.x.GetMeanPerBin(nbins, start, incr, fill_value);
break;
case PlotType::ROIWeightedY:
plot = roi.y.GetMeanPerBin(nbins, start, incr, fill_value);
break;
default:
continue;
}
plot.title = key;
ret.AddPlot(plot);
}
return ret;
}
void JFJochReceiverPlots::Setup(const DiffractionExperiment &experiment, const AzimuthalIntegration &mapping) {
std::unique_lock ul(m);
az_int_profile = std::make_unique<AzimuthalIntegrationProfile>(mapping);
az_int_profile->SetTitle("dataset");
goniometer = experiment.GetGoniometer();
grid_scan = experiment.GetGridScan();
default_binning = experiment.GetDefaultPlotBinning();
size_t r = experiment.GetImageNum();
// Reset all status vectors
xfel_pulse_id.Clear();
xfel_event_code.Clear();
if (experiment.IsPulsedSource()) {
xfel_pulse_id.reserve(r);
xfel_event_code.reserve(r);
}
bkg_estimate.Clear(r);
spot_count.Clear(r);
spot_count_low_res.Clear(r);
spot_count_indexed.Clear(r);
spot_count_ice.Clear(r);
indexing_solution.Clear(r);
indexing_uc_a.Clear(r);
indexing_uc_b.Clear(r);
indexing_uc_c.Clear(r);
indexing_uc_alpha.Clear(r);
indexing_uc_beta.Clear(r);
indexing_uc_gamma.Clear(r);
error_pixels.Clear(r);
saturated_pixels.Clear(r);
strong_pixels.Clear(r);
receiver_delay.Clear(r);
receiver_free_send_buf.Clear(r);
image_collection_efficiency.Clear(r);
{
std::unique_lock roi_lock(roi_m);
roi_status.clear();
for (const auto &[name, _id] : experiment.ROI().GetROINameMap()) {
auto &entry = roi_status[name];
entry.sum.Clear(r);
entry.max_count.Clear(r);
entry.pixels.Clear(r);
entry.x.Clear(r);
entry.y.Clear(r);
entry.mean.Clear(r);
}
}
packets_received.Clear(r);
max_value.Clear(r);
resolution_estimate.Clear(r);
indexing_time.Clear(r);
profile_radius.Clear(r);
mosaicity_deg.Clear(r);
b_factor.Clear(r);
processing_time.Clear(r);
beam_center_x.Clear(r);
beam_center_y.Clear(r);
pixel_sum.Clear(r);
}
void JFJochReceiverPlots::Add(const DataMessage &msg, const AzimuthalIntegrationProfile &profile) {
bkg_estimate.AddElement(msg.number, msg.bkg_estimate);
resolution_estimate.AddElement(msg.number, msg.resolution_estimate);
spot_count.AddElement(msg.number, msg.spot_count);
spot_count_low_res.AddElement(msg.number, msg.spot_count_low_res);
spot_count_indexed.AddElement(msg.number, msg.spot_count_indexed);
spot_count_ice.AddElement(msg.number, msg.spot_count_ice_rings);
error_pixels.AddElement(msg.number, msg.error_pixel_count);
saturated_pixels.AddElement(msg.number, msg.saturated_pixel_count);
pixel_sum.AddElement(msg.number, msg.pixel_sum);
strong_pixels.AddElement(msg.number, msg.strong_pixel_count);
packets_received.AddElement(msg.number, msg.packets_received);
image_collection_efficiency.AddElement(msg.number, msg.image_collection_efficiency);
receiver_delay.AddElement(msg.number, msg.receiver_aq_dev_delay);
receiver_free_send_buf.AddElement(msg.number, msg.receiver_free_send_buf);
max_value.AddElement(msg.number, msg.max_viable_pixel_value);
indexing_time.AddElement(msg.number, msg.indexing_time_s);
processing_time.AddElement(msg.number, msg.processing_time_s);
if (msg.indexing_unit_cell) {
indexing_uc_a.AddElement(msg.number, msg.indexing_unit_cell->a);
indexing_uc_b.AddElement(msg.number, msg.indexing_unit_cell->b);
indexing_uc_c.AddElement(msg.number, msg.indexing_unit_cell->c);
indexing_uc_alpha.AddElement(msg.number, msg.indexing_unit_cell->alpha);
indexing_uc_beta.AddElement(msg.number, msg.indexing_unit_cell->beta);
indexing_uc_gamma.AddElement(msg.number, msg.indexing_unit_cell->gamma);
}
beam_center_x.AddElement(msg.number, msg.beam_corr_x);
beam_center_y.AddElement(msg.number, msg.beam_corr_y);
profile_radius.AddElement(msg.number, msg.profile_radius);
mosaicity_deg.AddElement(msg.number, msg.mosaicity_deg);
b_factor.AddElement(msg.number, msg.b_factor);
indexing_solution.AddElement(msg.number, msg.indexing_result);
{
std::unique_lock ul(m);
if (az_int_profile)
*az_int_profile += profile;
if (msg.xfel_pulse_id.has_value())
xfel_pulse_id[msg.number] = msg.xfel_pulse_id.value();
if (msg.xfel_event_code.has_value())
xfel_event_code[msg.number] = msg.xfel_event_code.value();
}
for (const auto &[key, value] : msg.roi) {
if (value.pixels == 0)
continue;
std::shared_lock sl(roi_m);
auto it = roi_status.find(key);
if (it == roi_status.end())
continue; // ROI not configured in setup -> ignore
it->second.sum.AddElement(msg.number, value.sum);
it->second.mean.AddElement(msg.number, static_cast<double>(value.sum) / static_cast<double>(value.pixels));
it->second.max_count.AddElement(msg.number, value.max_count);
it->second.pixels.AddElement(msg.number, value.pixels);
if (value.sum > 0) {
it->second.x.AddElement(msg.number, static_cast<double>(value.x_weighted) / static_cast<double>(value.sum));
it->second.y.AddElement(msg.number, static_cast<double>(value.y_weighted) / static_cast<double>(value.sum));
}
}
}
void JFJochReceiverPlots::AddEmptyImage(const DataMessage &msg) {
image_collection_efficiency.AddElement(msg.number, msg.image_collection_efficiency);
}
MultiLinePlot JFJochReceiverPlots::GetPlots(const PlotRequest &request) {
MultiLinePlot ret;
MultiLinePlotUnits units = MultiLinePlotUnits::ImageNumber;
int64_t nbins = 1;
std::optional<GridScanSettings> local_grid_scan;
float start = 0.0;
float incr = 1.0;
if (request.type != PlotType::AzInt && request.type != PlotType::AzInt1D) {
std::unique_lock ul(m);
if (request.experimental_coord && grid_scan) {
local_grid_scan = grid_scan;
units = MultiLinePlotUnits::Grid_um;
nbins = 1;
} else {
nbins = default_binning;
if (request.binning > 0)
nbins = request.binning;
nbins = std::max<int64_t>(1, nbins);
if (request.experimental_coord && goniometer) {
start = goniometer->GetStart_deg();
incr = goniometer->GetIncrement_deg();
units = MultiLinePlotUnits::Angle_deg;
}
}
} else {
switch (request.azint_unit) {
case PlotAzintUnit::Q_recipA:
units = MultiLinePlotUnits::Q_recipA;
break;
case PlotAzintUnit::TwoTheta_deg:
units = MultiLinePlotUnits::Angle_deg;
break;
case PlotAzintUnit::D_A:
units = MultiLinePlotUnits::d_A;
break;
}
}
switch (request.type) {
case PlotType::SpotCount:
ret = spot_count.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::SpotCountLowRes:
ret = spot_count_low_res.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::SpotCountIndexed:
ret = spot_count_indexed.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::SpotCountIceRing:
ret = spot_count_ice.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::IndexingRate:
ret = indexing_solution.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::BkgEstimate:
ret = bkg_estimate.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::ResolutionEstimate:
ret = resolution_estimate.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::ErrorPixels:
ret = error_pixels.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::SaturatedPixels:
ret = saturated_pixels.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::IndexingTime:
ret = indexing_time.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::ProfileRadius:
ret = profile_radius.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::Mosaicity:
ret = mosaicity_deg.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::BFactor:
ret = b_factor.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::ImageCollectionEfficiency:
ret = image_collection_efficiency.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::ReceiverDelay:
ret = receiver_delay.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::ReceiverFreeSendBuf:
ret = receiver_free_send_buf.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::StrongPixels:
ret = strong_pixels.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::ROISum:
case PlotType::ROIMaxCount:
case PlotType::ROIPixels:
case PlotType::ROIMean:
case PlotType::ROIWeightedX:
case PlotType::ROIWeightedY:
ret = GetROIPlot(request.type, nbins, start, incr, request.fill_value);
break;
case PlotType::AzInt:
ret = GetAzIntProfilePlot(false, request.azint_unit);
break;
case PlotType::AzInt1D:
ret = GetAzIntProfilePlot(true, request.azint_unit);
break;
case PlotType::IndexingUnitCellLength: {
auto a = indexing_uc_a.GetMeanPerBin(nbins, start, incr, request.fill_value);
auto b = indexing_uc_b.GetMeanPerBin(nbins, start, incr, request.fill_value);
auto c = indexing_uc_c.GetMeanPerBin(nbins, start, incr, request.fill_value);
a.title = "a";
b.title = "b";
c.title = "c";
ret.AddPlot(a);
ret.AddPlot(b);
ret.AddPlot(c);
break;
}
case PlotType::IndexingUnitCellAngle: {
auto alpha = indexing_uc_alpha.GetMeanPerBin(nbins, start, incr, request.fill_value);
auto beta = indexing_uc_beta.GetMeanPerBin(nbins, start, incr, request.fill_value);
auto gamma = indexing_uc_gamma.GetMeanPerBin(nbins, start, incr, request.fill_value);
alpha.title = "alpha";
beta.title = "beta";
gamma.title = "gamma";
ret.AddPlot(alpha);
ret.AddPlot(beta);
ret.AddPlot(gamma);
break;
}
case PlotType::PacketsReceived:
ret = packets_received.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::MaxValue:
ret = max_value.GetMaxPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::PixelSum:
ret = pixel_sum.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::ImageProcessingTime:
ret = processing_time.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::RefinementBeamX:
ret = beam_center_x.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
case PlotType::RefinementBeamY:
ret = beam_center_y.GetMeanPlot(nbins, start, incr, request.fill_value);
break;
default:
break;
}
ret.SetUnits(units);
if (local_grid_scan
&& request.type != PlotType::AzInt
&& request.type != PlotType::AzInt1D)
ret.Convert2D(local_grid_scan.value());
return ret;
}
std::optional<float> JFJochReceiverPlots::GetIndexingRate() const {
auto tmp = indexing_solution.Mean();
if (std::isfinite(tmp))
return tmp;
else
return {};
}
std::optional<float> JFJochReceiverPlots::GetBkgEstimate() const {
auto tmp = bkg_estimate.Mean();
if (std::isfinite(tmp))
return tmp;
else
return {};
}
void JFJochReceiverPlots::GetXFELPulseID(std::vector<uint64_t> &v) const {
std::unique_lock ul(m);
v = xfel_pulse_id.vec();
}
void JFJochReceiverPlots::GetXFELEventCode(std::vector<uint64_t> &v) const {
std::unique_lock ul(m);
v = xfel_event_code.vec();
}
std::vector<float> JFJochReceiverPlots::GetAzIntProfile() const {
std::unique_lock ul(m);
if (!az_int_profile)
return {};
auto plot = az_int_profile->GetResult();
for (auto &i: plot)
if (!std::isfinite(i))
i = 0;
return plot;
}
MultiLinePlot JFJochReceiverPlots::GetAzIntProfilePlot(bool force_1d, PlotAzintUnit azint_unit) const {
std::unique_lock ul(m);
if (!az_int_profile)
return {};
return az_int_profile->GetPlot(force_1d, azint_unit);
}
void JFJochReceiverPlots::GetPlotRaw(std::vector<float> &v, PlotType type, const std::string &roi) {
switch (type) {
case PlotType::SpotCount:
v = spot_count.ExportArray();
break;
case PlotType::SpotCountLowRes:
v = spot_count_low_res.ExportArray();
break;
case PlotType::SpotCountIndexed:
v = spot_count_indexed.ExportArray();
break;
case PlotType::SpotCountIceRing:
v = spot_count_ice.ExportArray();
break;
case PlotType::IndexingRate:
v = indexing_solution.ExportArray();
break;
case PlotType::BkgEstimate:
v = bkg_estimate.ExportArray();
break;
case PlotType::ResolutionEstimate:
v = resolution_estimate.ExportArray();
break;
case PlotType::ErrorPixels:
v = error_pixels.ExportArray();
break;
case PlotType::SaturatedPixels:
v = saturated_pixels.ExportArray();
break;
case PlotType::IndexingTime:
v = indexing_time.ExportArray();
break;
case PlotType::ProfileRadius:
v = profile_radius.ExportArray();
break;
case PlotType::BFactor:
v = b_factor.ExportArray();
break;
case PlotType::ImageCollectionEfficiency:
v = image_collection_efficiency.ExportArray();
break;
case PlotType::ReceiverDelay:
v = receiver_delay.ExportArray();
break;
case PlotType::ReceiverFreeSendBuf:
v = receiver_free_send_buf.ExportArray();
break;
case PlotType::StrongPixels:
v = strong_pixels.ExportArray();
break;
case PlotType::ROISum:
case PlotType::ROIMaxCount:
case PlotType::ROIPixels:
case PlotType::ROIMean:
case PlotType::ROIWeightedX:
case PlotType::ROIWeightedY: {
std::shared_lock sl(roi_m);
auto it = roi_status.find(roi);
if (it == roi_status.end()) {
v.clear();
break;
}
switch (type) {
case PlotType::ROISum:
v = it->second.sum.ExportArray();
break;
case PlotType::ROIMaxCount:
v = it->second.max_count.ExportArray();
break;
case PlotType::ROIPixels:
v = it->second.pixels.ExportArray();
break;
case PlotType::ROIMean:
v = it->second.mean.ExportArray();
break;
case PlotType::ROIWeightedX:
v = it->second.x.ExportArray();
break;
case PlotType::ROIWeightedY:
v = it->second.y.ExportArray();
break;
default:
break;
}
break;
}
case PlotType::AzInt: {
std::unique_lock ul(m);
if (az_int_profile)
v = az_int_profile->GetResult();
break;
}
case PlotType::AzInt1D: {
std::unique_lock ul(m);
if (az_int_profile)
v = az_int_profile->GetResult1D();
break;
}
case PlotType::PacketsReceived:
v = packets_received.ExportArray();
break;
case PlotType::MaxValue:
v = max_value.ExportArray();
break;
case PlotType::PixelSum:
v = pixel_sum.ExportArray();
break;
case PlotType::ImageProcessingTime:
v = processing_time.ExportArray();
break;
case PlotType::RefinementBeamX:
v = beam_center_x.ExportArray();
break;
case PlotType::RefinementBeamY:
v = beam_center_y.ExportArray();
break;
default:
break;
}
}