GIRAFFE Pipeline Reference Manual

giframestack.c
1/*
2 * This file is part of the GIRAFFE Pipeline
3 * Copyright (C) 2002-2019 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (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
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif
23
24#include <math.h>
25
26#include <cxmessages.h>
27#include <cxmemory.h>
28#include <cxlist.h>
29
30#include <cpl_type.h>
31#include <cpl_recipe.h>
32#include <cpl_plugininfo.h>
33#include <cpl_parameterlist.h>
34#include <cpl_frameset.h>
35#include <cpl_propertylist.h>
36#include <cpl_msg.h>
37
38#include "gialias.h"
39#include "giframe.h"
40#include "giimage.h"
41#include "gifibers.h"
42#include "gibias.h"
43#include "gimath.h"
44#include "gistacking.h"
45#include "giqclog.h"
46#include "gierror.h"
47#include "giutils.h"
48
49
50#define GIMASTERBIAS_BIAS_EXTENSION_IMG 0
51#define GIMASTERBIAS_BIAS_EXTENSION_PL 0
52#define GIMASTERBIAS_BAD_PIXEL_EXTENSION 0
53
54
55static cxint giframestack(cpl_parameterlist*, cpl_frameset*);
56
57
58/*
59 * Create the recipe instance, i.e. setup the parameter list for this
60 * recipe and make it availble to the application using the interface.
61 */
62
63static cxint
64giframestack_create(cpl_plugin* plugin)
65{
66
67 cpl_recipe* recipe = (cpl_recipe*)plugin;
68
69 giraffe_error_init();
70
71
72 /*
73 * We have to provide the option we accept to the application. We
74 * need to setup our parameter list and hook it into the recipe
75 * interface.
76 */
77
78 recipe->parameters = cpl_parameterlist_new();
79 cx_assert(recipe->parameters != NULL);
80
81 /*
82 * Fill the parameter list.
83 */
84
85 giraffe_stacking_config_add(recipe->parameters);
86
87 return 0;
88
89}
90
91
92/*
93 * Execute the plugin instance given by the interface.
94 */
95
96static cxint
97giframestack_exec(cpl_plugin* plugin)
98{
99
100 cpl_recipe* recipe = (cpl_recipe*)plugin;
101
102 cxint status = 0;
103
104
105 if (recipe->parameters == NULL || recipe->frames == NULL) {
106 return 1;
107 }
108
109 status = giframestack(recipe->parameters, recipe->frames);
110
111 if (status != 0) {
112 return 1;
113 }
114
115 return 0;
116
117}
118
119
120static cxint
121giframestack_destroy(cpl_plugin* plugin)
122{
123
124 cpl_recipe* recipe = (cpl_recipe*)plugin;
125
126
127 /*
128 * We just destroy what was created during the plugin initialization
129 * phase, i.e. the parameter list. The frame set is managed by the
130 * application which called us, so we must not touch it,
131 */
132
133 cpl_parameterlist_delete(recipe->parameters);
134
135 giraffe_error_clear();
136
137 return 0;
138
139}
140
141/*
142 * The actual recipe starts here.
143 */
144
145static cxint
146giframestack(cpl_parameterlist* config, cpl_frameset* set)
147{
148
149 const cxchar* const _id = "giframestack";
150
151
152 cxint i = 0;
153 cxint status = 0;
154
155 cxdouble exptime = 0.;
156
157 cx_string *tag = NULL;
158
159 cx_list *frames = NULL;
160 cx_list *images = NULL;
161
162 cx_list_iterator position;
163
164 cpl_size count = 0;
165
166 cpl_propertylist *properties = NULL;
167
168 cpl_frame* frame = NULL;
169
170 cpl_frameset_iterator *it = NULL;
171
172 GiImage *image = NULL;
173 GiImage *result = NULL;
174 GiImage **stack = NULL;
175
176 GiStackingConfig *setup = NULL;
177
178 GiRecipeInfo info = {(cxchar*)_id, 1, NULL, config};
179
180
181
182 setup = giraffe_stacking_config_create(config);
183
184 if (setup == NULL) {
185 cpl_msg_error(_id, "Invalid parameter list! Aborting ...");
186 return 1;
187 }
188
189
190 /*
191 * Create the list of frames to combine.
192 */
193
194 /*
195 * Search for the first image in the input frameset. This is
196 * used as reference in the selection of the other frames.
197 */
198
199 cpl_msg_info(_id, "Searching for frames to combine ...");
200
201 it = cpl_frameset_iterator_new(set);
202
203 frame = cpl_frameset_iterator_get(it);
204
205 if (frame == NULL) {
206 cpl_msg_error(_id, "Empty input frameset encountered!");
207
208 cpl_frameset_iterator_delete(it);
209 it = NULL;
210
212 setup = NULL;
213
214 return 1;
215 }
216
217
218 image = giraffe_image_new(CPL_TYPE_DOUBLE);
219
220 status = giraffe_image_load(image, cpl_frame_get_filename(frame), 0);
221
222 while (status != 0 && count < cpl_frameset_get_size(set)) {
223
224 cpl_frameset_iterator_advance(it, 1);
225
226 frame = cpl_frameset_iterator_get(it);
227
228 status = giraffe_image_load(image, cpl_frame_get_filename(frame), 0);
229 ++count;
230
231 }
232
233 cpl_frameset_iterator_delete(it);
234 it = NULL;
235
236 if (count == cpl_frameset_get_size(set)) {
237 cpl_msg_error(_id, "The input frameset does not contain any "
238 "images.");
239
241 image = NULL;
242
244 setup = NULL;
245
246 return 1;
247 }
248
249 tag = cx_string_create(cpl_frame_get_tag(frame));
250
251
252 /*
253 * Select frames for combination. Only frames with the same tag
254 * and the same size as the first raw frame are combined. All
255 * other frames are ignored.
256 */
257
258 cpl_msg_info(_id, "Selecting '%s' frames for combination.",
259 cx_string_get(tag));
260
261 frames = cx_list_new();
262 cx_list_push_back(frames, frame);
263
264 images = cx_list_new();
265 cx_list_push_back(images, image);
266
267
268 frame = cpl_frameset_find(set, cx_string_get(tag));
269
270 if (frame == cx_list_front(frames)) {
271 frame = cpl_frameset_find(set, NULL);
272 }
273
274 while (frame != NULL) {
275
276 if (frame != cx_list_front(frames)) {
277
278 GiImage* _image = giraffe_image_new(CPL_TYPE_DOUBLE);
279
280
281 status = giraffe_image_load(_image,
282 cpl_frame_get_filename(frame), 0);
283
284 if (status == 0) {
285
286 cxint nx = cpl_image_get_size_x(giraffe_image_get(_image));
287 cxint ny = cpl_image_get_size_y(giraffe_image_get(_image));
288
289 if (nx == cpl_image_get_size_x(giraffe_image_get(image)) &&
290 ny == cpl_image_get_size_y(giraffe_image_get(image))) {
291
292 cx_list_push_back(frames, frame);
293 cx_list_push_back(images, _image);
294
295 }
296 else {
297
298 cpl_msg_warning(_id, "Ignoring frame '%s' because of "
299 "different size!",
300 cpl_frame_get_filename(frame));
301
302 giraffe_image_delete(_image);
303 _image = NULL;
304
305 }
306
307 }
308 else {
309 giraffe_image_delete(_image);
310 _image = NULL;
311 }
312
313 }
314
315 frame = cpl_frameset_find(set, NULL);
316
317 }
318
319
320 /*
321 * Check whether there are sufficient raw frames present in the
322 * set for the selected combination method.
323 */
324
325 count = cx_list_size(images);
326
327 if (count < setup->min_nr_frames) {
328
329 cpl_msg_error(_id, "Not enough frames (%" CPL_SIZE_FORMAT
330 "). Stacking method '%d' requires at least %d frames! "
331 "Aborting...", count, setup->stackmethod,
332 setup->min_nr_frames);
333
334 cx_list_destroy(images, (cx_free_func)giraffe_image_delete);
335 images = NULL;
336
337 cx_list_delete(frames);
338 frames = NULL;
339
340 cx_string_delete(tag);
341 tag = NULL;
342
344 setup = NULL;
345
346 return 1;
347
348 }
349
350
351 /*
352 * Combine the selected frames
353 */
354
355 cpl_msg_info(_id, "Combining %" CPL_SIZE_FORMAT " frames (%s) ...", count,
356 cx_string_get(tag));
357
358 stack = cx_calloc(count + 1, sizeof(GiImage*));
359
360 i = 0;
361 position = cx_list_begin(images);
362
363 while (position != cx_list_end(images)) {
364 stack[i] = cx_list_get(images, position);
365 position = cx_list_next(images, position);
366 ++i;
367 }
368
369 result = giraffe_stacking_stack_images(stack, setup);
370
371 if (result == NULL) {
372
373 cpl_msg_error(_id,"Frame combination failed! Aborting ...");
374
375 cx_free(stack);
376 stack = NULL;
377
378 cx_list_destroy(images, (cx_free_func)giraffe_image_delete);
379 images = NULL;
380
381 cx_list_delete(frames);
382 frames = NULL;
383
384 cx_string_delete(tag);
385 tag = NULL;
386
388 setup = NULL;
389
390 return 1;
391
392 }
393
394 cx_free(stack);
395 stack = NULL;
396
398 setup = NULL;
399
400
401 /*
402 * Update the properties of the combined result frame.
403 */
404
405 cpl_msg_info(_id, "Updating combined frame properties ...");
406
407 properties = giraffe_image_get_properties(cx_list_front(images));
408 cx_assert(properties != NULL);
409
410 giraffe_image_set_properties(result, properties);
411 properties = giraffe_image_get_properties(result);
412
413 if (properties == NULL) {
414
415 cpl_msg_error(_id, "Updating combined frame properties failed!");
416
417 giraffe_image_delete(result);
418 result = NULL;
419
420 cx_list_destroy(images, (cx_free_func)giraffe_image_delete);
421 images = NULL;
422
423 cx_list_delete(frames);
424 frames = NULL;
425
426 cx_string_delete(tag);
427 tag = NULL;
428
429 return 1;
430
431 }
432
433 giraffe_error_push();
434
435 cpl_propertylist_update_double(properties, GIALIAS_BZERO, 0.);
436 cpl_propertylist_update_double(properties, GIALIAS_CRPIX1, 1.);
437
438 exptime = 0.;
439 position = cx_list_begin(images);
440
441 while (position != cx_list_end(images)) {
442
443 cpl_propertylist* p =
444 giraffe_image_get_properties(cx_list_get(images, position));
445
446 exptime += cpl_propertylist_get_double(p, GIALIAS_EXPTIME);
447 position = cx_list_next(images, position);
448
449 }
450
451 cpl_propertylist_update_double(properties, GIALIAS_EXPTTOT, exptime);
452
453 cpl_propertylist_update_int(properties, GIALIAS_DATANCOM, count);
454
455 cpl_propertylist_erase(properties, GIALIAS_EXPTIME);
456 cpl_propertylist_erase(properties, GIALIAS_TPLEXPNO);
457
458
459 if (cpl_error_get_code() != CPL_ERROR_NONE) {
460
461 cpl_msg_error(_id, "Updating combined frame properties failed!");
462
463 giraffe_image_delete(result);
464 result = NULL;
465
466 cx_list_destroy(images, (cx_free_func)giraffe_image_delete);
467 images = NULL;
468
469 cx_list_delete(frames);
470 frames = NULL;
471
472 cx_string_delete(tag);
473 tag = NULL;
474
475 return 1;
476
477 }
478
479 giraffe_error_pop();
480
481
482 /*
483 * Save the combined result frame and register it as a product.
484 */
485
486 cpl_msg_info(_id, "Writing combined frame ...");
487
488 giraffe_image_add_info(result, &info, set);
489
490 cx_string_append(tag, "_COMBINED");
491
492 frame = giraffe_frame_create_image(result, cx_string_get(tag),
493 CPL_FRAME_LEVEL_FINAL, TRUE, TRUE);
494
495 if (frame == NULL) {
496
497 cpl_msg_error(_id, "Cannot create local file! Aborting ...");
498
499 giraffe_image_delete(result);
500 result = NULL;
501
502 cx_list_destroy(images, (cx_free_func)giraffe_image_delete);
503 images = NULL;
504
505 cx_list_delete(frames);
506 frames = NULL;
507
508 cx_string_delete(tag);
509 tag = NULL;
510
511 return 1;
512
513 }
514
515 cpl_frameset_insert(set, frame);
516
517
518 /*
519 * Cleanup
520 */
521
522 giraffe_image_delete(result);
523 result = NULL;
524
525 cx_list_destroy(images, (cx_free_func)giraffe_image_delete);
526 images = NULL;
527
528 cx_list_delete(frames);
529 frames = NULL;
530
531 cx_string_delete(tag);
532 tag = NULL;
533
534 return 0;
535
536}
537
538
539/*
540 * Build table of contents, i.e. the list of available plugins, for
541 * this module. This function is exported.
542 */
543
544int
545cpl_plugin_get_info(cpl_pluginlist* list)
546{
547
548 cpl_recipe* recipe = cx_calloc(1, sizeof *recipe);
549 cpl_plugin* plugin = &recipe->interface;
550
551
552 cpl_plugin_init(plugin,
553 CPL_PLUGIN_API,
554 GIRAFFE_BINARY_VERSION,
555 CPL_PLUGIN_TYPE_RECIPE,
556 "giframestack",
557 "Creates a stacked image from a set of raw images.",
558 "TBD",
559 "Giraffe Pipeline",
560 PACKAGE_BUGREPORT,
562 giframestack_create,
563 giframestack_exec,
564 giframestack_destroy);
565
566 cpl_pluginlist_append(list, plugin);
567
568 return 0;
569
570}
cpl_frame * giraffe_frame_create_image(GiImage *image, const cxchar *tag, cpl_frame_level level, cxbool save, cxbool update)
Create an image product frame.
Definition: giframe.c:393
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
Definition: giimage.c:218
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
Definition: giimage.c:282
void giraffe_image_delete(GiImage *self)
Destroys an image.
Definition: giimage.c:181
cxint giraffe_image_add_info(GiImage *image, const GiRecipeInfo *info, const cpl_frameset *set)
Add additional frame information to an image.
Definition: giimage.c:773
GiImage * giraffe_image_new(cpl_type type)
Creates an empty image container.
Definition: giimage.c:65
cxint giraffe_image_set_properties(GiImage *self, cpl_propertylist *properties)
Attaches a property list to an image.
Definition: giimage.c:312
cxint giraffe_image_load(GiImage *self, const cxchar *filename, cxint position)
Gets image data and properties from a file.
Definition: giimage.c:536
void giraffe_stacking_config_add(cpl_parameterlist *list)
Adds parameters for the stacking of images.
Definition: gistacking.c:812
void giraffe_stacking_config_destroy(GiStackingConfig *config)
Destroys a setup structure for the stacking of images.
Definition: gistacking.c:789
GiStackingConfig * giraffe_stacking_config_create(cpl_parameterlist *list)
Creates a setup structure for the stacking of images.
Definition: gistacking.c:673
GiImage * giraffe_stacking_stack_images(GiImage **img_array, const GiStackingConfig *config)
Stack a list of images using one of four different kinds of stacking and return the resulting image.
Definition: gistacking.c:571
const cxchar * giraffe_get_license(void)
Get the pipeline copyright and license.
Definition: giutils.c:420

This file is part of the GIRAFFE Pipeline Reference Manual 2.17.1.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Wed Jun 11 2025 17:59:51 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2004