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 
55 static 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 
63 static cxint
64 giframestack_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 
96 static cxint
97 giframestack_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 
120 static cxint
121 giframestack_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 
145 static cxint
146 giframestack(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 
240  giraffe_image_delete(image);
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 
544 int
545 cpl_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
void giraffe_image_delete(GiImage *self)
Destroys an image.
Definition: giimage.c:181
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
Definition: giimage.c:282
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
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
Definition: giimage.c:218
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:418

This file is part of the GIRAFFE Pipeline Reference Manual 2.16.10.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Dec 15 2022 21:18:51 by doxygen 1.9.1 written by Dimitri van Heesch, © 1997-2004