ui: Indicate when no local alignment details are available.
[Ale.git] / ui / ui.h
blob1fed61a4dc5547f3bda3de656b69f70d5663e48c
1 // Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
2 // <dhilvert@ugcs.caltech.edu>
4 /* This file is part of the Anti-Lamenessing Engine.
6 The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with the Anti-Lamenessing Engine; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #ifndef __ui_h__
22 #define __ui_h__
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <assert.h>
28 #include "../ale_pos.h"
29 #include "../config.h"
30 #if HAVE_TIME_H
31 #include <time.h>
32 #endif
33 #if HAVE_SYS_TIME_H
34 #include <sys/time.h>
35 #endif
37 #include <map>
40 * Time structures.
43 class ale_timer_t {
44 #if HAVE_GETTIMEOFDAY
45 struct timeval tv;
46 #else
47 time_t tt;
48 #endif
49 double total;
51 public:
53 ale_timer_t() {
54 total = 0;
57 void start() {
58 #if HAVE_GETTIMEOFDAY
59 gettimeofday(&tv, NULL);
60 #else
61 tt = time(NULL);
62 #endif
65 void stop() {
66 #if HAVE_GETTIMEOFDAY
67 timeval t;
69 gettimeofday(&t, NULL);
71 t.tv_sec -= tv.tv_sec;
72 t.tv_usec -= tv.tv_usec;
74 total += t.tv_sec + ((double) 1 / (double) 1000000) * t.tv_usec;
75 #else
76 time_t t = time(NULL);
77 t -= tt;
79 total += t;
80 #endif
83 double get_total() {
84 return total;
89 * User interface messages.
92 class ui_wo;
94 class ui {
95 private:
96 static ui *singleton;
99 * UI type
101 * 0. stream
102 * 1. tty
105 static int type;
107 static int output_performance_data;
109 protected:
112 * Data
115 FILE *ui_stream;
117 struct status_type {
118 enum {
120 * Special
123 UNDEFINED,
126 * Incremental rendering.
129 LOAD_FILE, EXPOSURE_PASS_1,
130 LODCLUSTER_CREATE, PREMATCH, ALIGN, POSTMATCH,
131 EXPOSURE_PASS_2, RENDERA, RENDERD, RENDERO, WRITED,
132 WRITEO, FRAME_DONE, SET_DONE,
135 * Irani-Peleg rendering.
138 IP_RENDER, IP_STEP_DONE, IP_UPDATE, IP_WRITE,
141 * 3D.
144 D3_CONTROL_POINT_SOLVE, D3_SUBDIVIDING_SPACE,
145 D3_UPDATING_OCCUPANCY, D3_RENDER
147 } code, orender_current;
149 int arender_current;
150 double match_value;
151 int onum;
152 int steps;
153 int steps_completed;
154 double exp_multiplier[3];
155 double perturb_size;
156 double align_lod;
157 double mc;
158 unsigned int frame_num;
159 unsigned int irani_peleg_stage;
160 unsigned int secondary_frame_num;
161 unsigned int view_num;
162 unsigned int x_coordinate, y_coordinate;;
163 unsigned int filtering, focusing;
164 unsigned int space_num;
165 unsigned int total_spaces;
166 double cp_max_perturb;
167 double cp_min_perturb;
168 double cp_cur_perturb;
169 double cp_cur_error;
171 status_type() {
172 code = UNDEFINED;
173 steps_completed = 0;
175 for (int k = 0; k < 3; k++)
176 exp_multiplier[k] = 1;
178 } status;
181 * Performance data
184 ale_timer_t d2_align_sample;
185 ale_timer_t d2_align_sim;
186 ale_timer_t d2_incremental;
187 ale_timer_t d2_irani_peleg;
188 std::map<double,ale_timer_t> perturb_timers;
191 * Constructor
194 ui() {
195 ui_stream = stderr;
199 * Print function
202 virtual void printf(char *format, ...) = 0;
205 * UI update function
208 virtual void update() = 0;
211 * Match format strings for textual UIs.
214 char *format_string_ok() {
215 return " okay (%9.6f%% match)";
217 char *format_string_no_match() {
218 return " no match (%9.6f%% match)";
220 char *format_string_working() {
221 return " (%9.6f%% match)";
224 public:
227 * Handle options and other user input.
230 static void handle_input(int argc, const char *argv[], const char *package,
231 const char *short_version, const char *version);
233 static ui *get();
235 static void set_stream() {
236 assert(singleton == NULL);
237 type = 0;
240 static void set_tty() {
241 assert(singleton == NULL);
242 type = 1;
245 static void set_profile() {
246 output_performance_data = 1;
250 * Messages from the engine
253 void d2_align_sim_start() {
254 d2_align_sim.start();
257 void d2_align_sim_stop() {
258 d2_align_sim.stop();
261 void d2_align_sample_start() {
262 d2_align_sample.start();
265 void d2_align_sample_stop() {
266 d2_align_sample.stop();
269 void d2_incremental_start() {
270 d2_incremental.start();
273 void d2_incremental_stop() {
274 d2_incremental.stop();
277 void d2_irani_peleg_start() {
278 d2_irani_peleg.start();
281 void d2_irani_peleg_stop() {
282 d2_irani_peleg.stop();
285 void exp_multiplier(double m0, double m1, double m2) {
286 status.exp_multiplier[0] = m0;
287 status.exp_multiplier[1] = m1;
288 status.exp_multiplier[2] = m2;
291 void exp_multiplier(double mult[3]) {
292 for (int k = 0; k < 3; k++)
293 status.exp_multiplier[k] = mult[k];
296 void set_steps(int count) {
297 status.steps = count;
300 void set_steps_completed(int count) {
301 status.steps_completed = count;
304 void set_match(double match) {
305 status.match_value = (1 - match) * 100;
306 update();
309 void loading_file() {
310 status.code = status.LOAD_FILE;
311 update();
314 void exposure_1() {
315 status.code = status.EXPOSURE_PASS_1;
316 update();
319 void exposure_2() {
320 status.code = status.EXPOSURE_PASS_2;
321 update();
324 void prematching() {
325 status.code = status.PREMATCH;
326 update();
329 void postmatching() {
330 status.code = status.POSTMATCH;
331 update();
334 void constructing_lod_clusters(ale_pos lod) {
335 status.code = status.LODCLUSTER_CREATE;
336 status.align_lod = lod;
337 update();
340 void aligning(ale_pos perturb, ale_pos lod) {
341 perturb_timers[perturb].start();
342 status.perturb_size = perturb;
343 status.align_lod = lod;
344 status.code = status.ALIGN;
345 update();
348 void set_orender_current(int num) {
349 status.onum = num;
350 if (num == 0)
351 status.orender_current = status.RENDERD;
352 else
353 status.orender_current = status.RENDERO;
356 void set_arender_current() {
357 status.arender_current = 1;
360 void clear_arender_current() {
361 status.arender_current = 0;
364 void rendering() {
366 * Current alignment rendering tasks must complete
367 * before any current output rendering tasks can
368 * start.
370 if (status.arender_current) {
371 status.code = status.RENDERA;
372 status.arender_current = 0;
373 } else {
374 status.code = status.orender_current;
376 update();
379 void writing_output(int num) {
380 status.onum = num;
381 if (num == 0)
382 status.code = status.WRITED;
383 else
384 status.code = status.WRITEO;
385 update();
388 void d3_control_point_data(double max_perturbation, double min_perturbation, double cur_perturbation,
389 double current_error) {
390 status.cp_max_perturb = max_perturbation;
391 status.cp_min_perturb = min_perturbation;
392 status.cp_cur_perturb = cur_perturbation;
393 status.cp_cur_error = current_error;
394 update();
397 void d3_control_point_step() {
398 printf(".");
399 update();
402 void d3_subdivision_status(unsigned int primary_frame, unsigned int secondary_frame,
403 unsigned int i, unsigned int j) {
404 status.code = status.D3_SUBDIVIDING_SPACE;
405 status.frame_num = primary_frame;
406 status.secondary_frame_num = secondary_frame;
407 status.y_coordinate = i;
408 status.x_coordinate = j;
410 update();
413 void d3_total_spaces(int total_spaces) {
414 status.total_spaces = total_spaces;
417 void d3_increment_spaces() {
418 status.total_spaces++;
421 void d3_occupancy_status(int frame) {
422 status.code = status.D3_UPDATING_OCCUPANCY;
423 status.frame_num = frame;
424 status.space_num = 0;
425 update();
428 void d3_increment_space_num() {
429 status.space_num++;
430 update();
433 void d3_render_status(int filter, int focus, int frame, int view, int i, int j, int space) {
434 status.code = status.D3_RENDER;
436 status.filtering = filter;
437 status.focusing = focus;
439 status.frame_num = frame;
440 status.view_num = view;
441 status.y_coordinate = i;
442 status.x_coordinate = j;
444 status.space_num = space;
446 update();
451 * Informational output
454 void ip_start() {
455 printf("Iterating Irani-Peleg");
458 void ip_frame_start(unsigned int num) {
459 status.code = status.IP_RENDER;
460 status.frame_num = num;
461 status.irani_peleg_stage = 0;
464 void ip_frame_simulate_start() {
465 status.irani_peleg_stage = 1;
466 update();
469 void ip_frame_correct_start() {
470 status.irani_peleg_stage = 2;
471 update();
474 void ip_update() {
475 status.code = status.IP_UPDATE;
476 update();
479 void ip_write() {
480 status.code = status.IP_WRITE;
481 update();
484 void ip_step_done() {
485 status.code = status.IP_STEP_DONE;
486 printf(".");
489 void ip_done() {
490 printf("\n");
493 void original_frame_start(const char *name) {
494 status.code = status.UNDEFINED;
495 printf("Original Frame:\n");
496 printf(" '%s'", name);
499 void original_frame_done() {
500 status.code = status.FRAME_DONE;
501 update();
504 void supplemental_frame_start(const char *name) {
505 static int section_announced = 0;
507 if (!section_announced) {
508 printf("Supplemental Frames:\n");
509 section_announced = 1;
512 status.code = status.UNDEFINED;
513 status.steps_completed = 0;
514 printf(" '%s'", name);
517 void supplemental_frame_done() {
518 status.code = status.FRAME_DONE;
519 update();
522 void alignment_monte_carlo_parameter(ale_pos mc) {
523 status.mc = (mc > 1) ? 1 : mc;
526 void alignment_perturbation_level(ale_pos perturb, ale_pos lod) {
527 perturb_timers[status.perturb_size].stop();
528 perturb_timers[perturb].start();
529 status.perturb_size = perturb;
530 status.align_lod = lod;
531 status.steps_completed++;
532 printf(".");
535 void alignment_match_ok() {
536 status.code = status.UNDEFINED;
537 printf(format_string_ok(), status.match_value);
540 void alignment_no_match() {
541 status.code = status.UNDEFINED;
542 printf(format_string_no_match(), status.match_value);
545 void ale_2d_done(double value) {
546 status.code = status.UNDEFINED;
547 printf("Average match: %f%%", value);
548 status.code = status.SET_DONE;
549 update();
550 if (output_performance_data) {
551 printf("\n");
552 printf("Real time measurements\n");
553 printf("======================\n");
554 printf("\n");
555 printf("Alignment (sampling) : %f s\n", d2_align_sample.get_total());
556 printf("Alignment (checking) : %f s\n", d2_align_sim.get_total());
557 printf("Incremental rendering : %f s\n", d2_incremental.get_total());
558 printf("Irani-Peleg rendering : %f s\n", d2_irani_peleg.get_total());
559 printf("\n");
561 printf("Details (local alignment)\n");
562 printf("-------------------------\n");
564 int have_details = 0;
565 for (std::map<double,ale_timer_t>::iterator i = perturb_timers.begin();
566 i != perturb_timers.end(); i++) {
567 if (i->second.get_total() == 0.0
568 && i == perturb_timers.begin())
569 continue;
571 printf("Alignment (perturb %f): %f s\n",
572 i->first, i->second.get_total());
574 have_details = 1;
577 if (!have_details) {
578 printf("No local alignment performed.\n");
581 printf("\n");
585 void d3_start() {
586 status.code = status.UNDEFINED;
587 printf("Rendering 3D");
588 update();
591 void d3_control_point_solve() {
592 status.code = status.D3_CONTROL_POINT_SOLVE;
593 update();
596 void d3_init_view_angle(double angle) {
597 status.code = status.UNDEFINED;
598 update();
601 void d3_final_view_angle(double angle) {
602 status.code = status.UNDEFINED;
603 update();
606 void d3_control_point_solve_done() {
607 status.code = status.UNDEFINED;
608 update();
611 void d3_subdividing_space() {
612 status.code = status.D3_SUBDIVIDING_SPACE;
613 update();
616 void d3_subdividing_space_done() {
617 status.code = status.UNDEFINED;
618 update();
621 void d3_updating_occupancy() {
622 status.code = status.D3_UPDATING_OCCUPANCY;
623 update();
626 void d3_updating_occupancy_done() {
627 status.code = status.UNDEFINED;
628 update();
631 void d3_writing_output(const char *name) {
632 static int section_announced = 0;
634 if (!section_announced) {
635 printf(":\n");
636 section_announced = 1;
639 printf(" '%s'", name);
641 update();
644 void d3_writing_output_done() {
645 status.code = status.UNDEFINED;
646 printf(".\n");
647 update();
651 * Warnings
654 void warn(const char *string) {
655 printf("\n\n*** Warning: %s. ***\n\n\n");
659 * Errors
662 void exec_failure(const char *exec, const char *arg1, const char *arg2) {
663 printf("\n\n*** An error occurred while running `%s %s %s`. ***\n\n\n", exec, arg1, arg2);
664 exit(1);
667 void fork_failure(const char *location) {
668 printf("\n\n*** Could not fork in %s. ***\n\n\n", location);
669 exit(1);
672 void memory_error(const char *purpose) {
673 printf("Unable to allocate memory for %s.\n", purpose);
674 exit(1);
677 void memory_error_location(const char *location) {
678 printf("Unable to allocate memory in %s.\n", location);
679 exit(1);
682 void cli_not_enough(const char *option) {
683 printf("\n\n*** Not enough arguments for `%s' ***\n\n", option);
684 exit(1);
687 void cli_bad_arg(const char *option) {
688 printf("\n\n*** Bad argument to `%s' ***\n\n", option);
689 exit(1);
692 void error(const char *string) {
693 printf("\n\n*** Error: %s. ***\n\n\n", string);
694 exit(1);
697 void illegal_option(const char *string) {
698 printf("\n\n*** Error: illegal option %s ***\n\n", string);
699 exit(1);
702 void unknown_device(const char *string) {
703 printf("\n\n*** Error: unknown device %s ***\n\n", string);
704 exit(1);
707 void error_hint(const char *error, const char *hint) {
708 printf("\n\n*** Error: %s", error);
709 printf( "\n*** Hint: %s\n\n\n", hint);
710 exit(1);
713 virtual ~ui() {
717 #include "ui_wo.h"
719 #endif