Skip to content

Commit a9d40d7

Browse files
committed
Real parallel processing
1 parent 674470e commit a9d40d7

18 files changed

+243
-123
lines changed

src/core/engine/Engine.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ namespace DynaRange {
2525
*/
2626
ReportOutput RunDynamicRangeAnalysis(ProgramOptions& opts, std::ostream& log_stream, const std::atomic<bool>& cancel_flag) {
2727
// Phase 1: Preparation
28-
if (!InitializeAnalysis(opts, log_stream)) {
29-
return {}; // Return an empty ReportOutput on failure
28+
auto [init_success, loaded_raw_files] = InitializeAnalysis(opts, log_stream);
29+
if (!init_success) {
30+
return {};
31+
// Return an empty ReportOutput on failure
3032
}
3133

3234
// Phase 2: Processing of all files
33-
ProcessingResult results = ProcessFiles(opts, log_stream, cancel_flag);
35+
ProcessingResult results = ProcessFiles(opts, log_stream, cancel_flag, loaded_raw_files);
3436

3537
// Check if the user cancelled the operation during processing
3638
if (cancel_flag) {
@@ -40,10 +42,10 @@ ReportOutput RunDynamicRangeAnalysis(ProgramOptions& opts, std::ostream& log_str
4042

4143
// Phase 3: Validate SNR data before final reporting
4244
ValidateSnrResults(results, opts, log_stream);
43-
45+
4446
// Phase 4: Generation of final reports
4547
ReportOutput report = FinalizeAndReport(results, opts, log_stream);
46-
48+
4749
// Populate the new dr_results member with the sorted results.
4850
// for combining the report artifacts with the numerical results
4951
// Needed when click event on grid results.csv and show graphic at GUI

src/core/engine/Engine.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@
1111
#include <atomic>
1212

1313
namespace DynaRange {
14+
// This declaration does not need to change as the new parameter is an internal detail.
1415
ReportOutput RunDynamicRangeAnalysis(ProgramOptions& opts, std::ostream& log_stream, const std::atomic<bool>& cancel_flag);
1516
}

src/core/engine/Initialization.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,34 @@
1212
#include "../setup/PlotLabelGenerator.hpp"
1313
#include "../setup/SensorResolution.hpp"
1414
#include "../utils/CommandGenerator.hpp"
15+
#include "../io/raw/RawFile.hpp"
1516
#include <libintl.h>
17+
#include <utility> // For std::pair and std::move
1618

1719
#define _(string) gettext(string)
1820

19-
bool InitializeAnalysis(ProgramOptions& opts, std::ostream& log_stream) {
21+
std::pair<bool, std::vector<RawFile>> InitializeAnalysis(ProgramOptions& opts, std::ostream& log_stream) {
2022

2123
const DynaRange::Engine::Initialization::InputFileFilter file_filter;
2224
file_filter.Filter(opts, log_stream);
2325

2426
if (opts.input_files.empty()) {
2527
log_stream << _("Error: No valid input files remain after filtering for calibration files.") << std::endl;
26-
return false;
28+
return {false, std::vector<RawFile>{}};
2729
}
2830

2931
log_stream << _("Pre-analyzing files to extract metadata...") << std::endl;
30-
auto file_info = ExtractFileInfo(opts.input_files, log_stream);
32+
auto [file_info, loaded_raw_files] = ExtractFileInfo(opts.input_files, log_stream);
33+
3134
if (file_info.empty()) {
3235
log_stream << _("Error: None of the input files could be processed.") << std::endl;
33-
return false;
36+
return {false, std::vector<RawFile>{}};
3437
}
3538

3639
const DynaRange::Engine::Initialization::CalibrationHandler calib_handler;
3740
if (!calib_handler.HandleCalibration(opts, file_info, log_stream)) {
38-
return false; // Fatal error during calibration file processing
41+
return {false, std::vector<RawFile>{}};
42+
// Fatal error during calibration file processing
3943
}
4044

4145
const DynaRange::Engine::Initialization::ConfigReporter reporter;
@@ -44,7 +48,7 @@ bool InitializeAnalysis(ProgramOptions& opts, std::ostream& log_stream) {
4448
FileOrderResult order = DetermineFileOrder(file_info, log_stream);
4549
opts.input_files = order.sorted_filenames;
4650
opts.plot_labels = GeneratePlotLabels(order.sorted_filenames, file_info, order.was_exif_sort_possible);
47-
51+
4852
if (opts.sensor_resolution_mpx == 0.0) {
4953
opts.sensor_resolution_mpx = DetectSensorResolution(opts.input_files, log_stream);
5054
}
@@ -57,5 +61,5 @@ bool InitializeAnalysis(ProgramOptions& opts, std::ostream& log_stream) {
5761
opts.generated_command = CommandGenerator::GenerateCommand(CommandFormat::PlotLong);
5862
}
5963

60-
return true;
64+
return {true, std::move(loaded_raw_files)};
6165
}

src/core/engine/Initialization.hpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@
55
*/
66
#pragma once
77
#include "../arguments/ArgumentsOptions.hpp"
8+
#include "../io/raw/RawFile.hpp"
89
#include <ostream>
910

1011
/**
1112
* @brief Prepares the analysis environment.
12-
* @details This function processes dark and saturation frames if provided,
13-
* prints the final configuration to the log, sorts the input files,
14-
* and generates a command string for plotting purposes.
13+
* @details This function processes dark/saturation frames, sorts input files, etc.
1514
* @param opts A reference to the program options, which will be updated.
1615
* @param log_stream The output stream for logging messages.
17-
* @return true if initialization is successful, false otherwise.
16+
* @return A pair containing a boolean for success and the vector of loaded RawFile objects.
1817
*/
19-
bool InitializeAnalysis(ProgramOptions& opts, std::ostream& log_stream);
18+
std::pair<bool, std::vector<RawFile>> InitializeAnalysis(ProgramOptions& opts, std::ostream& log_stream);

src/core/engine/PatchAnalysisStrategy.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "../analysis/ImageAnalyzer.hpp"
88
#include "../utils/Formatters.hpp"
99
#include <libintl.h>
10+
#include <mutex>
1011

1112
#define _(string) gettext(string)
1213

@@ -21,7 +22,8 @@ PatchAnalysisResult PerformTwoPassPatchAnalysis(
2122
double strict_min_snr_db,
2223
double permissive_min_snr_db,
2324
double max_requested_threshold,
24-
bool create_overlay_image)
25+
bool create_overlay_image,
26+
std::mutex& log_mutex)
2527
{
2628
// --- Pass 1: Analyze with the strict threshold ---
2729
PatchAnalysisResult patch_data = AnalyzePatches(prepared_image, chart.GetGridCols(), chart.GetGridRows(), opts.patch_ratio, create_overlay_image, strict_min_snr_db);
@@ -38,21 +40,24 @@ PatchAnalysisResult PerformTwoPassPatchAnalysis(
3840
}
3941
}
4042
}
41-
// Check if the lowest SNR found is still above the highest requested threshold.
4243
if (min_snr_found > max_requested_threshold) {
4344
needs_reanalysis = true;
4445
}
4546
}
4647

4748
// --- Pass 2 (Conditional): Re-analyze with the permissive threshold ---
4849
if (needs_reanalysis) {
49-
log_stream << " - Info: Re-analyzing channel " << Formatters::DataSourceToString(channel)
50-
<< " with permissive threshold to find low-SNR data."
51-
<< std::endl;
50+
{
51+
std::lock_guard<std::mutex> lock(log_mutex);
52+
log_stream << " - Info: Re-analyzing channel " << Formatters::DataSourceToString(channel)
53+
<< " with permissive threshold to find low-SNR data."
54+
<< std::endl;
55+
}
5256
patch_data = AnalyzePatches(prepared_image, chart.GetGridCols(), chart.GetGridRows(), opts.patch_ratio, create_overlay_image, permissive_min_snr_db);
5357
}
5458

5559
if (patch_data.signal.empty()) {
60+
std::lock_guard<std::mutex> lock(log_mutex);
5661
log_stream << _("Warning: No valid patches found for channel: ") << Formatters::DataSourceToString(channel) << std::endl;
5762
}
5863

src/core/engine/PatchAnalysisStrategy.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
// File: src/core/engine/PatchAnalysisStrategy.hpp
2+
/**
3+
* @file PatchAnalysisStrategy.hpp
4+
* @brief Implements the two-pass patch analysis strategy.
5+
*/
26
/**
37
* @file PatchAnalysisStrategy.hpp
48
* @brief Declares the function for executing the two-pass patch analysis strategy.
@@ -13,6 +17,7 @@
1317
#include "../arguments/ArgumentsOptions.hpp"
1418
#include "../setup/ChartProfile.hpp"
1519
#include <ostream>
20+
#include <mutex>
1621

1722
namespace DynaRange::Engine {
1823

@@ -32,6 +37,7 @@ namespace DynaRange::Engine {
3237
* @param permissive_min_snr_db The permissive minimum SNR threshold for the second pass.
3338
* @param max_requested_threshold The highest SNR threshold requested by the user, used for validation.
3439
* @param create_overlay_image Flag to indicate if an overlay image should be generated.
40+
* @param log_mutex A mutex to synchronize access to the log_stream.
3541
* @return A PatchAnalysisResult struct containing the signal, noise, and optional overlay image from the chosen pass.
3642
*/
3743
PatchAnalysisResult PerformTwoPassPatchAnalysis(
@@ -43,7 +49,8 @@ PatchAnalysisResult PerformTwoPassPatchAnalysis(
4349
double strict_min_snr_db,
4450
double permissive_min_snr_db,
4551
double max_requested_threshold,
46-
bool create_overlay_image
52+
bool create_overlay_image,
53+
std::mutex& log_mutex
4754
);
4855

4956
} // namespace DynaRange::Engine

0 commit comments

Comments
 (0)