Instrument Neutral Distributed Interface INDI 2.2.5
align.c
Go to the documentation of this file.
1/*
2* DSP API - a digital signal processing library for astronomy usage
3* Copyright © 2017-2021 Ilia Platone
4*
5* This program is free software; you can redistribute it and/or
6* modify it under the terms of the GNU Lesser General Public
7* License as published by the Free Software Foundation; either
8* version 3 of the License, or (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13* Lesser General Public License for more details.
14*
15* You should have received a copy of the GNU Lesser General Public License
16* along with this program; if not, write to the Free Software Foundation,
17* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18*/
19
20#include "dsp.h"
21#include <time.h>
22
23typedef struct {
24 double delta;
25 double *diff;
27
28static int dsp_qsort_delta_diff_desc (const void *arg1, const void *arg2)
29{
30 delta_diff* a1 = (delta_diff*)arg1;
31 delta_diff* a2 = (delta_diff*)arg2;
32 return ((*a1).delta < (*a2).delta ? 1 : -1);
33}
34
35static int dsp_qsort_delta_diff_asc (const void *arg1, const void *arg2)
36{
37 delta_diff* a1 = (delta_diff*)arg1;
38 delta_diff* a2 = (delta_diff*)arg2;
39 return ((*a1).delta > (*a2).delta ? 1 : -1);
40}
41
42static int dsp_qsort_triangle_delta_desc(const void *arg1, const void *arg2)
43{
44 dsp_triangle* a = (dsp_triangle*)arg1;
45 dsp_triangle* b = (dsp_triangle*)arg2;
46 int ret = 0;
47 int s = 0;
48 for(s = 0; s < (*a).stars_count; s++)
49 ret |= ((*a).sizes[s] < (*b).sizes[s]);
50 return (ret ? 1 : -1);
51}
52
53static int dsp_qsort_triangle_delta_asc(const void *arg1, const void *arg2)
54{
55 dsp_triangle* a = (dsp_triangle*)arg1;
56 dsp_triangle* b = (dsp_triangle*)arg2;
57 int ret = 0;
58 int s = 0;
59 for(s = 0; s < (*a).stars_count; s++)
60 ret |= ((*a).sizes[s] > (*b).sizes[s]);
61 return (ret ? 1 : -1);
62}
63
64static int dsp_qsort_triangle_diameter_desc(const void *arg1, const void *arg2)
65{
66 dsp_triangle* a = (dsp_triangle*)arg1;
67 dsp_triangle* b = (dsp_triangle*)arg2;
68 int ret = 0;
69 int s = 0;
70 for(s = 0; s < (*a).stars_count; s++) {
71 ret |= ((*a).stars[s].diameter < (*b).stars[s].diameter);
72 ret |= ((*a).stars[s].peak < (*b).stars[s].peak);
73 ret |= ((*a).stars[s].flux < (*b).stars[s].flux);
74 }
75 return (ret ? 1 : -1);
76}
77
78static int dsp_qsort_triangle_diameter_asc(const void *arg1, const void *arg2)
79{
80 dsp_triangle* a = (dsp_triangle*)arg1;
81 dsp_triangle* b = (dsp_triangle*)arg2;
82 int ret = 0;
83 int s = 0;
84 for(s = 0; s < (*a).stars_count; s++) {
85 ret |= ((*a).stars[s].diameter > (*b).stars[s].diameter);
86 ret |= ((*a).stars[s].peak > (*b).stars[s].peak);
87 ret |= ((*a).stars[s].flux > (*b).stars[s].flux);
88 }
89 return (ret ? 1 : -1);
90}
91
92static int dsp_qsort_star_diameter_desc(const void *arg1, const void *arg2)
93{
94 dsp_star* a = (dsp_star*)arg1;
95 dsp_star* b = (dsp_star*)arg2;
96 return ((*a).diameter < (*b).diameter ? 1 : -1);
97}
98
99static int dsp_qsort_star_diameter_asc(const void *arg1, const void *arg2)
100{
101 dsp_star* a = (dsp_star*)arg1;
102 dsp_star* b = (dsp_star*)arg2;
103 return ((*a).diameter > (*b).diameter ? 1 : -1);
104}
105
106static int dsp_qsort_double_desc (const void *arg1, const void *arg2)
107{
108 double* a = (double*)arg1;
109 double* b = (double*)arg2;
110 return ((*a) < (*b) ? 1 : -1);
111}
112
113static int dsp_qsort_double_asc (const void *arg1, const void *arg2)
114{
115 double* a = (double*)arg1;
116 double* b = (double*)arg2;
117 return ((*a) > (*b) ? 1 : -1);
118}
119
120static double calc_match_score(dsp_triangle t1, dsp_triangle t2, dsp_align_info align_info)
121{
122 int x = 0;
123 int d = 0;
124 int div = 0;
125 int stars_count = fmin(t1.stars_count, t2.stars_count);
126 int num_baselines = stars_count*(stars_count-1)/2;
127 double err = 0.0;
128 err += fabs((t2.index-t1.index)/t1.index);
129 div++;
130 for(d = 0; d < align_info.dims; d++) {
131 for(x = 0; x < stars_count; x++) {
132 err += fabs(t2.stars[x].diameter/align_info.factor[d]-t1.stars[x].diameter)/t1.stars[x].diameter;
133 div++;
134 err += fabs(t2.stars[x].flux/align_info.factor[d]-t1.stars[x].flux)/t1.stars[x].flux;
135 div++;
136 err += fabs(t2.stars[x].peak/align_info.factor[d]-t1.stars[x].peak)/t1.stars[x].peak;
137 div++;
138 }
139 for(x = 0; x < num_baselines; x++) {
140 err += fabs(t2.sizes[x]/align_info.factor[d]-t1.sizes[x])/t1.sizes[x];
141 div++;
142 }
143 }
144 return err / div;
145}
146
148{
149 dsp_align_info *align_info = (dsp_align_info*)malloc(sizeof(dsp_align_info));
150 int dims = t1.dims;
151 int d, x;
152 int num_baselines = t1.stars_count*(t1.stars_count-1)/2;
153 align_info->dims = dims;
154 align_info->center = (double*)malloc(sizeof(double)*(dims));
155 align_info->offset = (double*)malloc(sizeof(double)*(dims));
156 align_info->radians = (double*)malloc(sizeof(double)*(dims-1));
157 align_info->factor = (double*)malloc(sizeof(double)*(dims));
158 for(d = 0; d < dims; d++) {
159 align_info->factor[d] = 0;
160 align_info->offset[d] = 0;
161 align_info->center[d] = 0;
162 if(d < dims - 1)
163 align_info->radians[d] = 0;
164 }
165 for(d = 0; d < dims; d++) {
166 align_info->center[d] = t2.stars[0].center.location[d];
167 align_info->offset[d] = t2.stars[0].center.location[d] - t1.stars[0].center.location[d];
168 if(d < dims - 1) {
169 align_info->radians[d] = t1.theta[d] - t2.theta[d];
170 if(align_info->radians[d] >= M_PI*2.0)
171 align_info->radians[d] -= M_PI*2.0;
172 if(align_info->radians[d] < 0.0)
173 align_info->radians[d] += M_PI*2.0;
174 }
175 for(x = 0; x < num_baselines; x++) {
176 align_info->factor[d] += t2.sizes[x] / t1.sizes[x];
177 }
178 align_info->factor[d] /= num_baselines;
179 }
180 align_info->score = calc_match_score(t1, t2, *align_info);
181 return align_info;
182}
183
185{
186 int d;
187 free(t->sizes);
188 free(t->theta);
189 free(t->ratios);
190 for(d = 0; d < t->dims; d++) {
191 free(t->stars[d].center.location);
192 }
193 free(t->stars);
194 free(t);
195}
196
198{
199 int x;
200 int y;
201 int d;
202 dsp_triangle *triangle = (dsp_triangle*)malloc(sizeof(dsp_triangle));
203 triangle->dims = stars[0].center.dims;
204 triangle->stars_count = num_stars;
205 int num_baselines = triangle->stars_count*(triangle->stars_count-1)/2;
206 delta_diff *deltadiff = (delta_diff*)malloc(sizeof(delta_diff)*num_baselines);
207 triangle->sizes = (double*)malloc(sizeof(double)*num_baselines);
208 triangle->ratios = (double*)malloc(sizeof(double)*num_baselines);
209 triangle->stars = (dsp_star*)malloc(sizeof(dsp_star)*triangle->stars_count);
210 triangle->theta = (double*)malloc(sizeof(double)*(triangle->dims-1));
211 triangle->index = 0.0;
212 qsort(stars, triangle->stars_count, sizeof(dsp_star), dsp_qsort_star_diameter_desc);
213 int idx = 0;
214 for(x = 0; x < triangle->stars_count; x++) {
215 for(y = x+1; y < triangle->stars_count; y++) {
216 deltadiff[idx].diff = (double*)malloc(sizeof(double)*triangle->dims);
217 for(d = 0; d < triangle->dims; d++) {
218 deltadiff[idx].diff[d] = stars[x].center.location[d]-stars[y].center.location[d];
219 deltadiff[idx].delta += pow(deltadiff[idx].diff[d], 2);
220 }
221 deltadiff[idx].delta = sqrt(deltadiff[idx].delta);
222 idx++;
223 }
224 }
225 qsort(deltadiff, num_baselines, sizeof(delta_diff), dsp_qsort_delta_diff_desc);
226 for(d = 0; d < triangle->dims-1; d++) {
227 triangle->theta[d] = acos(deltadiff[0].diff[d] / deltadiff[0].delta);
228 if(deltadiff[0].diff[d+1] < 0)
229 triangle->theta[d] = M_PI*2.0-triangle->theta[d];
230 for(x = 1; x < num_baselines; x++) {
231 double index = acos(deltadiff[x].diff[d] / deltadiff[x].delta);
232 if(deltadiff[x].diff[d+1] < 0)
233 index = M_PI*2.0-index;
234 index -= triangle->theta[d];
235 triangle->index += index;
236 }
237 }
238 triangle->index /= (num_baselines+triangle->dims-2)*M_PI*2;
239 for(d = 0; d < triangle->stars_count; d++) {
240 triangle->stars[d].diameter = stars[d].diameter;
241 triangle->stars[d].peak = stars[d].peak;
242 triangle->stars[d].flux = stars[d].flux;
243 triangle->stars[d].theta = stars[d].theta;
244 triangle->stars[d].center.dims = stars[d].center.dims;
245 triangle->stars[d].center.location = (double*)malloc(sizeof(double)*stars[d].center.dims);
246 for(x = 0; x < triangle->stars[d].center.dims; x++) {
247 triangle->stars[d].center.location[x] = stars[d].center.location[x];
248 }
249 }
250 for(d = 0; d < num_baselines; d++) {
251 triangle->sizes[d] = deltadiff[d].delta;
252 triangle->ratios[d] = deltadiff[d].delta / deltadiff[0].delta;
253 free(deltadiff[d].diff);
254 }
255 free(deltadiff);
256 return triangle;
257}
258
259int dsp_align_get_offset(dsp_stream_p stream1, dsp_stream_p stream2, double tolerance, double target_score, int num_stars)
260{
261 dsp_align_info *align_info;
262 double decimals = pow(10, tolerance);
263 double div = 0.0;
264 int d, t1, t2, x, y;
265 double phi = 0.0;
266 double ratio = decimals*1600.0/div;
267 dsp_star *stars = (dsp_star*)malloc(sizeof(dsp_star)*num_stars);
268 for(d = 0; d < stream1->dims; d++) {
269 div += pow(stream2->sizes[d], 2);
270 }
271 div = pow(div, 0.5);
272 pwarn("decimals: %lf\n", decimals);
273 target_score = (1.0-target_score / 100.0);
274 stream2->align_info.dims = stream2->dims;
275 stream2->align_info.triangles_count = 2;
276 stream2->align_info.score = 1.0;
277 stream2->align_info.decimals = decimals;
278 pgarb("creating triangles for reference frame...\n");
279 while(stream1->triangles_count > 0)
280 dsp_stream_del_triangle(stream1, stream1->triangles_count-1);
281 for(x = 0; x < stream1->stars_count * (stream1->stars_count-num_stars+1) / 2; x++) {
282 for(y = 0; y < num_stars; y++) {
283 stars[y] = stream1->stars[(x + y * (x / stream1->stars_count + 1)) % stream1->stars_count];
284 }
285 dsp_triangle *t = dsp_align_calc_triangle(stars, num_stars);
286 dsp_stream_add_triangle(stream1, *t);
288 }
289 pgarb("creating triangles for current frame...\n");
290 while(stream2->triangles_count > 0)
291 dsp_stream_del_triangle(stream2, stream2->triangles_count-1);
292 for(x = 0; x < stream2->stars_count * (stream2->stars_count-num_stars+1) / 2; x++) {
293 for(y = 0; y < num_stars; y++) {
294 stars[y] = stream2->stars[(x + y * (x / stream2->stars_count + 1)) % stream2->stars_count];
295 }
296 dsp_triangle *t = dsp_align_calc_triangle(stars, num_stars);
297 dsp_stream_add_triangle(stream2, *t);
299 }
300 free(stars);
301 stream2->align_info.center = (double*)malloc(sizeof(double)*stream2->align_info.dims);
302 stream2->align_info.factor = (double*)malloc(sizeof(double)*stream2->align_info.dims);
303 stream2->align_info.offset = (double*)malloc(sizeof(double)*stream2->align_info.dims);
304 stream2->align_info.radians = (double*)malloc(sizeof(double)*(stream2->align_info.dims-1));
305 for(t1 = 0; t1 < stream1->triangles_count; t1++) {
306 for(t2 = 0; t2 < stream2->triangles_count; t2++) {
307 align_info = dsp_align_fill_info(stream1->triangles[t1], stream2->triangles[t2]);
308 if(align_info->score < stream2->align_info.score) {
309 memcpy(stream2->align_info.center, align_info->center, sizeof(double)*stream2->align_info.dims);
310 memcpy(stream2->align_info.factor, align_info->factor, sizeof(double)*stream2->align_info.dims);
311 memcpy(stream2->align_info.offset, align_info->offset, sizeof(double)*stream2->align_info.dims);
312 memcpy(stream2->align_info.radians, align_info->radians, sizeof(double)*(stream2->align_info.dims-1));
313 memcpy(stream2->align_info.triangles, align_info->triangles, sizeof(dsp_triangle)*2);
314 stream2->align_info.score = align_info->score;
315 stream2->align_info.decimals = decimals;
316 }
317 free(align_info->center);
318 free(align_info->factor);
319 free(align_info->offset);
320 free(align_info->radians);
321 free(align_info);
322 }
323 }
324 double radians = stream2->align_info.radians[0];
325 for(d = 0; d < stream1->dims; d++) {
326 phi += pow(stream2->align_info.offset[d], 2);
327 }
328 phi = pow(phi, 0.5);
329 stream2->align_info.err = 0xf;
330 if(floor(stream2->align_info.score * decimals) < floor(target_score * decimals))
331 stream2->align_info.err &= ~DSP_ALIGN_NO_MATCH;
332 if(fabs(phi * ratio * decimals) < 1.0)
333 stream2->align_info.err &= ~DSP_ALIGN_TRANSLATED;
334 if(floor(fabs(stream2->align_info.factor[0] - 1.0) * decimals) < 1)
335 stream2->align_info.err &= ~DSP_ALIGN_SCALED;
336 if(floor(fabs(radians) * decimals) < 1)
337 stream2->align_info.err &= ~DSP_ALIGN_ROTATED;
338 return stream2->align_info.err;
339}
#define M_PI
Definition dsp.h:52
#define pgarb(...)
Definition dsp.h:163
#define pwarn(...)
Definition dsp.h:162
int stars_count
The number of stars of the triangle.
Definition dsp.h:279
int err
Errors.
Definition dsp.h:306
dsp_point center
The center of the star.
Definition dsp.h:248
int triangles_count
Triangles of stars or objects quantity.
Definition dsp.h:439
int dims
Dimensions limit.
Definition dsp.h:296
double * factor
Scaling factor.
Definition dsp.h:294
double decimals
Decimals.
Definition dsp.h:304
double theta
The deviation of the star.
Definition dsp.h:256
double * center
Center of rotation coordinates.
Definition dsp.h:290
int * sizes
Sizes of each dimension.
Definition dsp.h:389
double * location
Center of the point.
Definition dsp.h:226
double * radians
Rotational offset.
Definition dsp.h:292
double index
The index of the triangle.
Definition dsp.h:267
dsp_star * stars
Stars or objects identified into the buffers - TODO.
Definition dsp.h:433
dsp_star * stars
The stars of the triangle.
Definition dsp.h:277
double * sizes
The sizes of the triangle.
Definition dsp.h:273
int stars_count
Stars or objects quantity.
Definition dsp.h:435
double diameter
The diameter of the star.
Definition dsp.h:250
int dims
The dimensions of the triangle.
Definition dsp.h:269
double * theta
The inclination of the triangle.
Definition dsp.h:271
dsp_align_info align_info
Align/scale/rotation settings.
Definition dsp.h:441
dsp_triangle * triangles
Triangles of stars or objects.
Definition dsp.h:437
int dims
Number of dimensions of the buffers.
Definition dsp.h:387
int triangles_count
Triangles quantity.
Definition dsp.h:300
int dims
Dimensions limit of the point.
Definition dsp.h:228
double score
Match score.
Definition dsp.h:302
double peak
The peak of the star.
Definition dsp.h:252
double * ratios
The sizes of the triangle.
Definition dsp.h:275
dsp_triangle triangles[2]
Reference triangles.
Definition dsp.h:298
double flux
The flux of the star.
Definition dsp.h:254
double * offset
Translation offset.
Definition dsp.h:288
DLL_EXPORT void dsp_stream_del_triangle(dsp_stream_p stream, int index)
Remove the triangle with index n to a DSP stream.
Definition stream.c:419
DLL_EXPORT void dsp_stream_add_triangle(dsp_stream_p stream, dsp_triangle triangle)
Add a triangle to the DSP Stream passed as argument.
Definition stream.c:378
int dsp_align_get_offset(dsp_stream_p stream1, dsp_stream_p stream2, double tolerance, double target_score, int num_stars)
Calculate offsets, rotation and scaling of two streams giving reference alignment point.
Definition align.c:259
dsp_triangle * dsp_align_calc_triangle(dsp_star *stars, int num_stars)
Create a dsp_triangle struct.
Definition align.c:197
dsp_align_info * dsp_align_fill_info(dsp_triangle t1, dsp_triangle t2)
Fill a dsp_align_info struct by comparing two triangles.
Definition align.c:147
void dsp_align_free_triangle(dsp_triangle *t)
Free a dsp_triangle struct pointer.
Definition align.c:184
double delta
Definition align.c:24
double * diff
Definition align.c:25
Alignment information needed.
Definition dsp.h:286
A star or object contained into a buffer.
Definition dsp.h:246
Contains a set of information and data relative to a buffer and how to use it.
Definition dsp.h:379
A star or object contained into a buffer.
Definition dsp.h:265