pyvale 2025.7.0__cp311-cp311-musllinux_1_2_aarch64.whl → 2025.7.2__cp311-cp311-musllinux_1_2_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pyvale might be problematic. Click here for more details.

@@ -11,7 +11,7 @@
11
11
  "-fopenmp"
12
12
  ],
13
13
  "include_dirs": [
14
- "/tmp/pip-build-env-052l3x_t/overlay/lib/python3.11/site-packages/numpy/core/include"
14
+ "/tmp/pip-build-env-eix67hnr/overlay/lib/python3.11/site-packages/numpy/core/include"
15
15
  ],
16
16
  "name": "pyvale.cython.rastercyth",
17
17
  "sources": [
pyvale/dataset.py CHANGED
@@ -397,7 +397,7 @@ class DataSet:
397
397
  Path to the reference image (*.tiff).
398
398
  """
399
399
  return Path(files("pyvale.data")
400
- .joinpath("DIC_Challenge_Star_Noise_Ref.tif"))
400
+ .joinpath("DIC_Challenge_Star_Noise_Ref.tiff"))
401
401
 
402
402
  @staticmethod
403
403
  def dic_challenge_def() -> Path:
@@ -409,7 +409,7 @@ class DataSet:
409
409
  Path to the reference image (*.tiff).
410
410
  """
411
411
  return Path(files("pyvale.data")
412
- .joinpath("DIC_Challenge_Star_Noise_Def.tif"))
412
+ .joinpath("DIC_Challenge_Star_Noise_Def.tiff"))
413
413
 
414
414
 
415
415
 
@@ -12,11 +12,13 @@
12
12
  #include <cmath>
13
13
  #include <algorithm>
14
14
  #include <omp.h>
15
+ #include <csignal>
15
16
 
16
17
  // Program Header files
17
18
  #include "./defines.hpp"
18
19
  #include "./dicutil.hpp"
19
20
  #include "./dicfourier.hpp"
21
+ #include "./dicsignalhandler.hpp"
20
22
 
