1 /*
2 * This file is part of Siril, an astronomy image processor.
3 * Copyright (C) 2005-2011 Francois Meyer (dulle at free.fr)
4 * Copyright (C) 2012-2021 team free-astro (see more in AUTHORS file)
5 * Reference site is https://free-astro.org/index.php/Siril
6 *
7 * Siril is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Siril is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Siril. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "core/siril.h"
26 #include "core/proto.h"
27 #include "core/OS_utils.h"
28 #include "io/single_image.h"
29 #include "io/sequence.h"
30 #include "gui/utils.h"
31 #include "gui/callbacks.h"
32 #include "gui/image_display.h"
33 #include "gui/image_interactions.h"
34 #include "gui/dialogs.h"
35 #include "gui/message_dialog.h"
36 #include "gui/PSF_list.h"
37 #include "gui/progress_and_log.h"
38 #include "algos/PSF.h"
39 #include "algos/star_finder.h"
40
41 static GtkListStore *liststore_stars = NULL;
42
43 enum {
44 COLUMN_CHANNEL, // int
45 COLUMN_B, // gdouble
46 COLUMN_A, // gdouble
47 COLUMN_X0, // gdouble
48 COLUMN_Y0, // gdouble
49 COLUMN_FWHMX, // gdouble
50 COLUMN_FWHMY, // gdouble
51 COLUMN_MAG, // gdouble
52 COLUMN_ROUNDNESS, // gdouble
53 COLUMN_ANGLE, // gdouble
54 COLUMN_RMSE, // gdouble
55 N_COLUMNS
56 };
57
58 enum { //different context_id of the GtkStatusBar
59 COUNT_STATE
60 };
61
62 static gchar *units = "";
63
gdouble_fwhmx_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)64 static void gdouble_fwhmx_cell_data_function(GtkTreeViewColumn *col,
65 GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter,
66 gpointer user_data) {
67 gdouble var;
68 gchar *buf;
69 gtk_tree_model_get(model, iter, COLUMN_FWHMX, &var, -1);
70 buf = g_strdup_printf("%.2f%s", var, units);
71 g_object_set(renderer, "text", buf, NULL);
72
73 g_free(buf);
74 }
75
gdouble_fwhmy_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)76 static void gdouble_fwhmy_cell_data_function(GtkTreeViewColumn *col,
77 GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter,
78 gpointer user_data) {
79 gdouble var;
80 gchar *buf;
81 gtk_tree_model_get(model, iter, COLUMN_FWHMY, &var, -1);
82 buf = g_strdup_printf("%.2f%s", var, units);
83 g_object_set(renderer, "text", buf, NULL);
84
85 g_free(buf);
86 }
87
gdouble_x0_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)88 static void gdouble_x0_cell_data_function(GtkTreeViewColumn *col,
89 GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter,
90 gpointer user_data) {
91 gdouble var;
92 gchar *buf;
93 gtk_tree_model_get(model, iter, COLUMN_X0, &var, -1);
94 buf = g_strdup_printf("%.2f", var);
95 g_object_set(renderer, "text", buf, NULL);
96
97 g_free(buf);
98 }
99
gdouble_y0_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)100 static void gdouble_y0_cell_data_function(GtkTreeViewColumn *col,
101 GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter,
102 gpointer user_data) {
103 gdouble var;
104 gchar *buf;
105 gtk_tree_model_get(model, iter, COLUMN_Y0, &var, -1);
106 buf = g_strdup_printf("%.2f", var);
107 g_object_set(renderer, "text", buf, NULL);
108
109 g_free(buf);
110 }
111
gdouble_mag_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)112 static void gdouble_mag_cell_data_function(GtkTreeViewColumn *col,
113 GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter,
114 gpointer user_data) {
115 gdouble var;
116 gchar *buf;
117 gtk_tree_model_get(model, iter, COLUMN_MAG, &var, -1);
118 buf = g_strdup_printf("%.2f", var);
119 g_object_set(renderer, "text", buf, NULL);
120
121 g_free(buf);
122 }
123
gdouble_r_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)124 static void gdouble_r_cell_data_function(GtkTreeViewColumn *col,
125 GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter,
126 gpointer user_data) {
127 gdouble var;
128 gchar *buf;
129 gtk_tree_model_get(model, iter, COLUMN_ROUNDNESS, &var, -1);
130 buf = g_strdup_printf("%.3f", var);
131 g_object_set(renderer, "text", buf, NULL);
132
133 g_free(buf);
134 }
135
gdouble_angle_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)136 static void gdouble_angle_cell_data_function(GtkTreeViewColumn *col,
137 GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter,
138 gpointer user_data) {
139 gdouble var;
140 gchar *buf;
141 gtk_tree_model_get(model, iter, COLUMN_ANGLE, &var, -1);
142 if (var == 0.0)
143 buf = g_strdup_printf("%s", "N/A");
144 else
145 buf = g_strdup_printf("%.2f", var);
146 g_object_set(renderer, "text", buf, NULL);
147
148 g_free(buf);
149 }
150
gdouble_rmse_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)151 static void gdouble_rmse_cell_data_function(GtkTreeViewColumn *col,
152 GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter,
153 gpointer user_data) {
154 gdouble var;
155 gchar *buf;
156 gtk_tree_model_get(model, iter, COLUMN_RMSE, &var, -1);
157 buf = g_strdup_printf("%.2e", var);
158 g_object_set(renderer, "text", buf, NULL);
159
160 g_free(buf);
161 }
162
get_stars_list_store()163 static void get_stars_list_store() {
164 if (liststore_stars == NULL)
165 liststore_stars = GTK_LIST_STORE(gtk_builder_get_object(builder, "liststore_stars"));
166
167 GtkTreeViewColumn *col;
168 GtkCellRenderer *cell;
169
170 col = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "treeviewcolumn7"));
171 cell = GTK_CELL_RENDERER(gtk_builder_get_object(builder, "cell_x0"));
172 gtk_tree_view_column_set_cell_data_func(col, cell, gdouble_x0_cell_data_function, NULL, NULL);
173
174 col = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "treeviewcolumn8"));
175 cell = GTK_CELL_RENDERER(gtk_builder_get_object(builder, "cell_y0"));
176 gtk_tree_view_column_set_cell_data_func(col, cell, gdouble_y0_cell_data_function, NULL, NULL);
177
178 col = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "treeviewcolumn9"));
179 cell = GTK_CELL_RENDERER(gtk_builder_get_object(builder, "cell_fwhmx"));
180 gtk_tree_view_column_set_cell_data_func(col, cell, gdouble_fwhmx_cell_data_function, NULL, NULL);
181
182 col = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "treeviewcolumn10"));
183 cell = GTK_CELL_RENDERER(gtk_builder_get_object(builder, "cell_fwhmy"));
184 gtk_tree_view_column_set_cell_data_func(col, cell, gdouble_fwhmy_cell_data_function, NULL, NULL);
185
186 col = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "treeviewcolumn_mag"));
187 cell = GTK_CELL_RENDERER(gtk_builder_get_object(builder, "cell_mag"));
188 gtk_tree_view_column_set_cell_data_func(col, cell, gdouble_mag_cell_data_function, NULL, NULL);
189
190 col = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "treeviewcolumn14"));
191 cell = GTK_CELL_RENDERER(gtk_builder_get_object(builder, "cell_r"));
192 gtk_tree_view_column_set_cell_data_func(col, cell, gdouble_r_cell_data_function, NULL, NULL);
193
194 col = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "treeviewcolumn6"));
195 cell = GTK_CELL_RENDERER(gtk_builder_get_object(builder, "cell_angle"));
196 gtk_tree_view_column_set_cell_data_func(col, cell, gdouble_angle_cell_data_function, NULL, NULL);
197
198 col = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "treeviewcolumn15"));
199 cell = GTK_CELL_RENDERER(gtk_builder_get_object(builder, "cell_rmse"));
200 gtk_tree_view_column_set_cell_data_func(col, cell, gdouble_rmse_cell_data_function, NULL, NULL);
201 }
202
display_PSF(fitted_PSF ** result)203 static void display_PSF(fitted_PSF **result) {
204 if (result) {
205 gchar *msg;
206 int i = 0;
207 double FWHMx = 0.0, FWHMy = 0.0, B = 0.0, A = 0.0, r = 0.0, angle = 0.0,
208 rmse = 0.0;
209 gboolean unit_is_arcsec;
210
211 while (result[i]) {
212 double fwhmx, fwhmy;
213 char *unit;
214 gboolean is_as = get_fwhm_as_arcsec_if_possible(result[i], &fwhmx, &fwhmy, &unit);
215 if (i == 0)
216 unit_is_arcsec = is_as;
217 else if (is_as != unit_is_arcsec) {
218 siril_message_dialog(GTK_MESSAGE_ERROR, _("Error"),
219 _("Stars FWHM must have the same units."));
220 return;
221 }
222
223 B += result[i]->B;
224 A += result[i]->A;
225 FWHMx += fwhmx;
226 FWHMy += fwhmy;
227 angle += result[i]->angle;
228 rmse += result[i]->rmse;
229 i++;
230 }
231 if (i <= 0) return;
232 /* compute average */
233 B = B / (double)i;
234 A = A / (double)i;
235 FWHMx = FWHMx / (double)i;
236 FWHMy = FWHMy / (double)i;
237 r = FWHMy / FWHMx;
238 angle = angle / (double)i;
239 rmse = rmse / (double)i;
240
241 msg = g_strdup_printf(_("Average Gaussian PSF\n\n"
242 "N:\t%d stars\nB:\t%.6f\nA:\t%.6f\nFWHMx:\t%.2f%s\n"
243 "FWHMy:\t%.2f%s\nr:\t%.3f\nAngle:\t%.2f deg\nrmse:\t%.3e\n"),
244 i, B, A, FWHMx, result[0]->units, FWHMy,
245 result[0]->units, r, angle, rmse);
246 show_data_dialog(msg, _("Average Star Data"), "stars_list_window", NULL);
247 g_free(msg);
248 }
249 }
250
get_index_of_selected_star(gdouble x,gdouble y)251 static gint get_index_of_selected_star(gdouble x, gdouble y) {
252 int i = 0;
253
254 while (com.stars && com.stars[i]) {
255 if ((com.stars[i]->xpos == x) && (com.stars[i]->ypos == y)) {
256 return i;
257 }
258 i++;
259 }
260 return -1;
261 }
262
display_status()263 static void display_status() {
264 gchar *text;
265 int i = 0;
266 GtkStatusbar *statusbar;
267
268 statusbar = GTK_STATUSBAR(lookup_widget("statusbar_PSF"));
269
270 while (com.stars && com.stars[i])
271 i++;
272 if (com.selected_star == -1) {
273 if (i > 0) {
274 text = ngettext("%d star", "%d stars", i);
275 text = g_strdup_printf(text, i);
276 } else {
277 text = g_strdup(" ");
278 }
279 } else {
280 text = g_strdup_printf(_("Star %d of %d"), com.selected_star + 1, i);
281 }
282 gtk_statusbar_push(statusbar, COUNT_STATE, text);
283 g_free(text);
284 }
285
remove_selected_star(int index)286 static void remove_selected_star(int index) {
287 GtkTreeSelection *selection = GTK_TREE_SELECTION(gtk_builder_get_object(builder, "treeview-selection"));
288 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtk_builder_get_object(builder, "Stars_stored")));
289 GtkTreeIter iter;
290
291 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
292 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
293 gtk_tree_selection_unselect_all(selection);
294
295 remove_star(index);
296
297 com.selected_star = -1;
298 display_status();
299 }
300 }
301
remove_all_stars()302 static void remove_all_stars(){
303 clear_stars_list();
304 com.selected_star = -1;
305 display_status();
306 redraw(com.cvport, REMAP_NONE);
307 }
308
save_list(gchar * filename)309 static int save_list(gchar *filename) {
310 int i = 0;
311 if (!com.stars)
312 return 1;
313 GError *error = NULL;
314
315 GFile *file = g_file_new_for_path(filename);
316 GOutputStream *output_stream = (GOutputStream*) g_file_replace(file, NULL, FALSE,
317 G_FILE_CREATE_NONE, NULL, &error);
318
319 if (output_stream == NULL) {
320 if (error != NULL) {
321 g_warning("%s\n", error->message);
322 g_clear_error(&error);
323 fprintf(stderr, "save_list: Cannot save star list\n");
324 }
325 g_object_unref(file);
326 return 1;
327 }
328
329 while (com.stars[i]) {
330 gchar *buffer = g_strdup_printf(
331 "%d\t%d\t%10.6f %10.6f %10.2f %10.2f %10.2f %10.2f %3.2f %10.3e %10.2f%s",
332 i + 1, com.stars[i]->layer, com.stars[i]->B, com.stars[i]->A,
333 com.stars[i]->xpos, com.stars[i]->ypos, com.stars[i]->fwhmx,
334 com.stars[i]->fwhmy, com.stars[i]->angle, com.stars[i]->rmse, com.stars[i]->mag, SIRIL_EOL);
335
336 if (!g_output_stream_write_all(output_stream, buffer, strlen(buffer), NULL, NULL, &error)) {
337 g_warning("%s\n", error->message);
338 g_free(buffer);
339 g_clear_error(&error);
340 g_object_unref(output_stream);
341 g_object_unref(file);
342 return 1;
343 }
344 i++;
345 g_free(buffer);
346 }
347 siril_log_message(_("The file %s has been created.\n"), filename);
348 g_object_unref(file);
349
350 return 0;
351 }
352
set_filter(GtkFileChooser * dialog)353 static void set_filter(GtkFileChooser *dialog) {
354 GtkFileFilter *f = gtk_file_filter_new();
355 gtk_file_filter_set_name(f, _("Star list file (*.lst)"));
356 gtk_file_filter_add_pattern(f, "*.lst");
357 gtk_file_chooser_add_filter(dialog, f);
358 gtk_file_chooser_set_filter(dialog, f);
359 }
360
save_stars_dialog()361 static void save_stars_dialog() {
362 SirilWidget *widgetdialog;
363 GtkFileChooser *dialog = NULL;
364 GtkWindow *parent = GTK_WINDOW(lookup_widget("stars_list_window"));
365 gint res;
366
367 widgetdialog = siril_file_chooser_save(parent, GTK_FILE_CHOOSER_ACTION_SAVE);
368 dialog = GTK_FILE_CHOOSER(widgetdialog);
369 gtk_file_chooser_set_current_folder(dialog, com.wd);
370 gtk_file_chooser_set_select_multiple(dialog, FALSE);
371 gtk_file_chooser_set_do_overwrite_confirmation(dialog, TRUE);
372 gtk_file_chooser_set_current_name(dialog, "stars.lst");
373 set_filter(dialog);
374
375 res = siril_dialog_run(widgetdialog);
376 if (res == GTK_RESPONSE_ACCEPT) {
377 gchar *file = gtk_file_chooser_get_filename(dialog);
378 save_list(file);
379
380 g_free(file);
381 }
382 siril_widget_destroy(widgetdialog);
383 }
384
385 /********************* public ***********************/
386
add_star_to_list(fitted_PSF * star)387 void add_star_to_list(fitted_PSF *star) {
388 static GtkTreeSelection *selection = NULL;
389 GtkTreeIter iter;
390
391 get_stars_list_store();
392 if (!selection)
393 selection = GTK_TREE_SELECTION(gtk_builder_get_object(builder, "treeview-selection"));
394 if (star == NULL) {
395 gtk_list_store_clear(liststore_stars);
396 return; // just clear the list
397 }
398
399 gtk_list_store_append (liststore_stars, &iter);
400 gtk_list_store_set (liststore_stars, &iter,
401 COLUMN_CHANNEL, star->layer,
402 COLUMN_B, star->B,
403 COLUMN_A, star->A,
404 COLUMN_X0, star->xpos,
405 COLUMN_Y0, star->ypos,
406 COLUMN_FWHMX, star->fwhmx,
407 COLUMN_FWHMY, star->fwhmy,
408 COLUMN_MAG, star->mag,
409 COLUMN_ROUNDNESS, star->fwhmy/star->fwhmx,
410 COLUMN_ANGLE, star->angle,
411 COLUMN_RMSE, star->rmse,
412 -1);
413
414 units = star->units;
415 display_status();
416 }
417
fill_stars_list(fits * fit,fitted_PSF ** stars)418 void fill_stars_list(fits *fit, fitted_PSF **stars) {
419 int i = 0;
420 if (stars == NULL)
421 return;
422 add_star_to_list(NULL); // clear
423
424 while (stars[i]) {
425 /* update units if needed */
426 fwhm_to_arcsec_if_needed(fit, stars[i]);
427 add_star_to_list(stars[i]);
428 i++;
429 }
430 com.selected_star = -1;
431 }
432
refresh_star_list(fitted_PSF ** star)433 void refresh_star_list(fitted_PSF **star){
434 get_stars_list_store();
435 gtk_list_store_clear(liststore_stars);
436 fill_stars_list(&gfit, com.stars);
437 redraw(com.cvport, REMAP_NONE);
438 }
439
clear_stars_list()440 void clear_stars_list() {
441 if (com.stars) {
442 if (!com.headless) {
443 get_stars_list_store();
444 gtk_list_store_clear(liststore_stars);
445 }
446 if (com.stars[0]) {
447 /* freeing found stars. It must not be done when the only star in
448 * com.stars is the same as com.seq.imgparam[xxx].fwhm, as set in
449 * set_fwhm_star_as_star_list(), because it will be reused */
450 if (com.stars[1] || !com.star_is_seqdata) {
451 int i = 0;
452 while (i < MAX_STARS && com.stars[i])
453 free(com.stars[i++]);
454 }
455 }
456 free(com.stars);
457 com.stars = NULL;
458 }
459 com.star_is_seqdata = FALSE;
460 }
461
pick_a_star()462 void pick_a_star() {
463 int layer = match_drawing_area_widget(com.vport[com.cvport], FALSE);
464 int new_index;
465
466 if (layer != -1) {
467 if (!(com.selection.h && com.selection.w))
468 return;
469 if (com.selection.w > 300 || com.selection.h > 300) {
470 siril_message_dialog(GTK_MESSAGE_WARNING, _("Current selection is too large"),
471 _("To determine the PSF, please make a selection around a star."));
472 return;
473 }
474 fitted_PSF *new_star = add_star(&gfit, layer, &new_index);
475 if (new_star) {
476 add_star_to_list(new_star);
477 siril_open_dialog("stars_list_window");
478 } else
479 return;
480 }
481 redraw(com.cvport, REMAP_NONE);
482 }
483
484 /***************** callbacks ****************/
485
on_treeview_cursor_changed(GtkTreeView * tree_view,gpointer user_data)486 void on_treeview_cursor_changed(GtkTreeView *tree_view,
487 gpointer user_data) {
488 GtkTreeModel *treeModel = gtk_tree_view_get_model(tree_view);
489 GtkTreeSelection *selection = gtk_tree_view_get_selection (tree_view);
490 GtkTreeIter iter;
491 GValue value_x = G_VALUE_INIT;
492 GValue value_y = G_VALUE_INIT;
493
494 if (gtk_tree_model_get_iter_first(treeModel, &iter) == FALSE)
495 return; //The tree is empty
496 if (gtk_tree_selection_get_selected(selection, &treeModel, &iter)) { //get selected item
497 gdouble x0, y0;
498
499 gtk_tree_model_get_value(treeModel, &iter, COLUMN_X0, &value_x);
500 x0 = g_value_get_double(&value_x);
501 gtk_tree_model_get_value(treeModel, &iter, COLUMN_Y0, &value_y);
502 y0 = g_value_get_double(&value_y);
503
504 g_value_unset(&value_x);
505 g_value_unset(&value_y);
506
507 com.selected_star = get_index_of_selected_star(x0, y0);
508 display_status();
509 redraw(com.cvport, REMAP_NONE);
510 }
511 }
512
on_Stars_stored_key_release_event(GtkWidget * widget,GdkEventKey * event,gpointer user_data)513 void on_Stars_stored_key_release_event(GtkWidget *widget, GdkEventKey *event,
514 gpointer user_data) {
515 if (event->keyval == GDK_KEY_Delete || event->keyval == GDK_KEY_KP_Delete
516 || event->keyval == GDK_KEY_BackSpace) {
517
518 remove_selected_star(com.selected_star);
519 }
520 }
521
on_stars_list_window_hide(GtkWidget * object,gpointer user_data)522 void on_stars_list_window_hide(GtkWidget *object, gpointer user_data) {
523 com.selected_star = -1;
524 }
525
on_sum_button_clicked(GtkButton * button,gpointer user_data)526 void on_sum_button_clicked(GtkButton *button, gpointer user_data) {
527 display_PSF(com.stars);
528 }
529
on_remove_button_clicked(GtkButton * button,gpointer user_data)530 void on_remove_button_clicked(GtkButton *button, gpointer user_data) {
531 remove_selected_star(com.selected_star);
532 }
533
on_remove_all_button_clicked(GtkButton * button,gpointer user_data)534 void on_remove_all_button_clicked(GtkButton *button, gpointer user_data) {
535 remove_all_stars();
536 }
537
on_process_starfinder_button_clicked(GtkButton * button,gpointer user_data)538 void on_process_starfinder_button_clicked(GtkButton *button, gpointer user_data) {
539 int nbstars = 0;
540 int layer = com.cvport == RGB_VPORT ? GLAYER : com.cvport;
541 if (!single_image_is_loaded() && !sequence_is_loaded()) {
542 siril_log_color_message(_("Load an image first, aborted.\n"), "red");
543 return;
544 }
545 set_cursor_waiting(TRUE);
546
547 confirm_peaker_GUI(); //making sure the spin buttons values are read even without confirmation
548 delete_selected_area();
549 com.stars = peaker(&gfit, layer, &com.starfinder_conf, &nbstars, NULL, TRUE);
550 siril_log_message(_("Found %d stars in image, channel #%d\n"), nbstars, layer);
551 if (com.stars)
552 refresh_star_list(com.stars);
553 set_cursor_waiting(FALSE);
554 }
555
on_export_button_clicked(GtkButton * button,gpointer user_data)556 void on_export_button_clicked(GtkButton *button, gpointer user_data) {
557 if (com.stars) {
558 save_stars_dialog();
559 } else {
560 siril_message_dialog(GTK_MESSAGE_WARNING, _("Nothing to export"),
561 _("There are no stars in the list."));
562 }
563 }
564
on_stars_list_window_show(GtkWidget * widget,gpointer user_data)565 void on_stars_list_window_show(GtkWidget *widget, gpointer user_data) {
566 update_peaker_GUI();
567 fill_stars_list(&gfit, com.stars);
568 }
569
on_button_stars_list_ok_clicked(GtkButton * button,gpointer user_data)570 void on_button_stars_list_ok_clicked(GtkButton *button, gpointer user_data) {
571 siril_close_dialog("stars_list_window");
572 }
573
574