pivtools 0.1.3__cp311-cp311-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pivtools-0.1.3.dist-info/METADATA +222 -0
- pivtools-0.1.3.dist-info/RECORD +127 -0
- pivtools-0.1.3.dist-info/WHEEL +5 -0
- pivtools-0.1.3.dist-info/entry_points.txt +3 -0
- pivtools-0.1.3.dist-info/top_level.txt +3 -0
- pivtools_cli/__init__.py +5 -0
- pivtools_cli/_build_marker.c +25 -0
- pivtools_cli/_build_marker.cp311-win_amd64.pyd +0 -0
- pivtools_cli/cli.py +225 -0
- pivtools_cli/example.py +139 -0
- pivtools_cli/lib/PIV_2d_cross_correlate.c +334 -0
- pivtools_cli/lib/PIV_2d_cross_correlate.h +22 -0
- pivtools_cli/lib/common.h +36 -0
- pivtools_cli/lib/interp2custom.c +146 -0
- pivtools_cli/lib/interp2custom.h +48 -0
- pivtools_cli/lib/peak_locate_gsl.c +711 -0
- pivtools_cli/lib/peak_locate_gsl.h +40 -0
- pivtools_cli/lib/peak_locate_gsl_print.c +736 -0
- pivtools_cli/lib/peak_locate_lm.c +751 -0
- pivtools_cli/lib/peak_locate_lm.h +27 -0
- pivtools_cli/lib/xcorr.c +342 -0
- pivtools_cli/lib/xcorr.h +31 -0
- pivtools_cli/lib/xcorr_cache.c +78 -0
- pivtools_cli/lib/xcorr_cache.h +26 -0
- pivtools_cli/piv/interp2custom/interp2custom.py +69 -0
- pivtools_cli/piv/piv.py +240 -0
- pivtools_cli/piv/piv_backend/base.py +825 -0
- pivtools_cli/piv/piv_backend/cpu_instantaneous.py +1005 -0
- pivtools_cli/piv/piv_backend/factory.py +28 -0
- pivtools_cli/piv/piv_backend/gpu_instantaneous.py +15 -0
- pivtools_cli/piv/piv_backend/infilling.py +445 -0
- pivtools_cli/piv/piv_backend/outlier_detection.py +306 -0
- pivtools_cli/piv/piv_backend/profile_cpu_instantaneous.py +230 -0
- pivtools_cli/piv/piv_result.py +40 -0
- pivtools_cli/piv/save_results.py +342 -0
- pivtools_cli/piv_cluster/cluster.py +108 -0
- pivtools_cli/preprocessing/filters.py +399 -0
- pivtools_cli/preprocessing/preprocess.py +79 -0
- pivtools_cli/tests/helpers.py +107 -0
- pivtools_cli/tests/instantaneous_piv/test_piv_integration.py +167 -0
- pivtools_cli/tests/instantaneous_piv/test_piv_integration_multi.py +553 -0
- pivtools_cli/tests/preprocessing/test_filters.py +41 -0
- pivtools_core/__init__.py +5 -0
- pivtools_core/config.py +703 -0
- pivtools_core/config.yaml +135 -0
- pivtools_core/image_handling/__init__.py +0 -0
- pivtools_core/image_handling/load_images.py +464 -0
- pivtools_core/image_handling/readers/__init__.py +53 -0
- pivtools_core/image_handling/readers/generic_readers.py +50 -0
- pivtools_core/image_handling/readers/lavision_reader.py +190 -0
- pivtools_core/image_handling/readers/registry.py +24 -0
- pivtools_core/paths.py +49 -0
- pivtools_core/vector_loading.py +248 -0
- pivtools_gui/__init__.py +3 -0
- pivtools_gui/app.py +687 -0
- pivtools_gui/calibration/__init__.py +0 -0
- pivtools_gui/calibration/app/__init__.py +0 -0
- pivtools_gui/calibration/app/views.py +1186 -0
- pivtools_gui/calibration/calibration_planar/planar_calibration_production.py +570 -0
- pivtools_gui/calibration/vector_calibration_production.py +544 -0
- pivtools_gui/config.py +703 -0
- pivtools_gui/image_handling/__init__.py +0 -0
- pivtools_gui/image_handling/load_images.py +464 -0
- pivtools_gui/image_handling/readers/__init__.py +53 -0
- pivtools_gui/image_handling/readers/generic_readers.py +50 -0
- pivtools_gui/image_handling/readers/lavision_reader.py +190 -0
- pivtools_gui/image_handling/readers/registry.py +24 -0
- pivtools_gui/masking/__init__.py +0 -0
- pivtools_gui/masking/app/__init__.py +0 -0
- pivtools_gui/masking/app/views.py +123 -0
- pivtools_gui/paths.py +49 -0
- pivtools_gui/piv_runner.py +261 -0
- pivtools_gui/pivtools.py +58 -0
- pivtools_gui/plotting/__init__.py +0 -0
- pivtools_gui/plotting/app/__init__.py +0 -0
- pivtools_gui/plotting/app/views.py +1671 -0
- pivtools_gui/plotting/plot_maker.py +220 -0
- pivtools_gui/post_processing/POD/__init__.py +0 -0
- pivtools_gui/post_processing/POD/app/__init__.py +0 -0
- pivtools_gui/post_processing/POD/app/views.py +647 -0
- pivtools_gui/post_processing/POD/pod_decompose.py +979 -0
- pivtools_gui/post_processing/POD/views.py +1096 -0
- pivtools_gui/post_processing/__init__.py +0 -0
- pivtools_gui/static/404.html +1 -0
- pivtools_gui/static/_next/static/chunks/117-d5793c8e79de5511.js +2 -0
- pivtools_gui/static/_next/static/chunks/484-cfa8b9348ce4f00e.js +1 -0
- pivtools_gui/static/_next/static/chunks/869-320a6b9bdafbb6d3.js +1 -0
- pivtools_gui/static/_next/static/chunks/app/_not-found/page-12f067ceb7415e55.js +1 -0
- pivtools_gui/static/_next/static/chunks/app/layout-b907d5f31ac82e9d.js +1 -0
- pivtools_gui/static/_next/static/chunks/app/page-334cc4e8444cde2f.js +1 -0
- pivtools_gui/static/_next/static/chunks/fd9d1056-ad15f396ddf9b7e5.js +1 -0
- pivtools_gui/static/_next/static/chunks/framework-f66176bb897dc684.js +1 -0
- pivtools_gui/static/_next/static/chunks/main-a1b3ced4d5f6d998.js +1 -0
- pivtools_gui/static/_next/static/chunks/main-app-8a63c6f5e7baee11.js +1 -0
- pivtools_gui/static/_next/static/chunks/pages/_app-72b849fbd24ac258.js +1 -0
- pivtools_gui/static/_next/static/chunks/pages/_error-7ba65e1336b92748.js +1 -0
- pivtools_gui/static/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- pivtools_gui/static/_next/static/chunks/webpack-4a8ca7c99e9bb3d8.js +1 -0
- pivtools_gui/static/_next/static/css/7d3f2337d7ea12a5.css +3 -0
- pivtools_gui/static/_next/static/vQeR20OUdSSKlK4vukC4q/_buildManifest.js +1 -0
- pivtools_gui/static/_next/static/vQeR20OUdSSKlK4vukC4q/_ssgManifest.js +1 -0
- pivtools_gui/static/file.svg +1 -0
- pivtools_gui/static/globe.svg +1 -0
- pivtools_gui/static/grid.svg +8 -0
- pivtools_gui/static/index.html +1 -0
- pivtools_gui/static/index.txt +8 -0
- pivtools_gui/static/next.svg +1 -0
- pivtools_gui/static/vercel.svg +1 -0
- pivtools_gui/static/window.svg +1 -0
- pivtools_gui/stereo_reconstruction/__init__.py +0 -0
- pivtools_gui/stereo_reconstruction/app/__init__.py +0 -0
- pivtools_gui/stereo_reconstruction/app/views.py +1985 -0
- pivtools_gui/stereo_reconstruction/stereo_calibration_production.py +606 -0
- pivtools_gui/stereo_reconstruction/stereo_reconstruction_production.py +544 -0
- pivtools_gui/utils.py +63 -0
- pivtools_gui/vector_loading.py +248 -0
- pivtools_gui/vector_merging/__init__.py +1 -0
- pivtools_gui/vector_merging/app/__init__.py +1 -0
- pivtools_gui/vector_merging/app/views.py +759 -0
- pivtools_gui/vector_statistics/app/__init__.py +1 -0
- pivtools_gui/vector_statistics/app/views.py +710 -0
- pivtools_gui/vector_statistics/ensemble_statistics.py +49 -0
- pivtools_gui/vector_statistics/instantaneous_statistics.py +311 -0
- pivtools_gui/video_maker/__init__.py +0 -0
- pivtools_gui/video_maker/app/__init__.py +0 -0
- pivtools_gui/video_maker/app/views.py +436 -0
- pivtools_gui/video_maker/video_maker.py +662 -0
|
@@ -0,0 +1,736 @@
|
|
|
1
|
+
#include "peak_locate_gsl.h"
|
|
2
|
+
#include "common.h"
|
|
3
|
+
#include <stdlib.h>
|
|
4
|
+
#include <string.h>
|
|
5
|
+
#include <math.h>
|
|
6
|
+
#include <float.h>
|
|
7
|
+
|
|
8
|
+
/******************************************************************************
|
|
9
|
+
* Function: lsqpeaklocate
|
|
10
|
+
* ---------------------------------------------------------------------------
|
|
11
|
+
* Description:
|
|
12
|
+
* This function locates the peaks in a cross-correlation matrix using a
|
|
13
|
+
* least-squares fitting approach. The function finds the specified number
|
|
14
|
+
* of peak locations (`nPeaks`) and estimates the peak's position using
|
|
15
|
+
* different fitting types, depending on the specified `iFitType`. The function
|
|
16
|
+
* returns the locations of the peaks in the `peak_loc` array and optionally
|
|
17
|
+
* provides the estimated standard deviation of the peak using `std_dev`.
|
|
18
|
+
*
|
|
19
|
+
* The function performs a 2D search to locate the maximum points in the
|
|
20
|
+
* cross-correlation matrix (`xcorr`). For each peak, the function applies
|
|
21
|
+
* least-squares fitting to refine the location estimate.
|
|
22
|
+
*
|
|
23
|
+
* The method of fitting is determined by the `iFitType` parameter, which
|
|
24
|
+
* specifies different fitting models based on the number of degrees of freedom
|
|
25
|
+
* (DOF).
|
|
26
|
+
*
|
|
27
|
+
* ---------------------------------------------------------------------------
|
|
28
|
+
* Inputs:
|
|
29
|
+
* float *xcorr : Pointer to the 2D array representing the cross-correlation
|
|
30
|
+
* matrix. The matrix should be of size [N[0], N[1]] where
|
|
31
|
+
* N[0] is the number of rows and N[1] is the number of columns.
|
|
32
|
+
*
|
|
33
|
+
* int *N : Pointer to an array of size 2 where:
|
|
34
|
+
* - N[0] : The number of rows in the xcorr matrix.
|
|
35
|
+
* - N[1] : The number of columns in the xcorr matrix.
|
|
36
|
+
*
|
|
37
|
+
* int nPeaks : The number of peaks to locate in the cross-correlation matrix.
|
|
38
|
+
* Should be a positive integer (e.g., 1 for a single peak).
|
|
39
|
+
*
|
|
40
|
+
* int iFitType : Specifies the type of least-squares fit to use for peak
|
|
41
|
+
* localization. Valid options include:
|
|
42
|
+
* - 3 : Use a 3-point least-squares estimator.
|
|
43
|
+
* - 4 : Use a 4-DOF Gaussian fit.
|
|
44
|
+
* - 5 : Use a 5-DOF Gaussian fit.
|
|
45
|
+
* - 6 : Use a 6-DOF Gaussian fit.
|
|
46
|
+
*
|
|
47
|
+
* ---------------------------------------------------------------------------
|
|
48
|
+
* Outputs:
|
|
49
|
+
* float *peak_loc : Pointer to an array where the locations of the peaks
|
|
50
|
+
* will be stored. It must be able to hold `nPeaks * 2` elements
|
|
51
|
+
* (x, y coordinates for each peak).
|
|
52
|
+
*
|
|
53
|
+
* float *std_dev : Pointer to a variable where the standard deviation of
|
|
54
|
+
* the peak location will be stored (optional, can be NULL).
|
|
55
|
+
*
|
|
56
|
+
* ---------------------------------------------------------------------------
|
|
57
|
+
* Procedures:
|
|
58
|
+
* 1. Parse the cross-correlation matrix and search for the highest values (peaks).
|
|
59
|
+
* 2. For each identified peak, refine the location using the least-squares
|
|
60
|
+
* fitting method based on the `iFitType` parameter.
|
|
61
|
+
* 3. Store the estimated peak locations in the `peak_loc` array.
|
|
62
|
+
* 4. Optionally, compute the standard deviation of the peak location and
|
|
63
|
+
* store it in `std_dev`.
|
|
64
|
+
*
|
|
65
|
+
* ---------------------------------------------------------------------------
|
|
66
|
+
* Example Usage:
|
|
67
|
+
* float xcorr[10][10]; // Cross-correlation matrix of size 10x10
|
|
68
|
+
* int N[2] = {10, 10}; // N[0] = 10 (rows), N[1] = 10 (columns)
|
|
69
|
+
* float peak_loc[2]; // Array to store peak locations (x, y)
|
|
70
|
+
* int nPeaks = 1; // Looking for 1 peak
|
|
71
|
+
* int iFitType = 4; // Use 4-point Gaussian fitting
|
|
72
|
+
* float std_dev; // Variable to store the peak standard deviation
|
|
73
|
+
*
|
|
74
|
+
* lsqpeaklocate(&xcorr[0][0], N, peak_loc, nPeaks, iFitType, &std_dev);
|
|
75
|
+
* printf("Peak at location: (%f, %f)\n", peak_loc[0], peak_loc[1]);
|
|
76
|
+
* printf("Peak standard deviation: %f\n", std_dev);
|
|
77
|
+
*
|
|
78
|
+
*****************************************************************************/
|
|
79
|
+
|
|
80
|
+
void lsqpeaklocate(const float *xcorr, const int *N, float *peak_loc, int nPeaks, int iFitType, float *std_dev)
|
|
81
|
+
{
|
|
82
|
+
int i, j, iPeak, idx;
|
|
83
|
+
int i0, j0;
|
|
84
|
+
float *xcorr_copy;
|
|
85
|
+
float fPeakHeight;
|
|
86
|
+
float subxcorr[PKSIZE_X][PKSIZE_Y];
|
|
87
|
+
float fitval[PKSIZE_X][PKSIZE_Y];
|
|
88
|
+
int Nsub[2];
|
|
89
|
+
float peak[2];
|
|
90
|
+
float sig[3];
|
|
91
|
+
if (!xcorr) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (!N) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (!peak_loc) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (!std_dev) {
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Validate N array
|
|
104
|
+
if (N[0] <= 0 || N[1] <= 0) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Validate number of peaks
|
|
109
|
+
if (nPeaks <= 0) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Validate fit type
|
|
114
|
+
if (iFitType < 3 || iFitType > 6) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
/* make a copy of xcorr that we can manipulate */
|
|
118
|
+
xcorr_copy = (float*)malloc(sizeof(float) * N[0]*N[1]);
|
|
119
|
+
memcpy(xcorr_copy, xcorr, N[0]*N[1]*sizeof(float));
|
|
120
|
+
Nsub[0] = PKSIZE_X;
|
|
121
|
+
Nsub[1] = PKSIZE_Y;
|
|
122
|
+
|
|
123
|
+
/* iterate over peaks */
|
|
124
|
+
for(iPeak = 0; iPeak < nPeaks; ++iPeak)
|
|
125
|
+
{
|
|
126
|
+
/* find maximum value in array
|
|
127
|
+
* only search for peaks in range
|
|
128
|
+
* N[0]/8 <= i < N[0]*7/8
|
|
129
|
+
* N[1]/8 <= j < N[1]*7/8
|
|
130
|
+
*/
|
|
131
|
+
i0 = j0 = 0;
|
|
132
|
+
fPeakHeight = 0;
|
|
133
|
+
for(i = N[0]/8; i < N[0]*7/8; ++i)
|
|
134
|
+
{
|
|
135
|
+
for(j = N[1]/8; j < N[1]*7/8; ++j)
|
|
136
|
+
{
|
|
137
|
+
if(xcorr_copy[SUB2IND_2D(i, j, N[0])] > fPeakHeight)
|
|
138
|
+
{
|
|
139
|
+
fPeakHeight = xcorr_copy[SUB2IND_2D(i, j, N[0])];
|
|
140
|
+
i0 = i;
|
|
141
|
+
j0 = j;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* error out if peak height is not positive */
|
|
147
|
+
if(fPeakHeight <= 0)
|
|
148
|
+
{
|
|
149
|
+
peak_loc[SUB2IND_2D(0, iPeak, 3)] = NAN;
|
|
150
|
+
peak_loc[SUB2IND_2D(1, iPeak, 3)] = NAN;
|
|
151
|
+
peak_loc[SUB2IND_2D(2, iPeak, 3)] = 0;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* error out if too close to the edges, or is not a local maximum */
|
|
156
|
+
if( i0 < (PKSIZE_X-1)/2 || i0 >= N[0]-(PKSIZE_X-1)/2
|
|
157
|
+
|| j0 < (PKSIZE_Y-1)/2 || j0 >= N[1]-(PKSIZE_Y-1)/2
|
|
158
|
+
|| fPeakHeight <= xcorr_copy[SUB2IND_2D(i0-1, j0 , N[0])]
|
|
159
|
+
|| fPeakHeight <= xcorr_copy[SUB2IND_2D(i0+1, j0 , N[0])]
|
|
160
|
+
|| fPeakHeight <= xcorr_copy[SUB2IND_2D(i0 , j0-1, N[0])]
|
|
161
|
+
|| fPeakHeight <= xcorr_copy[SUB2IND_2D(i0 , j0+1, N[0])] )
|
|
162
|
+
{
|
|
163
|
+
peak_loc[SUB2IND_2D(0, iPeak, 3)] = NAN;
|
|
164
|
+
peak_loc[SUB2IND_2D(1, iPeak, 3)] = NAN;
|
|
165
|
+
peak_loc[SUB2IND_2D(2, iPeak, 3)] = 0;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* copy into C-style matrix */
|
|
170
|
+
for(i = 0; i < PKSIZE_X; ++i)
|
|
171
|
+
{
|
|
172
|
+
for(j = 0; j < PKSIZE_Y; ++j)
|
|
173
|
+
{
|
|
174
|
+
subxcorr[i][j] = xcorr_copy[SUB2IND_2D(i0 + i - (PKSIZE_X-1)/2, j0 + j - (PKSIZE_Y-1)/2, N[0])];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* perform least-squares fit to get peak location
|
|
179
|
+
* only bother using high-order scheme for first peak
|
|
180
|
+
*/
|
|
181
|
+
peakfit(&subxcorr[0][0], Nsub, peak, &fitval[0][0], iPeak ? 3 : iFitType, sig);
|
|
182
|
+
|
|
183
|
+
/* save peak location and subtract fit from correlation plane
|
|
184
|
+
* note this could mean that the correlation plane is not strictly positive-valued everywhere
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
peak_loc[SUB2IND_2D(0, iPeak, 3)] = peak[0] + i0;
|
|
188
|
+
peak_loc[SUB2IND_2D(1, iPeak, 3)] = peak[1] + j0;
|
|
189
|
+
peak_loc[SUB2IND_2D(2, iPeak, 3)] = fPeakHeight;
|
|
190
|
+
std_dev[SUB2IND_2D(0, iPeak, 3)] = sig[0];
|
|
191
|
+
std_dev[SUB2IND_2D(1, iPeak, 3)] = sig[1];
|
|
192
|
+
std_dev[SUB2IND_2D(2, iPeak, 3)] = sig[2];
|
|
193
|
+
for(i = 0; i < PKSIZE_X; ++i)
|
|
194
|
+
{
|
|
195
|
+
for(j = 0; j < PKSIZE_Y; ++j)
|
|
196
|
+
{
|
|
197
|
+
idx = SUB2IND_2D( i0 + i - (PKSIZE_X-1)/2, j0 + j - (PKSIZE_Y-1)/2, N[0]);
|
|
198
|
+
xcorr_copy[idx] = MAX(0, xcorr_copy[idx] - fitval[i][j]);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/* clean up and exit */
|
|
204
|
+
free(xcorr_copy);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/****************************************************
|
|
209
|
+
* void peakfit(const float *xcorr, const int *N, float *peak_loc, float *fitval, int iFitType)
|
|
210
|
+
*
|
|
211
|
+
* finds the sub-grid location of the nPeaks largest correlation-peaks in
|
|
212
|
+
* the two-dimensional array xcorr
|
|
213
|
+
*
|
|
214
|
+
* xcorr is a two-dimensional array with an odd number of elements along each dimension
|
|
215
|
+
* typically five
|
|
216
|
+
* such that the element at the centre is at i = j = 0
|
|
217
|
+
*
|
|
218
|
+
* the sub-grid location is returned in peak_loc in this coordinate system
|
|
219
|
+
* the best fit function is returned in fitval for the fit parameters which best match the correlation peak
|
|
220
|
+
*
|
|
221
|
+
* the fit type to be used (3, 4, 5 or 6 degree of freedom) is specified by iFitType
|
|
222
|
+
*
|
|
223
|
+
*/
|
|
224
|
+
|
|
225
|
+
void peakfit(const float *xcorr, const int *N, float *peak_loc, float *fitval, int iFitType, float *sig)
|
|
226
|
+
{
|
|
227
|
+
float x_fit[3];
|
|
228
|
+
float y_fit[3];
|
|
229
|
+
int i;
|
|
230
|
+
int info, status;
|
|
231
|
+
float A, sx, sy, sx_lb, sy_lb, sx_ub, sy_ub, A_lb, A_ub;
|
|
232
|
+
|
|
233
|
+
size_t n_data;
|
|
234
|
+
double X[6];
|
|
235
|
+
pkdata pd;
|
|
236
|
+
gsl_vector *gsl_F, *gsl_X;
|
|
237
|
+
gsl_vector_view gsl_X0;
|
|
238
|
+
|
|
239
|
+
/* make initial guess of sub-pixel location and gaussian peak size
|
|
240
|
+
* using three-point estimator
|
|
241
|
+
*/
|
|
242
|
+
for(i = 0; i < 3; ++i)
|
|
243
|
+
{
|
|
244
|
+
x_fit[i] = xcorr[ (i - 1 + (N[0]-1)/2) *N[1]
|
|
245
|
+
+ (N[1]-1)/2 ];
|
|
246
|
+
y_fit[i] = xcorr[ (N[0]-1)/2 *N[1]
|
|
247
|
+
+ (i - 1 + (N[1]-1)/2) ];
|
|
248
|
+
x_fit[i] = (float)log((x_fit[i] < FLT_EPSILON) ? FLT_EPSILON : x_fit[i]);
|
|
249
|
+
y_fit[i] = (float)log((y_fit[i] < FLT_EPSILON) ? FLT_EPSILON : y_fit[i]);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/* peak location in i direction is at i0 = numer/denom
|
|
253
|
+
* numer = ln(R(i-1), j) - ln(R(i+1), j)
|
|
254
|
+
* ~= -4 (i0 - i) / sigma_x^2
|
|
255
|
+
* denom = 2ln(R(i-1, j)) - 4ln(R(i,j)) + 2ln(R(i+1,j))
|
|
256
|
+
* ~= -4 / sigma_x^2
|
|
257
|
+
* when R is modelled as a gaussian R ~ exp(-(i-i0)/sigma_x^2)
|
|
258
|
+
*/
|
|
259
|
+
peak_loc[0] = (x_fit[0] - x_fit[2]) / (2*x_fit[0] - 4*x_fit[1] + 2*x_fit[2]);
|
|
260
|
+
peak_loc[1] = (y_fit[0] - y_fit[2]) / (2*y_fit[0] - 4*y_fit[1] + 2*y_fit[2]);
|
|
261
|
+
A = xcorr[(N[0]-1)/2*N[1] + (N[1]-1)/2];
|
|
262
|
+
sx = (float)sqrt(-4 / (2*x_fit[0] - 4*x_fit[1] + 2*x_fit[2]));
|
|
263
|
+
sy = (float)sqrt(-4 / (2*y_fit[0] - 4*y_fit[1] + 2*y_fit[2]));
|
|
264
|
+
sx_lb = 0.25; sy_lb = 0.25;
|
|
265
|
+
sx_ub = 2*sx; sy_ub = 2*sy;
|
|
266
|
+
A_lb = A / 2;
|
|
267
|
+
A_ub = A * 2;
|
|
268
|
+
|
|
269
|
+
/***** allocate default result for 3-point fit *****/
|
|
270
|
+
X[0] = A;
|
|
271
|
+
X[1] = peak_loc[0];
|
|
272
|
+
X[2] = peak_loc[1];
|
|
273
|
+
X[3] = sqrt(sx*sx+sy*sy);
|
|
274
|
+
n_data = N[0] * N[1];
|
|
275
|
+
|
|
276
|
+
// evaluate fit function and copy
|
|
277
|
+
memset(fitval, 0, sizeof(float)*n_data);
|
|
278
|
+
pd.xcorr = fitval; // hand gauss4_f a zero array to evaluate fit function only
|
|
279
|
+
pd.N = N;
|
|
280
|
+
gsl_F = gsl_vector_alloc(n_data);
|
|
281
|
+
gsl_X0 = gsl_vector_view_array(X, 4);
|
|
282
|
+
gauss4_f(&(gsl_X0.vector), (void*)&pd, gsl_F);
|
|
283
|
+
for(i = 0; i < n_data; ++i)
|
|
284
|
+
fitval[i] = (float) gsl_vector_get(gsl_F, i);
|
|
285
|
+
gsl_vector_free(gsl_F);
|
|
286
|
+
|
|
287
|
+
/* if using three point estimator fit, stop here */
|
|
288
|
+
if(iFitType == 3)
|
|
289
|
+
return;
|
|
290
|
+
|
|
291
|
+
/***** set-up for non-linear least squares fitting *****/
|
|
292
|
+
const gsl_multifit_nlinear_type *gsl_fittype = gsl_multifit_nlinear_trust;
|
|
293
|
+
gsl_multifit_nlinear_workspace *gsl_ws;
|
|
294
|
+
gsl_multifit_nlinear_fdf gsl_fdf;
|
|
295
|
+
gsl_multifit_nlinear_parameters gsl_fdf_params = gsl_multifit_nlinear_default_parameters();
|
|
296
|
+
|
|
297
|
+
const double xtol = 1e-6;
|
|
298
|
+
const double gtol = 1e-6;
|
|
299
|
+
const double ftol = 0.0;
|
|
300
|
+
|
|
301
|
+
/* set common parameters for all types of fit */
|
|
302
|
+
pd.N = N;
|
|
303
|
+
pd.xcorr = xcorr;
|
|
304
|
+
gsl_fdf.fvv = NULL; // not using geodesic acceleration
|
|
305
|
+
gsl_fdf.n = N[0]*N[1]; // number of data
|
|
306
|
+
gsl_fdf.params =&pd; // data for optimisation
|
|
307
|
+
gsl_fdf_params.trs= gsl_multifit_nlinear_trs_lm;
|
|
308
|
+
|
|
309
|
+
/* specific settings for different fit types */
|
|
310
|
+
switch(iFitType)
|
|
311
|
+
{
|
|
312
|
+
case 4:
|
|
313
|
+
/* four DOF fit */
|
|
314
|
+
/* initial guess */
|
|
315
|
+
X[0] = A;
|
|
316
|
+
X[1] = peak_loc[0];
|
|
317
|
+
X[2] = peak_loc[1];
|
|
318
|
+
X[3] = sqrt(sx*sx+sy*sy);
|
|
319
|
+
gsl_X0 = gsl_vector_view_array(X, 4);
|
|
320
|
+
|
|
321
|
+
/* define the function to be minimized */
|
|
322
|
+
gsl_fdf.f = gauss4_f; // objective function to minimise
|
|
323
|
+
gsl_fdf.df = gauss4_jac; // jacobian
|
|
324
|
+
gsl_fdf.p = 4; // number of parameters
|
|
325
|
+
break;
|
|
326
|
+
case 5:
|
|
327
|
+
/* five DOF fit */
|
|
328
|
+
/* initial guess */
|
|
329
|
+
X[0] = A;
|
|
330
|
+
X[1] = peak_loc[0];
|
|
331
|
+
X[2] = peak_loc[1];
|
|
332
|
+
X[3] = sx;
|
|
333
|
+
X[4] = sy;
|
|
334
|
+
gsl_X0 = gsl_vector_view_array(X, 5);
|
|
335
|
+
|
|
336
|
+
/* define the function to be minimized */
|
|
337
|
+
gsl_fdf.f = gauss5_f; // objective function to minimise
|
|
338
|
+
gsl_fdf.df = gauss5_jac; // jacobian
|
|
339
|
+
gsl_fdf.p = 5; // number of parameters
|
|
340
|
+
break;
|
|
341
|
+
default:
|
|
342
|
+
case 6:
|
|
343
|
+
/* six DOF fit */
|
|
344
|
+
/* initial guess */
|
|
345
|
+
|
|
346
|
+
X[0] = A;
|
|
347
|
+
X[1] = peak_loc[0];
|
|
348
|
+
X[2] = peak_loc[1];
|
|
349
|
+
X[3] = sx*sx;
|
|
350
|
+
X[4] = sy*sy;
|
|
351
|
+
X[5] = 0;
|
|
352
|
+
gsl_X0 = gsl_vector_view_array(X, 6);
|
|
353
|
+
|
|
354
|
+
/* define the function to be minimized */
|
|
355
|
+
gsl_fdf.f = gauss6_f; // objective function to minimise
|
|
356
|
+
gsl_fdf.df = gauss6_jac; // jacobian
|
|
357
|
+
gsl_fdf.p = 6; // number of parameters
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**** run solver ****/
|
|
362
|
+
// allocate workspace with default parameters
|
|
363
|
+
gsl_ws = gsl_multifit_nlinear_alloc(gsl_fittype, &gsl_fdf_params, gsl_fdf.n, gsl_fdf.p);
|
|
364
|
+
// initialize solver with starting point and weights
|
|
365
|
+
gsl_multifit_nlinear_init(&(gsl_X0.vector), &gsl_fdf, gsl_ws);
|
|
366
|
+
// solve the system with a maximum of MAXITER iterations
|
|
367
|
+
gsl_X = gsl_multifit_nlinear_position(gsl_ws);
|
|
368
|
+
|
|
369
|
+
// note: fitting can crash with a memory access error if nan or bad values are returned by any of the fitting functions!
|
|
370
|
+
status = gsl_multifit_nlinear_driver(MAXITER, xtol, gtol, ftol, NULL, NULL, &info, gsl_ws);
|
|
371
|
+
|
|
372
|
+
/**** allocate result if successful ****/
|
|
373
|
+
if(status == GSL_SUCCESS)
|
|
374
|
+
//extract std 210224a
|
|
375
|
+
|
|
376
|
+
{
|
|
377
|
+
gsl_X = gsl_multifit_nlinear_position(gsl_ws);
|
|
378
|
+
if (gsl_fdf.p == 6) {
|
|
379
|
+
sig[0] = (float)gsl_vector_get(gsl_X,4);
|
|
380
|
+
sig[1] = (float)gsl_vector_get(gsl_X,3);
|
|
381
|
+
sig[2] = -(float)gsl_vector_get(gsl_X, 5)*(sig[0]*sig[1]-((float)gsl_vector_get(gsl_X, 5)*(float)gsl_vector_get(gsl_X, 5)));
|
|
382
|
+
} else {
|
|
383
|
+
sig[0] = 0.0;
|
|
384
|
+
sig[1] = 0.0;
|
|
385
|
+
sig[2] = 0.0;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
peak_loc[0] = (float)gsl_vector_get(gsl_X, 1);
|
|
389
|
+
peak_loc[1] = (float)gsl_vector_get(gsl_X, 2);
|
|
390
|
+
// evaluate fit function and copy
|
|
391
|
+
memset(fitval, 0, sizeof(float)*n_data);
|
|
392
|
+
pd.xcorr = fitval; // necessary
|
|
393
|
+
pd.N = N;
|
|
394
|
+
gsl_F = gsl_vector_alloc(n_data);
|
|
395
|
+
(*gsl_fdf.f)(gsl_X, (void*)&pd, gsl_F);
|
|
396
|
+
for(i = 0; i < n_data; ++i)
|
|
397
|
+
fitval[i] = (float) gsl_vector_get(gsl_F, i);
|
|
398
|
+
gsl_vector_free(gsl_F);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**** free ****/
|
|
402
|
+
gsl_multifit_nlinear_free(gsl_ws);
|
|
403
|
+
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/****************************************************
|
|
408
|
+
* fitting functions
|
|
409
|
+
*
|
|
410
|
+
* we provide the function which predicts
|
|
411
|
+
* the measurement vector x of dimension n x 1 that
|
|
412
|
+
* x = F(i, j; p)
|
|
413
|
+
* where p is the vector to be predicted with dimension m x 1
|
|
414
|
+
*
|
|
415
|
+
* the jacobian jac = \partial x / \partial p is organised in a C-style
|
|
416
|
+
* n x m matrix, such that
|
|
417
|
+
* jac[0] corresponds to \partial x_0 / \partial p_0
|
|
418
|
+
* jac[1] " " \partial x_0 / \partial p_1
|
|
419
|
+
* jac[i*m + j] " " \partial x_i / \partial p_j
|
|
420
|
+
*
|
|
421
|
+
* x represents a flattened C-style N[0] x N[1] array indexed by
|
|
422
|
+
* x[i][j], i = -(N[0]-1)/2 .. (N[0]-1)/2, j = -(N[1]-1)/2 ...
|
|
423
|
+
* and should contain F(i, j; p) evaluated at each i, j
|
|
424
|
+
*
|
|
425
|
+
* data is a pointer to an int array (int*) which contains the
|
|
426
|
+
* dimensions that the flattened array x corresponds to
|
|
427
|
+
*/
|
|
428
|
+
|
|
429
|
+
/********
|
|
430
|
+
* gauss4 and gauss4jac
|
|
431
|
+
* four-DOF gaussian fit
|
|
432
|
+
*
|
|
433
|
+
* F(i, j) = A * exp( -((i - i0)^2 + (j - j0)^2) / sigma^2)
|
|
434
|
+
*
|
|
435
|
+
* p = [A i0 j0 sigma]
|
|
436
|
+
*/
|
|
437
|
+
int gauss4_f(const gsl_vector *p, void *data, gsl_vector *res)
|
|
438
|
+
{
|
|
439
|
+
const int *N;
|
|
440
|
+
int ii, jj, xidx;
|
|
441
|
+
float i0, j0, A, s, i, j, ihat, jhat, F;
|
|
442
|
+
const float *f;
|
|
443
|
+
|
|
444
|
+
/* extract parameters */
|
|
445
|
+
N = ((pkdata*)data)->N;
|
|
446
|
+
f = ((pkdata*)data)->xcorr;
|
|
447
|
+
A = (float)gsl_vector_get(p, 0);
|
|
448
|
+
i0 = (float)gsl_vector_get(p, 1);
|
|
449
|
+
j0 = (float)gsl_vector_get(p, 2);
|
|
450
|
+
s = (float)gsl_vector_get(p, 3);
|
|
451
|
+
|
|
452
|
+
/* F(i, j) = A * exp( -((i - i0)^2 + (j - j0)^2) / s^2 ) */
|
|
453
|
+
for(ii = 0; ii < N[0]; ++ii)
|
|
454
|
+
{
|
|
455
|
+
i = (float)(ii - (N[0]-1)/2);
|
|
456
|
+
for(jj = 0; jj < N[1]; ++jj)
|
|
457
|
+
{
|
|
458
|
+
j = (float)(jj - (N[1]-1)/2);
|
|
459
|
+
xidx = ii*N[1] + jj;
|
|
460
|
+
ihat = (i-i0)/s;
|
|
461
|
+
jhat = (j-j0)/s;
|
|
462
|
+
F = A * expf( -ihat*ihat - jhat*jhat );
|
|
463
|
+
gsl_vector_set(res, xidx, F - f[xidx]);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return GSL_SUCCESS;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
int gauss4_jac(const gsl_vector *p, void *data, gsl_matrix *jac)
|
|
471
|
+
{
|
|
472
|
+
const int *N;
|
|
473
|
+
int ii, jj, xidx;
|
|
474
|
+
float i0, j0, A, s, i, j, ihat, jhat, F;
|
|
475
|
+
|
|
476
|
+
/* extract parameters */
|
|
477
|
+
N = ((pkdata*)data)->N;
|
|
478
|
+
A = (float)gsl_vector_get(p, 0);
|
|
479
|
+
i0 = (float)gsl_vector_get(p, 1);
|
|
480
|
+
j0 = (float)gsl_vector_get(p, 2);
|
|
481
|
+
s = (float)gsl_vector_get(p, 3);
|
|
482
|
+
|
|
483
|
+
/* F(i, j) = A * exp( -((i - i0)^2 + (j - j0)^2) / (s*s))
|
|
484
|
+
* dF / dA = F / A
|
|
485
|
+
* dF / di0 = 2*F*(i - i0)/s^2
|
|
486
|
+
* dF / dj0 = 2*F*(j - j0)/s^2
|
|
487
|
+
* dF / ds = 2*((i - i0)^2 + (j - j0)^2)/s^3
|
|
488
|
+
*/
|
|
489
|
+
for(ii = 0; ii < N[0]; ++ii)
|
|
490
|
+
{
|
|
491
|
+
i = (float)(ii - (N[0]-1)/2);
|
|
492
|
+
for(jj = 0; jj < N[1]; ++jj)
|
|
493
|
+
{
|
|
494
|
+
j = (float)(jj - (N[1]-1)/2);
|
|
495
|
+
xidx = ii*N[1] + jj;
|
|
496
|
+
ihat = (i-i0)/s;
|
|
497
|
+
jhat = (j-j0)/s;
|
|
498
|
+
F = A * expf( -ihat*ihat - jhat*jhat );
|
|
499
|
+
|
|
500
|
+
gsl_matrix_set(jac, xidx, 0, F / A); /* dF / dA */
|
|
501
|
+
gsl_matrix_set(jac, xidx, 1, 2*F*ihat/s); /* dF / di0 */
|
|
502
|
+
gsl_matrix_set(jac, xidx, 2, 2*F*jhat/s); /* dF / dj0 */
|
|
503
|
+
gsl_matrix_set(jac, xidx, 3, 2*F*(ihat*ihat+jhat*jhat)/s); /* dF / ds */
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
return GSL_SUCCESS;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
int gauss4_fvv(const gsl_vector *p, const gsl_vector *v, void *data, gsl_vector *fvv)
|
|
511
|
+
{
|
|
512
|
+
const int *N;
|
|
513
|
+
int ii, jj, xidx;
|
|
514
|
+
float i0, j0, A, s, i, j, F, ss, ihat, jhat;
|
|
515
|
+
float vA, vi, vj, vs;
|
|
516
|
+
float DAi, DAj, DAs, Dii, Dij, Dis, Djj, Djs, Dss, D2v;
|
|
517
|
+
const float *f;
|
|
518
|
+
|
|
519
|
+
/* extract parameters */
|
|
520
|
+
N = ((pkdata*)data)->N;
|
|
521
|
+
A = (float)gsl_vector_get(p, 0);
|
|
522
|
+
i0 = (float)gsl_vector_get(p, 1);
|
|
523
|
+
j0 = (float)gsl_vector_get(p, 2);
|
|
524
|
+
s = (float)gsl_vector_get(p, 3);
|
|
525
|
+
/* velocity */
|
|
526
|
+
vA = (float)gsl_vector_get(v, 0);
|
|
527
|
+
vi = (float)gsl_vector_get(v, 1);
|
|
528
|
+
vj = (float)gsl_vector_get(v, 2);
|
|
529
|
+
vs = (float)gsl_vector_get(v, 3);
|
|
530
|
+
|
|
531
|
+
/* F(i, j) = A * exp( -((i - i0)^2 + (j - j0)^2) / s^2 ) */
|
|
532
|
+
for(ii = 0; ii < N[0]; ++ii)
|
|
533
|
+
{
|
|
534
|
+
i = (float)(ii - (N[0]-1)/2);
|
|
535
|
+
for(jj = 0; jj < N[1]; ++jj)
|
|
536
|
+
{
|
|
537
|
+
j = (float)(jj - (N[1]-1)/2);
|
|
538
|
+
xidx = ii*N[1] + jj;
|
|
539
|
+
|
|
540
|
+
/* calculate second derivatives */
|
|
541
|
+
ihat = (i - i0)/s;
|
|
542
|
+
jhat = (j - j0)/s;
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
DAi = 2.0*ihat/(s*A);
|
|
546
|
+
DAj = 2.0*jhat/(s*A);
|
|
547
|
+
DAs = 2.0*(ihat*ihat + jhat*jhat)/(s*A);
|
|
548
|
+
Dii = 2.0*(ihat*ihat - 1.0)/(s*s);
|
|
549
|
+
Dij = 4.0*ihat*jhat/(s*s);
|
|
550
|
+
Dis = 4.0*ihat*(ihat*ihat + jhat*jhat - 1.0)/(s*s);
|
|
551
|
+
Djj = 2.0*(jhat*jhat - 1.0);
|
|
552
|
+
Djs = 4.0*jhat*(ihat*ihat + jhat*jhat - 1.0)/(s*s);
|
|
553
|
+
Dss = 4.0*(ihat*ihat + jhat*jhat)*(ihat*ihat + jhat*jhat - 1.5)/(s*s);
|
|
554
|
+
|
|
555
|
+
F = A * expf(-ihat*ihat - jhat*jhat);
|
|
556
|
+
D2v = F*(0 + 2*DAi*vA*vi + 2*DAj*vA*vj + 2*DAs*vA*vs
|
|
557
|
+
+ Dii*vi*vi + 2*Dij*vi*vj + 2*Dis*vi*vs
|
|
558
|
+
+ Djj*vj*vj + 2*Djs*vj*vs + Dss*vs*vs);
|
|
559
|
+
|
|
560
|
+
gsl_vector_set(fvv, xidx, D2v);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
return GSL_SUCCESS;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/********
|
|
568
|
+
* gauss5 and gauss5jac
|
|
569
|
+
* five-DOF gaussian fit
|
|
570
|
+
*
|
|
571
|
+
* F(i, j) = A * exp( -(i - i0)^2*sxx - (j - j0)^2*syy)
|
|
572
|
+
*
|
|
573
|
+
* p = [A i0 j0 sxx syy]
|
|
574
|
+
* (sxx = 1/sigma_x^2)
|
|
575
|
+
*/
|
|
576
|
+
int gauss5_f(const gsl_vector *p, void *data, gsl_vector *res)
|
|
577
|
+
{
|
|
578
|
+
const int *N;
|
|
579
|
+
int ii, jj, xidx;
|
|
580
|
+
float i0, j0, A, sx, sy, i, j, ihat, jhat, F;
|
|
581
|
+
const float *f;
|
|
582
|
+
|
|
583
|
+
/* extract parameters */
|
|
584
|
+
N = ((pkdata*)data)->N;
|
|
585
|
+
f = ((pkdata*)data)->xcorr;
|
|
586
|
+
A = (float)gsl_vector_get(p, 0);
|
|
587
|
+
i0 = (float)gsl_vector_get(p, 1);
|
|
588
|
+
j0 = (float)gsl_vector_get(p, 2);
|
|
589
|
+
sx = (float)gsl_vector_get(p, 3);
|
|
590
|
+
sy = (float)gsl_vector_get(p, 4);
|
|
591
|
+
|
|
592
|
+
/* F(i, j) = A * exp( -(i - i0)^2/sx^2 - (j - j0)^2/sy^2) */
|
|
593
|
+
for(ii = 0; ii < N[0]; ++ii)
|
|
594
|
+
{
|
|
595
|
+
i = (float)(ii - (N[0]-1)/2);
|
|
596
|
+
for(jj = 0; jj < N[1]; ++jj)
|
|
597
|
+
{
|
|
598
|
+
j = (float)(jj - (N[1]-1)/2);
|
|
599
|
+
xidx = ii*N[1] + jj;
|
|
600
|
+
ihat = (i-i0)/sx;
|
|
601
|
+
jhat = (j-j0)/sy;
|
|
602
|
+
F = A * expf( -ihat*ihat - jhat*jhat );
|
|
603
|
+
gsl_vector_set(res, xidx, F - f[xidx]);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return GSL_SUCCESS;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
int gauss5_jac(const gsl_vector *p, void *data, gsl_matrix *jac)
|
|
611
|
+
{
|
|
612
|
+
const int *N;
|
|
613
|
+
int ii, jj, xidx;
|
|
614
|
+
float i0, j0, A, sx, sy, i, j, ihat, jhat, F;
|
|
615
|
+
|
|
616
|
+
/* extract parameters */
|
|
617
|
+
N = ((pkdata*)data)->N;
|
|
618
|
+
A = (float)gsl_vector_get(p, 0);
|
|
619
|
+
i0 = (float)gsl_vector_get(p, 1);
|
|
620
|
+
j0 = (float)gsl_vector_get(p, 2);
|
|
621
|
+
sx = (float)gsl_vector_get(p, 3);
|
|
622
|
+
sy = (float)gsl_vector_get(p, 4);
|
|
623
|
+
|
|
624
|
+
/* F(i, j) = A * exp( -(i - i0)^2*sxx - (j - j0)^2*syy)
|
|
625
|
+
* dF / dA = F / A
|
|
626
|
+
* dF / di0 = 2*F*(i - i0)/sx^2
|
|
627
|
+
* dF / dj0 = 2*F*(j - j0)/sy^2
|
|
628
|
+
* dF / dsx = 2*F*(i - i0)^2/sx^3
|
|
629
|
+
* dF / dsy = 2*F*(j - j0)^2/sy^3
|
|
630
|
+
*/
|
|
631
|
+
for(ii = 0; ii < N[0]; ++ii)
|
|
632
|
+
{
|
|
633
|
+
i = (float)(ii - (N[0]-1)/2);
|
|
634
|
+
for(jj = 0; jj < N[1]; ++jj)
|
|
635
|
+
{
|
|
636
|
+
j = (float)(jj - (N[1]-1)/2);
|
|
637
|
+
xidx = ii*N[1] + jj;
|
|
638
|
+
ihat = (i-i0)/sx;
|
|
639
|
+
jhat = (j-j0)/sy;
|
|
640
|
+
F = A * expf( -ihat*ihat - jhat*jhat );
|
|
641
|
+
|
|
642
|
+
gsl_matrix_set(jac, xidx, 0, F / A); /* dF / dA */
|
|
643
|
+
gsl_matrix_set(jac, xidx, 1, 2*F*ihat/sx); /* dF / di0 */
|
|
644
|
+
gsl_matrix_set(jac, xidx, 2, 2*F*jhat/sy); /* dF / dj0 */
|
|
645
|
+
gsl_matrix_set(jac, xidx, 3, 2*F*ihat*ihat/sx); /* dF / dsx */
|
|
646
|
+
gsl_matrix_set(jac, xidx, 4, 2*F*jhat*jhat/sy); /* dF / dsy */
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
return GSL_SUCCESS;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
/********
|
|
655
|
+
* gauss6 and gauss6jac
|
|
656
|
+
* six-DOF gaussian fit
|
|
657
|
+
*
|
|
658
|
+
* F(i, j) = A * exp( -(i - i0)*(i - i0)/sx^2 -(j - j0)*(j - j0)/sy^2
|
|
659
|
+
* -(i - i0)*(j - j0)*sxy)
|
|
660
|
+
*
|
|
661
|
+
* p = [A i0 j0 sxx syy sxy]
|
|
662
|
+
* (sxx = 1/sigma_x^2 etc.)
|
|
663
|
+
*/
|
|
664
|
+
int gauss6_f(const gsl_vector *p, void *data, gsl_vector *res)
|
|
665
|
+
{
|
|
666
|
+
const int *N;
|
|
667
|
+
int ii, jj, xidx;
|
|
668
|
+
float i0, j0, A, sx, sy, sxy, i, j, F;
|
|
669
|
+
const float *f;
|
|
670
|
+
|
|
671
|
+
/* extract parameters */
|
|
672
|
+
N = ((pkdata*)data)->N;
|
|
673
|
+
f = ((pkdata*)data)->xcorr;
|
|
674
|
+
A = (float)gsl_vector_get(p, 0);
|
|
675
|
+
i0 = (float)gsl_vector_get(p, 1);
|
|
676
|
+
j0 = (float)gsl_vector_get(p, 2);
|
|
677
|
+
sx = (float)gsl_vector_get(p, 3);
|
|
678
|
+
sy = (float)gsl_vector_get(p, 4);
|
|
679
|
+
sxy = (float)gsl_vector_get(p, 5);
|
|
680
|
+
|
|
681
|
+
/* F(i, j) =A*exp(-0.5*((((j-xbar)^2*sy)-(2*(j-xbar)*(i-ybar)*sxy)+(i-ybar)^2*sx))/(sx*sy-sxy^2));
|
|
682
|
+
*/
|
|
683
|
+
for(ii = 0; ii < N[0]; ++ii)
|
|
684
|
+
{
|
|
685
|
+
i = (float)(ii - (N[0]-1)/2); /* goes from -N/2 to N/2 */
|
|
686
|
+
for(jj = 0; jj < N[1]; ++jj)
|
|
687
|
+
{
|
|
688
|
+
j = (float)(jj - (N[1]-1)/2);
|
|
689
|
+
xidx = ii*N[1] + jj;
|
|
690
|
+
F = A * expf(0.5*( -(i-i0)*(i-i0)/(sx)
|
|
691
|
+
-(j-j0)*(j-j0)/(sy)
|
|
692
|
+
-2*(i-i0)*(j-j0)* sxy));
|
|
693
|
+
gsl_vector_set(res, xidx, F - f[xidx]);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
return GSL_SUCCESS;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
int gauss6_jac(const gsl_vector *p, void *data, gsl_matrix *jac)
|
|
701
|
+
{
|
|
702
|
+
const int *N;
|
|
703
|
+
int ii, jj, xidx;
|
|
704
|
+
float i0, j0, A, sx, sy, sxy, i, j, F, ihat, jhat;
|
|
705
|
+
|
|
706
|
+
/* extract parameters */
|
|
707
|
+
N = ((pkdata*)data)->N;
|
|
708
|
+
A = (float)gsl_vector_get(p, 0);
|
|
709
|
+
i0 = (float)gsl_vector_get(p, 1);
|
|
710
|
+
j0 = (float)gsl_vector_get(p, 2);
|
|
711
|
+
sx = (float)gsl_vector_get(p, 3);
|
|
712
|
+
sy = (float)gsl_vector_get(p, 4);
|
|
713
|
+
sxy = (float)gsl_vector_get(p, 5);
|
|
714
|
+
|
|
715
|
+
for(ii = 0; ii < N[0]; ++ii)
|
|
716
|
+
{
|
|
717
|
+
i = (float)(ii - (N[0]-1)/2);
|
|
718
|
+
for(jj = 0; jj < N[1]; ++jj)
|
|
719
|
+
{
|
|
720
|
+
j = (float)(jj - (N[1]-1)/2);
|
|
721
|
+
xidx = ii*N[1] + jj;
|
|
722
|
+
F = A * expf(0.5*( -(i-i0)*(i-i0)/(sx)
|
|
723
|
+
-(j-j0)*(j-j0)/(sy)
|
|
724
|
+
-2*(i-i0)*(j-j0)* sxy));
|
|
725
|
+
|
|
726
|
+
gsl_matrix_set(jac, xidx, 0, F / A); /* dF / dA */
|
|
727
|
+
gsl_matrix_set(jac, xidx, 1, -(F*(i0 + (j0 - j) * sx * sxy - i))/(sx)); /* dF / di0 */
|
|
728
|
+
gsl_matrix_set(jac, xidx, 2, -(F*(j0 + (i0 - i) * sy * sxy - j))/(sy)); /* dF / dj0 */
|
|
729
|
+
gsl_matrix_set(jac, xidx, 3, (F*(i-i0)*(i-i0))/(2*sx*sx)); /* dF / dsx */
|
|
730
|
+
gsl_matrix_set(jac, xidx, 4, (F*(j-j0)*(j-j0))/(2*sy*sy)); /* dF / dsy */
|
|
731
|
+
gsl_matrix_set(jac, xidx, 5, -(i-i0)*(j-j0)*F); /* dF / dsxy */
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
return GSL_SUCCESS;
|
|
736
|
+
}
|