302 lines
10 KiB
C++
302 lines
10 KiB
C++
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include "JFJochImageReadingWorker.h"
|
|
#include "../image_analysis/geom_refinement/AssignSpotsToRings.h"
|
|
#include "../image_analysis/spot_finding/StrongPixelSet.h"
|
|
#include "../image_analysis/spot_finding/SpotUtils.h"
|
|
#include "../image_analysis/spot_finding/ImageSpotFinder.h"
|
|
#include <QVector>
|
|
#include <QMutexLocker>
|
|
|
|
JFJochImageReadingWorker::JFJochImageReadingWorker(const SpotFindingSettings& settings,
|
|
const IndexingSettings& in_indexing_settings,
|
|
QObject *parent) : QObject(parent) {
|
|
spot_finding_settings = settings;
|
|
indexing_settings = in_indexing_settings;
|
|
indexing = std::make_unique<IndexerThreadPool>(indexing_settings);
|
|
}
|
|
|
|
void JFJochImageReadingWorker::LoadFile(const QString &filename, qint64 image_number, qint64 summation) {
|
|
QMutexLocker ul(&m);
|
|
|
|
try {
|
|
std::shared_ptr<const JFJochReaderDataset> dataset;
|
|
auto start = std::chrono::high_resolution_clock::now();
|
|
|
|
if (!http_mode && filename == current_file)
|
|
logger.Info("File {} already loaded", filename.toStdString());
|
|
else {
|
|
if (filename.startsWith("http://")) {
|
|
http_mode = true;
|
|
http_reader.ReadURL(filename.toStdString());
|
|
total_images = http_reader.GetNumberOfImages();
|
|
dataset = http_reader.GetDataset();
|
|
if (image_number < 0)
|
|
emit setToolbarMode(JFJochViewerToolbar::ToolbarMode::Autoload);
|
|
else
|
|
emit setToolbarMode(JFJochViewerToolbar::ToolbarMode::None);
|
|
} else {
|
|
http_mode = false;
|
|
reader.ReadFile(filename.toStdString());
|
|
total_images = reader.GetNumberOfImages();
|
|
dataset = reader.GetDataset();
|
|
emit setToolbarMode(JFJochViewerToolbar::ToolbarMode::None);
|
|
}
|
|
current_image.reset();
|
|
current_summation = 1;
|
|
current_file = filename;
|
|
}
|
|
UpdateAzint_in(dataset.get());
|
|
emit datasetLoaded(dataset);
|
|
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
|
logger.Info("Loaded file {} in {} ms", filename.toStdString(), duration);
|
|
|
|
LoadImage_i(image_number, summation);
|
|
} catch (std::exception &e) {
|
|
logger.Error("Error loading file {} {}", filename.toStdString(), e.what());
|
|
}
|
|
}
|
|
|
|
void JFJochImageReadingWorker::CloseFile() {
|
|
QMutexLocker ul(&m);
|
|
|
|
if (http_mode)
|
|
http_reader.Close();
|
|
else
|
|
reader.Close();
|
|
|
|
current_image_ptr.reset();
|
|
current_image.reset();
|
|
current_summation = 1;
|
|
total_images = 0;
|
|
current_file = "";
|
|
emit imageLoaded({});
|
|
emit datasetLoaded({});
|
|
}
|
|
|
|
void JFJochImageReadingWorker::LoadImage(int64_t image_number, int64_t summation) {
|
|
QMutexLocker ul(&m);
|
|
if ((image_number == current_image) && (current_summation == summation))
|
|
return;
|
|
LoadImage_i(image_number, summation);
|
|
}
|
|
|
|
void JFJochImageReadingWorker::AnalyzeImage_i() {
|
|
if (current_image_ptr) {
|
|
if (roi)
|
|
current_image_ptr->CalcROI(roi.get());
|
|
}
|
|
}
|
|
|
|
void JFJochImageReadingWorker::UpdateAzint_in(const JFJochReaderDataset *dataset) {
|
|
if (dataset) {
|
|
azint_mapping = std::make_unique<AzimuthalIntegration>(dataset->experiment,
|
|
dataset->pixel_mask);
|
|
image_analysis = std::make_unique<ImageAnalysisCPU>(dataset->experiment,
|
|
*azint_mapping, dataset->pixel_mask);
|
|
image_analysis->SetIndexer(indexing.get());
|
|
}
|
|
}
|
|
|
|
void JFJochImageReadingWorker::LoadImage_i(int64_t image_number, int64_t summation) {
|
|
// Assumes m locked!
|
|
try {
|
|
if (summation <= 0 || image_number + summation > total_images)
|
|
return;
|
|
|
|
std::vector<int32_t> image;
|
|
auto start = std::chrono::high_resolution_clock::now();
|
|
if (http_mode) {
|
|
if (image_number < 0 && summation != 1)
|
|
return;
|
|
current_image_ptr = http_reader.LoadImage(image_number, summation);
|
|
total_images = http_reader.GetNumberOfImages();
|
|
emit datasetLoaded(http_reader.GetDataset());
|
|
} else {
|
|
if (image_number < 0)
|
|
return;
|
|
current_image_ptr = reader.LoadImage(image_number, summation);
|
|
}
|
|
|
|
if (!current_image_ptr) {
|
|
emit imageLoaded({});
|
|
return;
|
|
}
|
|
|
|
current_image = current_image_ptr->ImageData().number;
|
|
current_summation = summation;
|
|
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
|
|
AnalyzeImage_i();
|
|
|
|
auto end_analysis = std::chrono::high_resolution_clock::now();
|
|
|
|
auto duration_1 = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
|
auto duration_2 = std::chrono::duration_cast<std::chrono::milliseconds>(end_analysis - end).count();
|
|
|
|
logger.Info("Loaded image {} in {}/{} ms", image_number, duration_1, duration_2);
|
|
|
|
emit imageNumberChanged(total_images, current_image.value());
|
|
emit imageLoaded(current_image_ptr);
|
|
} catch (std::exception &e) {
|
|
logger.Error("Error loading image {}: {}", image_number, e.what());
|
|
}
|
|
}
|
|
|
|
void JFJochImageReadingWorker::SetROIBox(QRect box) {
|
|
QMutexLocker ul(&m);
|
|
roi = std::make_unique<ROIBox>("roi1", box.left(), box.right(), box.bottom(), box.top());
|
|
|
|
if (current_image_ptr) {
|
|
current_image_ptr->CalcROI(roi.get());
|
|
emit imageStatsUpdated(current_image_ptr);
|
|
}
|
|
}
|
|
|
|
void JFJochImageReadingWorker::SetROICircle(double x, double y, double radius) {
|
|
QMutexLocker ul(&m);
|
|
|
|
if (radius <= 0)
|
|
roi.reset();
|
|
else
|
|
roi = std::make_unique<ROICircle>("roi1", x, y, radius);
|
|
|
|
if (current_image_ptr) {
|
|
current_image_ptr->CalcROI(roi.get());
|
|
emit imageStatsUpdated(current_image_ptr);
|
|
}
|
|
}
|
|
|
|
void JFJochImageReadingWorker::UpdateDataset_i(const DiffractionExperiment &experiment) {
|
|
if (!current_image_ptr)
|
|
return;
|
|
|
|
std::shared_ptr<const JFJochReaderDataset> dataset;
|
|
if (http_mode) {
|
|
http_reader.UpdateGeomMetadata(experiment);
|
|
dataset = http_reader.GetDataset();
|
|
} else {
|
|
reader.UpdateGeomMetadata(experiment);
|
|
dataset = reader.GetDataset();
|
|
}
|
|
UpdateAzint_in(dataset.get());
|
|
emit datasetLoaded(dataset);
|
|
|
|
current_image_ptr = std::make_shared<JFJochReaderImage>(current_image_ptr->ImageData(), dataset);
|
|
AnalyzeImage_i();
|
|
emit imageLoaded(current_image_ptr);
|
|
}
|
|
|
|
void JFJochImageReadingWorker::UpdateDataset(const DiffractionExperiment &experiment) {
|
|
QMutexLocker ul(&m);
|
|
UpdateDataset_i(experiment);
|
|
}
|
|
|
|
void JFJochImageReadingWorker::ReanalyzeImage_i() {
|
|
if (!current_image_ptr || !azint_mapping || !image_analysis)
|
|
return;
|
|
|
|
auto start_time = std::chrono::high_resolution_clock::now();
|
|
auto new_image = std::make_shared<JFJochReaderImage>(*current_image_ptr);
|
|
auto new_image_dataset = new_image->CreateMutableDataset();
|
|
|
|
new_image_dataset->az_int_bin_to_phi = azint_mapping->GetBinToPhi();
|
|
new_image_dataset->az_int_bin_to_q = azint_mapping->GetBinToQ();
|
|
new_image_dataset->azimuthal_bins = azint_mapping->GetAzimuthalBinCount();
|
|
new_image_dataset->q_bins = azint_mapping->GetQBinCount();
|
|
|
|
std::vector<uint8_t> buffer;
|
|
AzimuthalIntegrationProfile azint_profile(*azint_mapping);
|
|
image_analysis->Analyze(new_image->ImageData(), buffer, azint_profile, spot_finding_settings);
|
|
|
|
current_image_ptr = new_image;
|
|
auto end_time = std::chrono::high_resolution_clock::now();
|
|
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);
|
|
logger.Info("Analysis of image in {} ms", duration.count());
|
|
|
|
emit imageLoaded(current_image_ptr);
|
|
}
|
|
|
|
void JFJochImageReadingWorker::Analyze() {
|
|
QMutexLocker locker(&m);
|
|
ReanalyzeImage_i();
|
|
}
|
|
|
|
void JFJochImageReadingWorker::FindSpots() {
|
|
QMutexLocker locker(&m);
|
|
if (!current_image_ptr || !azint_mapping)
|
|
return;
|
|
|
|
ImageSpotFinder finder(*azint_mapping);
|
|
|
|
std::shared_ptr<JFJochReaderImage> new_image = std::make_shared<JFJochReaderImage>(*current_image_ptr);
|
|
|
|
auto spots = finder.Run(new_image->Image().data(), spot_finding_settings);
|
|
|
|
std::vector<SpotToSave> spots_out;
|
|
auto geom = new_image->Dataset().experiment.GetDiffractionGeometry();
|
|
for (const auto &spot: spots)
|
|
spots_out.push_back(spot.Export(geom));
|
|
|
|
CountSpots(new_image->ImageData(), spots_out, spot_finding_settings.cutoff_spot_count_low_res);
|
|
|
|
new_image->ImageData().spots.clear();
|
|
|
|
FilterSpotsByCount(spots_out, 1000);
|
|
MarkIceRings(spots_out, 0.02);
|
|
|
|
new_image->ImageData().spots = spots_out;
|
|
|
|
current_image_ptr = new_image;
|
|
emit imageLoaded(new_image);
|
|
}
|
|
|
|
void JFJochImageReadingWorker::FindCenter() {
|
|
QMutexLocker locker(&m);
|
|
if (!current_image_ptr)
|
|
return;
|
|
logger.Info("Finding center");
|
|
|
|
DiffractionGeometry geom = current_image_ptr->Dataset().experiment.GetDiffractionGeometry();
|
|
try {
|
|
GuessGeometry(geom, current_image_ptr->ImageData().spots, LAB6_CELL_A);
|
|
} catch (const JFJochException &e) {
|
|
logger.ErrorException(e);
|
|
return;
|
|
}
|
|
|
|
logger.Info("Geometry found X: {} pxl Y: {} pxl Dist: {} mm", geom.GetBeamX_pxl(), geom.GetBeamY_pxl(),
|
|
geom.GetDetectorDistance_mm());
|
|
|
|
DiffractionExperiment new_experiment = current_image_ptr->Dataset().experiment;
|
|
new_experiment.BeamX_pxl(geom.GetBeamX_pxl()).BeamY_pxl(geom.GetBeamY_pxl())
|
|
.DetectorDistance_mm(geom.GetDetectorDistance_mm())
|
|
.PoniRot1_rad(geom.GetPoniRot1_rad())
|
|
.PoniRot2_rad(geom.GetPoniRot2_rad())
|
|
.PoniRot3_rad(geom.GetPoniRot3_rad());
|
|
|
|
UpdateDataset_i(new_experiment);
|
|
QVector<float> rings;
|
|
for (int i = 1; i < 7; i++)
|
|
rings.push_back(LAB6_CELL_A / sqrtf(i));
|
|
|
|
emit setRings(rings);
|
|
}
|
|
|
|
void JFJochImageReadingWorker::UpdateSpotFindingSettings(const SpotFindingSettings &settings, const IndexingSettings &indexing, bool reanalyze) {
|
|
QMutexLocker locker(&m);
|
|
spot_finding_settings = settings;
|
|
// "local" indexing settings
|
|
indexing_settings.Tolerance(indexing.GetTolerance());
|
|
indexing_settings.ViableCellMinSpots(indexing.GetViableCellMinSpots());
|
|
indexing_settings.IndexIceRings(indexing.GetIndexIceRings());
|
|
indexing_settings.UnitCellDistTolerance(indexing.GetUnitCellDistTolerance());
|
|
|
|
if (reanalyze)
|
|
ReanalyzeImage_i();
|
|
}
|