1 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 c-style: "K&R" -*- */
4 libgpiv - library for Particle Image Velocimetry
6 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
9 This file is part of libgpiv.
11 Libgpiv 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.
27 ------------------------------------------------------------------------------
31 gpiv_piv_count_pivdata_fromimage
32 gpiv_piv_select_int_point
33 gpiv_piv_interrogate_img
34 gpiv_piv_interrogate_ia
36 gpiv_piv_write_deformed_image
37 gpiv_piv_weight_kernel_1
38 gpiv_piv_weight_kernel_lin
39 gpiv_fread_fftw_wisdom
40 gpiv_fwrite_fftw_wisdom
43 LAST MODIFICATION DATE: $Id: piv.c,v 1.5 2008-09-25 13:19:53 gerber Exp $
44 ---------------------------------------------------------------------------- */
53 #define FFTWISDOM "gpiv_fftwis" /* filename containg a string of wisdom for fft */
54 #define FFTWISDOM_INV "gpiv_fftwis_inv" /* filename containg a string of wisdom for inverse fft */
58 /*-------------------------------------------------------------------------
59 Levenbergh-Margardt parameter estimation constants */
60 /* #define MA 4 */ /* Number of parameters to be estimated by
61 marquardt fit of cov peak */
62 /* #define NPT 9 */ /* Numbers of points to be fitted by mrqmin */
63 /* #define SPREAD 0.001 */ /* multiplication factor for individual
64 variances in measuremnts, i.e. covariance
71 #define NMIN_TO_INTERPOLATE 2
80 enum HorizontalPosition
{
87 enum VerticalPosition
{
95 typedef struct __LoVarInterrogateImg LoVarII
;
97 * Local variables of gpiv_interrogate_img to distinguish from global or from
100 struct __LoVarInterrogateImg
102 GpivImage
*image
; /* local image that might be deformed */
103 GpivPivPar
*piv_par
; /* local piv parameters */
104 GpivPivData
*out_piv_data
; /* output piv data */
105 GpivPivData
*piv_data
; /* local piv data */
106 gchar
**err_msg_ar
; /* array of error messages for each thread */
109 typedef struct __OpenMP Ompp
;
111 * OpenMP parallelization data
115 int max_nr_thr
; /* maximum number of threads possible */
116 int nr_thr
; /* current number of threads available to
118 int thr_id
; /* thread identity */
121 typedef struct __MessagePassingInterface Mpi
;
123 * Message Passing Interface data
125 struct __MessagePassingInterface
127 GpivPivData
*piv_data
; /* scattered and gathered piv data to be
128 used for parallel processing using MPI */
129 /* gboolean scatter; */
138 * Local functions prototypes
141 alloc_mpi(GpivPivData
*piv_data
);
147 alloc_pivdata_gridgen (const GpivImagePar
*image_par
,
148 const GpivPivPar
*piv_par
152 report_progress (gint
*progress_old
,
155 GpivPivData
*piv_data
,
162 assign_img2intarr (gint ipoint_x
,
178 assign_img2intarr_central (gint ipoint_x
,
194 assign_img2intarr_forward (gint ipoint_x
,
210 int_mean_old (guint16
**img
,
218 int_mean (gfloat
**int_area
,
223 int_range (gfloat
**int_area
,
228 int_const (gfloat
**int_area
,
233 cov_min_max (GpivCov
*cov
237 search_top (GpivCov
*cov
,
249 cov_subtop (float **z
,
259 cov_top (GpivPivPar piv_par
,
260 GpivPivData
* piv_data
,
270 int pre_shift_row_act
,
271 int pre_shift_col_act
,
274 gboolean
*flag_subtop
278 void pack_cov (float **covariance
,
284 piv_weight_kernel_lin (const guint int_size_0
,
289 weight_cov (GpivCov
*cov
,
294 filter_cov_spof (fftw_complex
*a
,
301 cova (const gboolean spof_filter
,
306 ia_weight_gauss (gint int_size
,
311 * Origined from piv_speed
314 nearest_point (gint i
,
323 nearest_index (enum Position pos
,
331 bilinear_interpol (gdouble alpha_hor
,
340 intpol_facts (gfloat
*src_point
,
352 dxdy_at_new_grid_block (const GpivPivData
*piv_data_src
,
353 GpivPivData
*piv_data_dest
,
354 gint expansion_factor
,
359 update_pivdata_imgdeform_zoff (const GpivImage
*image
,
361 const GpivPivPar
*piv_par
,
362 const GpivValidPar
*valid_par
,
363 GpivPivData
*piv_data
,
364 GpivPivData
*lo_piv_data
,
367 gboolean
*cum_residu_reached
,
369 gfloat
*sum_dxdy_old
,
377 piv_interrogate_img__init (const GpivImage
*image
,
378 const GpivPivPar
*piv_par
,
379 const GpivValidPar
*valid_par
,
382 gboolean
*sweep_last
,
383 const gboolean verbose
387 piv_interrogate_img__finish (LoVarII
*lo
391 piv_interrogate_img__err (LoVarII
*lo
,
400 piv_interrogate_img__scatterv_pivdata (GpivPivData
*piv_data
);
403 piv_interrogate_img__gatherv_pivdata (GpivPivData
*lo_piv_data
,
404 GpivPivData
*piv_data
);
407 substr_noremain (guint n
,
410 #endif /* ENABLE_MPI */
417 gpiv_piv_count_pivdata_fromimage (const GpivImagePar
*image_par
,
418 const GpivPivPar
*piv_par
,
422 /*-----------------------------------------------------------------------------
423 * Calculates the number of interrogation areas from the image sizes,
424 * pre-shift and area of interest
425 * NULL on success or error message on failure
426 *---------------------------------------------------------------------------*/
428 gchar
*err_msg
= NULL
;
429 int row
, column
, row_1
, column_1
,
430 pre_shift_row_max
, pre_shift_col_max
, count_x
= 0, count_y
= 0;
431 int row_max
, row_min
, column_max
, column_min
;
433 int ncolumns
= image_par
->ncolumns
;
434 int nrows
= image_par
->nrows
;
436 int int_geo
= piv_par
->int_geo
;
437 int row_start
= piv_par
->row_start
;
438 int row_end
= piv_par
->row_end
;
439 int col_start
= piv_par
->col_start
;
440 int col_end
= piv_par
->col_end
;
441 int int_line_col
= piv_par
->int_line_col
;
442 int int_line_col_start
= piv_par
->int_line_col_start
;
443 int int_line_col_end
= piv_par
->int_line_col_end
;
444 int int_line_row
= piv_par
->int_line_row
;
445 int int_line_row_start
= piv_par
->int_line_row_start
;
446 int int_line_row_end
= piv_par
->int_line_row_end
;
447 int int_point_col
= piv_par
->int_point_col
;
448 int int_point_row
= piv_par
->int_point_row
;
449 int int_size_f
= piv_par
->int_size_f
;
450 int int_size_i
= piv_par
->int_size_i
;
451 int int_shift
= piv_par
->int_shift
;
452 int pre_shift_row
= piv_par
->pre_shift_row
;
453 int pre_shift_col
= piv_par
->pre_shift_col
;
460 row_min
= gpiv_min(-int_size_f
/ 2 + 1,
461 pre_shift_row
- int_size_i
/ 2 + 1);
462 column_min
= gpiv_max(-int_size_f
/ 2 + 1,
463 pre_shift_col
- int_size_i
/ 2 + 1);
464 row_max
= gpiv_max(int_size_f
/ 2, pre_shift_row
+ int_size_i
/ 2);
465 column_max
= gpiv_max(int_size_f
/ 2, pre_shift_col
+ int_size_i
/ 2);
468 if (int_geo
== GPIV_POINT
) {
474 * Counts number of Interrrogation Area for a single row
476 } else if (int_geo
== GPIV_LINE_R
) {
477 if ((int_size_f
- int_size_i
) / 2 + pre_shift_col
< 0) {
478 column_1
= int_line_col_start
-
479 ((int_size_f
- int_size_i
) / 2 +
480 pre_shift_col
) + int_size_f
/ 2 - 1;
482 column_1
= int_line_col_start
+ int_size_f
/ 2 - 1;
485 for (column
= column_1
; column
<= int_line_col_end
- column_max
;
486 column
+= int_shift
) {
494 * Counts number of Interrrogation Area for a single column
496 } else if (int_geo
== GPIV_LINE_C
) {
497 if ((int_size_f
- int_size_i
) / 2 + pre_shift_row
< 0) {
498 row_1
= int_line_row_start
-
499 ((int_size_f
- int_size_i
) / 2 +
500 pre_shift_row
) + int_size_f
/ 2 - 1;
502 row_1
= int_line_row_start
+ int_size_f
/ 2 - 1;
505 for (row
= row_1
; row
<= int_line_row_end
- row_max
;
515 * Counts number of Interrrogation Area for a Area Of Interest
517 } else if (int_geo
== GPIV_AOI
) {
518 if ((int_size_f
- int_size_i
) / 2 + pre_shift_row
< 0) {
520 row_start
- ((int_size_f
- int_size_i
) / 2 +
521 pre_shift_row
) + int_size_f
/ 2 - 1;
523 row_1
= row_start
+ int_size_f
/ 2 - 1;
525 if ((int_size_f
- int_size_i
) / 2 + pre_shift_col
< 0) {
527 col_start
- ((int_size_f
- int_size_i
) / 2 +
528 pre_shift_col
) + int_size_f
/ 2 - 1;
530 column_1
= col_start
+ int_size_f
/ 2 - 1;
534 pre_shift_col_max
= gpiv_max (pre_shift_col
, 0);
536 gpiv_max(int_size_f
/ 2, pre_shift_col
+ int_size_i
/ 2);
537 pre_shift_row_max
= gpiv_max (pre_shift_row
, 0);
538 row_max
= gpiv_max (int_size_f
/ 2, pre_shift_row
+ int_size_i
/ 2);
541 for (row
= row_1
; row
+ row_max
<= row_end
; row
+= int_shift
) {
542 for (column
= column_1
; column
+ column_max
<= col_end
;
543 column
+= int_shift
) {
554 err_msg
= "gpiv_piv_count_pivdata_fromimage: should not arrive here";
555 gpiv_warning ("%s", err_msg
);
559 if (*nx
== 0 || *ny
== 0) {
560 err_msg
= "gpiv_piv_count_pivdata_fromimage: line or AOI too small: nx=0 ny=0";
561 gpiv_warning("gpiv_piv_count_pivdata_fromimage: line or AOI too small: nx = %d ny = %d\n",
567 g_message ("gpiv_piv_count_pivdata_fromimage:: 2 nx = %d, ny = %d", *nx
, *ny
);
575 gpiv_piv_interrogate_img (const GpivImage
*image
,
576 const GpivPivPar
*piv_par
,
577 const GpivValidPar
*valid_par
,
578 const gboolean verbose
580 /* ----------------------------------------------------------------------------
581 * PIV interrogation of an image pair at an entire grid or single point
583 * @param[in] image image containing data and header info
584 * @param[in] piv_par image evaluation parameters
585 * @param[in] valid_par structure of PIV data validation parameters
586 * @param[out] verbose prints progress of interrogation to stdout
587 * @return GpivPivData containing PIV estimators on succes
590 /*---------------------------------------------------------------------------*/
592 GpivPivData
*piv_data
= NULL
; /* piv data to be returned to caller */
593 gboolean error
= FALSE
; /* error flag */
594 long int index_x
= 0, index_y
= 0; /* array indices */
597 * Local variables with prefix lo_ to distinguish from global or from
600 LoVarII
*lo
= NULL
; /* Contains local variables */
601 GpivFt
**ft
= NULL
; /* arrays of stuctures to perform FFT */
602 guint sweep
= 1; /* itaration counter */
603 gboolean grid_last
= FALSE
; /* flag if final grid refinement has been
605 gboolean isi_last
= FALSE
; /* flag if final interrogation area shift
607 gboolean cum_residu_reached
= FALSE
;/* flag if max. cumulative residu has
609 gboolean sweep_last
= FALSE
; /* perform the last iteration sweep */
610 gboolean sweep_stop
= FALSE
; /* stop the current iteration at the end */
611 gfloat sum_dxdy
= 0.0, sum_dxdy_old
= 0.0; /* */
612 gfloat cum_residu
= 914.6; /* initial, large, arbitrary cumulative
614 guint progress_old
= 0; /* for monitoring calculation progress */
615 gint i
= 0; /* a counter */
618 * Variables for OMP and MPI
620 Ompp
*ompp
= g_new0(Ompp
, 1);
624 Mpi
*mpi
= g_new0(Mpi
,1);
628 * Initializing all variables
630 lo
= piv_interrogate_img__init(image
, piv_par
, valid_par
, ompp
, mpi
,
631 &sweep_last
, verbose
);
632 max_nr_thr
= ompp
->max_nr_thr
;
635 * Interrogates at single a point or at a grid, using advanced schemes
637 while (sweep
<= GPIV_MAX_PIV_SWEEP
&& !sweep_stop
) {
640 * Memory allocation of interrogation area's, covariance and FFT plans.
642 ft
= g_new0 (GpivFt
, ompp
->max_nr_thr
);
643 for (i
= 0; i
< ompp
->max_nr_thr
; i
++) {
644 ft
[i
] = gpiv_alloc_ft (GPIV_ZEROPAD_FACT
* lo
->piv_par
->int_size_i
);
648 * Interrogates a single interrogation area
650 if (lo
->piv_par
->int_geo
== GPIV_POINT
) {
652 if ((lo
->err_msg_ar
[0] =
653 gpiv_piv_interrogate_ia(0, 0, lo
->image
, lo
->piv_par
, sweep
,
654 sweep_last
, lo
->piv_data
, ft
[0]))
656 piv_interrogate_img__err(lo
, ft
, 0);
663 * Interrogates at a rectangular grid of points within the Area Of
664 * Interest of the image
669 * Scatter the PIV data over the rows to the different nodes.
671 lo
->piv_data
= piv_interrogate_img__scatterv_pivdata(lo
->piv_data
);
672 #endif /* ENABLE_MPI */
674 /* grid_last, isi_last, cum_residu_reached, sum_dxdy, sum_dxdy_old */
675 #pragma omp parallel default(none) \
676 private(thr_id, index_x) \
677 shared(nr_thr, max_nr_thr, index_y, error, sweep, sweep_stop, \
678 sweep_last, lo, cum_residu, progress_old, ft)
681 nr_thr
= omp_get_num_threads();
682 thr_id
= omp_get_thread_num();
683 #else /* ENABLE_OMP */
686 #endif /* ENABLE_OMP */
688 #pragma omp for schedule(dynamic, 1)
689 for (index_y
= 0; index_y
< lo
->piv_data
->ny
; index_y
++) {
690 for (index_x
= 0; index_x
< lo
->piv_data
->nx
; index_x
++) {
694 g_message ("gpiv_piv_interrogate_img:: MPI: rank=%d",
697 g_message("gpiv_piv_interrogate_img:: OMP: nr_thr = %d thr_id = %d i=%d j=%d",
698 nr_thr
, thr_id
, index_y
, index_x
);
702 * Interrogates a single interrogation area at the grid.
704 if ((lo
->err_msg_ar
[thr_id
] =
705 gpiv_piv_interrogate_ia(index_y
, index_x
,
706 lo
->image
, lo
->piv_par
,
718 * Printing the progress of processing
722 report_progress(&progress_old
, index_y
, index_x
,
723 lo
->piv_data
, lo
->piv_par
, sweep
,
732 * Gather the scattered PIV data
733 * and broadcasts the entire array to all nodes.
736 piv_interrogate_img__gatherv_pivdata(lo
->piv_data
, lo
->out_piv_data
);
737 gpiv_piv_mpi_bcast_pivdata (lo
->piv_data
);
745 piv_interrogate_img__err(lo
, ft
, nr_thr
);
753 if (lo
->piv_par
->int_scheme
== GPIV_IMG_DEFORM
754 || lo
->piv_par
->int_scheme
== GPIV_ZERO_OFF_FORWARD
755 || lo
->piv_par
->int_scheme
== GPIV_ZERO_OFF_CENTRAL
) {
757 if((lo
->err_msg_ar
[thr_id
] =
758 update_pivdata_imgdeform_zoff(image
, lo
->image
, lo
->piv_par
,
759 valid_par
, lo
->out_piv_data
, lo
->piv_data
,
761 &cum_residu_reached
, &sum_dxdy
,
762 &sum_dxdy_old
, isi_last
,
763 grid_last
, sweep_last
, verbose
))
765 piv_interrogate_img__err(lo
, ft
, nr_thr
);
772 * Apply results to output piv_data
775 gpiv_free_pivdata(lo
->out_piv_data
);
776 lo
->out_piv_data
= gpiv_cp_pivdata(lo
->piv_data
);
777 cum_residu_reached
= TRUE
;
781 * De-allocating memory: other (smaller) sizes are eventually needed
782 * for a next iteration sweep
784 for (i
= 0; i
< max_nr_thr
; i
++) {
791 * If final grid has been reached, grid_last will be set.
793 if (lo
->piv_par
->int_shift
> piv_par
->int_shift
795 GpivPivData
*pd
= NULL
;
797 pd
= gpiv_piv_gridadapt(image
->header
, piv_par
, lo
->piv_par
,
798 lo
->out_piv_data
, sweep
, &grid_last
);
799 gpiv_free_pivdata(lo
->out_piv_data
);
800 lo
->out_piv_data
= gpiv_cp_pivdata(pd
);
801 gpiv_free_pivdata(pd
);
802 gpiv_free_pivdata(lo
->piv_data
);
803 lo
->piv_data
= gpiv_cp_pivdata(lo
->out_piv_data
);
805 if (lo
->piv_par
->int_scheme
== GPIV_IMG_DEFORM
) {
806 gpiv_0_pivdata(lo
->piv_data
);
814 * Adapt interrogation area size.
815 * If final size has been reached, isi_last will be set.
817 gpiv_piv_isizadapt(piv_par
, lo
->piv_par
, &isi_last
);
820 * Test if all conditions have been reached
822 if (cum_residu_reached
&& isi_last
&& grid_last
) {
829 if (verbose
) printf("\n");
832 * clean-up allocated memory, save existing fftw wisdom
833 * and returns resulting PIV data to caller
835 piv_data
= gpiv_cp_pivdata(lo
->out_piv_data
);
836 piv_interrogate_img__finish(lo
);
843 gpiv_piv_interrogate_ia (const guint index_y
,
845 const GpivImage
*image
,
846 const GpivPivPar
*piv_par
,
848 const guint last_sweep
,
849 GpivPivData
*piv_data
,
852 /**----------------------------------------------------------------------------
853 * Interrogates a single Interrogation Area
856 gchar
*err_msg
= NULL
;
858 guint ncolumns
= image
->header
->ncolumns
;
859 guint nrows
= image
->header
->nrows
;
860 gboolean x_corr
= image
->header
->x_corr
;
862 guint ifit
= piv_par
->ifit
;
863 guint int_size_f
= piv_par
->int_size_f
;
864 guint int_size_i
= piv_par
->int_size_i
;
865 gint peak
= piv_par
->peak
;
866 int pre_shift_row
= piv_par
->pre_shift_row
;
867 int pre_shift_col
= piv_par
->pre_shift_col
;
868 enum GpivIntScheme int_scheme
= piv_par
->int_scheme
;
871 int idum
= gpiv_max((int_size_i
- int_size_f
) / 2, 0);
873 float intreg1_mean
= 0.0, intreg2_mean
= 0.0;
874 /* BUGFIX: gpiv_piv_interrogate_ia: disabled normalization I.A */
876 float intreg1_range
= 0.0, intreg2_range
= 0.0;
877 float norm_fact
= 0.0;
878 guint img_top
= (1 << image
->header
->depth
) - 1;
883 int pre_shift_row_act
= 0, pre_shift_col_act
= 0;
884 int peak_act
= 0, i_skip_act
= 0, j_skip_act
= 0;
886 gboolean flag_subtop
= FALSE
, flag_intar0
= FALSE
, flag_accept
= FALSE
;
888 * Interrogation area with zero padding
890 GpivCov
*w_k
= NULL
; /* covariance weighting kernel */
891 int int_size_0
= GPIV_ZEROPAD_FACT
* int_size_i
;
896 * Checking for memory allocation of input variables
898 if ((err_msg
= gpiv_check_alloc_ft(ft
)) != NULL
) {
902 if ((err_msg
= gpiv_check_alloc_pivdata(piv_data
)) != NULL
) {
906 ipoint_x
= (int) piv_data
->point_x
[index_y
][index_x
];
907 ipoint_y
= (int) piv_data
->point_y
[index_y
][index_x
];
910 * uses piv values from previous estimation as pre-shifts and
911 * searches closest Int. Area
913 if (int_scheme
== GPIV_ZERO_OFF_FORWARD
914 || int_scheme
== GPIV_ZERO_OFF_CENTRAL
) {
915 pre_shift_col_act
= piv_data
->dx
[index_y
][index_x
] + pre_shift_col
;
916 pre_shift_row_act
= piv_data
->dy
[index_y
][index_x
] + pre_shift_row
;
917 piv_data
->dx
[index_y
][index_x
] = 0.0;
918 piv_data
->dy
[index_y
][index_x
] = 0.0;
920 pre_shift_col_act
= pre_shift_col
;
921 pre_shift_row_act
= pre_shift_row
;
927 * Assigning image data to the interrogation area's
929 if (int_scheme
== GPIV_ZERO_OFF_CENTRAL
) {
931 assign_img2intarr_central (ipoint_x
, ipoint_y
,
932 image
->frame1
, image
->frame2
,
933 int_size_f
, int_size_i
,
934 ft
->intreg1
, ft
->intreg2
,
935 pre_shift_row_act
, pre_shift_col_act
,
936 nrows
, ncolumns
, int_size_0
);
938 } else if (int_scheme
== GPIV_ZERO_OFF_FORWARD
) {
940 assign_img2intarr_central (ipoint_x
, ipoint_y
,
941 image
->frame1
, image
->frame2
,
942 int_size_f
, int_size_i
,
943 ft
->intreg1
, ft
->intreg2
,
944 pre_shift_row_act
, pre_shift_col_act
,
945 nrows
, ncolumns
, int_size_0
);
948 assign_img2intarr (ipoint_x
, ipoint_y
,
949 image
->frame1
, image
->frame2
,
950 int_size_f
, int_size_i
,
951 ft
->intreg1
, ft
->intreg2
,
952 pre_shift_row_act
, pre_shift_col_act
,
953 nrows
, ncolumns
, int_size_0
);
959 * Weighting Interrogation Area with Gaussian function
961 if (piv_par
->gauss_weight_ia
) {
962 if ((err_msg
= ia_weight_gauss (int_size_f
, ft
->intreg1
))
967 if ((err_msg
= ia_weight_gauss (int_size_i
, ft
->intreg2
))
974 * The mean value of the image data within an interrogation area will be
975 * subtracted from the data
976 * BUXFIX: test on differences in estimator!
978 intreg1_mean
= int_mean (ft
->intreg1
, int_size_f
);
979 intreg2_mean
= int_mean (ft
->intreg2
, int_size_i
);
981 intreg1_range
= int_range (ft
->intreg1
, int_size_f
);
982 intreg2_range
= int_range (ft
->intreg2
, int_size_i
);
986 * BUGFIX: this might be substituted by counting the number of particles within
987 * Int. Area, as done in PTV
989 if (intreg1_mean
== 0.0 || intreg2_mean
== 0.0
990 || int_const (ft
->intreg1
, int_size_f
)
991 || int_const (ft
->intreg2
, int_size_i
)
993 /* err_msg = "gpiv_piv_interrogate_ia: intreg1/2_mean = 0.0"; */
995 /* return err_msg; */
1000 norm_fact
= (gfloat
) img_top
/ intreg1_range
;
1002 for (m
= 0; m
< int_size_f
; m
++) {
1003 for (n
= 0; n
< int_size_f
; n
++) {
1004 ft
->intreg1
[m
+ idum
][n
+ idum
] -= intreg1_mean
;
1006 ft
->intreg1
[m
+ idum
][n
+ idum
] *= norm_fact
;
1012 norm_fact
= (gfloat
) img_top
/ intreg2_range
;
1014 for (m
= 0; m
< int_size_i
; m
++) {
1015 for (n
= 0; n
< int_size_i
; n
++) {
1016 ft
->intreg2
[m
][n
] -= intreg2_mean
;
1018 ft
->intreg2
[m
][n
] *= norm_fact
;
1024 * Calculate covariance function
1027 if ((err_msg
= cova (piv_par
->spof_filter
, ft
))
1029 gpiv_warning("%s", err_msg
);
1034 * Weighting covariance data with weight kernel
1036 if (piv_par
->int_scheme
== GPIV_LK_WEIGHT
) {
1037 w_k
= gpiv_alloc_cov (int_size_0
, image
->header
->x_corr
);
1038 piv_weight_kernel_lin (int_size_0
, w_k
);
1039 weight_cov (ft
->cov
, w_k
);
1040 gpiv_free_cov (w_k
);
1044 * Searching maximum peak in covariance function
1047 cov_top (*piv_par
, piv_data
, index_y
, index_x
, ft
->cov
, x_corr
,
1048 ifit
, sweep
, last_sweep
, peak
, peak_act
,
1049 pre_shift_row_act
, pre_shift_col_act
,
1050 i_skip_act
, j_skip_act
, &flag_subtop
)) != 0) {
1051 err_msg
= "gpiv_piv_interrogate_ia: Unable to call cov_top";
1052 gpiv_warning("%s", err_msg
);
1057 * Writing values to piv_data
1059 piv_data
->dx
[index_y
][index_x
] =
1060 (double) pre_shift_col_act
+
1061 (double) ft
->cov
->top_x
+ ft
->cov
->subtop_x
;
1063 piv_data
->dy
[index_y
][index_x
] =
1064 (double) pre_shift_row_act
+
1065 (double) ft
->cov
->top_y
+ ft
->cov
->subtop_y
;
1068 * Disabled as outliers are tested after each iteration
1070 /* if (last_sweep == 1) { */
1071 piv_data
->snr
[index_y
][index_x
] = ft
->cov
->snr
;
1072 piv_data
->peak_no
[index_y
][index_x
] = peak_act
;
1077 * Check on validity of data
1079 if (isnan(piv_data
->dx
[index_y
][index_x
]) != 0
1080 || isnan(piv_data
->dy
[index_y
][index_x
]) != 0
1081 || isnan(piv_data
->snr
[index_y
][index_x
]) != 0
1085 piv_data
->dx
[index_y
][index_x
] = 0.0;
1086 piv_data
->dy
[index_y
][index_x
] = 0.0;
1087 piv_data
->snr
[index_y
][index_x
] = GPIV_SNR_NAN
;
1088 piv_data
->peak_no
[index_y
][index_x
] = -1;
1092 * Uses old piv data and sets flag peak_no to -1 if:
1093 * for zero offsetting: 2nd Interrogation Area is out of image boundaries
1094 * for zero offsetting with central diff: one of the Interrogation Area's
1095 * is out of image boundaries
1098 piv_data
->dx
[index_y
][index_x
] = piv_data
->dx
[index_y
][index_x
];
1099 piv_data
->dy
[index_y
][index_x
] = piv_data
->dy
[index_y
][index_x
];
1100 piv_data
->snr
[index_y
][index_x
] = piv_data
->snr
[index_y
][index_x
];
1101 piv_data
->peak_no
[index_y
][index_x
] = -1;
1112 gpiv_piv_isizadapt (const GpivPivPar
*piv_par_src
,
1113 GpivPivPar
*piv_par_dest
,
1116 /*---------------------------------------------------------------------------*/
1118 * Adjusts interrogation area sizes. For each interrogation sweep,
1119 * (dest) int_size_i is halved, until it reaches (src)
1120 * int_size_f. Then, isiz_last is set TRUE, which will avoid
1121 * changing the interrogation sizes in next calls.
1123 * @param[in] piv_par_src original parameters
1124 * @param[out] piv_par_dest actual parameters, to be modified during sweeps
1125 * @param[out] isiz_last flag for last interrogation sweep
1128 /*---------------------------------------------------------------------------*/
1132 /* if (piv_par_dest->int_size_i == piv_par_src->int_size_i) */
1133 /* piv_par_dest->ad_int = 0; */
1135 /* if (piv_par_dest->ad_int == 1) { */
1136 if ((piv_par_dest
->int_size_i
) / 2 <= piv_par_src
->int_size_f
) {
1138 piv_par_dest
->int_size_f
=
1139 (piv_par_src
->int_size_f
- GPIV_DIFF_ISI
);
1140 piv_par_dest
->int_size_i
=
1141 piv_par_src
->int_size_f
;
1143 piv_par_dest
->int_size_f
= piv_par_dest
->int_size_i
/ 2;
1144 piv_par_dest
->int_size_i
= piv_par_dest
->int_size_i
/ 2;
1147 /* } else if (piv_par_src->int_scheme == GPIV_ZERO_OFF_FORWARD */
1148 /* || piv_par_src->int_scheme == GPIV_ZERO_OFF_CENTRAL */
1149 /* || piv_par_src->int_scheme == GPIV_IMG_DEFORM */
1151 /* *isiz_last = TRUE; */
1152 /* piv_par_dest->ifit = piv_par_src->ifit; */
1153 /* piv_par_dest->int_size_f = (piv_par_src->int_size_f - */
1154 /* GPIV_DIFF_ISI); */
1155 /* piv_par_dest->int_size_i = piv_par_src->int_size_f; */
1162 /* #define SAVE_TMP */
1165 gpiv_piv_write_deformed_image (GpivImage
*image
1167 /*-----------------------------------------------------------------------------
1169 * Stores deformed image to file system with pre defined name to TMPDIR
1170 * and prints message to stdout
1173 * img1: first image of PIV image pair
1174 * img2: second image of PIV image pair
1175 * image_par: image parameters to be stored in header
1176 * verbose: prints the storing to stdout
1181 * char * to NULL on success or *err_msg on failure
1182 *---------------------------------------------------------------------------*/
1184 gchar
*err_msg
= NULL
;
1189 def_img
= g_strdup_printf ("%s%s", GPIV_DEFORMED_IMG_NAME
,
1190 GPIV_EXT_PNG_IMAGE
);
1193 if ((fp
= my_utils_fopen_tmp (def_img
, "wb")) == NULL
) {
1194 err_msg
= "gpiv_piv_write_deformed_image: Failure opening for output";
1198 g_message ("gpiv_piv_write_deformed_image: Writing deformed image to: %s",
1199 g_strdup_printf ("%s/%s/%s", tmp_dir
, user_name
, def_img
));
1201 fp
= fopen (def_img
, "wb");
1202 g_message ("gpiv_piv_write_deformed_image: Writing deformed image to: %s",
1206 gpiv_write_png_image (fp
, image
, FALSE
)) != NULL
) {
1223 piv_interrogate_img__init (const GpivImage
*image
,
1224 const GpivPivPar
*piv_par
,
1225 const GpivValidPar
*valid_par
,
1228 gboolean
*sweep_last
,
1229 const gboolean verbose
1231 /* ----------------------------------------------------------------------------
1232 * Initializes variables for gpiv_interrogate_img
1235 gchar
*err_msg
= NULL
;
1238 LoVarII
*lo
= g_new0(LoVarII
, 1); /* struct containing local variables */
1242 #ifdef ENABLE_OMP /* allocate "thread array" for later use as xy[thr_id] */
1243 ompp
->max_nr_thr
= omp_get_max_threads();
1245 ompp
->max_nr_thr
= 1;
1246 #endif /* ENABLE_OMP */
1249 * allocate err_msg_ar[] for each thread
1251 lo
->err_msg_ar
= g_new0(gchar
, ompp
->max_nr_thr
);
1254 * Testing parameters on consistency and initializing derived
1255 * parameters/variables
1258 gpiv_piv_testonly_parameters (image
->header
, piv_par
)) != NULL
) {
1259 gpiv_warning ("gpiv_piv_interrogate_img: %s", err_msg
);
1264 gpiv_valid_testonly_parameters (valid_par
)) != NULL
) {
1265 gpiv_warning ("gpiv_piv_interrogate_img: %s", err_msg
);
1270 * Local (actualized) parameters
1271 * Setting initial parameters and variables for adaptive grid and
1272 * Interrogation Area dimensions
1274 lo
->piv_par
= gpiv_piv_cp_parameters (piv_par
);
1276 if (lo
->piv_par
->int_scheme
== GPIV_ZERO_OFF_FORWARD
1277 || lo
->piv_par
->int_scheme
== GPIV_ZERO_OFF_CENTRAL
1278 || lo
->piv_par
->int_scheme
== GPIV_IMG_DEFORM
1279 || lo
->piv_par
->int_size_i
> lo
->piv_par
->int_size_f
) {
1280 lo
->piv_par
->int_size_f
= lo
->piv_par
->int_size_i
;
1281 *sweep_last
= FALSE
;
1286 if (lo
->piv_par
->int_shift
< lo
->piv_par
->int_size_i
/ GPIV_SHIFT_FACTOR
) {
1287 lo
->piv_par
->int_shift
= lo
->piv_par
->int_size_i
/ GPIV_SHIFT_FACTOR
;
1291 * A copy of the image and PIV data are needed when image deformation is used.
1292 * To keep the algorithm simple (well, what's in the name :), copies are made
1295 lo
->image
= gpiv_cp_img(image
);
1296 lo
->out_piv_data
= alloc_pivdata_gridgen(image
->header
, lo
->piv_par
);
1299 MPI_Comm_size(MPI_COMM_WORLD
, mpi
->nprocs
);
1300 MPI_Comm_rank(MPI_COMM_WORLD
, mpi
->rank
);
1301 #endif /* ENABLE_MPI */
1303 lo
->piv_data
= gpiv_cp_pivdata(lo
->out_piv_data
);
1306 gpiv_write_pivdata(NULL
, lo
->piv_data
, FALSE
);
1310 gpiv_0_pivdata(lo
->piv_data
);
1313 * Reads eventually existing fftw wisdom
1315 gpiv_fread_fftw_wisdom(1);
1316 gpiv_fread_fftw_wisdom(-1);
1325 piv_interrogate_img__finish (LoVarII
*lo
1327 /* ----------------------------------------------------------------------------
1328 * Saves existing fftw wisdom
1329 * free allocated memory by gpiv_interrogate_img
1332 gchar
*err_msg
= NULL
;
1336 gpiv_fwrite_fftw_wisdom(1);
1337 gpiv_fwrite_fftw_wisdom(-1);
1338 gpiv_free_img(lo
->image
);
1339 gpiv_free_pivdata(lo
->piv_data
);
1340 gpiv_free_pivdata(lo
->out_piv_data
);
1341 g_free(*lo
->err_msg_ar
);
1349 piv_interrogate_img__err (LoVarII
*lo
,
1352 /**----------------------------------------------------------------------------
1353 * Prints error message (of specific thread in case of OpenMP)
1360 for (i
= 0; i
< nr_thr
; i
++) {
1361 gpiv_free_ft(ft
[i
]);
1362 if (lo
->err_msg_ar
[i
] != NULL
) {
1363 gpiv_warning("interrogate_img: thr_id = %d: %s",
1364 i
, lo
->err_msg_ar
[i
]);
1368 gpiv_free_pivdata(lo
->out_piv_data
);
1369 piv_interrogate_img__finish(lo
);
1378 piv_weight_kernel_lin (const guint int_size_0
,
1381 /*-----------------------------------------------------------------------------
1383 * Calculate linear weight kernel values for covariance data
1388 * w_k: Structure containing weighting data
1389 * int_size_0: zero-padded interrogation size
1393 *---------------------------------------------------------------------------*/
1396 int z_rnl
= w_k
->z_rnl
, z_rnh
= w_k
->z_rnh
, z_rpl
= w_k
->z_rpl
,
1398 int z_cnl
= w_k
->z_cnl
, z_cnh
= w_k
->z_cnh
, z_cpl
= w_k
->z_cpl
,
1402 g_return_if_fail (w_k
!= NULL
);
1404 for (i
= z_rnl
; i
< z_rnh
; i
++) {
1405 for (j
= z_cnl
; j
< z_cnh
; j
++) {
1406 w_k
->z
[i
- int_size_0
][j
- int_size_0
] =
1407 (1 - abs(z_rnh
- i
) / (int_size_0
/ 2.0))
1408 * (1 - abs(z_cnh
- j
) / (int_size_0
/ 2.0));
1411 for (j
= z_cpl
; j
< z_cph
; j
++) {
1412 w_k
->z
[i
- int_size_0
][j
] =
1413 (1 - abs(z_rnh
- i
) / (int_size_0
/ 2.0))
1414 * (1 - abs(z_cpl
- j
) / (int_size_0
/ 2.0));
1419 for (i
= z_rpl
; i
< z_rph
; i
++) {
1420 for (j
= z_cnl
; j
< z_cnh
; j
++) {
1421 w_k
->z
[i
][j
- int_size_0
] =
1422 (1 - abs(z_rpl
- i
) / (int_size_0
/ 2.0))
1423 * (1 - abs(z_cnh
- j
) / (int_size_0
/ 2.0));
1426 for (j
= z_cpl
; j
< z_cph
; j
++) {
1427 w_k
->z
[i
][j
] = (1 - abs(z_rpl
- i
) / (int_size_0
/ 2.0))
1428 * (1 - abs(z_cpl
- j
) / (int_size_0
/ 2.0));
1436 write_cov (int int_x
,
1442 /*-----------------------------------------------------------------------------
1444 * Prints covariance data
1452 * SOME MNENOSYNTACTICS OF LOCAL VARIABLES:
1453 * cov_area: name of array
1456 * n: negative displacements ; from 3/4 to 1 of int_size_0
1457 * p: positive displacements; from 0 to 1/4 of int_size_0
1460 *---------------------------------------------------------------------------*/
1463 int cov_area_rnl
, cov_area_rnh
, cov_area_rpl
, cov_area_rph
,
1464 cov_area_cnl
, cov_area_cnh
, cov_area_cpl
, cov_area_cph
;
1465 float weight_kernel
;
1466 int int_size_0
= GPIV_ZEROPAD_FACT
* int_size
;
1469 cov_area_rnl
= 3.0 * (int_size_0
) / 4 + 1;
1470 cov_area_rnh
= int_size_0
;
1472 cov_area_rph
= int_size_0
/ 4;
1474 cov_area_cnl
= 3.0 * (int_size_0
) / 4 + 1;
1475 cov_area_cnh
= int_size_0
;
1477 cov_area_cph
= int_size_0
/ 4;
1480 for (i
= cov_area_rnl
; i
< cov_area_rnh
; i
++) {
1481 for (j
= cov_area_cnl
; j
< cov_area_cnh
; j
++) {
1484 (1 - abs(cov_area_rnh
- i
) / (int_size_0
/ 2.0)) *
1485 (1 - abs(cov_area_cnh
- j
) / (int_size_0
/ 2.0));
1488 for (j
= cov_area_cpl
; j
< cov_area_cph
; j
++) {
1491 (1 - abs(cov_area_rnh
- i
) / (int_size_0
/ 2.0)) *
1492 (1 - abs(cov_area_cpl
- j
) / (int_size_0
/ 2.0));
1498 for (i
= cov_area_rpl
; i
< cov_area_rph
; i
++) {
1499 for (j
= cov_area_cnl
; j
< cov_area_cnh
; j
++) {
1502 (1 - abs(cov_area_rpl
- i
) / (int_size_0
/ 2.0)) *
1503 (1 - abs(cov_area_cnh
- j
) / (int_size_0
/ 2.0));
1506 for (j
= cov_area_cpl
; j
< cov_area_cph
; j
++) {
1509 (1 - abs(cov_area_rpl
- i
) / (int_size_0
/ 2.0)) *
1510 (1 - abs(cov_area_cpl
- j
) / (int_size_0
/ 2.0));
1519 gpiv_fread_fftw_wisdom (const gint dir
1521 /*-----------------------------------------------------------------------------
1523 * Reads fftw wisdoms from file and stores into a string
1526 * dir: direction of fft; forward (+1) or inverse (-1)
1532 *---------------------------------------------------------------------------*/
1534 gchar
*fftw_filename
;
1538 g_return_if_fail (dir
== 1 || dir
== -1);
1541 * Forward FFT or inverse FFT
1544 fftw_filename
= g_strdup_printf ("%s", FFTWISDOM
);
1546 fftw_filename
= g_strdup_printf ("%s", FFTWISDOM_INV
);
1549 if ((fp
= my_utils_fopen_tmp (fftw_filename
, "r")) != NULL
) {
1550 fftw_import_wisdom_from_file(fp
);
1554 g_free (fftw_filename
);
1560 gpiv_fwrite_fftw_wisdom (const gint dir
1562 /*-----------------------------------------------------------------------------
1564 * Writes fftw wisdoms to a file
1567 * dir: direction of fft; forward (+1) or inverse (-1)
1573 *---------------------------------------------------------------------------*/
1575 gchar
*fftw_filename
;
1578 g_return_if_fail (dir
== 1 || dir
== -1);
1581 * Forward FFT or inverse FFT
1584 fftw_filename
= g_strdup_printf ("%s", FFTWISDOM
);
1586 fftw_filename
= g_strdup_printf ("%s", FFTWISDOM_INV
);
1589 if ((fp
= my_utils_fopen_tmp (fftw_filename
, "w")) != NULL
) {
1590 fftw_export_wisdom_to_file(fp
);
1594 fftw_forget_wisdom();
1595 g_free (fftw_filename
);
1600 * Public functions, original from piv_speed
1604 gpiv_piv_dxdy_at_new_grid (const GpivPivData
*piv_data_src
,
1605 GpivPivData
*piv_data_dest
1607 /*---------------------------------------------------------------------------*/
1609 * calculates dx, dy of piv_data_dest from piv_data_src
1610 * by bi-linear interpolation of inner points with shifted knots
1611 * or extrapolation of outer lying points
1618 * _nn: at NORTH of NORTH, etc.
1620 * @param[in] piv_data_src input piv data
1621 * @param[out] piv_data_dest output piv data
1622 * @return NULL on success or *err_msg on failure
1624 /*---------------------------------------------------------------------------*/
1626 char c_line
[GPIV_MAX_LINES_C
][GPIV_MAX_CHARS
];
1627 char *err_msg
= NULL
;
1629 gint
*index_n
, *index_s
, *index_e
, *index_w
;
1630 gint
*index_nn
, *index_ss
, *index_ee
, *index_ww
;
1632 float *src_point_x
= NULL
, *dest_point_x
= NULL
;
1633 float *src_point_y
= NULL
, *dest_point_y
= NULL
;
1634 double *alpha_hor
, *alpha_vert
;
1637 enum VerticalPosition vert_pos
;
1638 enum HorizontalPosition hor_pos
;
1641 GpivPivData
*gpd
= NULL
;
1645 * shift the knots of the grid for higher accuracies.
1646 * in order not to affect piv_data_src, a new PIV dataset will be copied
1649 g_message ("gpiv_piv_dxdy_at_new_grid:: 0, src_nx = %d src_ny = %d dest_nx = %d dest_ny = %d",
1650 piv_data_src
->nx
, piv_data_src
->ny
,
1651 piv_data_dest
->nx
, piv_data_dest
->ny
);
1653 gpd
= gpiv_cp_pivdata (piv_data_src
);
1656 if ((err_msg
= gpiv_piv_shift_grid (gpd
)) != NULL
) {
1657 err_msg
= "gpiv_piv_dxdy_at_new_grid: failing gpiv_piv_shift_grid";
1658 g_warning ("%s", err_msg
);
1663 index_n
= gpiv_ivector (piv_data_dest
->ny
);
1664 index_s
= gpiv_ivector (piv_data_dest
->ny
);
1665 index_e
= gpiv_ivector (piv_data_dest
->nx
);
1666 index_w
= gpiv_ivector (piv_data_dest
->nx
);
1667 index_nn
= gpiv_ivector (piv_data_dest
->ny
);
1668 index_ss
= gpiv_ivector (piv_data_dest
->ny
);
1669 index_ee
= gpiv_ivector (piv_data_dest
->nx
);
1670 index_ww
= gpiv_ivector (piv_data_dest
->nx
);
1672 alpha_vert
= gpiv_dvector (piv_data_dest
->ny
);
1673 alpha_hor
= gpiv_dvector (piv_data_dest
->nx
);
1675 src_point_x
= gpiv_vector (gpd
->nx
);
1676 src_point_y
= gpiv_vector (gpd
->ny
);
1677 dest_point_x
= gpiv_vector (piv_data_dest
->nx
);
1678 dest_point_y
= gpiv_vector (piv_data_dest
->ny
);
1681 * Calculate interpolation factors
1682 * in Horizontal direction
1685 g_message ("gpiv_piv_dxdy_at_new_grid:: 1a, gpd_nx = %d gpd_ny = %d _ny",
1688 if (gpd
->nx
>= NMIN_TO_INTERPOLATE
) {
1689 for (i
= 0, j
= 0; j
< gpd
->nx
; j
++) {
1690 src_point_x
[j
] = gpd
->point_x
[i
][j
];
1693 for (i
= 0, j
= 0; j
< piv_data_dest
->nx
; j
++) {
1694 dest_point_x
[j
] = piv_data_dest
->point_x
[i
][j
];
1697 intpol_facts (src_point_x
,
1707 err_msg
= "gpiv_piv_dxdy_at_new_grid: Not enough points in horizontal direction";
1712 * Calculate interpolation factors
1713 * in Vertical direction
1715 if (gpd
->ny
>= NMIN_TO_INTERPOLATE
) {
1716 for (i
= 0, j
= 0; i
< gpd
->ny
; i
++) {
1717 src_point_y
[i
] = gpd
->point_y
[i
][j
];
1720 for (i
= 0, j
= 0; i
< piv_data_dest
->ny
; i
++) {
1721 dest_point_y
[i
] = piv_data_dest
->point_y
[i
][j
];
1724 intpol_facts (src_point_y
,
1734 err_msg
= "gpiv_piv_dxdy_at_new_grid: Not enough points in horizontal direction";
1739 * Calculate new displacements by bi-lineair interpolation
1741 for (i
= 0; i
< piv_data_dest
->ny
; i
++) {
1742 for (j
= 0; j
< piv_data_dest
->nx
; j
++) {
1743 piv_data_dest
->dx
[i
][j
] = bilinear_interpol
1746 gpd
->dx
[index_n
[i
]][index_w
[j
]],
1747 gpd
->dx
[index_n
[i
]][index_e
[j
]],
1748 gpd
->dx
[index_s
[i
]][index_w
[j
]],
1749 gpd
->dx
[index_s
[i
]][index_e
[j
]]);
1752 g_message ("piv_dxdy_at_new_grid:: alpha_hor[%d]=%f alpha_vert[%d]=%f dx_nw=%f dx_ne=%f dx_sw=%f dx_se=%f => dx=%f",
1753 j
, alpha_hor
[j
], i
, alpha_vert
[i
],
1754 gpd
->dx
[index_n
[i
]][index_w
[j
]],
1755 gpd
->dx
[index_n
[i
]][index_e
[j
]],
1756 gpd
->dx
[index_s
[i
]][index_w
[j
]],
1757 gpd
->dx
[index_s
[i
]][index_e
[j
]],
1758 piv_data_dest
->dx
[i
][j
]
1762 piv_data_dest
->dy
[i
][j
] = bilinear_interpol
1765 gpd
->dy
[index_n
[i
]][index_w
[j
]],
1766 gpd
->dy
[index_n
[i
]][index_e
[j
]],
1767 gpd
->dy
[index_s
[i
]][index_w
[j
]],
1768 gpd
->dy
[index_s
[i
]][index_e
[j
]]);
1771 g_message ("piv_dxdy_at_new_grid:: alpha_hor[%d]=%f alpha_vert[%d]=%f dy_nw=%f dy_ne=%f dy_sw=%f dy_se=%f => dy=%f",
1772 j
, alpha_hor
[j
], i
, alpha_vert
[i
],
1773 gpd
->dy
[index_n
[i
]][index_w
[j
]],
1774 gpd
->dy
[index_n
[i
]][index_e
[j
]],
1775 gpd
->dy
[index_s
[i
]][index_w
[j
]],
1776 gpd
->dy
[index_s
[i
]][index_e
[j
]],
1777 piv_data_dest
->dy
[i
][j
]
1785 gpiv_free_ivector (index_n
);
1786 gpiv_free_ivector (index_s
);
1787 gpiv_free_ivector (index_e
);
1788 gpiv_free_ivector (index_w
);
1789 gpiv_free_ivector (index_nn
);
1790 gpiv_free_ivector (index_ss
);
1791 gpiv_free_ivector (index_ee
);
1792 gpiv_free_ivector (index_ww
);
1794 gpiv_free_dvector (alpha_vert
);
1795 gpiv_free_dvector (alpha_hor
);
1797 gpiv_free_vector (src_point_x
);
1798 gpiv_free_vector (src_point_y
);
1799 gpiv_free_vector (dest_point_x
);
1800 gpiv_free_vector (dest_point_y
);
1802 gpiv_free_pivdata (gpd
);
1809 gpiv_piv_shift_grid (GpivPivData
*gpd_src
1811 /*---------------------------------------------------------------------------*/
1813 * shifts the knots of a 2-dimensional grid containing PIV data for improved
1814 * (bi-linear) interpolation
1816 * See: T. Blu, P. Thevenaz, "Linear Interpolation Revitalized",
1817 * IEEE Trans. in Image Processing, vol13, no 5, May 2004
1819 * @param[in] piv_data_src input piv data
1820 * @return NULL on success or *err_msg on failure
1822 /*---------------------------------------------------------------------------*/
1826 char *err_msg
= NULL
;
1827 GpivPivData
*h_gpd
= NULL
;
1828 GpivPivData
*v_gpd
= NULL
;
1829 gfloat fact1
= -SHIFT
/ (1.0 - SHIFT
);
1830 gfloat fact2
= 1.0 / (1 - SHIFT
);
1836 delta
= gpd_src
->point_x
[0][1] - gpd_src
->point_x
[0][0];
1839 * Shift in horizontal (column-wise) direction
1841 h_gpd
= gpiv_alloc_pivdata (gpd_src
->nx
, gpd_src
->ny
);
1844 for (i
= 0; i
< gpd_src
->ny
; i
++) {
1845 for (j
= 0; j
< gpd_src
->nx
; j
++) {
1847 * Shift the knot (sample points)
1849 h_gpd
->point_x
[i
][j
] = gpd_src
->point_x
[i
][j
] + SHIFT
* delta
;
1850 h_gpd
->point_y
[i
][j
] = gpd_src
->point_y
[i
][j
];
1852 h_gpd
->dx
[i
][j
] = gpd_src
->dx
[i
][j
];
1853 h_gpd
->dy
[i
][j
] = gpd_src
->dy
[i
][j
];
1856 * Calculate value at shifted knot
1858 h_gpd
->dx
[i
][j
] = fact1
* h_gpd
->dx
[i
][j
-1] + fact2
*
1860 h_gpd
->dy
[i
][j
] = fact1
* h_gpd
->dy
[i
][j
-1] + fact2
*
1868 * Shift in vertical (row-wise) direction by using the horizontal shifted nodes
1870 v_gpd
= gpiv_alloc_pivdata (gpd_src
->nx
, gpd_src
->ny
);
1873 for (i
= 0; i
< gpd_src
->ny
; i
++) {
1874 for (j
= 0; j
< gpd_src
->nx
; j
++) {
1875 v_gpd
->point_x
[i
][j
] = h_gpd
->point_x
[i
][j
];
1876 v_gpd
->point_y
[i
][j
] = h_gpd
->point_y
[i
][j
] + SHIFT
* delta
;
1878 v_gpd
->dx
[i
][j
] = h_gpd
->dx
[i
][j
];
1879 v_gpd
->dy
[i
][j
] = h_gpd
->dy
[i
][j
];
1881 v_gpd
->dx
[i
][j
] = fact1
* v_gpd
->dx
[i
-1][j
] + fact2
*
1883 v_gpd
->dy
[i
][j
] = fact1
* v_gpd
->dy
[i
-1][j
] + fact2
*
1890 /* gpiv_free_pivdata (gpd_src); */
1891 /* gpd_src = gpiv_cp_pivdata (v_gpd); */
1893 for (i
= 0; i
< gpd_src
->ny
; i
++) {
1894 for (j
= 0; j
< gpd_src
->nx
; j
++) {
1895 gpd_src
->point_x
[i
][j
] = v_gpd
->point_x
[i
][j
];
1896 gpd_src
->point_y
[i
][j
] = v_gpd
->point_y
[i
][j
];
1897 gpd_src
->dx
[i
][j
] = v_gpd
->dx
[i
][j
];
1898 gpd_src
->dy
[i
][j
] = v_gpd
->dy
[i
][j
];
1899 gpd_src
->snr
[i
][j
] = v_gpd
->snr
[i
][j
];
1900 gpd_src
->peak_no
[i
][j
] = v_gpd
->peak_no
[i
][j
];
1904 /* gpiv_write_pivdata (NULL, gpd_src, FALSE); */
1907 gpiv_free_pivdata (h_gpd
);
1908 gpiv_free_pivdata (v_gpd
);
1916 gpiv_piv_gridgen (const guint nx
,
1918 const GpivImagePar
*image_par
,
1919 const GpivPivPar
*piv_par
1921 /*-----------------------------------------------------------------------------
1923 * Generates grid by Calculating the positions of interrogation areas
1924 * Substitutes gpiv_piv_select_int_point
1927 * nx number of columns
1929 * @image_par: structure of image parameters
1930 * @piv_par: structure of piv pivuation parameters
1933 * @out_data: output piv data from image analysis
1936 * %char * NULL on success or *err_msg on failure
1937 *---------------------------------------------------------------------------*/
1939 GpivPivData
*piv_data
= NULL
;
1940 gchar
*err_msg
= NULL
;
1941 int row
, column
, row_1
, column_1
, i
, j
;
1942 int row_max
, row_min
, column_max
, column_min
;
1944 int ncolumns
= image_par
->ncolumns
;
1945 int nrows
= image_par
->nrows
;
1947 int int_geo
= piv_par
->int_geo
;
1948 int row_start
= piv_par
->row_start
;
1949 int row_end
= piv_par
->row_end
;
1950 int col_start
= piv_par
->col_start
;
1951 int col_end
= piv_par
->col_end
;
1952 int int_line_col
= piv_par
->int_line_col
;
1953 int int_line_col_start
= piv_par
->int_line_col_start
;
1954 int int_line_col_end
= piv_par
->int_line_col_end
;
1955 int int_line_row
= piv_par
->int_line_row
;
1956 int int_line_row_start
= piv_par
->int_line_row_start
;
1957 int int_line_row_end
= piv_par
->int_line_row_end
;
1958 int int_point_col
= piv_par
->int_point_col
;
1959 int int_point_row
= piv_par
->int_point_row
;
1960 int int_size_f
= piv_par
->int_size_f
;
1961 int int_size_i
= piv_par
->int_size_i
;
1962 int int_shift
= piv_par
->int_shift
;
1963 int pre_shift_row
= piv_par
->pre_shift_row
;
1964 int pre_shift_col
= piv_par
->pre_shift_col
;
1967 /* g_return_val_if_fail (piv_data->point_x != NULL, "piv_data->point_x != NULL"); */
1968 /* g_return_val_if_fail (piv_data->point_y != NULL, "piv_data->point_y != NULL"); */
1970 row_min
= gpiv_min (-int_size_f
/ 2 + 1,
1971 pre_shift_row
- int_size_i
/ 2 + 1);
1972 column_min
= gpiv_max (-int_size_f
/ 2 + 1,
1973 pre_shift_col
- int_size_i
/ 2 + 1);
1974 row_max
= gpiv_max (int_size_f
/ 2, pre_shift_row
+ int_size_i
/ 2);
1975 column_max
= gpiv_max (int_size_f
/ 2, pre_shift_col
+ int_size_i
/ 2);
1979 * Creates piv_data and centre points for one single interrogation area
1981 piv_data
= gpiv_alloc_pivdata (nx
, ny
);
1983 if (int_geo
== GPIV_POINT
) {
1984 piv_data
->point_y
[0][0] = int_point_row
;
1985 piv_data
->point_x
[0][0] = int_point_col
;
1989 * Creates centre points for one single row
1991 } else if (int_geo
== GPIV_LINE_R
) {
1992 if ((int_size_f
- int_size_i
) / 2 + pre_shift_col
< 0) {
1993 column_1
= int_line_col_start
-
1994 ((int_size_f
- int_size_i
) / 2 +
1995 pre_shift_col
) + int_size_f
/ 2 - 1;
1997 column_1
= int_line_col_start
+ int_size_f
/ 2 - 1;
2000 for (i
= 0, j
= 0, row
= int_line_row
, column
= column_1
;
2001 j
< piv_data
->nx
; j
++, column
+= int_shift
) {
2002 piv_data
->point_y
[i
][j
] = row
;
2003 piv_data
->point_x
[i
][j
] = column
;
2008 * Creates centre points for one single column
2010 } else if (int_geo
== GPIV_LINE_C
) {
2011 if ((int_size_f
- int_size_i
) / 2 + pre_shift_row
< 0) {
2012 row_1
= int_line_row_start
-
2013 ((int_size_f
- int_size_i
) / 2 +
2014 pre_shift_row
) + int_size_f
/ 2 - 1;
2016 row_1
= int_line_row_start
+ int_size_f
/ 2 - 1;
2019 for (i
= 0, j
= 0, column
= int_line_col
, row
= row_1
;
2020 i
< piv_data
->ny
; i
++, row
+= int_shift
) {
2021 piv_data
->point_y
[i
][j
] = row
;
2022 piv_data
->point_x
[i
][j
] = column
;
2027 * Creates an array of centre points of the Interrrogation Area's:
2028 * int_ar_x and int_ar_y within the defined region of the image
2030 } else if (int_geo
== GPIV_AOI
) {
2031 if ((int_size_f
- int_size_i
) / 2 + pre_shift_row
< 0) {
2033 row_start
- ((int_size_f
- int_size_i
) / 2 +
2034 pre_shift_row
) + int_size_f
/ 2 - 1;
2036 row_1
= row_start
+ int_size_f
/ 2 - 1;
2039 if ((int_size_f
- int_size_i
) / 2 + pre_shift_col
< 0) {
2041 col_start
- ((int_size_f
- int_size_i
) / 2 +
2042 pre_shift_col
) + int_size_f
/ 2 - 1;
2044 column_1
= col_start
+ int_size_f
/ 2 - 1;
2047 for (i
= 0, row
= row_1
; i
< ny
; i
++, row
+= int_shift
) {
2048 for (j
= 0, column
= column_1
; j
< nx
;
2049 j
++, column
+= int_shift
) {
2050 piv_data
->point_y
[i
][j
] = row
;
2051 piv_data
->point_x
[i
][j
] = column
;
2055 err_msg
= "gpiv_piv_gridgen: should not arrive here";
2056 gpiv_warning ("%s", err_msg
);
2067 gpiv_piv_gridadapt (const GpivImagePar
*image_par
,
2068 const GpivPivPar
*piv_par_src
,
2069 GpivPivPar
*piv_par_dest
,
2070 const GpivPivData
*piv_data
,
2074 /*-----------------------------------------------------------------------------
2076 * Adjust grid nodes if zero_off or adaptive interrogation
2077 * area has been used. This is performed by modifying int_shift equal
2078 * to int_shift / GPIV_SHIFT_FACTOR , until it reaches (src)
2079 * int_shift. Then, grid_last is set TRUE, which will avoid
2080 * changing the interrogation shift in next calls and signal the
2081 * (while loop in) the calling function.
2084 * @image_par: image parameters
2085 * @piv_par_src: piv parameters
2086 * @piv_data: input PIV data
2087 * @sweep: interrogation sweep step
2090 * @image_par: image parameters
2091 * @piv_par_dest: modified piv parameters
2092 * @grid_last: flag if final grid refinement has been
2096 * piv_data: modified PIV data
2097 *---------------------------------------------------------------------------*/
2099 GpivPivData
*pd
= NULL
;
2100 gint local_int_shift
, local_int_size_f
, local_int_size_i
;
2101 gint LOCAL_SHIFT_FACTOR
= 2;
2106 local_int_shift
= piv_par_dest
->int_shift
/ LOCAL_SHIFT_FACTOR
;
2107 if (local_int_shift
<= piv_par_src
->int_shift
) {
2111 if (*grid_last
== FALSE
) {
2113 * - renew grid of PIV dataset
2114 * - calculate displacements at new grid points
2116 piv_par_dest
->int_shift
= piv_par_dest
->int_shift
/
2118 gpiv_piv_count_pivdata_fromimage (image_par
, piv_par_dest
, &nx
, &ny
);
2119 pd
= gpiv_piv_gridgen (nx
, ny
, image_par
, piv_par_dest
);
2120 gpiv_piv_dxdy_at_new_grid (piv_data
, pd
);
2124 * reset int_shift (and data positions) to the originally defined
2126 * For the last grid adaption, the number of interrogation area's may
2127 * not have been doubled perse, as int_size may be of
2128 * arbitrary quantity.
2131 piv_par_dest
->int_shift
= piv_par_src
->int_shift
;
2133 * Set int_size_f and int_size_i of piv_par_dest temporarly to the
2134 * original settings, so that an identic grid will be constructued as
2135 * during the gpiv_gridgen call.
2137 local_int_size_f
= piv_par_dest
->int_size_f
;
2138 local_int_size_i
= piv_par_dest
->int_size_i
;
2139 piv_par_dest
->int_size_f
= piv_par_src
->int_size_f
;
2140 piv_par_dest
->int_size_i
= piv_par_src
->int_size_i
;
2141 gpiv_piv_count_pivdata_fromimage (image_par
, piv_par_dest
, &nx
, &ny
);
2142 pd
= gpiv_piv_gridgen (nx
, ny
, image_par
, piv_par_dest
);
2143 piv_par_dest
->int_size_f
= local_int_size_f
;
2144 piv_par_dest
->int_size_i
= local_int_size_i
;
2146 gpiv_piv_dxdy_at_new_grid (piv_data
, pd
);
2158 static GpivPivData
*
2159 alloc_pivdata_gridgen (const GpivImagePar
*image_par
,
2160 const GpivPivPar
*piv_par
2162 /*-----------------------------------------------------------------------------
2163 * Determines the number of grid points, allocating memory for output
2164 * data and generates the grid
2167 GpivPivData
*piv_data
= NULL
;
2168 gchar
*err_msg
= NULL
;
2169 GpivPivPar
*lo_piv_par
= NULL
;
2172 if ((lo_piv_par
= gpiv_piv_cp_parameters (piv_par
)) == NULL
) {
2173 gpiv_error ("LIBGPIV internal error: alloc_pivdata_gridgen: failing gpiv_piv_cp_parameters");
2176 if (piv_par
->int_size_i
> piv_par
->int_size_f
2177 && piv_par
->int_shift
< piv_par
->int_size_i
/ GPIV_SHIFT_FACTOR
) {
2178 lo_piv_par
->int_shift
= lo_piv_par
->int_size_i
/ GPIV_SHIFT_FACTOR
;
2182 gpiv_piv_count_pivdata_fromimage (image_par
, lo_piv_par
, &nx
, &ny
))
2184 g_message ("LIBGPIV internal error: alloc_pivdata_gridgen: %s", err_msg
);
2190 gpiv_piv_gridgen (nx
, ny
, image_par
, lo_piv_par
))
2192 g_message ("LIBGPIV internal error: alloc_pivdata_gridgen: failing gpiv_piv_gridgen");
2203 report_progress (gint
*progress_old
,
2206 GpivPivData
*piv_data
,
2207 GpivPivPar
*piv_par
,
2211 /*-----------------------------------------------------------------------------
2212 * Printing the progress (between 0 and 100) of piv interrogation to stdout
2215 gint progress
= 100 * (index_y
* piv_data
->nx
+ index_x
+ 1) /
2216 (piv_data
->nx
* piv_data
->ny
);
2223 if (progress
!= *progress_old
) {
2224 *progress_old
= progress
;
2226 if (index_y
> 0 || index_x
> 0)
2227 printf ("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
2229 if (piv_par
->int_scheme
== GPIV_ZERO_OFF_FORWARD
2230 || piv_par
->int_scheme
== GPIV_ZERO_OFF_CENTRAL
2231 || piv_par
->int_scheme
== GPIV_ZERO_OFF_CENTRAL
2232 || piv_par
->int_scheme
== GPIV_IMG_DEFORM
2233 || piv_par
->int_size_i
> piv_par
->int_size_f
) {
2235 ("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
2236 "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
2237 "\b\b\b\b\b\b\b\b\b\b\b"
2238 "\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
2242 printf ("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
2243 printf ("nr_thr = %2d thr_id = %2d ",
2244 omp_get_num_threads(), omp_get_thread_num());
2248 MPI_Comm_rank(MPI_COMM_WORLD
, &rank
);
2249 MPI_Comm_size(MPI_COMM_WORLD
, &size
);
2250 printf ("\b\b\b\b\b\b\b\b\b\b\b\b");
2251 printf ("rank %2d/%2d, ", rank
, size
);
2253 printf ("sweep #%2d, int_size = %d int_shift = %d residu = %.3f: ",
2254 sweep
, piv_par
->int_size_f
, piv_par
->int_shift
,
2258 printf ("%3d %%", progress
);
2266 assign_img2intarr (gint ipoint_x
,
2272 gfloat
**int_area_1
,
2273 gfloat
**int_area_2
,
2280 /*-----------------------------------------------------------------------------
2281 * Assigns image data to the interrogation area arrays in a straightforward way
2285 gint arg_int1_r
= ipoint_y
- int_size_f
/ 2 + 1;
2286 gint arg_int1_c
= ipoint_x
- int_size_f
/ 2 + 1;
2287 gint arg_int2_r
= ipoint_y
- int_size_i
/ 2 + 1;
2288 gint arg_int2_c
= ipoint_x
- int_size_i
/ 2 + 1;
2290 gboolean flag_valid
;
2293 assert (img_1
[0] != NULL
);
2294 assert (img_2
[0] != NULL
);
2295 assert (int_area_1
[0] != NULL
);
2296 assert (int_area_2
[0] != NULL
);
2299 * Check if Interrogation Areas are within the image boundaries.
2300 * Principally arg_int1_r,c don't have to be tested as
2301 * int_size_i >= int_size_f, but has been kept to maintain generallity with the
2302 * other assign_img2intarr* functions
2304 if ((arg_int1_r
) >= 0
2305 && (arg_int1_r
+ int_size_f
- 1) < nrows
2306 && (arg_int1_c
) >= 0
2307 && (arg_int1_c
+ int_size_f
- 1) < ncolumns
2309 && (arg_int2_r
) >= 0
2310 && (arg_int2_r
+ int_size_i
- 1) < nrows
2311 && (arg_int2_c
) >= 0
2312 && (arg_int2_c
+ int_size_i
- 1) < ncolumns
) {
2320 if (flag_valid
== TRUE
) {
2322 * reset int_area_1, int_area_2 values
2324 memset (int_area_1
[0], 0.0, (sizeof(gfloat
)) * int_size_0
* int_size_0
);
2325 memset (int_area_2
[0], 0.0, (sizeof(gfloat
)) * int_size_0
* int_size_0
);
2327 for (m
= 0; m
< int_size_f
; m
++) {
2328 for (n
= 0; n
< int_size_f
; n
++) {
2330 (float) img_1
[m
+ arg_int1_r
][n
+ arg_int1_c
];
2334 for (m
= 0; m
< int_size_i
; m
++) {
2335 for (n
= 0; n
< int_size_i
; n
++) {
2337 (float) img_2
[m
+ arg_int2_r
][n
+ arg_int2_c
];
2349 assign_img2intarr_central (gint ipoint_x
,
2355 gfloat
**int_area_1
,
2356 gfloat
**int_area_2
,
2363 /*-----------------------------------------------------------------------------
2364 * Assigns image data to the interrogation area arrays using the central
2365 * differential scheme
2369 gint idum
= gpiv_max((int_size_i
- int_size_f
) / 2, 0);
2370 gint arg_int1_r
= ipoint_y
- int_size_f
/ 2 + 1 - pre_shift_row
/ 2 -
2372 gint arg_int1_c
= ipoint_x
- int_size_f
/ 2 + 1 - pre_shift_col
/ 2 -
2374 gint arg_int2_r
= ipoint_y
- int_size_i
/ 2 + 1 + pre_shift_row
/ 2;
2375 gint arg_int2_c
= ipoint_x
- int_size_i
/ 2 + 1 + pre_shift_col
/ 2;
2376 gboolean flag_valid
;
2379 assert (img_1
[0] != NULL
);
2380 assert (img_2
[0] != NULL
);
2381 assert (int_area_1
[0] != NULL
);
2382 assert (int_area_2
[0] != NULL
);
2384 * Check if Interrogation Areas are within the image boundaries.
2386 if ((arg_int1_r
) >= 0
2387 && (arg_int1_r
+ int_size_f
- 1) < nrows
2388 && (arg_int1_c
) >= 0
2389 && (arg_int1_c
+ int_size_f
- 1) < ncolumns
2391 && (arg_int2_r
) >= 0
2392 && (arg_int2_r
+ int_size_i
- 1) < nrows
2393 && (arg_int2_c
) >= 0
2394 && (arg_int2_c
+ int_size_i
- 1) < ncolumns
) {
2401 if (flag_valid
== TRUE
) {
2403 * reset int_area_1, int_area_2 values
2405 memset(int_area_1
[0], 0.0, (sizeof(gfloat
)) * int_size_0
* int_size_0
);
2406 memset(int_area_2
[0], 0.0, (sizeof(gfloat
)) * int_size_0
* int_size_0
);
2408 for (m
= 0; m
< int_size_f
; m
++) {
2409 for (n
= 0; n
< int_size_f
; n
++) {
2410 int_area_1
[m
+ idum
][n
+ idum
] =
2411 (float) img_1
[m
+ arg_int1_r
][n
+ arg_int1_c
];
2416 for (m
= 0; m
< int_size_i
; m
++) {
2417 for (n
= 0; n
< int_size_i
; n
++) {
2419 (float) img_2
[m
+ arg_int2_r
][n
+ arg_int2_c
];
2432 assign_img2intarr_forward (gint ipoint_x
,
2438 gfloat
**int_area_1
,
2439 gfloat
**int_area_2
,
2446 /*-----------------------------------------------------------------------------
2447 * Assigns image data to the interrogation area arrays for forward differential
2452 gint idum
= gpiv_max((int_size_i
- int_size_f
) / 2, 0);
2453 gint arg_int1_r
= ipoint_y
- int_size_f
/ 2 + 1 + pre_shift_row
+ idum
;
2454 gint arg_int1_c
= ipoint_x
- int_size_f
/ 2 + 1 + pre_shift_col
+ idum
;
2455 gint arg_int2_r
= ipoint_y
- int_size_i
/ 2 + 1 + pre_shift_row
;
2456 gint arg_int2_c
= ipoint_x
- int_size_i
/ 2 + 1 + pre_shift_col
;
2457 gboolean flag_valid
;
2460 assert (img_1
[0] != NULL
);
2461 assert (img_2
[0] != NULL
);
2462 assert (int_area_1
[0] != NULL
);
2463 assert (int_area_2
[0] != NULL
);
2465 * Check if Interrogation Areas are within the image boundaries.
2467 if ((arg_int1_r
) >= 0
2468 && (arg_int1_r
+ int_size_f
- 1) < nrows
2469 && (arg_int1_c
) >= 0
2470 && (arg_int1_c
+ int_size_f
- 1) < ncolumns
2472 && (arg_int2_r
) >= 0
2473 && (arg_int2_r
+ int_size_i
- 1) < nrows
2474 && (arg_int2_c
) >= 0
2475 && (arg_int2_c
+ int_size_i
- 1) < ncolumns
) {
2482 if (flag_valid
== TRUE
) {
2484 * reset int_area_1, int_area_2 values
2486 memset(int_area_1
[0], 0.0,
2487 (sizeof(float)) * int_size_0
* int_size_0
);
2488 memset(int_area_2
[0], 0.0,
2489 (sizeof(float)) * int_size_0
* int_size_0
);
2491 for (m
= 0; m
< int_size_f
; m
++) {
2492 for (n
= 0; n
< int_size_f
; n
++) {
2493 int_area_1
[m
+ idum
][n
+ idum
] =
2494 (float) img_1
[m
+ arg_int1_r
][n
+ arg_int1_c
];
2499 for (m
= 0; m
< int_size_i
; m
++) {
2500 for (n
= 0; n
< int_size_i
; n
++) {
2502 (float) img_2
[m
+ arg_int2_r
][n
+ arg_int2_c
];
2515 int_mean_old (guint16
**img
,
2521 /* ----------------------------------------------------------------------------
2522 * calculates mean image value from which image data are taken
2525 int m
= 0, n
= 0, idum
= gpiv_max((int_size_i
- int_size
) / 2, 0);
2526 int int_area_sum
= 0;
2530 assert (img
[0] != NULL
);
2532 for (m
= 0; m
< int_size
; m
++) {
2533 for (n
= 0; n
< int_size
; n
++) {
2535 img
[m
+ ipoint_y
- int_size_i
/ 2 + 1 + idum
]
2536 [n
+ ipoint_x
- int_size_i
/ 2 + 1 + idum
];
2540 mean
= int_area_sum
/ (int_size
* int_size
);
2549 int_mean (gfloat
**int_area
,
2552 /* ----------------------------------------------------------------------------
2553 * calculates mean value from interrogation area intensities
2557 gfloat int_area_sum
= 0;
2561 assert (int_area
[0] != NULL
);
2563 for (m
= 0; m
< int_size
; m
++) {
2564 for (n
= 0; n
< int_size
; n
++) {
2565 int_area_sum
+= int_area
[m
][n
];
2569 mean
= int_area_sum
/ (int_size
* int_size
);
2578 int_range (gfloat
**int_area
,
2581 /* ----------------------------------------------------------------------------
2582 * calculates range of values from interrogation area intensities
2586 gfloat int_area_sum
= 0;
2587 gfloat min
= 10.0e9
, max
= -10.0e9
, range
= 0.0;
2590 assert (int_area
[0] != NULL
);
2592 for (m
= 0; m
< int_size
; m
++) {
2593 for (n
= 0; n
< int_size
; n
++) {
2594 if (int_area
[m
][n
] > max
) max
= int_area
[m
][n
];
2595 if (int_area
[m
][n
] < min
) min
= int_area
[m
][n
];
2608 int_const (gfloat
**int_area
,
2609 const guint int_size
2611 /* ----------------------------------------------------------------------------
2612 * Tests if all intesities values with an interrogation area are equal
2616 gboolean flag
= TRUE
;
2620 assert (int_area
[0] != NULL
);
2622 val
= int_area
[0][0];
2623 for (m
= 1; m
< int_size
; m
++) {
2624 for (n
= 1; n
< int_size
; n
++) {
2625 if (int_area
[m
][n
] != val
) flag
= FALSE
;
2636 cov_min_max (GpivCov
*cov
2638 /* ----------------------------------------------------------------------------
2639 * calculates minimum and maximum in cov
2642 gfloat max
= -10.0e+9, min
= 10.0e+9;
2643 gint z_rl
= cov
->z_rl
, z_rh
= cov
->z_rh
, z_cl
= cov
->z_cl
,
2648 for (i
= z_rl
+ 1; i
< z_rh
- 1; i
++) {
2649 for (j
= z_cl
+ 1; j
< z_ch
- 1; j
++) {
2650 if (cov
->z
[i
][j
] > max
) max
= cov
->z
[i
][j
];
2651 if (cov
->z
[i
][j
] < min
) min
= cov
->z
[i
][j
];
2661 search_top (GpivCov
*cov
,
2671 /* ----------------------------------------------------------------------------
2672 * searches top in cov. function
2676 gint z_rl
= cov
->z_rl
, z_rh
= cov
->z_rh
, z_cl
= cov
->z_cl
,
2680 for (h
= 1; h
<= peak_act
+ 1; h
++) {
2686 for (h
= 1; h
<= peak_act
; h
++) {
2687 for (i
= z_rl
+ 1; i
< z_rh
- 1; i
++) {
2688 for (j
= z_cl
+ 1; j
< z_ch
- 1; j
++) {
2690 if (x_corr
== 1 || (sweep
== 0 || (i
!= i_skip_act
||
2691 j
!= j_skip_act
))) {
2694 && (i
!= i_max
[1] || j
!= j_max
[1]))
2696 && (i
!= i_max
[1] || j
!= j_max
[1])
2697 && (i
!= i_max
[2] || j
!= j_max
[2]))) {
2698 if (cov
->z
[i
][j
] > z_max
[h
]) {
2699 if ((cov
->z
[i
][j
] >= cov
->z
[i
- 1][j
]) &&
2700 (cov
->z
[i
][j
] >= cov
->z
[i
+ 1][j
]) &&
2701 (cov
->z
[i
][j
] >= cov
->z
[i
][j
- 1]) &&
2702 (cov
->z
[i
][j
] >= cov
->z
[i
][j
+ 1])) {
2703 z_max
[h
] = cov
->z
[i
][j
];
2719 cov_subtop (float **z
,
2727 /*-----------------------------------------------------------------------------
2728 * Calculates particle displacements at sub-pixel level
2731 char *err_msg
= NULL
;
2732 double A_log
, B_log
, C_log
;
2734 gboolean flag
= TRUE
;
2737 if (ifit
== GPIV_GAUSS
) {
2739 * sub-pixel estimator by gaussian fit
2741 if (z
[i_max
[peak_act
]][j_max
[peak_act
]] > min
) {
2742 C_log
= log((double) z
[i_max
[peak_act
]][j_max
[peak_act
]]);
2747 if (flag
&& z
[i_max
[peak_act
] - 1][j_max
[peak_act
]] > min
) {
2748 A_log
= log((double) z
[i_max
[peak_act
] - 1][j_max
[peak_act
]]);
2753 if (flag
&& z
[i_max
[peak_act
] + 1][j_max
[peak_act
]] > min
) {
2754 B_log
= log((double) z
[i_max
[peak_act
] + 1][j_max
[peak_act
]]);
2759 if (flag
&& (2 * (A_log
+ B_log
- 2 * C_log
)) != 0.0) {
2760 *epsi_y
= (A_log
- B_log
) / (2 * (A_log
+ B_log
- 2 * C_log
));
2764 err_msg
= "epsi_y = 0.0";
2769 if (flag
&& z
[i_max
[peak_act
]][j_max
[peak_act
] - 1] != 0.0) {
2770 A_log
= log((double) z
[i_max
[peak_act
]][j_max
[peak_act
] - 1]);
2775 if (flag
&& z
[i_max
[peak_act
]][j_max
[peak_act
] + 1] != 0.0) {
2776 B_log
= log((double) z
[i_max
[peak_act
]][j_max
[peak_act
] + 1]);
2781 if (flag
&& (2 * (A_log
+ B_log
- 2 * C_log
)) != 0.0) {
2782 *epsi_x
= (A_log
- B_log
) / (2 * (A_log
+ B_log
- 2 * C_log
));
2786 err_msg
= "epsi_x = 0.0";
2791 } else if (ifit
== GPIV_POWER
) {
2793 * sub-pixel estimator by quadratic fit
2795 *epsi_y
= (z
[i_max
[peak_act
] - 1][j_max
[peak_act
]] -
2796 z
[i_max
[peak_act
] + 1][j_max
[peak_act
]]) /
2797 (2 * (z
[i_max
[peak_act
] - 1][j_max
[peak_act
]] +
2798 z
[i_max
[peak_act
] + 1][j_max
[peak_act
]] -
2799 2 * z
[i_max
[peak_act
]][j_max
[peak_act
]]));
2801 *epsi_x
= (z
[i_max
[peak_act
]][j_max
[peak_act
] - 1] -
2802 z
[i_max
[peak_act
]][j_max
[peak_act
] + 1]) /
2803 (2 * (z
[i_max
[peak_act
]][j_max
[peak_act
] - 1] +
2804 z
[i_max
[peak_act
]][j_max
[peak_act
] + 1] -
2805 2 * z
[i_max
[peak_act
]][j_max
[peak_act
]]));
2808 } else if (ifit
== GPIV_GRAVITY
) {
2810 * sub-pixel estimator by centre of gravity
2812 *epsi_y
= (z
[i_max
[peak_act
] - 1][j_max
[peak_act
]] -
2813 z
[i_max
[peak_act
] + 1][j_max
[peak_act
]]) /
2814 (z
[i_max
[peak_act
] - 1][j_max
[peak_act
]] +
2815 z
[i_max
[peak_act
] + 1][j_max
[peak_act
]] +
2816 z
[i_max
[peak_act
]][j_max
[peak_act
]]);
2818 *epsi_x
= (z
[i_max
[peak_act
]][j_max
[peak_act
] - 1] -
2819 z
[i_max
[peak_act
]][j_max
[peak_act
] + 1]) /
2820 (z
[i_max
[peak_act
]][j_max
[peak_act
] - 1] +
2821 z
[i_max
[peak_act
]][j_max
[peak_act
] + 1] +
2822 z
[i_max
[peak_act
]][j_max
[peak_act
]]);
2826 err_msg
= "LIBGPIV internal error: cov_subtop: invalid fit parameter";
2827 gpiv_warning("%s", err_msg
);
2838 cov_top (GpivPivPar piv_par
,
2839 GpivPivData
* piv_data
,
2849 int pre_shift_row_act
,
2850 int pre_shift_col_act
,
2853 gboolean
*flag_subtop
2855 /* ----------------------------------------------------------------------------
2856 * detects location of peak and snr in correlation function
2859 #define INITIAL_MIN 9999.9
2860 char *err_msg
= NULL
;
2861 float z_min
, *z_max
, *z_max_next
;
2862 int h
, i
, j
, i_min
, j_min
;
2863 long *i_max
, *j_max
, *i_max_next
, *j_max_next
;
2865 int z_rl
= cov
->z_rl
, z_rh
= cov
->z_rh
, z_cl
= cov
->z_cl
, z_ch
= cov
->z_ch
;
2867 int ipoint_x
= (int) piv_data
->point_x
[index_y
][index_x
];
2868 int ipoint_y
= (int) piv_data
->point_y
[index_y
][index_x
];
2869 /* float epsi_x = 0.0, epsi_y = 0.0; */
2870 gboolean flag_snr
= TRUE
;
2871 gint dim
= peak_act
;
2874 i_max
= gpiv_nulvector_index(1, dim
+ 1);
2875 j_max
= gpiv_nulvector_index(1, dim
+ 1);
2876 z_max
= gpiv_vector_index(1, dim
+ 1);
2877 i_max_next
= gpiv_nulvector_index(1, dim
+ 2);
2878 j_max_next
= gpiv_nulvector_index(1, dim
+ 2);
2879 z_max_next
= gpiv_vector_index(1, dim
+ 2);
2883 * finding a local top within the interrogation region. In case of
2884 * autocorrelation, exclude the first max (normally at i = 0,j = 0 if no
2885 * pre-shifting has been used), by increasing peak_act with 1 during the first
2886 * iteration sweep, then call it skip_act
2889 if (sweep
== 0 && x_corr
== 0) {
2890 peak_act
= peak
+ 1;
2896 search_top (cov
, peak_act
, x_corr
, sweep
, i_skip_act
, j_skip_act
,
2897 z_max
, i_max
, j_max
);
2899 for (h
= 1; h
<= peak_act
+ 1; h
++) {
2900 if (z_max_next
[h
] == -1.0) {
2907 * Define first max to be skipped if autocorr, eventually shift this
2908 * point with new pre-shifting values
2912 if (x_corr
== 0 && sweep
== 0) {
2913 i_skip_act
= i_max
[1];
2914 j_skip_act
= j_max
[1];
2917 /* BUGFIX: don't calculate snr for the Challenge project */
2918 /* flag_snr = FALSE; */
2921 * Search next higher peak for SNR calculation
2924 search_top (cov
, peak_act
+ 1, x_corr
, sweep
, i_skip_act
, j_skip_act
,
2925 z_max_next
, i_max_next
, j_max_next
);
2929 * Check if second top has been found
2931 for (h
= 1; h
<= peak_act
+ 1; h
++) {
2932 if (z_max_next
[h
] == -1.0) {
2939 && cov
->z
[i_max_next
[peak_act
+ 1]][j_max_next
[peak_act
+ 1]] != 0.0) {
2940 cov
->snr
= (cov
->z
[i_max
[peak_act
]][j_max
[peak_act
]] - cov
->min
) /
2941 (cov
->z
[i_max_next
[peak_act
+ 1]][j_max_next
[peak_act
+ 1]] - cov
->min
);
2944 piv_data
->snr
[index_y
][index_x
] = cov
->snr
;
2945 /* piv_data->peak_no[index_y][index_x] = -1; */
2949 * Searching of minimum around cov. peak_act and remove 'pedestal'
2951 z_min
= INITIAL_MIN
;
2952 i_min
= INITIAL_MIN
;
2953 j_min
= INITIAL_MIN
;
2954 for (i
= i_max
[peak_act
] - 1; i
<= i_max
[peak_act
] + 1; i
++) {
2955 for (j
= j_max
[peak_act
] - 1; j
<= j_max
[peak_act
] + 1; j
++) {
2956 if ((i
>= z_rl
&& i
<= z_rh
) && (j
>= z_cl
&& j
<= z_ch
)) {
2957 if (cov
->z
[i
][j
] < z_min
) {
2958 z_min
= cov
->z
[i
][j
];
2966 if (z_min
<= INITIAL_MIN
) {
2967 for (i
= i_max
[peak_act
] - 1; i
<= i_max
[peak_act
] + 1; i
++) {
2968 for (j
= j_max
[peak_act
] - 1; j
<= j_max
[peak_act
] + 1; j
++) {
2969 /* cov->z[i][j] = cov->z[i][j]-z_min; */
2970 cov
->z
[i
][j
] = cov
->z
[i
][j
] - z_min
+ 0.1;
2978 * Calculate particle displacement at integer pixel numbers or at sub-pixel
2980 if (ifit
== GPIV_NONE
) {
2981 cov
->subtop_x
= 0.0;
2982 cov
->subtop_y
= 0.0;
2985 if ((err_msg
= cov_subtop (cov
->z
, i_max
, j_max
, &cov
->subtop_x
,
2986 &cov
->subtop_y
, ifit
, peak_act
))
2988 g_message("%s", err_msg
);
2989 *flag_subtop
= TRUE
;
2994 * Writing maximuma to cov
2996 cov
->top_y
= i_max
[peak_act
];
2997 cov
->top_x
= j_max
[peak_act
];
3002 gpiv_free_nulvector_index(i_max
, 1, dim
+ 1);
3003 gpiv_free_nulvector_index(j_max
, 1, dim
+ 1);
3004 gpiv_free_vector_index(z_max
, 1, dim
+ 1);
3005 gpiv_free_nulvector_index(i_max_next
, 1, dim
+ 2);
3006 gpiv_free_nulvector_index(j_max_next
, 1, dim
+ 2);
3007 gpiv_free_vector_index(z_max_next
, 1, dim
+ 2);
3015 void pack_cov (float **covariance
,
3019 /*-----------------------------------------------------------------------------
3020 * Packs the unordered covariance data in an ordered sequence when returning
3025 int z_rnl
= cov
->z_rnl
, z_rnh
= cov
->z_rnh
, z_rpl
= cov
->z_rpl
,
3027 int z_cnl
= cov
->z_cnl
, z_cnh
= cov
->z_cnh
, z_cpl
= cov
->z_cpl
,
3031 for (i
= z_rnl
; i
< z_rnh
; i
++) {
3032 for (j
= z_cnl
; j
< z_cnh
; j
++) {
3033 cov
->z
[i
- int_size_0
][j
- int_size_0
] = covariance
[i
][j
];
3035 for (j
= z_cpl
; j
< z_cph
; j
++) {
3036 cov
->z
[i
- int_size_0
][j
] = covariance
[i
][j
];
3040 for (i
= z_rpl
; i
< z_rph
; i
++) {
3041 for (j
= z_cnl
; j
< z_cnh
; j
++) {
3042 cov
->z
[i
][j
- int_size_0
] = covariance
[i
][j
];
3044 for (j
= z_cpl
; j
< z_cph
; j
++) {
3045 cov
->z
[i
][j
] = covariance
[i
][j
];
3053 weight_cov (GpivCov
*cov
,
3056 /*-----------------------------------------------------------------------------
3057 * Corrects ordered covariance data with weighting kernel
3061 int z_rl
= w_k
->z_rl
, z_rh
= w_k
->z_rh
;
3062 int z_cl
= w_k
->z_cl
, z_ch
= w_k
->z_ch
;
3066 g_message("LIBGPIV internal error: weight_cov: w_k = NULL");
3070 for (i
= z_rl
; i
< z_rh
; i
++) {
3071 for (j
= z_cl
; j
< z_ch
; j
++) {
3072 cov
->z
[i
][j
] = cov
->z
[i
][j
] / w_k
->z
[i
][j
];
3080 filter_cov_spof (fftw_complex
*a
,
3085 /*-----------------------------------------------------------------------------
3086 * Applies Symmetric Phase Only filtering on the complex arrays a and b
3089 * M.P. Wernet, "Symmetric phase only filtering: a new paradigm for DPIV
3090 * data processing", Meas. Sci. Technol, vol 16 (2005), pp 601 - 618
3093 gchar
*err_msg
= NULL
;
3094 gfloat amplitude_a
, amplitude_b
;
3098 /* assert (a[0] != NULL); */
3099 /* assert (b[0] != NULL); */
3101 for (i
= 0; i
< m
; i
++) {
3102 for (j
= 0; j
< n
/ 2 + 1; j
++) {
3103 ij
= i
* (n
/ 2 + 1) + j
;
3104 amplitude_a
= sqrt(a
[ij
][0] * a
[ij
][0] + a
[ij
][1] * a
[ij
][1]);
3105 amplitude_b
= sqrt(b
[ij
][0] * b
[ij
][0] + b
[ij
][1] * b
[ij
][1]);
3107 if (amplitude_a
== 0.0 || amplitude_b
== 0.0) {
3113 a
[ij
][0] /= sqrt(amplitude_a
) * sqrt(amplitude_b
);
3114 a
[ij
][1] /= sqrt(amplitude_a
) * sqrt(amplitude_b
);
3115 b
[ij
][0] /= sqrt(amplitude_a
) * sqrt(amplitude_b
);
3116 b
[ij
][1] /= sqrt(amplitude_a
) * sqrt(amplitude_b
);
3128 cova (const gboolean spof_filter
,
3131 /*-----------------------------------------------------------------------------
3132 * Calculates the covariance function of intreg1 and intreg2 by
3133 * means of Fast Fourier Transforms.
3136 gchar
*err_msg
= NULL
;
3137 int M
= ft
->size
, N
= ft
->size
;
3138 float covariance_max
, covariance_min
;
3142 gdouble scale
= 1.0 / (M
* N
);
3143 double *l_re
= &ft
->re
[0][0];
3144 fftw_complex
*l_co
= &ft
->co
[0][0];
3145 fftw_complex
*l_A
= &ft
->A
[0][0];
3146 fftw_complex
*l_B
= &ft
->B
[0][0];
3150 FILE *fp
= my_utils_fopen_tmp (GPIV_LOGFILE
, "w");
3156 gpiv_check_alloc_ft (ft
);
3158 covariance
= gpiv_matrix(M
, N
);
3159 memset(covariance
[0], 0, (sizeof(float)) * M
* N
);
3162 * FFT both interrogation areas
3165 fprintf (fp
, "New I.A:\n");
3167 /* copying intreg1 to re[][] for first FFT */
3168 for (i
= 0; i
< M
; ++i
) {
3169 for (j
= 0; j
< N
; ++j
) {
3171 l_re
[ij
] = (double) ft
->intreg1
[i
][j
];
3173 fprintf (fp
, "cova:: intreg1[%d][%d] = %f re[%d] = %f\n",
3174 i
, j
, ft
->intreg1
[i
][j
],
3181 fprintf (fp
, "\n\n");
3184 fftw_execute(ft
->plan_forwardFFT
);
3187 * save first FFT result in A[][]
3189 for (i
= 0; i
< M
; ++i
) {
3190 for (j
= 0; j
< (N
/2+1); ++j
) {
3191 ij
= i
* (N
/2+1) + j
;
3192 l_A
[ij
][0] = l_co
[ij
][0]; /* real part */
3193 l_A
[ij
][1] = l_co
[ij
][1]; /* imaginary part */
3199 * copying intreg2 to re[][] for second FFT
3201 for (i
= 0; i
< M
; ++i
) {
3202 for (j
= 0; j
< N
; ++j
) {
3204 l_re
[ij
] = (double) ft
->intreg2
[i
][j
];
3208 fftw_execute(ft
->plan_forwardFFT
);
3211 * save second FFT result in B[][]
3213 for (i
= 0; i
< M
; ++i
) {
3214 for (j
= 0; j
< (N
/2+1); ++j
) {
3215 ij
= i
* (N
/2+1) + j
;
3216 l_B
[ij
][0] = l_co
[ij
][0]; /* real part */
3217 l_B
[ij
][1] = l_co
[ij
][1]; /* imaginary part */
3223 if ((err_msg
= filter_cov_spof(l_A
, l_B
, M
, N
)) != NULL
) {
3229 * B * conjugate(A) result in correct sign of displacements!
3231 /* copying B x A* to co[][] */
3232 for (i
= 0; i
< M
; ++i
) {
3233 for (j
= 0; j
< N
/ 2 + 1; ++j
) {
3234 ij
= i
* (N
/ 2 + 1) + j
;
3236 (l_B
[ij
][0] * l_A
[ij
][0] +
3237 l_B
[ij
][1] * l_A
[ij
][1]) * scale
;
3239 (l_B
[ij
][1] * l_A
[ij
][0] -
3240 l_B
[ij
][0] * l_A
[ij
][1]) * scale
;
3243 fprintf (fp
, "cova:: A[%d]_re = %f A[%d]_im = %f B[%d]_re = %f B[%d]_im = %f\n",
3244 ij
, l_A
[ij
][0], ij
, l_A
[ij
][1],
3245 ij
, l_B
[ij
][0], ij
, l_B
[ij
][1]
3251 fprintf (fp
, "\n\n");
3255 * inverse transform to get the covariance of intreg1 and intreg2;
3256 * executing reverse-FFT on co[][], result in re[][]
3258 fftw_execute(ft
->plan_reverseFFT
);
3262 * Put the data back in a 2-dim array covariance[][]
3263 * copying re[][] to covariance[][]
3265 for (i
= 0; i
< M
; i
++) {
3266 for (j
= 0; j
< N
; j
++) {
3268 covariance
[i
][j
] = (float) l_re
[ij
];
3273 fprintf (fp
, "\n\n");
3277 * normalisation => correlation function
3279 /* using system limits from float.h here */
3280 covariance_max
= FLT_MIN
;
3281 covariance_min
= FLT_MAX
;
3282 for (i
= 0; i
< M
; i
++) {
3283 for (j
= 0; j
< N
; j
++) {
3284 if (covariance
[i
][j
] > covariance_max
)
3285 covariance_max
= covariance
[i
][j
];
3286 if (covariance
[i
][j
] < covariance_min
)
3287 covariance_min
= covariance
[i
][j
];
3291 for (i
= 0; i
< M
; i
++) {
3292 for (j
= 0; j
< N
; j
++) {
3293 covariance
[i
][j
] = covariance
[i
][j
] / covariance_max
;
3299 * Packing the unordered covariance data into the ordered array of
3300 * Covariance structure
3302 pack_cov(covariance
, ft
->cov
, M
);
3303 /* BUGFIX: may be changed */
3304 cov_min_max(ft
->cov
);
3305 /* cov->min = covariance_min; */
3306 /* cov->max = covariance_max; */
3312 gpiv_free_matrix (covariance
);
3315 * REMARK: fftw_cleanup really slows down!
3317 /* fftw_forget_wisdom(); */
3318 /* fftw_cleanup(); */
3333 ia_weight_gauss (gint int_size
,
3336 /**----------------------------------------------------------------------------
3338 * Weights Interrogation Area's
3341 gchar
*err_msg
= NULL
;
3346 assert (int_area
[0] != NULL
);
3348 for (i
= 0; i
< int_size
; i
++) {
3349 for (j
= 0; j
< int_size
; j
++) {
3350 weight
= exp( -16.0 * (((double)i
- (double)int_size
/ 2.0)
3351 * ((double)i
- (double)int_size
/ 2.0)
3352 + ((double)j
- (double)int_size
/ 2.0)
3353 * ((double)j
- (double)int_size
/ 2.0))
3354 / ((double)int_size
* (double)int_size
));
3355 int_area
[i
][j
] *= weight
;
3368 nearest_point (gint i
,
3375 /*-----------------------------------------------------------------------------
3376 * Test if current point_x is nearest from x
3379 gfloat dif
= abs (x
- point_x
);
3391 nearest_index (enum Position pos
,
3397 /*-----------------------------------------------------------------------------
3398 * Search nearest index from piv_data belonging to point (x, y)
3399 * in horizontal direction
3400 * pos_x/y index left/right, top/bottom of point
3404 gfloat min
= 10.0e4
;
3405 gboolean exist
= FALSE
;
3408 for (i
= 0; i
< vlength
; i
++) {
3411 && src_point
[i
] <= dest_point
) {
3412 nearest_point (i
, dest_point
, src_point
[i
], &min
,
3415 } else if (pos
== NEXT_LOWER
3417 && src_point
[i
- 1] < dest_point
) {
3419 nearest_point (i
- 1, dest_point
, src_point
[i
- 1], &min
,
3422 } else if (pos
== HIGHER
3423 && src_point
[i
] > dest_point
) {
3424 nearest_point (i
, dest_point
, src_point
[i
], &min
, index
, &exist
);
3426 } else if (pos
== NEXT_HIGHER
3428 && src_point
[i
+ 1] > dest_point
) {
3429 nearest_point (i
+ 1, dest_point
, src_point
[i
+ 1],
3443 bilinear_interpol (gdouble alpha_hor
,
3450 /*-----------------------------------------------------------------------------
3451 * Bilinear interpolation of src_dx_*
3458 gdouble dx
, dx_n
, dx_s
;
3461 dx_n
= (1.0 - alpha_hor
) * src_dx_nw
+ alpha_hor
* src_dx_ne
;
3462 dx_s
= (1.0 - alpha_hor
) * src_dx_sw
+ alpha_hor
* src_dx_se
;
3463 dx
= (1.0 - alpha_vert
) * dx_n
+ alpha_vert
* dx_s
;
3472 intpol_facts (gfloat
*src_point
,
3482 /*-----------------------------------------------------------------------------
3483 * calculates normalized interpolation factors for piv_data_src
3485 * _l (LOWER) is used for _w (WEST) or _n (NORTH),
3486 * _h (HIGHER) is used for _e (EAST) or _s (SOUTH)
3487 * _ll (NEXT_LOWER) is used for _ww (WEST_WEST) or _nn (NORTH_NORTH),
3488 * _hh (NEXT_HIGHER) is used for _ee (EAST_EAST) or _ss (SOUTH_SOUTH)
3491 gboolean
*exist_l
, *exist_h
, *exist_ll
, *exist_hh
;
3492 double *dist_l
, *dist_h
, *dist_ll
, *dist_hh
;
3497 exist_l
= gpiv_gbolvector (dest_vlength
);
3498 exist_h
= gpiv_gbolvector (dest_vlength
);
3499 exist_ll
= gpiv_gbolvector (dest_vlength
);
3500 exist_hh
= gpiv_gbolvector (dest_vlength
);
3502 dist_l
= gpiv_dvector (dest_vlength
);
3503 dist_h
= gpiv_dvector (dest_vlength
);
3504 dist_ll
= gpiv_dvector (dest_vlength
);
3505 dist_hh
= gpiv_dvector (dest_vlength
);
3508 * Searching adjacent and next to adjacent points of dest_point in src_point
3511 for (i
= 0; i
< dest_vlength
; i
++) {
3520 dist_l
[i
] = dest_point
[i
] - src_point
[index_l
[i
]];
3523 * To be used for extrapolation in negative direction
3524 * by applying higher and next to higher points of src data
3527 exist_hh
[i
] = FALSE
;
3534 dist_hh
[i
] = dest_point
[i
] - src_point
[index_hh
[i
]];
3548 dist_h
[i
] = dest_point
[i
] - src_point
[index_h
[i
]];
3552 * To be used for extrapolation in positive direction
3553 * by applying lower and next to lower points of src data
3556 exist_ll
[i
] = FALSE
;
3564 dist_ll
[i
] = dest_point
[i
] - src_point
[index_ll
[i
]];
3569 * calculating of weight factors for inter- or extrapolation
3572 if (exist_l
[i
] && exist_h
[i
]) {
3574 * Inner point: bilinear interpolation
3576 if (src_point
[index_l
[i
]] != src_point
[index_h
[i
]]) {
3577 alpha
[i
] = dist_l
[i
] /
3578 (src_point
[index_h
[i
]] - src_point
[index_l
[i
]]);
3584 } else if (exist_l
[i
] && exist_ll
[i
] && !exist_h
[i
]) {
3586 * extrapolation from two lower values
3588 if (src_point
[index_ll
[i
]] != src_point
[index_l
[i
]]) {
3589 alpha
[i
] = dist_ll
[i
] /
3590 (src_point
[index_l
[i
]] - src_point
[index_ll
[i
]]);
3591 index_h
[i
] = index_l
[i
];
3592 index_l
[i
] = index_ll
[i
];
3598 } else if (!exist_l
[i
] && exist_h
[i
] && exist_hh
[i
]) {
3600 * extrapolation from two higher values
3602 if (src_point
[index_hh
[i
]] != src_point
[index_h
[i
]]) {
3603 alpha
[i
] = dist_h
[i
] /
3604 (src_point
[index_hh
[i
]] - src_point
[index_h
[i
]]);
3605 index_l
[i
] = index_h
[i
];
3606 index_h
[i
] = index_hh
[i
];
3618 gpiv_free_gbolvector (exist_l
);
3619 gpiv_free_gbolvector (exist_h
);
3620 gpiv_free_gbolvector (exist_ll
);
3621 gpiv_free_gbolvector (exist_hh
);
3623 gpiv_free_dvector (dist_l
);
3624 gpiv_free_dvector (dist_h
);
3625 gpiv_free_dvector (dist_ll
);
3626 gpiv_free_dvector (dist_hh
);
3632 dxdy_at_new_grid_block (const GpivPivData
*piv_data_src
,
3633 GpivPivData
*piv_data_dest
,
3634 gint expansion_factor
,
3637 /*-----------------------------------------------------------------------------
3638 * Calculates displacements from old to new grid, that has been expanded by
3639 * factor 2 and avarages with smoothing window. Works only correct if all neighbours
3640 * at equal distances
3643 int i
, j
, k
, l
, ef
= expansion_factor
, sw
= smooth_window
;
3645 GpivPivData
*pd
= NULL
;
3647 pd
= gpiv_alloc_pivdata (piv_data_dest
->nx
, piv_data_dest
->ny
);
3650 * Copy blocks of 2x2 input data to pd
3652 for (i
= 0; i
< piv_data_src
->ny
; i
++) {
3653 for (j
= 0; j
< piv_data_src
->nx
; j
++) {
3654 for (k
= 0; k
< 2; k
++) {
3655 if (ef
* i
+k
< pd
->ny
) {
3656 for (l
= 0; l
< 2; l
++) {
3657 if (ef
* j
+l
< pd
->nx
) {
3658 pd
->dx
[ef
* i
+k
][ef
* j
+l
] = piv_data_src
->dx
[i
][j
];
3659 pd
->dy
[ef
* i
+k
][ef
* j
+l
] = piv_data_src
->dy
[i
][j
];
3670 for (i
= 0; i
< piv_data_src
->ny
; i
++) {
3671 for (j
= 0; j
< piv_data_src
->nx
; j
++) {
3673 for (k
= -sw
+ 1; k
< sw
; k
++) {
3674 if (i
+ k
> 0 && i
+ k
< pd
->ny
) {
3675 for (l
= -sw
+ 1; l
< sw
; l
++) {
3676 if (j
+ l
> 0 && j
+ l
< pd
->ny
) {
3678 piv_data_dest
->dx
[i
][j
] += pd
->dx
[i
+k
][j
+l
];
3679 piv_data_dest
->dy
[i
][j
] += pd
->dy
[i
+k
][j
+l
];
3684 piv_data_dest
->dx
[i
][j
] = piv_data_dest
->dx
[i
][j
] / (float)count
;
3685 piv_data_dest
->dy
[i
][j
] = piv_data_dest
->dx
[i
][j
] / (float)count
;
3689 gpiv_free_pivdata (pd
);
3695 update_pivdata_imgdeform_zoff (const GpivImage
*image
,
3696 GpivImage
*lo_image
,
3697 const GpivPivPar
*piv_par
,
3698 const GpivValidPar
*valid_par
,
3699 GpivPivData
*piv_data
,
3700 GpivPivData
*lo_piv_data
,
3703 gboolean
*cum_residu_reached
,
3705 gfloat
*sum_dxdy_old
,
3708 gboolean sweep_last
,
3711 /*-----------------------------------------------------------------------------
3712 * Validates and updates / renews pivdata and some other variables when image
3713 * deformation or zero-offset interrogation scheme is used
3716 gchar
*err_msg
= NULL
;
3723 gpiv_valid_errvec (lo_piv_data
, image
, piv_par
, valid_par
, ft
, TRUE
))
3729 if (piv_par
->int_scheme
== GPIV_IMG_DEFORM
) {
3732 * Update PIV estimators with those from the last interrogation
3733 * Resetting local PIV estimators for eventual next interrogation
3735 if ((err_msg
= gpiv_add_dxdy_pivdata (lo_piv_data
, piv_data
))
3739 if ((err_msg
= gpiv_0_pivdata (lo_piv_data
))
3745 * Deform image with updated PIV estimators.
3746 * First, copy local from original image.
3747 * Deform with newly updated PIV estimators.
3748 * Eventually write deformed image.
3751 if ((err_msg
= gpiv_cp_img_data (image
, lo_image
))
3756 if ((err_msg
= gpiv_imgproc_deform (lo_image
, piv_data
))
3763 if (sweep_last
&& verbose
) {
3766 my_utils_write_tmp_image (lo_image
, GPIV_DEFORMED_IMG_NAME
,
3767 "Writing deformed image to:"))
3778 * Renew PIV estimators with those from the last interrogation
3780 if ((err_msg
= gpiv_0_pivdata (piv_data
))
3784 if ((err_msg
= gpiv_add_dxdy_pivdata (lo_piv_data
, piv_data
))
3791 * Checking the relative cumulative residu for convergence
3792 * if final residu has been reached, cum_residu_reached will be set.
3794 if (isi_last
&& grid_last
) {
3795 *sum_dxdy_old
= *sum_dxdy
;
3797 gpiv_sum_dxdy_pivdata (piv_data
, sum_dxdy
);
3798 *cum_residu
= fabsf ((*sum_dxdy
- *sum_dxdy_old
) /
3799 ((gfloat
)piv_data
->nx
* (gfloat
)piv_data
->ny
));
3800 if (*cum_residu
< GPIV_CUM_RESIDU_MIN
) {
3801 *cum_residu_reached
= TRUE
;
3811 #undef NMIN_TO_INTERPOLATE
3815 static GpivPivData
*
3816 piv_interrogate_img__scatterv_pivdata(GpivPivData
*piv_data
)
3817 /*---------------------------------------------------------------------------------------
3818 * Scatter the piv_data equally over its rows.
3820 * The number of rows in piv_data need not be a multiple of nprocs.
3821 * Therefore, the first (piv_data->ny)%nprocs processes get
3822 * ceil(piv_data->ny/np/nprocs) rows, and the remaining processes get
3823 * floor(piv_data->ny)/nprocs) rows.
3826 GpivPivData
*pd
= NULL
;
3831 mpi
= alloc_mpi(piv_data
);
3832 MPI_Comm_size(MPI_COMM_WORLD
, mpi
->nprocs
);
3833 MPI_Comm_rank(MPI_COMM_WORLD
, mpi
->rank
);
3836 if (rank
==0) g_message ("gpiv_piv_interrogate_img:: nx=%d ny=%d nprocs = %d",
3837 piv_data
->nx
, piv_data
->ny
, mpi
->nprocs
);
3840 gpiv_free_pivdata (piv_data
);
3842 for (i
= 0; i
< mpi
->nprocs
; i
++) {
3843 if (mpi
->rank
== i
) pd
= gpiv_alloc_pivdata(mpi
->piv_data
->nx
, mpi
->counts
[i
] / mpi
->piv_data
->nx
);
3846 gpiv_piv_mpi_scatterv_pivdata (mpi
->piv_data
, pd
, mpi
->counts
, mpi
->displs
);
3855 static GpivPivData
*
3856 piv_interrogate_img__gatherv_pivdata(GpivPivData
*lo_piv_data
,
3857 GpivPivData
*piv_data
)
3858 /*---------------------------------------------------------------------------------------
3859 * Gathers the piv_data equally over its rows.
3860 * Counterpart of piv_interrogate_img__scatterv_pivdata
3862 * The number of rows in piv_data need not be a multiple of nprocs.
3863 * Therefore, the first (piv_data->ny)%nprocs processes get
3864 * ceil(piv_data->ny/np/nprocs) rows, and the remaining processes get
3865 * floor(piv_data->ny)/nprocs) rows.
3868 GpivPivData
*pd
= NULL
;
3872 mpi
= alloc_mpi(piv_data
);
3873 gpiv_piv_mpi_gatherv_pivdata (lo_piv_data
, mpi
->piv_data
, mpi
->counts
,
3875 pd
= gpiv_cp_pivdata (mpi
->piv_data
);
3886 alloc_mpi(GpivPivData
*piv_data
)
3888 Mpi
*mpi
= g_new0(Mpi
, 1);
3891 mpi
->counts
= gpiv_piv_mpi_compute_counts(piv_data
->nx
, piv_data
->ny
);
3892 mpi
->displs
= gpiv_piv_mpi_compute_displs(mpi
->counts
, piv_data
->nx
,
3894 mpi
->piv_data
= gpiv_cp_pivdata (piv_data
);
3905 gpiv_free_pivdata (mpi
->piv_data
);
3906 gpiv_free_ivector (mpi
->counts
);
3907 gpiv_free_ivector (mpi
->displs
);
3913 substr_noremain(guint n
,
3915 /*-------------------------------------------------------------------
3916 * Substracts 1 while remainder of n not equal to zero
3919 while (fmod((double) n
, (double) m
) != 0) {
3929 #endif /* ENABLE_MPI */
3931 gpiv_piv_gnuplot (const gchar
*title
,
3932 const gfloat gnuplot_scale
,
3933 const gchar
*GNUPLOT_DISPLAY_COLOR
,
3934 const guint GNUPLOT_DISPLAY_SIZE
,
3935 const GpivImagePar
*image_par
,
3936 const GpivPivPar
*piv_par
,
3937 const GpivPivData
*piv_data
3939 /*-----------------------------------------------------------------------------
3941 * Plots piv data as vectors on screen with gnuplot
3944 * fname: file name containing plot
3945 * title: title of plot
3946 * gnuplot_scale: vector scale
3947 * GNUPLOT_DISPLAY_COLOR: display color of window containing graph
3948 * GNUPLOT_DISPLAY_SIZE: display size of window containing graph
3949 * image_par: image parameters
3950 * piv_par: piv evaluation parameters
3951 * piv_data: piv data
3952 * RCSID: program name and version that interrogated the image
3957 * NULL on success or *err_msg on failure
3958 *---------------------------------------------------------------------------*/
3960 gchar
*err_msg
= NULL
;
3962 const gchar
*tmp_dir
= g_get_tmp_dir ();
3963 gchar
*fname_loc
= "gpiv_gnuplot.cmd";
3964 gchar command
[GPIV_MAX_CHARS
];
3965 gchar fname_cmd
[GPIV_MAX_CHARS
];
3969 snprintf (fname_cmd
, GPIV_MAX_CHARS
, "%s/%s", tmp_dir
, fname_loc
);
3971 if ((fp_cmd
= fopen (fname_cmd
, "w")) == NULL
)
3972 gpiv_error ("gpiv_piv_gnuplot: error: Failure opening %s for output",
3975 fprintf (fp_cmd
, "set xlabel \"x (pixels)\"");
3976 fprintf (fp_cmd
, "\nset ylabel \"y (pixels)\"");
3977 fprintf (fp_cmd
, "\nset title \"Piv of %s\" ", title
);
3979 for (i
= 0; i
< piv_data
->ny
; i
++) {
3980 for (j
= 0; j
< piv_data
->nx
; j
++) {
3981 fprintf (fp_cmd
, "\nset arrow from %f, %f to %f, %f",
3982 piv_data
->point_x
[i
][j
],
3983 piv_data
->point_y
[i
][j
],
3984 piv_data
->point_x
[i
][j
] + piv_data
->dx
[i
][j
]
3986 piv_data
->point_y
[i
][j
] + piv_data
->dy
[i
][j
]
3991 fprintf (fp_cmd
, "\nset nokey");
3992 if (piv_par
->int_geo
== GPIV_AOI
) {
3993 fprintf (fp_cmd
, "\nplot [%d:%d] [%d:%d] %d",
3994 piv_par
->col_start
, piv_par
->col_end
,
3995 piv_par
->row_start
, piv_par
->row_end
,
3998 fprintf (fp_cmd
, "\nplot [%d:%d] [%d:%d] %d",
3999 0, image_par
->ncolumns
,
4000 0, image_par
->nrows
,
4004 fprintf (fp_cmd
, "\npause -1 \"Hit return to exit\"");
4005 fprintf (fp_cmd
, "\nquit");
4008 snprintf (command
, GPIV_MAX_CHARS
,
4009 "gnuplot -bg %s -geometry %dx%d %s",
4010 GNUPLOT_DISPLAY_COLOR
, GNUPLOT_DISPLAY_SIZE
, GNUPLOT_DISPLAY_SIZE
,
4013 if (system (command
) != 0) {
4014 err_msg
= "gpiv_piv_gnuplot: could not exec shell command";
4015 gpiv_warning ("%s", err_msg
);
4026 gpiv_histo_gnuplot (const gchar
*fname_out
,
4028 const gchar
*GNUPLOT_DISPLAY_COLOR
,
4029 const gint GNUPLOT_DISPLAY_SIZE
4031 /*-----------------------------------------------------------------------------
4033 * Plots histogram on screen with gnuplot
4036 * fname_out: output filename
4038 * GNUPLOT_DISPLAY_COLOR: display color of window containing graph
4039 * GNUPLOT_DISPLAY_SIZE: display size of window containing graph
4044 * NULL on success or *err_msg on failure
4045 *---------------------------------------------------------------------------*/
4047 gchar
*err_msg
= NULL
;
4049 const gchar
*tmp_dir
= g_get_tmp_dir ();
4050 gchar
*fname_loc
= "gpiv_gnuplot.cmd";
4051 gchar
*function_name
= "gpiv_histo_gnuplot";
4052 gchar fname_cmd
[GPIV_MAX_CHARS
];
4053 gchar command
[GPIV_MAX_CHARS
];
4056 snprintf (fname_cmd
, GPIV_MAX_CHARS
, "%s/%s", tmp_dir
, fname_loc
);
4057 if ((fp_cmd
= fopen (fname_cmd
,"w")) == NULL
) {
4058 err_msg
= "GPIV_HISTO_GNUPLOT: Failure opening for output";
4059 gpiv_warning ("%s", err_msg
);
4063 fprintf (fp_cmd
, "set xlabel \"residu (pixels)\"");
4064 fprintf (fp_cmd
, "\nset ylabel \"frequency\"");
4065 fprintf (fp_cmd
, "\nplot \"%s\" title \"%s\" with boxes",
4068 fprintf (fp_cmd
, "\npause -1 \"Hit return to exit\"");
4069 fprintf (fp_cmd
, "\nquit");
4074 snprintf (command
, GPIV_MAX_CHARS
, "gnuplot -bg %s -geometry %dx%d %s",
4075 GNUPLOT_DISPLAY_COLOR
, GNUPLOT_DISPLAY_SIZE
,
4076 GNUPLOT_DISPLAY_SIZE
, fname_cmd
);
4078 if (system (command
) != 0) {
4079 g_warning ("%s:%s could not exec shell command",
4080 LIBNAME
, function_name
);
4092 gpiv_histo (const GpivPivData
*data
,
4095 /*-----------------------------------------------------------------------------
4097 * Calculates histogram from GpivPivData (NOT from ScalarData!!)
4103 * klass: Output data
4106 *---------------------------------------------------------------------------*/
4109 gint nx
= data
->nx
, ny
= data
->ny
, **peak_no
= data
->peak_no
;
4110 float **snr
= data
->snr
;
4112 float *bound
= klass
->bound
, *centre
= klass
->centre
;
4113 gint
*count
= klass
->count
, nbins
= klass
->nbins
;
4116 g_return_if_fail (data
->point_x
!= NULL
); /* gpiv_error ("data->point_x not allocated"); */
4117 g_return_if_fail (data
->point_y
!= NULL
); /* gpiv_error ("data->point_y not allocated"); */
4118 g_return_if_fail (data
->dx
!= NULL
); /* gpiv_error ("data->dx not allocated"); */
4119 g_return_if_fail (data
->dy
!= NULL
); /* gpiv_error ("data->dy not allocated"); */
4120 g_return_if_fail (data
->snr
!= NULL
); /* gpiv_error ("data->snr not allocated"); */
4121 g_return_if_fail (data
->peak_no
!= NULL
); /* gpiv_error ("ata->peak_no not allocated"); */
4123 g_return_if_fail (klass
->count
!= NULL
); /* gpiv_error ("klass->count not allocated"); */
4124 g_return_if_fail (klass
->bound
!= NULL
); /* gpiv_error ("klass->bound not allocated"); */
4125 g_return_if_fail (klass
->centre
!= NULL
); /* gpiv_error ("klass->centre not allocated"); */
4127 klass
->min
= 10.0e+9, klass
->max
= -10.0e+9;
4129 * find min and max value
4131 for (i
= 0; i
< ny
; i
++) {
4132 for (j
= 0; j
< nx
; j
++) {
4133 if (peak_no
[i
][j
] != -1) {
4135 if (snr
[i
][j
] < klass
->min
)
4136 klass
->min
= snr
[i
][j
];
4137 if (snr
[i
][j
] >= klass
->max
)
4138 klass
->max
= snr
[i
][j
];
4147 * Calculating boundaries of bins
4149 delta
= (klass
->max
- klass
->min
) / nbins
;
4150 for (i
= 0; i
< nbins
; i
++) {
4151 centre
[i
] = klass
->min
+ delta
/ 2.0 + (float) i
*delta
;
4155 for (i
= 0; i
< nbins
; i
++) {
4156 bound
[i
] = klass
->min
+ (float) i
* delta
;
4162 * Sorting of snr data in bins
4164 for (i
= 0; i
< ny
; i
++) {
4165 for (j
= 0; j
< nx
; j
++) {
4166 if (peak_no
[i
][j
] != -1) {
4168 for (k
= 0; k
< nbins
; k
++) {
4169 if ((snr
[i
][j
] > bound
[k
])
4170 && (snr
[i
][j
] <= bound
[k
] + delta
)) {
4171 count
[k
] = count
[k
] + 1;
4183 gpiv_cumhisto (const GpivPivData
*data
,
4186 /*-----------------------------------------------------------------------------
4188 * Calculates cumulative histogram from GpivPivData (NOT from ScalarData!!)
4194 * klass: Output data
4197 *---------------------------------------------------------------------------*/
4200 gint nx
= data
->nx
, ny
= data
->ny
, **peak_no
= data
->peak_no
;
4201 float **snr
= data
->snr
;
4203 float *bound
= klass
->bound
, *centre
= klass
->centre
;
4204 gint
*count
= klass
->count
, nbins
= klass
->nbins
;
4207 g_return_if_fail (data
->point_x
!= NULL
); /* gpiv_error ("data->point_x not allocated"); */
4208 g_return_if_fail (data
->point_y
!= NULL
); /* gpiv_error ("data->point_y not allocated"); */
4209 g_return_if_fail (data
->dx
!= NULL
); /* gpiv_error ("data->dx not allocated"); */
4210 g_return_if_fail (data
->dy
!= NULL
); /* gpiv_error ("data->dy not allocated"); */
4211 g_return_if_fail (data
->snr
!= NULL
); /* gpiv_error ("data->snr not allocated"); */
4212 g_return_if_fail (data
->peak_no
!= NULL
); /* gpiv_error ("ata->peak_no not allocated"); */
4214 g_return_if_fail (klass
->count
!= NULL
); /* gpiv_error ("klass->count not allocated"); */
4215 g_return_if_fail (klass
->bound
!= NULL
); /* gpiv_error ("klass->bound not allocated"); */
4216 g_return_if_fail (klass
->centre
!= NULL
); /* gpiv_error ("klass->centre not allocated"); */
4218 klass
->min
= 10e+9, klass
->max
= -10e+9;
4220 * find min and max value
4222 for (i
= 0; i
< ny
; i
++) {
4223 for (j
= 0; j
< nx
; j
++) {
4224 if (peak_no
[i
][j
] != -1) {
4226 if (snr
[i
][j
] < klass
->min
)
4227 klass
->min
= snr
[i
][j
];
4228 if (snr
[i
][j
] >= klass
->max
)
4229 klass
->max
= snr
[i
][j
];
4237 * Calculating boundaries of bins
4239 delta
= (klass
->max
- klass
->min
) / nbins
;
4240 for (i
= 0; i
< nbins
; i
++) {
4241 centre
[i
] = klass
->min
+ delta
/ 2.0 + (float) i
*delta
;
4245 for (i
= 0; i
< nbins
; i
++) {
4246 bound
[i
] = klass
->min
+ (float) i
* delta
;
4251 * Sorting of snr data in bins
4253 for (i
= 0; i
< ny
; i
++) {
4254 for (j
= 0; j
< nx
; j
++) {
4255 if (peak_no
[i
][j
] != -1) {
4257 for (k
= 0; k
< nbins
; k
++) {
4258 if (snr
[i
][j
] <= bound
[k
] + delta
) {
4259 count
[k
] = count
[k
] + 1;