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
8 Copyright (C) 2006 Gerber van der Graaf
9 This file is part of gpiv.
11 Gpiv is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software Foundation,
23 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 ----------------------------------------------------------------------*/
27 /* $Log: piveval_interrogate.c,v $
28 /* Revision 1.1 2008-09-16 10:17:36 gerber
29 /* added piveval_interrogate routines
34 /* #include "utils.h" */
36 #include "piveval_interrogate.h"
45 report_progress (const guint index_y
,
47 gdouble
*progress_value_prev
,
48 const GpivPivData
*piv_data
,
49 const GpivPivPar
*piv_par
,
51 const gfloat cum_residu
,
52 const GpivConsole
*gpiv
,
57 alloc_pivdata_gridgen (const GpivImagePar
*image_par
,
58 const GpivPivPar
*piv_par
62 update_pivdata_imgdeform_zoff (const GpivImage
*image
,
64 const GpivPivPar
*piv_par
,
65 const GpivValidPar
*valid_par
,
66 GpivPivData
*piv_data
,
67 GpivPivData
*lo_piv_data
,
69 gboolean
*cum_residu_reached
,
79 * Program-wide public piv interrogation functions
84 exec_piv (GpivConsole
*gpiv
86 /*-----------------------------------------------------------------------------
90 char message
[2 * GPIV_MAX_CHARS
];
94 if (display_act
== NULL
95 || display_act
->img
->exist_img
== FALSE
98 _("At first, open an image. \n"
99 "Than we'll further see what will happen.");
101 warning_gpiv (err_msg
);
106 * Free memory of pivdata and clean the display from its vectors
108 if (display_act
->pida
->exist_piv
109 /* && (m_select != SINGLE_AREA_MS */
110 /* || m_select != DRAG_AREA_MS) */
112 destroy_all_vectors (display_act
->pida
);
113 gpiv_free_pivdata (display_act
->pida
->piv_data
);
114 display_act
->pida
->exist_piv
= FALSE
;
115 display_act
->pida
->averaged_piv
= FALSE
;
116 if (display_act
->pida
->scaled_piv
) {
117 gpiv_free_pivdata (display_act
->pida
->piv_data_scaled
);
118 display_act
->pida
->scaled_piv
= FALSE
;
123 * Free eventually existing memory of vor_data and cleanup the display
124 * as they do not belong to the piv data anymore
126 free_post_bufmems (display_act
);
131 * Set mouse selection to None for using correct AOI
133 /* if (m_select != NO_MS) { */
134 /* gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON */
135 /* (gpiv->piveval->radiobutton_mouse_1), */
140 * Setting interrogation scheme to GPIV_ZERO_OFF_CENTRAL if image deformation
141 * is impossible with too small (initial or final) grid.
143 if (gl_piv_par
->int_scheme
== GPIV_IMG_DEFORM
) {
144 gpiv_piv_count_pivdata_fromimage (display_act
->img
->image
->header
,
145 gl_piv_par
, &nx
, &ny
);
146 if (nx
< 2 || ny
< 2) {
147 g_snprintf (message
, 2 * GPIV_MAX_CHARS
,
148 _("Image deformation is impossibe with grid of nx = %d ny =%d.\n\
149 Setting Interrogation scheme to Central difference.\n \
150 This will be reset automatically."),
152 warning_gpiv ("%s", message
);
153 gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON
154 (gpiv
->piveval
->radiobutton_centraldiff
),
156 int_scheme_autochanged
= TRUE
;
161 * checking parameters and interrogating image by local function
163 display_act
->pida
->piv_par
= gpiv_piv_cp_parameters (gl_piv_par
);
165 gpiv_piv_testadjust_parameters (display_act
->img
->image
->header
,
166 display_act
->pida
->piv_par
))
168 warning_gpiv ("%s", err_msg
);
172 display_act
->pida
->valid_par
= gpiv_valid_cp_parameters (gl_valid_par
);
173 gpiv_valid_print_parameters (stdout
, display_act
->pida
->valid_par
);
175 gpiv_valid_testadjust_parameters (display_act
->pida
->valid_par
))
177 warning_gpiv ("%s", err_msg
);
180 gpiv_valid_print_parameters (stdout
, display_act
->pida
->valid_par
);
182 if ((display_act
->pida
->piv_data
=
183 #define USE_MY_INTERR
185 /* Gpiv's own function for image interrogation */
186 interrogate_img (display_act
->img
->image
,
187 display_act
->pida
->piv_par
,
188 display_act
->pida
->valid_par
,
191 /* Library function */
192 gpiv_piv_interrogate_img (display_act
->img
->image
,
193 display_act
->pida
->piv_par
,
194 display_act
->pida
->valid_par
,
201 warning_gpiv ("exec_piv: failing interrogate_img");
204 display_act
->pida
->exist_piv
= TRUE
;
207 * Adding some comment to piv_data
209 display_act
->pida
->piv_data
->comment
=
210 g_strdup_printf ("# Software: %s %s\n", PACKAGE
, VERSION
);
211 display_act
->pida
->piv_data
->comment
=
212 gpiv_add_datetime_to_comment (display_act
->pida
->piv_data
->comment
);
213 display_act
->pida
->piv_data
->comment
=
214 g_strconcat (display_act
->pida
->piv_data
->comment
,
215 "# Data type: Particle Image Velocities\n", NULL
);
218 * Drawing and displaying PIV vectors
220 if (gl_piv_par
->int_geo
== GPIV_POINT
221 || m_select
== SINGLE_AREA_MS
222 || m_select
== SINGLE_POINT_MS
223 || m_select
== DRAG_MS
) {
225 if (display_act
->display_piv
) {
226 create_all_vectors (display_act
->pida
);
228 display_act
->display_piv
= TRUE
;
232 * Some settings for displaying features
233 * Update vectors to correct for colors/gray-scale
235 display_act
->pida
->scaled_piv
= FALSE
;
236 display_act
->pida
->saved_piv
= FALSE
;
237 display_act
->pida
->averaged_piv
= FALSE
;
238 display_act
->pida
->exist_cov
= TRUE
;
239 update_all_vectors (display_act
->pida
);
240 exec_process
= FALSE
;
243 * Resetting interrogation scheme
245 if (int_scheme_autochanged
) {
246 int_scheme_autochanged
= FALSE
;
247 gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON
248 (gpiv
->piveval
->radiobutton_imgdeform
),
252 gtk_progress_set_value (GTK_PROGRESS (gnome_appbar_get_progress
253 (GNOME_APPBAR (gpiv
->appbar
))),
260 interrogate_img (const GpivImage
*image
,
261 const GpivPivPar
*piv_par
,
262 const GpivValidPar
*valid_par
,
265 /* ----------------------------------------------------------------------------
266 * PIV interrogation of an image pair at an entire grid or single point
267 * Similar to gpiv_piv_interr_img, but adapted for the GUI
270 GpivPivData
*piv_data
= NULL
; /* piv data to be returned */
271 gchar
*err_msg
= NULL
; /* error message */
272 guint index_x
= 0, index_y
= 0; /* array indices */
275 * Local variables with prefix lo_ to distinguish from global or from
278 GpivImage
*lo_image
= NULL
; /* local image that might be deformed */
279 GpivPivData
*lo_piv_data
= NULL
; /* local piv data */
280 GpivPivPar
*lo_piv_par
= NULL
; /* local piv parameters */
282 gfloat
**intreg1
= display_act
->pida
->intreg1
; /* first interrogation area */
283 gfloat
**intreg2
= display_act
->pida
->intreg2
; /* second interrogation area */
284 guint int_size_0
; /* zero-padded interrogation area size */
286 GpivCov
*cov
= NULL
; /* covariance */
287 guint sweep
= 1; /* itaration counter */
288 gboolean grid_last
= FALSE
; /* flag if final grid refinement has been reached */
289 gboolean isi_last
= FALSE
; /* flag if final interrogation area shift has been reached */
290 gboolean cum_residu_reached
= FALSE
;/* flag if max. cumulative residu has been reached */
291 gboolean sweep_last
= FALSE
; /* perform the last iteration sweep */
292 gboolean sweep_stop
= FALSE
; /* stop the current iteration at the end */
293 gfloat sum_dxdy
= 0.0, sum_dxdy_old
= 0.0; /* */
294 gfloat cum_residu
= 914.6; /* initial, large, arbitrary cumulative residu */
295 gdouble progress
= 0.0; /* for monitoring calculation progress */
299 * Testing parameters on consistency and initializing derived
300 * parameters/variables
303 gpiv_piv_testonly_parameters (image
->header
, piv_par
))
305 warning_gpiv ("%s", err_msg
);
310 gpiv_valid_testonly_parameters (valid_par
))
312 warning_gpiv ("%s", err_msg
);
317 * Local (actualized) parameters
318 * Setting initial parameters and variables for adaptive grid and
319 * Interrogation Area dimensions
321 lo_piv_par
= gpiv_piv_cp_parameters (piv_par
);
323 if (lo_piv_par
->int_scheme
== GPIV_ZERO_OFF_FORWARD
324 || lo_piv_par
->int_scheme
== GPIV_ZERO_OFF_CENTRAL
325 || lo_piv_par
->int_scheme
== GPIV_IMG_DEFORM
326 || lo_piv_par
->int_size_i
> lo_piv_par
->int_size_f
) {
327 lo_piv_par
->int_size_f
= lo_piv_par
->int_size_i
;
333 if (lo_piv_par
->int_shift
< lo_piv_par
->int_size_i
/ GPIV_SHIFT_FACTOR
) {
334 lo_piv_par
->int_shift
= lo_piv_par
->int_size_i
/ GPIV_SHIFT_FACTOR
;
338 * A copy of the image and PIV data are needed when image deformation is used.
339 * To keep the algorithm simple, copies are made unconditionally.
341 lo_image
= gpiv_cp_img (image
);
342 piv_data
= alloc_pivdata_gridgen (image
->header
, lo_piv_par
);
343 lo_piv_data
= gpiv_cp_pivdata (piv_data
);
344 gpiv_0_pivdata (lo_piv_data
);
347 * Reads eventually existing fftw wisdom
349 gpiv_fread_fftw_wisdom(1);
350 gpiv_fread_fftw_wisdom(-1);
356 while (sweep
<= GPIV_MAX_PIV_SWEEP
358 && !cancel_process
) {
361 * Memory allocation of interrogation area's and covariance.
362 * These memory chunks are allocated here to optimize calculation
363 * speed and for eventually monitoring their contents.
365 int_size_0
= GPIV_ZEROPAD_FACT
* lo_piv_par
->int_size_i
;
366 intreg1
= gpiv_matrix (int_size_0
, int_size_0
);
367 intreg2
= gpiv_matrix (int_size_0
, int_size_0
);
368 cov
= gpiv_alloc_cov (int_size_0
, image
->header
->x_corr
);
369 display_act
->pida
->cov
= cov
;
372 * Interrogates a single interrogation area
374 if (m_select
!= SINGLE_AREA_MS
375 && m_select
!= DRAG_MS
) {
376 destroy_all_vectors (display_act
->pida
);
377 gnome_canvas_update_now (GNOME_CANVAS (display_act
->canvas
));
380 if (lo_piv_par
->int_geo
== GPIV_POINT
381 || m_select
== SINGLE_AREA_MS
382 || m_select
== SINGLE_POINT_MS
383 || m_select
== DRAG_MS
) {
386 gpiv_piv_interrogate_ia (m_select_index_y
,
398 gpiv_free_img (lo_image
);
399 gpiv_free_pivdata (lo_piv_data
);
400 gpiv_free_pivdata (piv_data
);
401 gpiv_free_matrix (intreg1
);
402 gpiv_free_matrix (intreg2
);
404 error_gpiv ("interrogate_img: %s", err_msg
);
408 * display piv values, draw interrogation areas and
409 * covariance function
411 if (gpiv_var
->piv_disproc
== TRUE
) {
412 display_piv_vector (m_select_index_y
,
416 display_img_intreg1 (intreg1
,
417 lo_piv_par
->int_size_i
,
419 display_img_intreg2 (intreg2
,
420 lo_piv_par
->int_size_i
,
422 display_img_cov (cov
,
423 lo_piv_par
->int_size_i
,
431 * Interrogates at a rectangular grid of points within the Area Of
432 * Interest of the image
434 for (index_y
= 0; index_y
< lo_piv_data
->ny
; index_y
++) {
435 for (index_x
= 0; index_x
< lo_piv_data
->nx
; index_x
++) {
436 if (cancel_process
) break;
439 * Interrogates a single interrogation area.
442 gpiv_piv_interrogate_ia (index_y
,
454 gpiv_free_img (lo_image
);
455 gpiv_free_pivdata (lo_piv_data
);
456 gpiv_free_pivdata (piv_data
);
457 gpiv_free_matrix (intreg1
);
458 gpiv_free_matrix (intreg2
);
460 error_gpiv ("interrogate_img: %s", err_msg
);
464 gpiv_warning("interrogate_img:: back from gpiv_piv_interr_ia: sweep=%d x[%d][%d]=%f y[%d][%d]=%f dx[%d][%d]=%f dy[%d][%d]=%f snr=%f p_no=%d",
466 index_y
, index_x
, lo_piv_data
->point_x
[index_y
][index_x
],
467 index_y
, index_x
, lo_piv_data
->point_y
[index_y
][index_x
],
468 index_y
, index_x
, lo_piv_data
->dx
[index_y
][index_x
],
469 index_y
, index_x
, lo_piv_data
->dy
[index_y
][index_x
],
470 lo_piv_data
->snr
[index_y
][index_x
],
471 lo_piv_data
->peak_no
[index_y
][index_x
]
475 * Printing the progress of processing
477 report_progress (index_y
,
488 * Draw interrogation areas, covariance function,
489 * display piv vector to monitor the process.
490 * Includes report_rogress to include
491 * as an argument in gpiv_piv_interr_img
493 if (gpiv_var
->piv_disproc
== TRUE
) {
494 display_piv_vector (index_y
,
498 display_img_intreg1 (intreg1
,
499 lo_piv_par
->int_size_i
,
501 display_img_intreg2 (intreg2
,
502 lo_piv_par
->int_size_i
,
504 display_img_cov (cov
,
505 lo_piv_par
->int_size_i
,
516 * De-allocating memory: other (smaller) sizes are eventually needed
517 * for a next iteration sweep
519 gpiv_free_matrix (intreg1
);
520 gpiv_free_matrix (intreg2
);
527 if ((lo_piv_par
->int_scheme
== GPIV_IMG_DEFORM
528 || lo_piv_par
->int_scheme
== GPIV_ZERO_OFF_FORWARD
529 || lo_piv_par
->int_scheme
== GPIV_ZERO_OFF_CENTRAL
)
530 /* BUGFIX: crashes with single point */
531 && (lo_piv_par
->int_geo
!= GPIV_POINT
532 && m_select
!= SINGLE_AREA_MS
533 && m_select
!= SINGLE_POINT_MS
534 && m_select
!= DRAG_MS
)
538 update_pivdata_imgdeform_zoff (image
, lo_image
,
539 lo_piv_par
, valid_par
,
540 piv_data
, lo_piv_data
,
543 &sum_dxdy
, &sum_dxdy_old
,
545 sweep_last
, gpiv_par
->verbose
))
547 g_warning ("GPIV_PIV_INTERR_IMG: %s", err_msg
);
548 gpiv_free_img (lo_image
);
549 gpiv_free_pivdata (lo_piv_data
);
550 gpiv_free_pivdata (piv_data
);
557 * Apply results to output piv_data
559 gpiv_free_pivdata (piv_data
);
560 piv_data
= gpiv_cp_pivdata (lo_piv_data
);
561 cum_residu_reached
= TRUE
;
566 * If final grid has been reached, grid_last will be set.
568 if (lo_piv_par
->int_shift
> piv_par
->int_shift
570 GpivPivData
*pd
= NULL
;
572 pd
= gpiv_piv_gridadapt (image
->header
,
578 gpiv_free_pivdata (piv_data
);
579 piv_data
= gpiv_cp_pivdata (pd
);
580 gpiv_free_pivdata (pd
);
582 gpiv_free_pivdata (lo_piv_data
);
583 lo_piv_data
= gpiv_cp_pivdata (piv_data
);
585 if (lo_piv_par
->int_scheme
== GPIV_IMG_DEFORM
) {
586 gpiv_0_pivdata (lo_piv_data
);
594 * Adapt interrogation area size.
595 * If final size has been reached, isi_last will be set.
597 gpiv_piv_isizadapt (piv_par
,
601 if (cum_residu_reached
&& isi_last
&& grid_last
) {
603 /* if (lo_piv_par->int_scheme == GPIV_ZERO_OFF_FORWARD */
604 /* || lo_piv_par->int_scheme == GPIV_ZERO_OFF_CENTRAL) { */
605 /* lo_piv_par->ifit = piv_par->ifit; */
612 * Writes existing fftw wisdom
614 gpiv_fwrite_fftw_wisdom (1);
615 gpiv_fwrite_fftw_wisdom (-1);
616 fftw_forget_wisdom();
622 gpiv_free_img (lo_image
);
623 gpiv_free_pivdata (lo_piv_data
);
632 * Private piv interrogation functions
635 alloc_pivdata_gridgen (const GpivImagePar
*image_par
,
636 const GpivPivPar
*piv_par
638 /*-----------------------------------------------------------------------------
639 * Determining the number of grid points, allocating memory for output data
640 * and calculate locations of Interrogation Area's. If ad_int is enabled, a
641 * course grid is started with and adapted for subsequent sweeps.
642 ----------------------------------------------------------------------------*/
644 GpivPivData
*piv_data
= NULL
;
645 gchar
*err_msg
= NULL
;
646 GpivPivPar
*lo_piv_par
= NULL
;
650 if ((lo_piv_par
= gpiv_piv_cp_parameters (piv_par
)) == NULL
) {
651 gpiv_error ("alloc_pivdata_gridgen: failing gpiv_piv_cp_parameters");
654 if (piv_par
->int_size_i
> piv_par
->int_size_f
655 && piv_par
->int_shift
< piv_par
->int_size_i
/ GPIV_SHIFT_FACTOR
) {
656 lo_piv_par
->int_shift
= lo_piv_par
->int_size_i
/ GPIV_SHIFT_FACTOR
;
660 gpiv_piv_count_pivdata_fromimage (image_par
, lo_piv_par
, &nx
, &ny
))
662 warning_gpiv ("%s", err_msg
);
667 if ((piv_data
= gpiv_piv_gridgen (nx
, ny
, image_par
, lo_piv_par
))
668 == NULL
) error_gpiv ("%s: %s", RCSID
, err_msg
);
677 report_progress (const guint index_y
,
679 gdouble
*progress_value_prev
,
680 const GpivPivData
*piv_data
,
681 const GpivPivPar
*piv_par
,
683 const gfloat cum_residu
,
684 const GpivConsole
*gpiv
,
687 /*-----------------------------------------------------------------------------
688 * Calculates progress of interrogation processing and other variables
689 * and prints to message bar of the console if progress value has been changed
692 gchar progress_string
[GPIV_MAX_CHARS
];
693 gdouble progress_value
= 100 * (index_y
* piv_data
->nx
+ index_x
+1) /
694 (piv_data
->nx
* piv_data
->ny
);
697 if (progress_value
!= *progress_value_prev
) {
698 *progress_value_prev
= progress_value
;
699 if (piv_par
->int_scheme
== GPIV_ZERO_OFF_FORWARD
700 || piv_par
->int_scheme
== GPIV_ZERO_OFF_CENTRAL
701 || piv_par
->int_scheme
== GPIV_IMG_DEFORM
) {
702 if (piv_par
->int_size_i
> piv_par
->int_size_f
/* substitutes ad_int == TRUE */
705 g_snprintf (progress_string
, GPIV_MAX_CHARS
,
706 "Interrogating image #%d:"
721 g_snprintf (progress_string
, GPIV_MAX_CHARS
,
722 "Interrogating image #%d:"
738 g_snprintf (progress_string
, GPIV_MAX_CHARS
,
739 "Interrogating image #%d: "
743 piv_par
/* _dest */ ->int_shift
747 while (g_main_context_iteration (NULL
, FALSE
));
748 gtk_progress_set_value (GTK_PROGRESS (gnome_appbar_get_progress
749 (GNOME_APPBAR (gpiv
->appbar
))),
752 gnome_appbar_set_status (GNOME_APPBAR(gpiv
->appbar
),
760 update_pivdata_imgdeform_zoff (const GpivImage
*image
,
762 const GpivPivPar
*piv_par
,
763 const GpivValidPar
*valid_par
,
764 GpivPivData
*piv_data
,
765 GpivPivData
*lo_piv_data
,
767 gboolean
*cum_residu_reached
,
769 gfloat
*sum_dxdy_old
,
775 /*-----------------------------------------------------------------------------
776 * Validates and updates / renews pivdata and some other variables when image
777 * deformation or zero-offset interrogation scheme is used
781 gchar
*err_msg
= NULL
;
788 gpiv_valid_errvec (lo_piv_data
,
798 if (piv_par
->int_scheme
== GPIV_IMG_DEFORM
) {
801 * Update PIV estimators with those from the last interrogation
802 * Resetting local PIV estimators for eventual next interrogation
804 if ((err_msg
= gpiv_add_dxdy_pivdata (lo_piv_data
, piv_data
))
809 if ((err_msg
= gpiv_0_pivdata (lo_piv_data
))
815 * Deform image with updated PIV estimators.
816 * First, copy local from original image.
817 * Deform with newly updated PIV estimators.
818 * Eventually write deformed image.
821 if ((err_msg
= gpiv_cp_img_data (image
, lo_image
))
826 if ((err_msg
= gpiv_imgproc_deform (lo_image
, piv_data
))
832 if (sweep_last
&& verbose
) {
835 gpiv_piv_write_deformed_image (lo_image
))
846 * Renew PIV estimators with those from the last interrogation
848 if ((err_msg
= gpiv_0_pivdata (piv_data
))
852 if ((err_msg
= gpiv_add_dxdy_pivdata (lo_piv_data
, piv_data
))
859 * Checking the relative cumulative residu for convergence
860 * if final residu has been reached, cum_residu_reached will be set.
862 if (isi_last
&& grid_last
) {
863 *sum_dxdy_old
= *sum_dxdy
;
865 gpiv_sum_dxdy_pivdata (piv_data
, sum_dxdy
);
866 *cum_residu
= fabsf ((*sum_dxdy
- *sum_dxdy_old
) /
867 ((gfloat
)piv_data
->nx
* (gfloat
)piv_data
->ny
));
868 if (*cum_residu
< GPIV_CUM_RESIDU_MIN
) {
869 *cum_residu_reached
= TRUE
;