92int main(
int argc,
char* argv[]) {
94 std::string subject_override =
"";
95 int reftrial_override = -1;
96 std::string config_file =
"config/default.cfg";
97 std::string dic_params_file =
"dic_params.txt";
98 std::string ncorr_params_file =
"ncorr_params.txt";
99 std::string viz_params_file =
"visualization_params.txt";
102 int single_trial = -1;
103 std::string trials_spec;
104 std::string trials_file;
105 std::string subject_trial_csv;
108 std::string cli_log_level;
109 std::string cli_log_file;
110 int verbose_count = 0;
112 bool cli_debug =
false;
115 std::string stages_spec;
119 static struct option long_options[] = {{
"subject", required_argument, 0,
's'},
120 {
"reftrial", required_argument, 0,
'r'},
121 {
"config", required_argument, 0,
'C'},
122 {
"dic-params", required_argument, 0,
'd'},
123 {
"ncorr-params", required_argument, 0,
'n'},
124 {
"viz-params", required_argument, 0,
'v'},
125 {
"trial", required_argument, 0,
OPT_TRIAL},
129 {
"verbose", no_argument, 0,
'V'},
130 {
"quiet", no_argument, 0,
'q'},
135 {
"pair", required_argument, 0,
OPT_PAIR},
136 {
"cam", required_argument, 0,
OPT_CAM},
137 {
"help", no_argument, 0,
'h'},
141 int option_index = 0;
142 while ((opt = getopt_long(argc, argv,
"s:r:C:d:n:v:hVq", long_options, &option_index)) != -1) {
145 subject_override = optarg;
148 config_file = optarg;
151 reftrial_override = std::stoi(optarg);
154 dic_params_file = optarg;
157 ncorr_params_file = optarg;
160 viz_params_file = optarg;
163 stages_spec = optarg;
166 only_pair = std::stoi(optarg);
169 only_cam = std::stoi(optarg);
172 single_trial = std::stoi(optarg);
175 trials_spec = optarg;
178 trials_file = optarg;
181 subject_trial_csv = optarg;
190 cli_log_level = optarg;
193 cli_log_file = optarg;
212 if (!cli_log_level.empty()) {
217 logopts.
debug = cli_debug;
218 logopts.
verbose = verbose_count;
219 logopts.
quiet = quiet;
223 LOG_INFO <<
"FINGERTIP 3D RECONSTRUCTION using DIC";
224 LOG_INFO <<
"--------------------------------------";
225 LOG_INFO <<
"DIC analysis for the fingertip";
232 std::vector<int> selected_trials;
234 int mode_count = (single_trial >= 0 ? 1 : 0) + (!trials_spec.empty() ? 1 : 0) +
235 (!trials_file.empty() ? 1 : 0) + (!subject_trial_csv.empty() ? 1 : 0);
236 if (mode_count > 1) {
237 LOG_ERROR <<
"--trial, --trials, --trials-file and --subject-trial-csv "
238 "are mutually exclusive.";
244 if (single_trial >= 0) {
246 selected_trials = {single_trial};
247 }
else if (!trials_spec.empty() || !trials_file.empty()) {
249 std::vector<int> trials = trials_file.empty()
252 if (trials.empty()) {
257 if (task_id < 1 ||
static_cast<size_t>(task_id) > trials.size()) {
258 LOG_ERROR <<
"SLURM_ARRAY_TASK_ID=" << task_id
259 <<
" out of range 1.." << trials.size();
262 selected_trials = {trials[task_id - 1]};
263 LOG_INFO <<
"[SLURM array] task " << task_id <<
" -> trial "
264 << selected_trials.front();
266 selected_trials = trials;
268 }
else if (!subject_trial_csv.empty()) {
270 std::vector<cppxdic::SubjectTrial> rows =
273 LOG_ERROR <<
"subject_trial CSV has no data rows: " << subject_trial_csv;
277 if (task_id < 1 ||
static_cast<size_t>(task_id) > rows.size()) {
278 LOG_ERROR <<
"SLURM_ARRAY_TASK_ID=" << task_id
279 <<
" out of range 1.." << rows.size();
282 const auto& row = rows[task_id - 1];
283 subject_override = row.subject;
284 selected_trials = {row.trial};
285 LOG_INFO <<
"[SLURM array] task " << task_id <<
" -> subject "
286 << row.subject <<
", trial " << row.trial;
291 const std::string& subj0 = rows.front().subject;
292 for (
const auto& row : rows) {
293 if (row.subject != subj0) {
294 LOG_ERROR <<
"subject_trial CSV spans multiple subjects ("
295 << subj0 <<
", " << row.subject
296 <<
"). Use SLURM_ARRAY_TASK_ID to select a row, "
297 "or split the CSV per subject.";
300 selected_trials.push_back(row.trial);
302 subject_override = subj0;
305 }
catch (
const std::exception& e) {
306 LOG_ERROR <<
"Error resolving trial selection: " << e.what();
320 LOG_INFO <<
"Loading configuration files...";
321 LOG_INFO <<
"------------------------------";
332 if (!subject_override.empty()) {
335 if (reftrial_override >= 0) {
359 if (!cli_log_level.empty()) {
363 if (!cli_log_file.empty()) logopts.
log_file = cli_log_file;
364 if (cli_debug) logopts.
debug =
true;
365 logopts.
verbose = verbose_count;
366 logopts.
quiet = quiet;
377 <<
", Material: " << config.
material <<
", Stereo Pairs: " << config.
num_pair;
382 :
" (protocol window applies when a .mat protocol exists)");
384 std::ostringstream pairs;
385 for (
int p = 1; p <= config.
num_pair; ++p) {
388 pairs << (p > 1 ?
" " :
"") <<
"pair" << p <<
"=(" << c1 <<
"," << c2 <<
")";
390 LOG_INFO <<
"Camera pairs: " << pairs.str();
393 << config.
num_pair <<
"; missing pairs default to (2N-1, 2N)";
398 : std::string(
"auto"))
399 <<
"), Image filtering: " << (config.
im_filter_mode ?
"on" :
"off")
407#if defined(XDIC_MODE_CAMERAPAIRS)
410 LOG_INFO <<
"Checking the data and protocol...";
412 LOG_ERROR <<
"Data and protocol check failed!";
417 if (!stages_spec.empty()) {
420 LOG_ERROR <<
"Invalid --stages '" << stages_spec <<
"': " << perr
421 <<
" (valid tokens: all, d, match, track, format, e, f)";
427 const bool custom_plan = !stages_spec.empty() || only_pair != 0 || only_cam != 0;
430 if (custom_plan && selected_trials.empty()) {
431 LOG_ERROR <<
"--stages/--pair/--cam require an explicit trial selection "
432 "(--trial / --trials / --trials-file / --subject-trial-csv).";
440 if (!selected_trials.empty()) {
441 std::ostringstream trial_list;
442 for (
size_t i = 0; i < selected_trials.size(); ++i) {
443 trial_list << selected_trials[i];
444 if (i + 1 < selected_trials.size()) trial_list <<
", ";
446 LOG_INFO <<
"Running selected trials: [" << trial_list.str() <<
"]";
448 LOG_INFO <<
"Stage selection: stages='" << (stages_spec.empty() ?
"all" : stages_spec)
449 <<
"' pair=" << only_pair <<
" cam=" << only_cam;
451 success = dicAnalysis.
run(selected_trials, plan);
453 success = dicAnalysis.
run();
457 LOG_INFO <<
"Analysis completed successfully!";
462#elif defined(XDIC_MODE_MIRRORED)
468#elif defined(XDIC_MODE_MULTI)
473#error "xdic multi-camera mode is not implemented"
476 }
catch (
const std::exception& e) {
int main(int argc, char *argv[])
void print_usage(const char *prog_name)
Level levelFromString(const std::string &s, Level fallback=Level::Info)
Parse a level name (case-insensitive): trace, debug, info, warn|warning, error, off.