21
23
  namespace fourier {
22
24
 
@@ -134,8 +136,10 @@ namespace fourier {
134
136
  }
135
137
 
136
138
  void mgwd(const std::vector<util::SubsetData> &ssdata,
137
- const double *img_ref, const double *img_def,
138
- const Interpolator &interp_def, const bool fft_mad,
139
+ const double *img_ref,
140
+ const double *img_def,
141
+ const Interpolator &interp_def,
142
+ const bool fft_mad,
139
143
  const double fft_mad_scale){
140
144
 
141
145
  const int px_hori = interp_def.px_hori;
@@ -150,11 +154,21 @@ namespace fourier {
150
154
  //util::Timer timer("FFT windowing for subset size: " + std::to_string(ssdata[i].size));
151
155
 
152
156
  const int ss_size = ssdata[i].size;
157
+ const int num_ss = ssdata[i].num;
153
158
 
154
159
  std::fill(shifts[i].x.begin(), shifts[i].x.end(), 0.0);
155
160
  std::fill(shifts[i].y.begin(), shifts[i].y.end(), 0.0);
156
161
 
157
- #pragma omp parallel
162
+ indicators::ProgressBar bar;
163
+ std::atomic<int> current_progress = 0;
164
+ int prev_pct = 0;
165
+
166
+ if (g_debug_level == 1){
167
+ std::string bar_title = "FFT windowing for size: " + std::to_string(ss_size);
168
+ util::create_progress_bar(bar, bar_title, ssdata[i].num);
169
+ }
170
+
171
+ #pragma omp parallel shared(stop_request)
158
172
  {
159
173
 
160
174
 
@@ -165,6 +179,11 @@ namespace fourier {
165
179
  #pragma omp for
166
180
  for (int ss = 0; ss < ssdata[i].num; ss++){
167
181
 
182
+ // exit when ctrl+C
183
+ if (stop_request){
184
+ continue;
185
+ }
186
+
168
187
  int ss_x = ssdata[i].coords[2*ss];
169
188
  int ss_y = ssdata[i].coords[2*ss+1];
170
189
 
@@ -213,6 +232,12 @@ namespace fourier {
213
232
  //util::extract_ss_subpx(fft.ss_def, ss_x+shifts[i].x[ss], ss_y+shifts[i].y[ss], interp_def);
214
233
  //shifts[i].cost[ss] = debugcost(fft.ss_ref,fft.ss_def);
215
234
  shifts[i].max_val[ss] = max_val;
235
+
236
+
237
+ if (g_debug_level == 1){
238
+ int progress = current_progress.fetch_add(1);
239
+ if (omp_get_thread_num()==0) util::update_progress_bar(bar, progress, num_ss, prev_pct);
240
+ }
216
241
  }
217
242
  }
218
243
 
@@ -222,7 +247,6 @@ namespace fourier {
222
247
  remove_outliers(shifts[i].y, ssdata[i], fft_mad);
223
248
  }
224
249
 
225
-
226
250
  //smooth_field(shifts[i].x, ssdata[i], 7.0, 5);
227
251
  //smooth_field(shifts[i].y, ssdata[i], 7.0, 5);
228
252
 
@@ -233,9 +257,17 @@ namespace fourier {
233
257
  // std::cout << shifts[i].cost[ss] << std::endl;
234
258
  //}
235
259
  //std::cout << std::endl;
260
+
261
+ if (g_debug_level == 1){
262
+ int progress = current_progress;
263
+ util::update_progress_bar(bar, progress-1, num_ss, prev_pct);
264
+ bar.mark_as_completed();
265
+ indicators::show_console_cursor(true);
266
+ }
236
267
  }
237
268
 
238
269
 
270
+
239
271
  }
240
272
 
241
273
 
@@ -11,7 +11,9 @@
11
11
 
12
12
  // Program Header files
13
13
  #include "./dicinterpolator.hpp"
14
-
14
+ #include "./dicutil.hpp"
15
+ #include "defines.hpp"
16
+ #include "./dicsignalhandler.hpp"
15
17
 
16
18
 
17
19
  inline int idx_from_2d(const int x, const int y, const int length){
@@ -49,10 +51,27 @@ Interpolator::Interpolator(double*img, int px_hori, int px_vert){
49
51
 
50
52
  //interpolator data
51
53
  std::vector<double> data(px_hori,0);
54
+
55
+
56
+ indicators::ProgressBar bar;
57
+ std::atomic<int> current_progress = 0;
58
+ int prev_pct = 0;
59
+ int niters = px_vert+px_hori+px_hori;
60
+
61
+ if (g_debug_level == 1){
62
+ std::string bar_title = "Creating Interpolator: ";
63
+ util::create_progress_bar(bar, bar_title, niters);
64
+ }
65
+
52
66
 
53
67
  //#pragma omp parallel for
54
68
  for (int j = 0; j < px_vert; j++){
55
69
 
70
+ // exit if ctrl+C
71
+ if (stop_request){
72
+ continue;
73
+ }
74
+
56
75
  // get 1D data
57
76
  for (int i = 0; i < px_hori; i++) {
58
77
  data[i] = image[j*px_hori + i];
@@ -62,6 +81,12 @@ Interpolator::Interpolator(double*img, int px_hori, int px_vert){
62
81
  for (int i = 0; i < px_hori; i++){
63
82
  dx[j*px_hori + i] = cspline_eval_deriv(px_x, data, px_x[i], px_hori);
64
83
  }
84
+
85
+ // update progress bar if enabled
86
+ if (g_debug_level == 1){
87
+ int progress = current_progress.fetch_add(1);
88
+ util::update_progress_bar(bar, progress, niters, prev_pct);
89
+ }
65
90
  }
66
91
 
67
92
  data.resize(px_vert,0);
@@ -69,6 +94,11 @@ Interpolator::Interpolator(double*img, int px_hori, int px_vert){
69
94
  //#pragma omp parallel for
70
95
  for (int i = 0; i < px_hori; ++i) {
71
96
 
97
+ // exit if ctrl+C
98
+ if (stop_request){
99
+ continue;
100
+ }
101
+
72
102
  // get 1D data
73
103
  for (int j = 0; j < px_vert; j++){
74
104
  data[j] = image[j*px_hori + i];
@@ -78,6 +108,12 @@ Interpolator::Interpolator(double*img, int px_hori, int px_vert){
78
108
  for (int j = 0; j < px_vert; j++){
79
109
  dy[j*px_hori + i] = cspline_eval_deriv(px_y, data, px_y[j], px_vert);
80
110
  }
111
+
112
+ // update progress bar if enabled
113
+ if (g_debug_level == 1){
114
+ int progress = current_progress.fetch_add(1);
115
+ util::update_progress_bar(bar, progress, niters, prev_pct);
116
+ }
81
117
  }
82
118
 
83
119
 
@@ -86,6 +122,11 @@ Interpolator::Interpolator(double*img, int px_hori, int px_vert){
86
122
  //#pragma omp parallel for
87
123
  for (int j = 0; j < px_vert; j++){
88
124
 
125
+ // exit if ctrl+C
126
+ if (stop_request){
127
+ continue;
128
+ }
129
+
89
130
  // get 1D data
90
131
  for (int i = 0; i < px_hori; i++) {
91
132
  data[i] = dy[j*px_hori + i];
@@ -95,6 +136,20 @@ Interpolator::Interpolator(double*img, int px_hori, int px_vert){
95
136
  for (int i = 0; i < px_hori; i++){
96
137
  dxy[j*px_hori + i] = cspline_eval_deriv(px_x, data, px_x[i], px_hori);
97
138
  }
139
+
140
+ // update progress bar if enabled
141
+ if (g_debug_level == 1){
142
+ int progress = current_progress.fetch_add(1);
143
+ util::update_progress_bar(bar, progress, niters, prev_pct);
144
+ }
145
+ }
146
+
147
+
148
+ if (g_debug_level == 1){
149
+ int progress = current_progress;
150
+ util::update_progress_bar(bar, progress-1, niters, prev_pct);
151
+ bar.mark_as_completed();
152
+ indicators::show_console_cursor(true);
98
153
  }
99
154
  }
100
155
 
@@ -16,6 +16,7 @@
16
16
  #include <pybind11/pybind11.h>
17
17
  #include <pybind11/numpy.h>
18
18
  #include <pybind11/stl.h>
19
+ #include <pybind11/iostream.h>
19
20
 
20
21
  // Program Header files
21
22
  #include "./dicinterpolator.hpp"
@@ -26,6 +27,7 @@
26
27
  #include "./dicutil.hpp"
27
28
  #include "./dicstrain.hpp"
28
29
  #include "./dicfourier.hpp"
30
+ #include "./dicsignalhandler.hpp"
29
31
 
30
32
  // cuda Header files
31
33
  #include "../cuda/malloc.hpp"
@@ -39,6 +41,10 @@ void DICengine(const py::array_t<double>& img_ref_arr,
39
41
  util::Config &conf,
40
42
  util::SaveConfig &saveconf){
41
43
 
44
+ // Register signal handler for Ctrl+C and set debug_level
45
+ signal(SIGINT, signalHandler);
46
+ g_debug_level = conf.debug_level;
47
+
42
48
  // ------------------------------------------------------------------------
43
49
  // Initialisation
44
50
  // ------------------------------------------------------------------------
@@ -59,28 +65,16 @@ void DICengine(const py::array_t<double>& img_ref_arr,
59
65
  INFO_OUT("Subset Size:", conf.ss_size << " [px]");
60
66
  INFO_OUT("Subset Step:", conf.ss_step << " [px]" );
61
67
  INFO_OUT("Number of OMP threads:", omp_get_max_threads());
68
+ INFO_OUT("Debug level: ", conf.debug_level);
62
69
  if (conf.scan_method=="RG") INFO_OUT("Reliability Guided Seed central px location: ", "("
63
70
  << conf.rg_seed.first+conf.ss_size/2 << ", " << conf.rg_seed.second+conf.ss_size/2 << ") [px] " )
64
71
 
65
- // Register signal handler for Ctrl+C
66
- signal(SIGINT, scanmethod::signalHandler);
67
72
 
68
- // get raw pointers
73
+ // get raw pointers
69
74
  bool* img_roi = static_cast<bool*>(img_roi_arr.request().ptr);
70
75
  double* img_ref = static_cast<double*>(img_ref_arr.request().ptr);
71
76
  double* img_def_stack = static_cast<double*>(img_def_stack_arr.request().ptr);
72
77
 
73
- // debugging
74
- //for (int y = 0; y < conf.px_vert; y++){
75
- // for (int x = 0; x < conf.px_hori; x++){
76
- // std::cout << x << " " << y << " ";
77
- // std::cout << img_ref[y*conf.px_hori + x] << " ";
78
- // std::cout << img_def_stack[y*conf.px_hori + x] << " ";
79
- // std::cout << img_roi[y*conf.px_hori+x] << std::endl;
80
- // }
81
- //}
82
- //exit(0);
83
-
84
78
  // ------------------------------------------------------------------------
85
79
  // get a list of ss coordinates within RIO;
86
80
  // ------------------------------------------------------------------------
@@ -108,8 +102,8 @@ void DICengine(const py::array_t<double>& img_ref_arr,
108
102
  optimizer::init(conf.corr_crit, conf.shape_func);
109
103
 
110
104
  // initialise the brute force scan
111
- std::string brute_method = "EXPANDING_WAVEFRONT";
112
- brute::init(conf.corr_crit, brute_method);
105
+ // std::string brute_method = "EXPANDING_WAVEFRONT";
106
+ // brute::init(conf.corr_crit, brute_method);
113
107
 
114
108
 
115
109
 
@@ -150,7 +144,6 @@ void DICengine(const py::array_t<double>& img_ref_arr,
150
144
 
151
145
  if (!saveconf.at_end)
152
146
  util::save_to_disk(img_num, saveconf, ssdata.back(), conf.num_def_img, conf.num_params, conf.filenames);
153
-
154
147
  }
155
148
 
156
149
  if (saveconf.at_end)
@@ -172,8 +165,16 @@ void build_info(){
172
165
  }
173
166
 
174
167
 
168
+ void set_num_threads(int n) {
169
+ omp_set_num_threads(n);
170
+ }
171
+
172
+
175
173
 
176
174
  PYBIND11_MODULE(dic2dcpp, m) {
175
+
176
+ py::add_ostream_redirect(m, "ostream_redirect");
177
+
177
178
  py::class_<util::Config>(m, "Config")
178
179
  .def(py::init<>())
179
180
  .def_readwrite("ss_step", &util::Config::ss_step)
@@ -194,7 +195,8 @@ PYBIND11_MODULE(dic2dcpp, m) {
194
195
  .def_readwrite("num_params", &util::Config::num_params)
195
196
  .def_readwrite("fft_mad", &util::Config::fft_mad)
196
197
  .def_readwrite("fft_mad_scale", &util::Config::fft_mad_scale)
197
- .def_readwrite("filenames", &util::Config::filenames);
198
+ .def_readwrite("filenames", &util::Config::filenames)
199
+ .def_readwrite("debug_level", &util::Config::debug_level);
198
200
 
199
201
  py::class_<util::SaveConfig>(m, "SaveConfig")
200
202
  .def(py::init<>())
@@ -202,12 +204,15 @@ PYBIND11_MODULE(dic2dcpp, m) {
202
204
  .def_readwrite("binary", &util::SaveConfig::binary)
203
205
  .def_readwrite("prefix", &util::SaveConfig::prefix)
204
206
  .def_readwrite("delimiter", &util::SaveConfig::delimiter)
205
- .def_readwrite("at_end", &util::SaveConfig::at_end);
207
+ .def_readwrite("at_end", &util::SaveConfig::at_end)
208
+ .def_readwrite("output_unconverged", &util::SaveConfig::output_unconverged)
209
+ .def_readwrite("shape_params", &util::SaveConfig::shape_params);
206
210
 
207
211
  // Bind the engine function
208
212
  m.def("build_info", &build_info, "build information");
209
213
  m.def("dic_engine", &DICengine, "Run 2D analysis on input images with config");
210
214
  m.def("strain_engine", &strain::engine, "Strain C++ calculations");
215
+ m.def("set_num_threads", &set_num_threads, "Set the number of OpenMP threads");
211
216
  }
212
217
 
213
218
 
@@ -52,7 +52,7 @@ namespace optimizer {
52
52
  double ftol = 0;
53
53
  double xtol = 0;
54
54
  opt.lambda = 0.001;
55
- bool converged = false;
55
+ uint8_t converged = false;
56
56
 
57
57
 
58
58
  // trying relative instead of global coordinates for the optimization
@@ -69,6 +69,9 @@ namespace optimizer {
69
69
  optimize_cost(ss_ref, ss_def, interp_def, opt, global_x, global_y);
70
70
  update_lambda(opt.costp, opt.costpdp, opt.p, opt.pdp, opt.lambda, opt.num_params);
71
71
 
72
+ // TODO: have a look at removing the two square roots in the below. Can we get away without
73
+ // it? cache is locally and perform the square root only once?
74
+
72
75
  // relative change of all parameters
73
76
  xtol = std::sqrt(std::inner_product(opt.dp.begin(), opt.dp.end(), opt.dp.begin(), 0.0)) /
74
77
  std::sqrt(std::inner_product( opt.p.begin(), opt.p.end(), opt.p.begin(), 0.0));
@@ -78,6 +81,8 @@ namespace optimizer {
78
81
  // variation on correlation coefficient
79
82
  ftol = std::abs(opt.costpdp - opt.costp);
80
83
 
84
+
85
+ // TODO: convert ssd if statement into func pointer.
81
86
  // convergence criteria
82
87
  // - rel change in parameters is less than user precision
83
88
  // - change in corr coeff is less than precision
@@ -23,19 +23,11 @@
23
23
  #include "./indicators.hpp"
24
24
  #include "./cursor_control.hpp"
25
25
  #include "./dicfourier.hpp"
26
+ #include "./dicsignalhandler.hpp"
26
27
 
27
28
  namespace scanmethod {
28
29
 
29
30
 
30
- // for graceful exit
31
- std::atomic<bool> stop_request(false);
32
-
33
- void signalHandler(int signal) {
34
- if (signal == SIGINT) {
35
- stop_request = true;
36
- }
37
- }
38
-
39
31
  void image(const double *img_ref,
40
32
  const Interpolator &interp_def,
41
33
  const util::SubsetData &ssdata,
@@ -47,11 +39,11 @@ namespace scanmethod {
47
39
 
48
40
  // progress bar
49
41
  indicators::ProgressBar bar;
50
- util::create_progress_bar(bar, conf.filenames, img_num, 100);
42
+ util::create_progress_bar(bar, conf.filenames[img_num], num_ss);
51
43
  std::atomic<int> current_progress = 0;
52
- std::atomic<int> prev_pct = 0;
44
+ int prev_pct = 0;
53
45
 
54
- // loop over subsets within the ROI
46
+ // loop over subsets within the ROI
55
47
  #pragma omp parallel shared(stop_request)
56
48
  {
57
49
 
@@ -103,10 +95,13 @@ namespace scanmethod {
103
95
 
104
96
  // update progress bar
105
97
  int progress = current_progress.fetch_add(1);
106
- util::update_progress_bar(bar, progress, num_ss, prev_pct);
98
+ if (omp_get_thread_num()==0) util::update_progress_bar(bar, progress, num_ss, prev_pct);
107
99
 
108
100
  }
109
101
  }
102
+
103
+ int progress = current_progress;
104
+ util::update_progress_bar(bar, progress-1, num_ss, prev_pct);
110
105
  bar.mark_as_completed();
111
106
  indicators::show_console_cursor(true);
112
107
 
@@ -126,9 +121,9 @@ namespace scanmethod {
126
121
 
127
122
  // progress bar
128
123
  indicators::ProgressBar bar;
129
- util::create_progress_bar(bar, conf.filenames, img_num, num_ss);
124
+ util::create_progress_bar(bar, conf.filenames[img_num], num_ss);
130
125
  std::atomic<int> current_progress = 0;
131
- std::atomic<int> prev_pct = 0;
126
+ int prev_pct = 0;
132
127
 
133
128
  // initialise subsets
134
129
  util::Subset ss_def(ss_size);
@@ -211,9 +206,11 @@ namespace scanmethod {
211
206
 
212
207
  // update progress bar
213
208
  int progress = current_progress.fetch_add(1);
214
- util::update_progress_bar(bar, progress, num_ss, prev_pct);
209
+ if (omp_get_thread_num()==0) util::update_progress_bar(bar, progress, num_ss, prev_pct);
215
210
 
216
211
  }
212
+ int progress = current_progress;
213
+ util::update_progress_bar(bar, progress-1, num_ss, prev_pct);
217
214
  bar.mark_as_completed();
218
215
  indicators::show_console_cursor(true);
219
216
  }
@@ -242,15 +239,16 @@ namespace scanmethod {
242
239
  const int ss_size = ssdata[last_size].size;
243
240
  const int ss_step = ssdata[last_size].step;
244
241
 
245
-
242
+ //TODO: sort this function name out
246
243
  fourier::mgwd(ssdata, img_ref, img_def, interp_def,
247
244
  conf.fft_mad, conf.fft_mad_scale);
248
245
 
249
246
  // progress bar
250
247
  indicators::ProgressBar bar;
251
- util::create_progress_bar(bar, conf.filenames, img_num, num_ss);
248
+ util::create_progress_bar(bar, conf.filenames[img_num], num_ss);
252
249
  std::atomic<int> current_progress(0);
253
- std::atomic<int> prev_pct(0);
250
+ //int prev_pct(0);
251
+ int prev_pct = 0;
254
252
 
255
253
  // quick check for the initial seed point
256
254
  if (!rg::is_valid_point(seed_x, seed_y, ssdata[last_size])) {
@@ -259,7 +257,7 @@ namespace scanmethod {
259
257
 
260
258
  // Initialize binary mask for computed points (initialized to 0)
261
259
  std::vector<std::atomic<int>> computed_mask(ssdata[last_size].mask.size());
262
- for (auto& val : computed_mask) val.store(0);
260
+ for (auto& val : computed_mask) val.store(0);
263
261
 
264
262
  // queue for each thread
265
263
  std::vector<std::priority_queue<rg::Point>> local_q(omp_get_max_threads());
@@ -287,7 +285,7 @@ namespace scanmethod {
287
285
  if (conf.corr_crit=="SSD")
288
286
  opt.opt_threshold = std::numeric_limits<double>::max();
289
287
 
290
- brute::Parameters brute(conf.bf_threshold, conf.max_disp);
288
+ // brute::Parameters brute(conf.bf_threshold, conf.max_disp);
291
289
 
292
290
  std::vector<std::unique_ptr<fourier::FFT>> fft_windows;
293
291
 
@@ -299,6 +297,8 @@ namespace scanmethod {
299
297
  // number of iterations to make sure we get a good convergence.
300
298
  // this is hardcoded for now. Could do with updating so that
301
299
  // the seed location is checked ahead of the main correlation run.
300
+
301
+ // TODO: opt.seed_iter exposed to user.
302
302
  opt.max_iter = 200;
303
303
 
304
304
  // ---------------------------------------------------------------------------------------------------------------------------
@@ -336,9 +336,6 @@ namespace scanmethod {
336
336
 
337
337
  computed_mask[idx].store(1);
338
338
 
339
- // int progress = current_progress.fetch_add(1);
340
- // util::update_progress_bar(bar, progress, num_ss, prev_pct);
341
-
342
339
  // loop over the neighbours for the initial seed point
343
340
  for (size_t n = 0; n < ssdata[last_size].neigh[idx].size(); n++) {
344
341
 
@@ -369,7 +366,7 @@ namespace scanmethod {
369
366
  util::append_results(img_num, nidx, nres, num_ss);
370
367
 
371
368
  // update mask
372
- computed_mask[idx].store(1);
369
+ computed_mask[nidx].store(1);
373
370
 
374
371
  // add this point to queue
375
372
  // Protect push with mutex
@@ -390,6 +387,7 @@ namespace scanmethod {
390
387
  // ---------------------------------------------------------------------------------------------------------------------------
391
388
  #pragma omp barrier
392
389
 
390
+ // TODO: reset seed location using the last computed point
393
391
  opt.max_iter = conf.max_iter;
394
392
 
395
393
  std::vector<rg::Point> temp_neigh;
@@ -494,7 +492,7 @@ namespace scanmethod {
494
492
 
495
493
  // update progress bar
496
494
  int progress = current_progress.fetch_add(1);
497
- util::update_progress_bar(bar, progress, num_ss, prev_pct);
495
+ if (omp_get_thread_num()==0) util::update_progress_bar(bar, progress, num_ss, prev_pct);
498
496
 
499
497
  }
500
498
  }
@@ -505,6 +503,8 @@ namespace scanmethod {
505
503
  }
506
504
  }
507
505
  }
506
+ int progress = current_progress;
507
+ util::update_progress_bar(bar, progress-1, num_ss, prev_pct);
508
508
  bar.mark_as_completed();
509
509
  indicators::show_console_cursor(true);
510
510
 
@@ -532,9 +532,9 @@ namespace scanmethod {
532
532
 
533
533
  // progress bar
534
534
  indicators::ProgressBar bar;
535
- util::create_progress_bar(bar, conf.filenames, img_num, num_ss);
535
+ util::create_progress_bar(bar, conf.filenames[img_num], num_ss);
536
536
  std::atomic<int> current_progress = 0;
537
- std::atomic<int> prev_pct = 0;
537
+ int prev_pct = 0;
538
538
 
539
539
  // loop over subsets within the ROI
540
540
  #pragma omp parallel shared(stop_request)
@@ -587,7 +587,7 @@ namespace scanmethod {
587
587
 
588
588
  // update progress bar
589
589
  int progress = current_progress.fetch_add(1);
590
- util::update_progress_bar(bar, progress, num_ss, prev_pct);
590
+ if (omp_get_thread_num()==0) util::update_progress_bar(bar, progress, num_ss, prev_pct);
591
591
 
592
592
  }
593
593
  }
@@ -613,9 +613,9 @@ namespace scanmethod {
613
613
 
614
614
  // progress bar
615
615
  indicators::ProgressBar bar;
616
- util::create_progress_bar(bar, conf.filenames, img_num, num_ss);
616
+ util::create_progress_bar(bar, conf.filenames[img_num], num_ss);
617
617
  std::atomic<int> current_progress = 0;
618
- std::atomic<int> prev_pct = 0;
618
+ int prev_pct = 0;
619
619
 
620
620
  // loop over subsets within the ROI
621
621
  #pragma omp parallel shared(stop_request)
@@ -666,7 +666,7 @@ namespace scanmethod {
666
666
 
667
667
  // update progress bar
668
668
  int progress = current_progress.fetch_add(1);
669
- util::update_progress_bar(bar, progress, num_ss, prev_pct);
669
+ if (omp_get_thread_num()==0) util::update_progress_bar(bar, progress, num_ss, prev_pct);
670
670
 
671
671
  }
672
672
  }
@@ -0,0 +1,16 @@
1
+ // ================================================================================
2
+ // pyvale: the python validation engine
3
+ // License: MIT
4
+ // Copyright (C) 2025 The Computer Aided Validation Team
5
+ // ================================================================================
6
+
7
+ #include "./dicsignalhandler.hpp"
8
+ #include <csignal>
9
+
10
+ std::atomic<bool> stop_request = false;
11
+
12
+ void signalHandler(int signal) {
13
+ if (signal == SIGINT) {
14
+ stop_request = true;
15
+ }
16
+ }
@@ -6,6 +6,7 @@
6
6
 
7
7
  // STD library Header files
8
8
  #include <cmath>
9
+ #include <omp.h>
9
10
  #include <vector>
10
11
  #include <iostream>
11
12
  #include <iomanip>
@@ -70,8 +71,8 @@ namespace strain {
70
71
  for (int img_num = 0; img_num < nimg; img_num++) {
71
72
 
72
73
  indicators::ProgressBar bar;
73
- util::create_progress_bar(bar, filenames, img_num, nwindows);
74
- std::atomic<int> prev_pct = 0;
74
+ util::create_progress_bar(bar, filenames[img_num], nwindows);
75
+ int prev_pct = 0;
75
76
 
76
77
  // loop over strain windows within the image
77
78
  for (int sw = 0; sw < nwindows; sw++){
@@ -81,6 +82,9 @@ namespace strain {
81
82
  results.x[sw] = x0;
82
83
  results.y[sw] = y0;
83
84
 
85
+ // TODO: through a warning. NAN out the entire window.
86
+ // it should be up to the user whether they correct with
87
+ // outlier removal / smoothing.
84
88
  results.valid_window[sw] = fill_window(ss_x, ss_y, u, v, img_num,
85
89
  sw, window, nss_x,
86
90
  nss_y, sw_size);
@@ -102,7 +106,7 @@ namespace strain {
102
106
  deform_grad, eps, nwindows, img_num);
103
107
  }
104
108
 
105
- util::update_progress_bar(bar, sw, nwindows, prev_pct);
109
+ if (omp_get_thread_num() == 0) util::update_progress_bar(bar, sw, nwindows, prev_pct);
106
110
 
107
111
  }
108
112