Initial revision
[gpiv.git] / src / pivvalid.c
blob0ed704331867f83a046692a7e2f514690d7750df
1 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 c-style: "K&R" -*- */
3 /*----------------------------------------------------------------------
5 gpiv - Graphic program for Particle Image Velocimetry, based on gtk/gnome
6 libraries.
8 Copyright (C) 2002 Gerber van der Graaf
10 This file is part of gpiv.
12 Gpiv is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software Foundation,
24 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 ----------------------------------------------------------------------*/
29 * (callback) functions for Piv validation window/tabulator
30 * $Log: pivvalid.c,v $
31 * Revision 1.1 2003-06-17 17:10:52 gerber
32 * Initial revision
37 #include "gpiv_gtk.h"
38 #include "utils.h"
39 #include "pivvalid.h"
40 #include "display.h"
42 * Piv validation window/tabulator callbacks
44 void
45 on_button_valid_gradient_enter(GtkWidget * widget, gpointer data)
47 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
48 gchar *msg = _("Examines PIV data on velocity gradients");
49 gnome_appbar_set_status(GNOME_APPBAR(gpiv->appbar), msg);
54 void
55 on_button_valid_gradient(GtkWidget * widget,
56 gpointer data)
58 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
59 gint row, ibuf;
61 if (nbufs > 0) {
62 for (row = gpiv->first_selected_row; row <= gpiv->last_selected_row;
63 row++) {
64 display_act = gtk_clist_get_row_data(GTK_CLIST(gpiv->clist_buf),
65 row);
67 ibuf = display_act->count;
68 if (display[ibuf] != NULL
69 && display_act->mwin != NULL
70 && GTK_WIDGET_VISIBLE(GTK_WIDGET(display_act->mwin)) ) {
71 gdk_window_show(GTK_WIDGET(display_act->mwin)->window);
72 gdk_window_raise(GTK_WIDGET(display_act->mwin)->window);
75 exec_gradient();
81 void
82 on_radiobutton_valid_disable_0_enter(GtkWidget * widget, gpointer data)
84 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
85 gchar *msg = _("No mouse activity within displayer");
86 gnome_appbar_set_status(GNOME_APPBAR(gpiv->appbar), msg);
91 void
92 on_radiobutton_valid_disable_1_enter(GtkWidget * widget, gpointer data)
94 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
95 gchar *msg = _("Enables a single PIV data-point");
96 gnome_appbar_set_status(GNOME_APPBAR(gpiv->appbar), msg);
101 void
102 on_radiobutton_valid_disable_2_enter(GtkWidget * widget, gpointer data)
104 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
105 gchar *msg = _("Disables a single PIV data-point");
106 gnome_appbar_set_status(GNOME_APPBAR(gpiv->appbar), msg);
111 void
112 on_radiobutton_valid_disable_3_enter(GtkWidget * widget, gpointer data)
114 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
115 gchar *msg = _("Enables an area containing PIV data");
116 gnome_appbar_set_status(GNOME_APPBAR(gpiv->appbar), msg);
121 void
122 on_radiobutton_valid_disable_4_enter(GtkWidget * widget, gpointer data)
124 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
125 gchar *msg = _("Disables an area containing PIV data");
126 gnome_appbar_set_status(GNOME_APPBAR(gpiv->appbar), msg);
131 void
132 on_radiobutton_valid_disable(GtkWidget * widget,
133 gpointer data)
135 m_select = atoi(gtk_object_get_data(GTK_OBJECT(widget),
136 "mouse_select"));
139 void on_radiobutton_valid_errvec_residu_enter(GtkWidget * widget, gpointer data)
141 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
142 gchar *msg = _("Defines residu type to examine data on");
143 gnome_appbar_set_status(GNOME_APPBAR(gpiv->appbar), msg);
147 void on_radiobutton_valid_errvec_residu(GtkWidget * widget, gpointer data)
149 piv_valid_par.residu_type = atoi(gtk_object_get_data(GTK_OBJECT(widget),
150 "residu"));
152 /* if (piv_valid_par.residu_type == SNR) { */
153 /* fprintf(stderr, "residu_type SNR\n"); */
154 /* } else if (piv_valid_par.residu_type == MEDIAN) { */
155 /* fprintf(stderr, "residu_type MEDIAN\n"); */
156 /* } else { */
157 /* fprintf(stderr, "NO valid residu_type\n"); */
158 /* } */
164 void
165 on_button_valid_errvec_resstats_enter(GtkWidget * widget, gpointer data)
167 GpivConsole * gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
168 gchar *msg = _("Displays inverse cumulative histogram of residus");
169 gnome_appbar_set_status(GNOME_APPBAR(gpiv->appbar), msg);
173 void
174 on_button_valid_errvec_resstats(GtkWidget * widget, gpointer data)
176 PivValid * valid = gtk_object_get_data(GTK_OBJECT(widget), "valid");
177 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
178 gint row, ibuf;
180 piv_valid_par.res_stats = 1;
182 if (nbufs > 0) {
183 for (row = gpiv->first_selected_row; row <= gpiv->last_selected_row;
184 row++) {
185 display_act = gtk_clist_get_row_data(GTK_CLIST(gpiv->clist_buf),
186 row);
188 ibuf = display_act->count;
189 if (display[ibuf] != NULL
190 && display_act->mwin != NULL
191 && GTK_WIDGET_VISIBLE(GTK_WIDGET(display_act->mwin)) ) {
192 gdk_window_show(GTK_WIDGET(display_act->mwin)->window);
193 gdk_window_raise(GTK_WIDGET(display_act->mwin)->window);
196 exec_errvec(valid);
199 piv_valid_par.res_stats = 0;
205 void
206 on_spinbutton_valid_errvec_yield(GtkSpinButton *widget,
207 GtkWidget *entry)
209 piv_valid_par.data_yield = gtk_spin_button_get_value_as_float(widget);
214 void
215 on_spinbutton_valid_errvec_res(GtkSpinButton *widget,
216 GtkWidget *entry)
218 piv_valid_par.residu_max = gtk_spin_button_get_value_as_float(widget);
219 if (v_color == SHOW_SNR && display_act->gpd.exist_piv) {
220 update_all_vectors(&display_act->gpd);
226 void
227 on_checkbutton_valid_errvec_disres_enter(GtkWidget * widget, gpointer data)
229 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
230 gchar *msg = _("Display PIV vector colors related to residu or SNR value");
231 gnome_appbar_set_status(GNOME_APPBAR(gpiv->appbar), msg);
234 void
235 on_checkbutton_valid_errvec_disres(GtkSpinButton *widget,
236 GtkWidget *entry)
238 if (GTK_TOGGLE_BUTTON(widget)->active) {
239 v_color = SHOW_SNR;
240 } else {
241 v_color = SHOW_PEAKNR;
245 if (display_act->gpd.exist_piv && display_act->display_piv) {
246 update_all_vectors(&display_act->gpd);
251 void on_radiobutton_valid_errvec_subst_enter(GtkWidget * widget, gpointer data)
253 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
254 gchar *msg = _("Defines how to substitute the data");
255 gnome_appbar_set_status(GNOME_APPBAR(gpiv->appbar), msg);
260 void on_radiobutton_valid_errvec_subst(GtkWidget * widget, gpointer data)
262 piv_valid_par.subst_type = atoi(gtk_object_get_data(GTK_OBJECT(widget),
263 "substitute"));
265 /* if (piv_valid_par.subst_type == L_MEAN) { */
266 /* fprintf(stderr, "subst_type L_MEAN\n"); */
267 /* } else if (piv_valid_par.subst_type == SUBTYPE_MEDIAN) { */
268 /* fprintf(stderr, "subst_type SUBTYPE_MEDIAN\n"); */
269 /* } else if (piv_valid_par.subst_type == COV_PEAK) { */
270 /* fprintf(stderr, "subst_type COV_PEAK\n"); */
271 /* } else { */
272 /* fprintf(stderr, "NO valid subst_type\n"); */
273 /* } */
278 void
279 on_button_valid_errvec_enter(GtkWidget * widget, gpointer data)
281 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
282 gchar *msg = _("Examines PIV data on outliers and substitutes");
283 gnome_appbar_set_status(GNOME_APPBAR(gpiv->appbar), msg);
287 void
288 on_button_valid_errvec(GtkWidget * widget, gpointer data)
290 PivValid * valid = gtk_object_get_data(GTK_OBJECT(widget), "valid");
291 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
292 gint row, ibuf;
294 piv_valid_par.res_stats = 0;
296 if (nbufs > 0) {
297 for (row = gpiv->first_selected_row; row <= gpiv->last_selected_row;
298 row++) {
299 display_act = gtk_clist_get_row_data(GTK_CLIST(gpiv->clist_buf),
300 row);
302 ibuf = display_act->count;
303 if (display[ibuf] != NULL
304 && display_act->mwin != NULL
305 && GTK_WIDGET_VISIBLE(GTK_WIDGET(display_act->mwin)) ) {
306 gdk_window_show(GTK_WIDGET(display_act->mwin)->window);
307 gdk_window_raise(GTK_WIDGET(display_act->mwin)->window);
310 exec_errvec(valid);
316 void on_spinbutton_valid_peaklck_bins(GtkSpinButton * widget,
317 GtkWidget * entry)
319 gpiv_par.nbins = gtk_spin_button_get_value_as_int(widget);
324 void on_button_valid_peaklck_enter(GtkWidget * widget, gpointer data)
326 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
327 gchar *msg = _("Calculates a histogram of sub-pixel displacements");
328 gnome_appbar_set_status(GNOME_APPBAR(gpiv->appbar), msg);
333 void on_button_valid_peaklck(GtkWidget * widget, gpointer data)
335 PivValid * valid = gtk_object_get_data(GTK_OBJECT(widget), "valid");
336 GpivConsole *gpiv = gtk_object_get_data(GTK_OBJECT(widget), "gpiv");
337 gint row, ibuf;
339 if (nbufs > 0) {
340 for (row = gpiv->first_selected_row; row <= gpiv->last_selected_row;
341 row++) {
342 display_act = gtk_clist_get_row_data(GTK_CLIST(gpiv->clist_buf),
343 row);
345 ibuf = display_act->count;
346 if (display[ibuf] != NULL
347 && display_act->mwin != NULL
348 && GTK_WIDGET_VISIBLE(GTK_WIDGET(display_act->mwin)) ) {
349 gdk_window_show(GTK_WIDGET(display_act->mwin)->window);
350 gdk_window_raise(GTK_WIDGET(display_act->mwin)->window);
353 exec_peaklock(valid);
361 * Other validation functions than callbacks
364 void exec_gradient(void)
365 /* -----------------------------------------------------------------
366 Testing on gradient of displacements/veocity within Int. Area */
368 if (display_act->gpd.exist_piv && !cancel_process) {
369 exec_process = TRUE;
370 /* g_warning("on_button_valid_gradient:: gpiv_valid_gradient"); */
371 gpiv_valid_gradient(piv_valid_par,
372 piv_eval_par,
373 &display_act->gpd.piv_data);
374 /* g_warning("on_button_valid_gradient:: update_all_vectors"); */
375 update_all_vectors(&display_act->gpd);
376 exec_process = FALSE;
377 } else {
378 gtk_warning(_("no PIV data"));
380 /* g_warning("on_button_valid_gradient:: LEAVE"); */
385 void exec_errvec(PivValid * valid)
387 gint i, j;
390 GnomeCanvasItem *bg, *bar, *fitline;
391 GnomeCanvasPoints *points;
392 double canvas_margin = 20.;
394 double canvas_startx = -50.;
395 double canvas_endx = 150.;
396 double disp_width = canvas_endx - canvas_startx - 2 * canvas_margin;
398 double canvas_starty = -50.;
399 double canvas_endy = 150.;
400 double disp_height = canvas_endy - canvas_starty - 2 * canvas_margin;
402 double canvas_x1 = canvas_startx + canvas_margin;
403 double canvas_y1 = canvas_starty + canvas_margin + disp_height;
405 double x_val, y_val, x_normf, y_normf;
406 PivData out_data;
407 BinData klass;
408 LinRegData linreg;
410 double centre_max = -10.0E+9;
412 out_data.point_x = NULL;
413 out_data.point_y = NULL;
414 out_data.dx = NULL;
415 out_data.dy = NULL;
416 out_data.snr = NULL;
417 out_data.peak_no = NULL;
419 klass.bound = NULL;
420 klass.centre = NULL;
421 klass.count = NULL;
423 linreg.c0 = 0.0;
424 linreg.c1 = 0.0;
425 linreg.cov00 = 0.0;
426 linreg.cov11 = 0.0;
427 linreg.cov01 = 0.0;
428 linreg.sumsq = 0.0;
430 points = gnome_canvas_points_new(2);
433 if (display_act->gpd.exist_piv && !cancel_process) {
434 exec_process = TRUE;
435 out_data.nx = display_act->gpd.piv_data.nx;
436 out_data.ny = display_act->gpd.piv_data.ny;
437 gpiv_alloc_pivdata(&out_data);
438 klass.nbins = out_data.nx * out_data.ny / NBINS_DEFAULT;
439 gpiv_alloc_bindata(&klass);
441 if (piv_valid_par.res_stats == 1) {
442 /* g_warning(" exec_errvec:: will process err_vec res_stats nbins=%d", */
443 /* klass.nbins); */
444 bg = gnome_canvas_item_new(gnome_canvas_root
445 (GNOME_CANVAS(valid->canvas_peaklck)),
446 gnome_canvas_rect_get_type(),
447 "x1", (double) canvas_startx ,
448 "y1", (double) canvas_starty,
449 "x2", (double) canvas_endx ,
450 "y2", (double) canvas_endy,
451 "fill_color", "darkblue",
452 "outline_color", "red",
453 "width_units", 2.0,
454 NULL);
456 gpiv_valid_errvec(fname, image_par, piv_eval_par, piv_valid_par,
457 display_act->gpd.piv_data, &out_data, &klass,
458 &linreg, (int) display_act->img.exist_img,
459 display_act->img.img1, display_act->img.img2);
461 /* --------------------------------------------------------------------
462 normalizing data between 0 and 1 and displaying histo and estimated
463 line curve */
464 for (i = 0; i < klass.nbins; i++) {
465 if (klass.centre[i] > centre_max)
466 centre_max = klass.centre[i];
469 x_normf = (double) disp_width / (klass.max - klass.min);
470 y_normf = (double) centre_max;
472 for (i = 0; i < klass.nbins - 1; i++) {
473 x_val = (double) (klass.bound[i]) / x_normf;
474 y_val = (double) klass.centre[i] / y_normf;
475 bar =
476 gnome_canvas_item_new(gnome_canvas_root
477 (GNOME_CANVAS(valid->canvas_peaklck)),
478 gnome_canvas_rect_get_type(),
479 "x1", canvas_x1 +
480 (double) klass.bound[i] * x_normf,
481 "y1", canvas_y1 -
482 (double) disp_height * y_val,
483 "x2", canvas_x1 +
484 (double) klass.bound[i + 1] * x_normf,
485 "y2", (double) canvas_y1,
486 "fill_color", "darkgreen",
487 "outline_color", "blue",
488 "width_units", 2.0,
489 NULL);
492 piv_valid_par.residu_max =
493 gpiv_valid_threshold(display_act->gpd.piv_eval_par,
494 piv_valid_par, linreg);
495 gtk_spin_button_set_value(GTK_SPIN_BUTTON
496 (valid->spinbutton_errvec_res),
497 piv_valid_par.residu_max);
501 points->coords[0] = (double) canvas_x1;
502 points->coords[1] = (double) canvas_y1
503 - (double) linreg.c0 / y_normf * (double) disp_height
505 points->coords[2] = (double) canvas_x1
506 + (double) disp_width;
507 points->coords[3] = (double) canvas_y1
508 - (double) linreg.c0 / y_normf * (double) disp_height
509 - (double) linreg.c1 * (double) (disp_width) * (double) (disp_height)
510 / ( x_normf * y_normf)
513 /* points->coords[0] = (double) canvas_x1; */
514 /* points->coords[1] = (double) canvas_y1; */
515 /* points->coords[2] = (double) canvas_x1 + (double) disp_width; */
516 /* points->coords[3] = (double) canvas_y1 - (double) disp_height; */
518 fitline =
519 gnome_canvas_item_new(gnome_canvas_root
520 (GNOME_CANVAS(valid->canvas_peaklck)),
521 gnome_canvas_line_get_type(),
522 "points", points,
523 "fill_color", "red",
524 "width_units", (double) 2.0,
525 NULL);
527 } else {
528 /* g_warning(" exec_errvec:: err_vec with subst = %d", piv_valid_par.subst_type); */
529 gpiv_valid_errvec(fname, image_par, piv_eval_par, piv_valid_par,
530 display_act->gpd.piv_data, &out_data, &klass,
531 &linreg, (int) display_act->img.exist_img,
532 display_act->img.img1, display_act->img.img2);
535 for (i = 0; i < out_data.ny; i++) {
536 for (j = 0; j < out_data.nx; j++) {
537 display_act->gpd.piv_data.dx[i][j] = out_data.dx[i][j];
538 display_act->gpd.piv_data.dy[i][j] = out_data.dy[i][j];
539 display_act->gpd.piv_data.snr[i][j] = out_data.snr[i][j];
540 display_act->gpd.piv_data.peak_no[i][j] = out_data.peak_no[i][j];
543 update_all_vectors(&display_act->gpd);
546 gpiv_free_bindata(&klass);
547 gpiv_free_pivdata(&out_data);
549 display_act->gpd.exist_valid = TRUE;
551 /* --------------------------------------------------------------------
552 Copy parameters in Buffer structure for saving and, eventual,
553 later use */
555 display_act->gpd.piv_valid_par.auto_thresh = piv_valid_par.auto_thresh;
556 display_act->gpd.piv_valid_par.residu_max = piv_valid_par.residu_max;
557 display_act->gpd.piv_valid_par.res_stats = piv_valid_par.res_stats;
558 display_act->gpd.piv_valid_par.data_yield = piv_valid_par.data_yield;
559 display_act->gpd.piv_valid_par.residu_type = piv_valid_par.residu_type;
560 display_act->gpd.piv_valid_par.subst_type = piv_valid_par.subst_type;
561 display_act->gpd.piv_valid_par.histo_type = piv_valid_par.histo_type;
563 display_act->gpd.piv_valid_par.auto_thresh_logic = 1;
564 display_act->gpd.piv_valid_par.residu_max_logic = 1;
565 display_act->gpd.piv_valid_par.res_stats_logic = 1;
566 display_act->gpd.piv_valid_par.data_yield_logic = piv_valid_par.data_yield_logic;
567 display_act->gpd.piv_valid_par.residu_type_logic = 1;
568 display_act->gpd.piv_valid_par.subst_type_logic = 1;
569 display_act->gpd.piv_valid_par.histo_type_logic = 1;
570 exec_process = FALSE;
572 } else {
573 gtk_warning(_("no PIV data"));
576 gnome_canvas_points_free(points);
582 void exec_peaklock(PivValid * valid)
585 gint i;
586 GnomeCanvasItem *bg, *bar;
587 double canvas_margin = 20.;
589 double canvas_startx = -50.;
590 double canvas_endx = 150.;
591 double d_width = canvas_endx - canvas_startx - 2 * canvas_margin;
593 double canvas_starty = -50.;
594 double canvas_endy = 150.;
595 double d_height = canvas_endy - canvas_starty - 2 * canvas_margin;
597 double canvas_x1 = canvas_startx + canvas_margin;
598 double canvas_y1 = canvas_starty + canvas_margin + d_height;
600 double y_val;
601 gint count_max = -10000;
602 BinData klass;
604 klass.bound = NULL;
605 klass.centre = NULL;
606 klass.count = NULL;
608 klass.nbins = gpiv_par.nbins;
610 if (display_act->gpd.exist_piv && !cancel_process) {
611 exec_process = TRUE;
612 /* g_warning("will process peaklock\n"); */
613 gpiv_alloc_bindata(&klass);
615 bg =
616 gnome_canvas_item_new(gnome_canvas_root
617 (GNOME_CANVAS(valid->canvas_peaklck)),
618 gnome_canvas_rect_get_type(),
619 "x1", (double) canvas_startx ,
620 "y1", (double) canvas_starty,
621 "x2", (double) canvas_endx ,
622 "y2", (double) canvas_endy,
623 "fill_color", "darkgreen",
624 "outline_color", "red",
625 "width_units", 2.0,
626 NULL);
628 gpiv_valid_peaklck(display_act->gpd.piv_data, &klass);
630 /* --------------------------------------------------------------------
631 normalizing data between 0 and 1 */
632 for (i = 0; i < klass.nbins; i++) {
633 if (klass.count[i] > count_max) count_max = klass.count[i];
636 for (i = 0; i < klass.nbins; i++) {
637 y_val = (double) klass.count[i] / (double) count_max;
638 bar =
639 gnome_canvas_item_new(gnome_canvas_root
640 (GNOME_CANVAS(valid->canvas_peaklck)),
641 gnome_canvas_rect_get_type(),
642 "x1", canvas_x1 +
643 (double) klass.bound[i] * d_width,
644 "y1", canvas_y1 -
645 (double) d_height * y_val,
646 "x2", canvas_x1 +
647 (double) klass.bound[i+1] * d_width,
648 "y2", canvas_y1,
649 "fill_color", "yellow",
650 "outline_color", "blue",
651 "width_units", 2.0,
652 NULL);
655 gpiv_free_bindata(&klass);
656 display_act->gpd.exist_valid = TRUE;
657 exec_process = FALSE;
659 } else {
660 gtk_warning(_("no PIV data"));