GIRAFFE Pipeline Reference Manual

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

This file is part of the GIRAFFE Pipeline Reference Manual 2.14.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Wed Mar 11 2015 13:19:41 by doxygen 1.8.9.1 written by Dimitri van Heesch, © 1997-2004