pyvale 2025.5.3__cp311-cp311-macosx_14_0_arm64.whl → 2025.7.0__cp311-cp311-macosx_14_0_arm64.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.

Files changed (95) hide show
  1. pyvale/.dylibs/libomp.dylib +0 -0
  2. pyvale/.dylibs/libunwind.1.0.dylib +0 -0
  3. pyvale/__init__.py +12 -0
  4. pyvale/blendercalibrationdata.py +3 -1
  5. pyvale/blenderscene.py +7 -5
  6. pyvale/blendertools.py +27 -5
  7. pyvale/camera.py +1 -0
  8. pyvale/cameradata.py +3 -0
  9. pyvale/camerasensor.py +147 -0
  10. pyvale/camerastereo.py +4 -4
  11. pyvale/cameratools.py +23 -61
  12. pyvale/cython/rastercyth.c +1657 -1352
  13. pyvale/cython/rastercyth.cpython-311-darwin.so +0 -0
  14. pyvale/cython/rastercyth.py +71 -26
  15. pyvale/data/plate_hole_def0000.tiff +0 -0
  16. pyvale/data/plate_hole_def0001.tiff +0 -0
  17. pyvale/data/plate_hole_ref0000.tiff +0 -0
  18. pyvale/data/plate_rigid_def0000.tiff +0 -0
  19. pyvale/data/plate_rigid_def0001.tiff +0 -0
  20. pyvale/data/plate_rigid_ref0000.tiff +0 -0
  21. pyvale/dataset.py +96 -6
  22. pyvale/dic/cpp/dicbruteforce.cpp +370 -0
  23. pyvale/dic/cpp/dicfourier.cpp +648 -0
  24. pyvale/dic/cpp/dicinterpolator.cpp +559 -0
  25. pyvale/dic/cpp/dicmain.cpp +215 -0
  26. pyvale/dic/cpp/dicoptimizer.cpp +675 -0
  27. pyvale/dic/cpp/dicrg.cpp +137 -0
  28. pyvale/dic/cpp/dicscanmethod.cpp +677 -0
  29. pyvale/dic/cpp/dicsmooth.cpp +138 -0
  30. pyvale/dic/cpp/dicstrain.cpp +383 -0
  31. pyvale/dic/cpp/dicutil.cpp +563 -0
  32. pyvale/dic2d.py +164 -0
  33. pyvale/dic2dcpp.cpython-311-darwin.so +0 -0
  34. pyvale/dicchecks.py +476 -0
  35. pyvale/dicdataimport.py +247 -0
  36. pyvale/dicregionofinterest.py +887 -0
  37. pyvale/dicresults.py +55 -0
  38. pyvale/dicspecklegenerator.py +238 -0
  39. pyvale/dicspecklequality.py +305 -0
  40. pyvale/dicstrain.py +387 -0
  41. pyvale/dicstrainresults.py +37 -0
  42. pyvale/errorintegrator.py +10 -8
  43. pyvale/examples/basics/ex1_1_basicscalars_therm2d.py +124 -113
  44. pyvale/examples/basics/ex1_2_sensormodel_therm2d.py +124 -132
  45. pyvale/examples/basics/ex1_3_customsens_therm3d.py +199 -195
  46. pyvale/examples/basics/ex1_4_basicerrors_therm3d.py +125 -121
  47. pyvale/examples/basics/ex1_5_fielderrs_therm3d.py +145 -141
  48. pyvale/examples/basics/ex1_6_caliberrs_therm2d.py +96 -101
  49. pyvale/examples/basics/ex1_7_spatavg_therm2d.py +109 -105
  50. pyvale/examples/basics/ex2_1_basicvectors_disp2d.py +92 -91
  51. pyvale/examples/basics/ex2_2_vectorsens_disp2d.py +96 -90
  52. pyvale/examples/basics/ex2_3_sensangle_disp2d.py +88 -89
  53. pyvale/examples/basics/ex2_4_chainfielderrs_disp2d.py +172 -171
  54. pyvale/examples/basics/ex2_5_vectorfields3d_disp3d.py +88 -86
  55. pyvale/examples/basics/ex3_1_basictensors_strain2d.py +90 -90
  56. pyvale/examples/basics/ex3_2_tensorsens2d_strain2d.py +93 -91
  57. pyvale/examples/basics/ex3_3_tensorsens3d_strain3d.py +172 -160
  58. pyvale/examples/basics/ex4_1_expsim2d_thermmech2d.py +154 -148
  59. pyvale/examples/basics/ex4_2_expsim3d_thermmech3d.py +249 -231
  60. pyvale/examples/dic/ex1_region_of_interest.py +98 -0
  61. pyvale/examples/dic/ex2_plate_with_hole.py +149 -0
  62. pyvale/examples/dic/ex3_plate_with_hole_strain.py +93 -0
  63. pyvale/examples/dic/ex4_dic_blender.py +95 -0
  64. pyvale/examples/dic/ex5_dic_challenge.py +102 -0
  65. pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +4 -2
  66. pyvale/examples/renderblender/ex1_1_blenderscene.py +152 -105
  67. pyvale/examples/renderblender/ex1_2_blenderdeformed.py +151 -100
  68. pyvale/examples/renderblender/ex2_1_stereoscene.py +183 -116
  69. pyvale/examples/renderblender/ex2_2_stereodeformed.py +185 -112
  70. pyvale/examples/renderblender/ex3_1_blendercalibration.py +164 -109
  71. pyvale/examples/renderrasterisation/ex_rastenp.py +74 -35
  72. pyvale/examples/renderrasterisation/ex_rastercyth_oneframe.py +6 -13
  73. pyvale/examples/renderrasterisation/ex_rastercyth_static_cypara.py +2 -2
  74. pyvale/examples/renderrasterisation/ex_rastercyth_static_pypara.py +2 -4
  75. pyvale/imagedef2d.py +3 -2
  76. pyvale/imagetools.py +137 -0
  77. pyvale/rastercy.py +34 -4
  78. pyvale/rasternp.py +300 -276
  79. pyvale/rasteropts.py +58 -0
  80. pyvale/renderer.py +47 -0
  81. pyvale/rendermesh.py +52 -62
  82. pyvale/renderscene.py +51 -0
  83. pyvale/sensorarrayfactory.py +2 -2
  84. pyvale/sensortools.py +19 -35
  85. pyvale/simcases/case21.i +1 -1
  86. pyvale/simcases/run_1case.py +8 -0
  87. pyvale/simtools.py +2 -2
  88. pyvale/visualsimplotter.py +180 -0
  89. {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/METADATA +11 -57
  90. {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/RECORD +93 -57
  91. {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/WHEEL +1 -1
  92. pyvale/examples/visualisation/ex1_1_plot_traces.py +0 -102
  93. pyvale/examples/visualisation/ex2_1_animate_sim.py +0 -89
  94. {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/licenses/LICENSE +0 -0
  95. {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,563 @@
1
+ // ================================================================================
2
+ // pyvale: the python validation engine
3
+ // License: MIT
4
+ // Copyright (C) 2025 The Computer Aided Validation Team
5
+ // ================================================================================
6
+
7
+
8
+ // STD library Header files
9
+ #include <cstdlib>
10
+ #include <iostream>
11
+ #include <fstream>
12
+ #include <sstream>
13
+ #include <vector>
14
+ #include <cmath>
15
+
16
+ // Program Header files
17
+ #include "./dicinterpolator.hpp"
18
+ #include "./indicators.hpp"
19
+ #include "./defines.hpp"
20
+ #include "./dicutil.hpp"
21
+
22
+
23
+ namespace util {
24
+
25
+
26
+ std::vector<int> niter_arr;
27
+ std::vector<double> u_arr;
28
+ std::vector<double> v_arr;
29
+ std::vector<double> p_arr;
30
+ std::vector<double> ftol_arr;
31
+ std::vector<double> xtol_arr;
32
+ std::vector<double> cost_arr;
33
+ std::vector<bool> conv_arr;
34
+ bool at_end;
35
+
36
+
37
+
38
+ void extract_image(double *img_def_stack,
39
+ int image_number,
40
+ int px_hori,
41
+ int px_vert){
42
+
43
+ int count = 0;
44
+ for (int px_y = 0; px_y < px_vert; px_y++){
45
+ for (int px_x = 0; px_x < px_hori; px_x++){
46
+ int idx = image_number * px_hori * px_vert + px_y * px_hori + px_x;
47
+ std::cout << img_def_stack[idx] << " ";
48
+ //img_def->vals[count] = img_def_stack[idx];
49
+ count++;
50
+ }
51
+ std::cout << std::endl;
52
+ }
53
+ exit(0);
54
+ }
55
+
56
+ int get_num_params(std::string &shape_func){
57
+ int num_params;
58
+ if (shape_func == "RIGID") num_params = 2;
59
+ else if (shape_func == "AFFINE") num_params = 6;
60
+ else {
61
+ std::cerr << "Unknown shape function: \'" << shape_func << "\'." << std::endl;
62
+ std::cerr << "Allowed values: \'AFFINE\', \'RIGID\'. " << std::endl;
63
+ exit(EXIT_FAILURE);
64
+ }
65
+ return num_params;
66
+ }
67
+
68
+
69
+
70
+ void extract_ss(util::Subset &ss_ref,
71
+ const int ss_x, const int ss_y,
72
+ const int px_hori,
73
+ const int px_vert,
74
+ const double *img_def){
75
+
76
+ int count = 0;
77
+ int idx;
78
+
79
+ for (int px_y = ss_y; px_y < ss_y+ss_ref.size; px_y++){
80
+ for (int px_x = ss_x; px_x < ss_x+ss_ref.size; px_x++){
81
+
82
+ // get coordinate values
83
+ ss_ref.x[count] = px_x;
84
+ ss_ref.y[count] = px_y;
85
+
86
+ // get pixel values
87
+ idx = px_y * px_hori + px_x;
88
+ ss_ref.vals[count] = img_def[idx];
89
+ count++;
90
+
91
+ // debugging
92
+ //std::cout << px_x << " " << px_y << " ";
93
+ //std::cout << img_def[idx] << std::endl;
94
+ }
95
+ }
96
+ }
97
+
98
+ void extract_ss_subpx(util::Subset &ss_def,
99
+ const double subpx_x, const double subpx_y,
100
+ const Interpolator &interp_def){
101
+
102
+ int count = 0;
103
+
104
+ for (int y = 0; y < ss_def.size; y++){
105
+ for (int x = 0; x < ss_def.size; x++){
106
+ if (count >= ss_def.size*ss_def.size){
107
+ std::cerr << "issue with count for subpixel subset population" << std::endl;
108
+ std::cerr << "count: " << count << std::endl;
109
+ std::cerr << "subset size: " << ss_def.size << std::endl;
110
+ std::cerr << "num px (size*size): " << ss_def.size*ss_def.size << std::endl;
111
+ std::cerr << "subpixel value: " << subpx_x+x << " " << subpx_y+y << std::endl;
112
+ std::cerr << "subset coordinates: " << " " << subpx_x << " " << subpx_y << " " << std::endl;
113
+ exit(EXIT_FAILURE);
114
+ }
115
+ // get coordinate values
116
+ ss_def.x[count] = subpx_x+x;
117
+ ss_def.y[count] = subpx_y+y;
118
+
119
+ // get pixel values
120
+ ss_def.vals[count] = interp_def.eval_bicubic(0, 0, ss_def.x[count], ss_def.y[count]);
121
+
122
+ // debugging
123
+ //std::cout << ss_def.x[count] << " " << ss_def.y[count] << " " << ss_def.vals[count] << std::endl;
124
+
125
+ count++;
126
+ }
127
+ }
128
+ if (count!=ss_def.size*ss_def.size){
129
+ std::cerr << "count for subpixel population is not the same as the number of subset pixels.";
130
+ std::cout << "count: " << count << std::endl;
131
+ std::cerr << "number of pixels: " << ss_def.size*ss_def.size << std::endl;
132
+ exit(EXIT_FAILURE);
133
+ }
134
+ }
135
+
136
+ SubsetData gen_ss_list(const bool *img_roi, const int ss_step,
137
+ const int ss_size, const int px_hori,
138
+ const int px_vert, const bool partial) {
139
+
140
+ //Timer timer("subset list generation for subset size " + std::to_string(ss_size) + " [px] with step " + std::to_string(ss_step) + " [px]:" );
141
+
142
+ SubsetData ssdata;
143
+
144
+ int dx[4] = {ss_step, 0, -ss_step, 0};
145
+ int dy[4] = {0, ss_step, 0, -ss_step};
146
+
147
+ int subset_counter = 0;
148
+
149
+ int num_ss_x = px_hori / ss_step;
150
+ int num_ss_y = px_vert / ss_step;
151
+ //ssdata.mask.resize(num_ss_x*num_ss_y, NAN);
152
+ ssdata.num_ss_x = num_ss_x;
153
+ ssdata.num_ss_y = num_ss_y;
154
+ ssdata.num_in_mask = num_ss_x * num_ss_y;
155
+ ssdata.num = 0;
156
+ ssdata.step = ss_step;
157
+ ssdata.size = ss_size;
158
+
159
+ ssdata.mask.resize(ssdata.num_in_mask, -1);
160
+ ssdata.coords.resize(2*ssdata.num_in_mask, -1);
161
+
162
+ // First pass: collect valid subset centers and idx them
163
+ // TODO: Parallelise this with openMP
164
+ for (int j = 0; j < num_ss_y; j++) {
165
+ for (int i = 0; i < num_ss_x; i++) {
166
+
167
+ // calculate the coordinates of the subset
168
+ int ss_x = i * ss_step;
169
+ int ss_y = j * ss_step;
170
+
171
+ // pixel range of subset
172
+ int xmin = ss_x;
173
+ int ymin = ss_y;
174
+ int xmax = ss_x + ss_size-1;
175
+ int ymax = ss_y + ss_size-1;
176
+
177
+ // check if subset is within image and ROI.
178
+ bool valid = true;
179
+ int valid_count = 0;
180
+ for (int px_y = ymin; px_y <= ymax && valid; px_y++) {
181
+ for (int px_x = xmin; px_x <= xmax && valid; px_x++) {
182
+
183
+ // When no partial subset filling all px must be within roi
184
+ if (!partial) {
185
+ if (!is_valid_in_dims(px_x, px_y, px_hori, px_vert) ||
186
+ !is_valid_in_roi(px_x, px_y, px_hori, px_vert, img_roi)) {
187
+ valid = false;
188
+ break;
189
+ }
190
+ }
191
+
192
+ // When partial count num of px in roi
193
+ else {
194
+ if (is_valid_in_dims(px_x, px_y, px_hori, px_vert) &&
195
+ is_valid_in_roi(px_x, px_y, px_hori, px_vert, img_roi)) {
196
+ valid_count++;
197
+ }
198
+ }
199
+ }
200
+
201
+ if (!valid && !partial) break;
202
+ }
203
+
204
+ // TODO: this is hardcoded so that atleast 70% of pixels in subset must be in ROI
205
+ if (partial) {
206
+ if (valid_count >= (ss_size*ss_size) * (0.70)) {
207
+ valid = true;
208
+ } else {
209
+ valid = false;
210
+ }
211
+ }
212
+
213
+ // if its a valid subset. add it to a list of coordinates
214
+ if (valid) {
215
+ ssdata.coords[2*subset_counter] = ss_x;
216
+ ssdata.coords[2*subset_counter+1] = ss_y;
217
+ ssdata.mask[j * num_ss_x + i] = subset_counter;
218
+ subset_counter++;
219
+ }
220
+ }
221
+ }
222
+
223
+ ssdata.coords.resize(2*subset_counter);
224
+ ssdata.num = subset_counter;
225
+ ssdata.neigh.resize(ssdata.num);
226
+
227
+ // neighbours for each of the above subset
228
+ // TODO: Parallelise with openMP
229
+ for (int j = 0; j < num_ss_y; ++j) {
230
+ for (int i = 0; i < num_ss_x; ++i) {
231
+
232
+ // calculate the coordinates of the subset
233
+ int idx = ssdata.mask[j * num_ss_x + i];
234
+
235
+ if (idx == -1) continue;
236
+
237
+ std::vector<int> temp_neigh;
238
+
239
+ for (int d = 0; d < 4; ++d) {
240
+ int ni = i + dx[d] / ss_step;
241
+ int nj = j + dy[d] / ss_step;
242
+
243
+ if (ni >= 0 && ni < num_ss_x && nj >= 0 && nj < num_ss_y) {
244
+ int neigh_idx = ssdata.mask[nj * num_ss_x + ni];
245
+ if (neigh_idx != -1) {
246
+ temp_neigh.push_back(neigh_idx);
247
+ }
248
+ }
249
+ }
250
+
251
+ ssdata.neigh[idx] = temp_neigh;
252
+
253
+ // debugging
254
+ //int ss_x = ssdata.coords[2*idx];
255
+ //int ss_y = ssdata.coords[2*idx+1];
256
+ //std::cout << idx << " " << ss_x << " " << ss_y << " ";
257
+ //for (int n = 0; n < ssdata.neigh[idx].size(); n++){
258
+ // int nidx = ssdata.neigh[idx][n];
259
+ // std::cout << ssdata.coords[2*nidx] << " " << ssdata.coords[2*nidx+1] << " ";
260
+ //}
261
+ //std::cout << std::endl;
262
+ }
263
+ }
264
+
265
+ //for (const auto& kv : ssdata.coords_to_idx) {
266
+ // const std::pair<int, int>& coord = kv.first;
267
+ // int center_idx = kv.second;
268
+
269
+ // std::vector<int> temp_neigh;
270
+
271
+ // for (int i = 0; i < 4; ++i) {
272
+ // int neigh_x = coord.first + dx[i];
273
+ // int neigh_y = coord.second + dy[i];
274
+
275
+ // int xmin = neigh_x;
276
+ // int ymin = neigh_y;
277
+ // int xmax = neigh_x + ss_size;
278
+ // int ymax = neigh_y + ss_size;
279
+
280
+ // bool valid = true;
281
+
282
+ // // checking if the neigbour is valid
283
+ // for (int y = ymin; y <= ymax && valid; ++y) {
284
+ // for (int x = xmin; x <= xmax && valid; ++x) {
285
+
286
+ // if(!is_valid_pixel(x,y,px_hori,
287
+ // px_vert,img_roi)){
288
+
289
+ // valid = false;
290
+ // break;
291
+ // }
292
+
293
+ // }
294
+ // }
295
+
296
+ // if (valid) {
297
+ // auto it = ssdata.coords_to_idx.find({neigh_x, neigh_y});
298
+ // if (it != ssdata.coords_to_idx.end()) {
299
+ // temp_neigh.push_back(it->second);
300
+ // }
301
+ // }
302
+ // }
303
+
304
+ // ssdata.neigh[center_idx] = std::move(temp_neigh);
305
+ //}
306
+
307
+ return ssdata;
308
+ }
309
+
310
+ void resize_results(int num_def_img, int num_ss,
311
+ int num_params, bool at_end){
312
+
313
+
314
+ util::Timer timer("resizing of result arrays:");
315
+ util::at_end = at_end;
316
+
317
+ if (at_end){
318
+ niter_arr.resize(num_def_img * num_ss);
319
+ u_arr.resize(num_def_img * num_ss);
320
+ v_arr.resize(num_def_img * num_ss);
321
+ p_arr.resize(num_def_img * num_ss * num_params);
322
+ ftol_arr.resize(num_def_img * num_ss);
323
+ xtol_arr.resize(num_def_img * num_ss);
324
+ cost_arr.resize(num_def_img * num_ss);
325
+ conv_arr.resize(num_def_img * num_ss);
326
+ }
327
+ else {
328
+ niter_arr.resize(num_ss);
329
+ u_arr.resize(num_ss);
330
+ v_arr.resize(num_ss);
331
+ p_arr.resize(num_ss * num_params);
332
+ ftol_arr.resize(num_ss);
333
+ xtol_arr.resize(num_ss);
334
+ cost_arr.resize(num_ss);
335
+ conv_arr.resize(num_ss);
336
+ }
337
+ }
338
+
339
+
340
+ void append_results(int img_num, int ss, util::Results &res,
341
+ int num_ss) {
342
+ int idx;
343
+ if (util::at_end) idx = img_num * num_ss + ss;
344
+ else idx = ss;
345
+
346
+ int idx_p = res.p.size()*idx;
347
+ niter_arr[idx] = res.iter;
348
+ u_arr[idx] = res.u;
349
+ v_arr[idx] = res.v;
350
+ ftol_arr[idx] = res.ftol;
351
+ xtol_arr[idx] = res.xtol;
352
+ cost_arr[idx] = res.cost;
353
+ conv_arr[idx] = res.converged;
354
+ for (size_t i = 0; i < res.p.size(); i++){
355
+ p_arr[idx_p+i] = res.p[i];
356
+ }
357
+ }
358
+
359
+
360
+ void save_to_disk(int img, const util::SaveConfig &saveconf,
361
+ const util::SubsetData &ssdata, const int num_def_img,
362
+ const int num_params, const std::vector<std::string> &filenames){
363
+
364
+ const std::string delimiter = saveconf.delimiter;
365
+
366
+ // open the file
367
+ std::stringstream outfile_str;
368
+ std::ofstream outfile;
369
+
370
+ std::string file_ext;
371
+ if (saveconf.binary) file_ext=".dic2d";
372
+ else file_ext=".csv";
373
+
374
+ // Extract the base filename without extension
375
+ std::string full_filename = filenames[img];
376
+ size_t dot_pos = full_filename.find(".");
377
+ if (dot_pos != std::string::npos) {
378
+ full_filename = full_filename.substr(0, dot_pos);
379
+ }
380
+
381
+ // output filename
382
+ outfile_str << saveconf.basepath << "/" <<
383
+ saveconf.prefix << full_filename << file_ext;
384
+
385
+ // set the img var to 0 after opening file if not saving at end
386
+ if (!saveconf.at_end) img = 0;
387
+
388
+ // save in binary format
389
+ if (saveconf.binary){
390
+ outfile.open(outfile_str.str(), std::ios::binary);
391
+
392
+ for (int i = 0; i < ssdata.num; ++i) {
393
+
394
+ int idx = img * ssdata.num + i;
395
+ //int idx_p = num_params*idx;
396
+
397
+ double mag = std::sqrt(u_arr[idx]*u_arr[idx]+
398
+ v_arr[idx]*v_arr[idx]);
399
+
400
+ // convert from corner to centre subset coords
401
+ double ss_x = ssdata.coords[2*i ] + static_cast<double>(ssdata.size)/2.0 - 0.5;
402
+ double ss_y = ssdata.coords[2*i+1] + static_cast<double>(ssdata.size)/2.0 - 0.5;
403
+
404
+ write_int(outfile, ss_x);
405
+ write_int(outfile, ss_y);
406
+ write_dbl(outfile, u_arr[idx]);
407
+ write_dbl(outfile, v_arr[idx]);
408
+ write_dbl(outfile, mag);
409
+ write_bool(outfile, conv_arr[idx]);
410
+ write_dbl(outfile, cost_arr[idx]);
411
+ write_dbl(outfile, ftol_arr[idx]);
412
+ write_dbl(outfile, xtol_arr[idx]);
413
+ write_int(outfile, niter_arr[idx]);
414
+ }
415
+
416
+ outfile.close();
417
+ }
418
+ else {
419
+
420
+ outfile.open(outfile_str.str());
421
+
422
+ // column headers
423
+ outfile << "subset_x" << delimiter;
424
+ outfile << "subset_y" << delimiter;
425
+ outfile << "displacement_u" << delimiter;
426
+ outfile << "displacement_v" << delimiter;
427
+ outfile << "displacement_mag" << delimiter;
428
+ outfile << "converged" << delimiter;
429
+ outfile << "cost" << delimiter;
430
+ outfile << "ftol" << delimiter;
431
+ outfile << "xtol" << delimiter;
432
+ outfile << "num_iterations\n";
433
+
434
+ for (int i = 0; i < ssdata.num; i++) {
435
+
436
+ int idx = img * ssdata.num + i;
437
+ //int idx_p = num_params*idx;
438
+
439
+ // convert from corner to centre subset coords
440
+ double ss_x = ssdata.coords[2*i ] + static_cast<double>(ssdata.size)/2.0 - 0.5;
441
+ double ss_y = ssdata.coords[2*i+1] + static_cast<double>(ssdata.size)/2.0 - 0.5;
442
+
443
+
444
+ outfile << ss_x << delimiter;
445
+ outfile << ss_y << delimiter;
446
+ outfile << u_arr[idx] << delimiter;
447
+ outfile << v_arr[idx] << delimiter;
448
+ outfile << sqrt(u_arr[idx]*u_arr[idx]+
449
+ v_arr[idx]*v_arr[idx]) << delimiter;
450
+ //for (int p = 0; p < num_params; p++){
451
+ // outfile << p_arr[idx_p+p] << delimiter;
452
+ //}
453
+ outfile << conv_arr[idx] << delimiter;
454
+ outfile << cost_arr[idx] << delimiter;
455
+ outfile << ftol_arr[idx] << delimiter;
456
+ outfile << xtol_arr[idx] << delimiter;
457
+ outfile << niter_arr[idx] << "\n";
458
+ }
459
+ outfile.close();
460
+ }
461
+ }
462
+
463
+ inline bool is_valid_in_dims(const int px_x, const int px_y, const int px_hori,
464
+ const int px_vert) {
465
+
466
+ if (px_x < 0 || px_y < 0 ||
467
+ px_x >= px_hori || px_y >= px_vert) {
468
+ return false;
469
+ }
470
+ return true;
471
+ }
472
+
473
+ inline bool is_valid_in_roi(const int px_x, const int px_y, const int px_hori,
474
+ const int px_vert, const bool *img_roi) {
475
+
476
+ int idx = px_y * px_hori + px_x;
477
+ if (!img_roi[idx]) {
478
+ return false;
479
+ }
480
+ return true;
481
+ }
482
+
483
+ int next_pow2(int n) {
484
+ if (n <= 0){
485
+ std::cerr << __FILE__ << " " << __LINE__ << std::endl;
486
+ std::cerr << "Expected a positive integer to calculate next power of 2 " << std::endl;
487
+ std::cerr << "n = " << n << std::endl;
488
+ exit(EXIT_FAILURE);
489
+ }
490
+
491
+ // If already a power of 2, return as-is
492
+ if ((n & (n - 1)) == 0) return n;
493
+
494
+ n--;
495
+ n |= n >> 1;
496
+ n |= n >> 2;
497
+ n |= n >> 4;
498
+ n |= n >> 8;
499
+ n |= n >> 16;
500
+ n++;
501
+
502
+ // Handle possible overflow
503
+ if (n < 0) return std::numeric_limits<int>::max();
504
+
505
+ return n;
506
+ }
507
+
508
+
509
+ void gen_size_and_step_vector(std::vector<int> &ss_sizes, std::vector<int> &ss_steps,
510
+ const int ss_size, const int ss_step, const int max_disp) {
511
+
512
+ ss_sizes.clear();
513
+ ss_steps.clear();
514
+
515
+ int power = next_pow2(max_disp);
516
+
517
+ // Generate sizes down to just above ss_size
518
+ while (power > ss_size) {
519
+ ss_sizes.push_back(power);
520
+ ss_steps.push_back(power / 2);
521
+ power /= 2;
522
+ }
523
+
524
+ // Finally, add the original ss_size and ss_step
525
+ ss_sizes.push_back(ss_size);
526
+ ss_steps.push_back(ss_step);
527
+
528
+ // debugging
529
+ //for (size_t i = 0; i < ss_sizes.size(); ++i) {
530
+ // std::cout << "ss_size = " << ss_sizes[i] << ", step = " << ss_steps[i] << std::endl;
531
+ //}
532
+ }
533
+
534
+ void create_progress_bar(indicators::ProgressBar &bar,
535
+ const std::vector<std::string> &filenames,
536
+ const int img_num, const int num_ss){
537
+ //Hide cursor
538
+ indicators::show_console_cursor(false);
539
+ bar.set_option(indicators::option::BarWidth{50});
540
+ bar.set_option(indicators::option::Start{" ["});
541
+ bar.set_option(indicators::option::Fill{"#"});
542
+ bar.set_option(indicators::option::Lead{"#"});
543
+ bar.set_option(indicators::option::Remainder{"-"});
544
+ bar.set_option(indicators::option::End{"]"});
545
+ bar.set_option(indicators::option::PrefixText{filenames[img_num]});
546
+ bar.set_option(indicators::option::ShowPercentage{true});
547
+ bar.set_option(indicators::option::ShowElapsedTime{true});
548
+ }
549
+
550
+ void update_progress_bar(indicators::ProgressBar &bar, int i, int num_ss, std::atomic<int> &prev_pct) {
551
+ int curr_pct = static_cast<float>(i) / static_cast<float>(num_ss) * 100;
552
+ int expected = prev_pct.load();
553
+
554
+ // Only update bar if we've passed the previous percentage
555
+ if (curr_pct > expected && prev_pct.compare_exchange_strong(expected, curr_pct)) {
556
+ #pragma omp critical
557
+ bar.set_progress(curr_pct);
558
+ }
559
+ }
560
+
561
+
562
+
563
+ }