VISIR Pipeline Reference Manual  4.1.0
visir_util_clip.c
1 /* $Id: visir_util_clip.c,v 1.53 2013-05-23 14:33:29 jtaylor Exp $
2  *
3  * This file is part of the VISIR Pipeline
4  * Copyright (C) 2002,2003 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., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: jtaylor $
23  * $Date: 2013-05-23 14:33:29 $
24  * $Revision: 1.53 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 
36 #include "visir_recipe.h"
37 
38 #include <string.h>
39 #include <strings.h> /* for strcasecmp */
40 #include <math.h>
41 #ifdef _OPENMP
42 #include <omp.h>
43 #endif
44 
45 /*-----------------------------------------------------------------------------
46  Defines
47  -----------------------------------------------------------------------------*/
48 
49 #define RECIPE_STRING "visir_util_clip"
50 
51 #ifndef VISIR_UTIL_CLIP_KEEPFRAC
52 #define VISIR_UTIL_CLIP_KEEPFRAC 0.9
53 #endif
54 #ifndef VISIR_UTIL_CLIP_KAPPA
55 #define VISIR_UTIL_CLIP_KAPPA 5.0
56 #endif
57 
58 #ifndef VISIR_UTIL_CLIP_MAXITE
59 #define VISIR_UTIL_CLIP_MAXITE 3
60 #endif
61 
62 #define VISIR_UTIL_CLIP_QC_MAP_MAX "ESO QC CONTRIBUTION MAX"
63 #define VISIR_UTIL_CLIP_QC_MAP_MEAN "ESO QC CONTRIBUTION MEAN"
64 #define VISIR_UTIL_CLIP_QC_MAP_MEDIAN "ESO QC CONTRIBUTION MEDIAN"
65 
66 typedef enum {
67  VISIR_ERROR_SRC_IMG_STDEV,
68  VISIR_ERROR_SRC_TIMESERIES,
69 } visir_error_source;
70 
71 /* used by sigmaclipping to cache some expensive values */
72 static int prnok_nz = 0;
73 static double * prnok = NULL;
74 
75 /*-----------------------------------------------------------------------------
76  Private Functions prototypes
77  -----------------------------------------------------------------------------*/
78 static double median_abs_dev(const cpl_image * img)
79 {
80  /* use cpl_image_get_mad when cpl 6.2 only supported version */
81  const size_t npix = cpl_image_get_size_x(img) * cpl_image_get_size_y(img);
82  const double median = cpl_image_get_median(img);
83  const cpl_mask * bpm = cpl_image_get_bpm_const(img);
84  const cpl_binary * bpm_ = cpl_mask_get_data_const(bpm);
85  const float * data = cpl_image_get_data_float_const(img);
86  cpl_array * tmp = cpl_array_new(npix, CPL_TYPE_FLOAT);
87 
88  for (size_t i = 0; i < npix; i++)
89  if (bpm_[i] != CPL_BINARY_0)
90  cpl_array_set_invalid(tmp, i);
91  else
92  cpl_array_set_float(tmp, i, fabs(data[i] - median));
93 
94  double mad = cpl_array_get_median(tmp);
95  cpl_array_delete(tmp);
96  return mad;
97 }
98 
99 static
100 cpl_error_code visir_util_clip_kappa_sigma_double(cpl_imagelist *,
101  cpl_imagelist *,
102  double, double, int,
103  const int *);
104 static
105 cpl_error_code visir_util_clip_kappa_sigma_float(cpl_imagelist *,
106  cpl_imagelist *,
107  double, double, int,
108  const int *);
109 static
110 cpl_error_code visir_util_clip_kappa_sigma_int(cpl_imagelist *,
111  cpl_imagelist *,
112  double, double, int,
113  const int *);
114 
115 static cpl_error_code visir_util_clip_one(cpl_frameset *,
116  irplib_framelist *,
117  irplib_framelist *,
118  const cpl_mask *,
119  int, cpl_boolean,
120  const cpl_parameterlist *);
121 
122 static cpl_error_code visir_util_clip_kappa_sigma(cpl_imagelist *,
123  cpl_imagelist *,
124  const cpl_parameterlist *,
125  const int * shifts);
126 
127 
128 #ifdef VISIR_CHAIN
129 #define cpl_plugin_get_info visir_util_clip_get_info
130 #endif
131 cpl_recipe_define(visir_util_clip, VISIR_BINARY_VERSION,
132  "Lars Lundin", PACKAGE_BUGREPORT, "2011",
133  "Kappa-sigma clipping of outliers for each pixel",
134  "The files listed in the Set Of Frames (sof-file) "
135  "must be tagged pair-wise:\n"
136  "VISIR-raw-file.fits " VISIR_UTIL_INPUTS_RAW "\n"
137  "VISIR-bpm-file.fits " VISIR_CALIB_BPM "\n"
138  "\nThe product(s) will have a FITS card\n"
139  "'HIERARCH ESO PRO CATG' with a value of:\n"
140  VISIR_IMG_CLIPPED_PROCATG "\n"
141  "The outliers are marked as rejected in the matching\n"
142  "bad pixel map.");
143 
144 /*----------------------------------------------------------------------------*/
148 /*----------------------------------------------------------------------------*/
149 
150 /*-----------------------------------------------------------------------------
151  Functions code
152  -----------------------------------------------------------------------------*/
153 
154 /*----------------------------------------------------------------------------*/
162 /*----------------------------------------------------------------------------*/
163 static
164 cpl_error_code visir_util_clip_fill_parameterlist(cpl_parameterlist * self)
165 {
166 
167  const char * context = PACKAGE "." RECIPE_STRING;
168  cpl_error_code err;
169 
170  cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
171 
172  /* Fill the parameters list */
173 
174  /* --keepfrac */
175  err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING,
176  "keepfrac", VISIR_UTIL_CLIP_KEEPFRAC,
177  NULL, context, "The fraction of "
178  "pixels to keep for the initial"
179  "median");
180  cpl_ensure_code(!err, err);
181 
182 
183  /* --kappa */
184  err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING,
185  "kappa", VISIR_UTIL_CLIP_KAPPA,
186  NULL, context, "Clip outside "
187  "+ or - kappa * sigma "
188  "(the standard deviation)");
189  cpl_ensure_code(!err, err);
190 
191 
192  /* --maxite */
193  err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
194  "maxite", VISIR_UTIL_CLIP_MAXITE, NULL,
195  context, "Max number of kappa-sigma "
196  "clipping iterations");
197  cpl_ensure_code(!err, err);
198 
199  /* --shift-beams */
200  err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
201  "shift-beams", CPL_TRUE, NULL,
202  context, "Account for movements of the "
203  "object defined in CRPIX[12]");
204  cpl_ensure_code(!err, err);
205 
206  /* FIXME: add an adaptive mode that just requires n pixels
207  * and prefers timeseries mode */
208  /* --error-source */
209  err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
210  "error-source", "img-stdev", NULL,
211  context, "Defines the way errors "
212  "are generated:\n"
213  " img-stdev: stdev of image\n"
214  " timeseries: stdev of each pixel "
215  "over the time axis of the cube\n"
216  " none: no error generation");
217  cpl_ensure_code(!err, err);
218 
219  /* --error-out-type */
220  err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
221  "error-out-type", "error", NULL,
222  context, "Output clipped error as "
223  "error, variance, weight or none");
224  cpl_ensure_code(!err, err);
225 
226  /* --badimage */
227  err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING,
228  "badimage", 0.2, NULL,
229  context, "If percentage of clipped "
230  "pixels above this value the whole "
231  "image is considered bad");
232  cpl_ensure_code(!err, err);
233 
234  return CPL_ERROR_NONE;
235 
236 }
237 
238 /*----------------------------------------------------------------------------*/
245 /*----------------------------------------------------------------------------*/
246 static int visir_util_clip(cpl_frameset * framelist,
247  const cpl_parameterlist * parlist)
248 {
249  cpl_errorstate cleanstate = cpl_errorstate_get();
250  cpl_error_code didfail = CPL_ERROR_NONE;
251  irplib_framelist * allframes = NULL;
252  irplib_framelist * rawframes = NULL;
253  irplib_framelist * bpmframes = NULL;
254  cpl_size n, nbad = 0;
255  cpl_mask * static_mask = NULL;
256  prnok = NULL;
257 
258 #ifdef _OPENMP
259  omp_set_num_threads(visir_get_num_threads(CPL_FALSE));
260 #endif
261 
262  /* Identify the RAW and CALIB frames in the input frameset */
263  skip_if (visir_dfs_set_groups(framelist));
264  cpl_fits_set_mode(CPL_FITS_START_CACHING);
265 
266  /* Objects observation */
267  allframes = irplib_framelist_cast(framelist);
268  skip_if(allframes == NULL);
269  rawframes =
270  irplib_framelist_extract_regexp(allframes, "^("VISIR_UTIL_INPUTS_RAW
271  "|"VISIR_UTIL_CORRECTED")$",
272  CPL_FALSE);
273  skip_if (rawframes == NULL);
274  bpmframes = irplib_framelist_extract_regexp(allframes, "^(" VISIR_CALIB_BPM
275  ")$", CPL_FALSE);
276 
277  if (bpmframes == NULL)
278  cpl_errorstate_set(cleanstate);
279  else
280  nbad = irplib_framelist_get_size(bpmframes);
281 
282  {
283  cpl_frame * static_frm = cpl_frameset_find(framelist,
284  VISIR_CALIB_STATIC_MASK);
285  if (static_frm) {
286  const char * fn = cpl_frame_get_filename(static_frm);
287  static_mask = cpl_mask_load(fn, 0, 0);
288  if (!static_mask) {
289  cpl_errorstate_set(cleanstate);
290  static_mask = cpl_mask_load(fn, 0, 1);
291  if (!static_mask)
292  cpl_errorstate_set(cleanstate);
293  }
294  }
295  }
296 
297  n = irplib_framelist_get_size(rawframes);
298  error_if(nbad != n && nbad != 1 && nbad != 0, CPL_ERROR_INCOMPATIBLE_INPUT,
299  "%d raw-frames <=> %d bpm frames", (int)n, (int)nbad);
300 
301  /* cpl 6.0 fits caching is buggy when paralizing over many files */
302 #if defined _OPENMP && \
303  defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(6, 1, 0)
304 #pragma omp parallel for
305 #endif
306  for (cpl_size i = 0; i < n; i++) {
307  if (!didfail) {
308 
309  /* The total number of iterations must be pre-determined for the
310  parallelism to work. In case of an error we can therefore not
311  break, so instead we skip immediately to the next iteration.
312  FIXME: This check on didfail does not guarantee that only one
313  iteration can cause an error to be dumped, but it is not
314  worse than checking on a thread-local state, e.g. errori. */
315 
316  if (visir_util_clip_one(framelist, rawframes, bpmframes,
317  static_mask, i,
318  nbad == 1, parlist)) {
319  const cpl_error_code errori = cpl_error_set_where(cpl_func);
320 #ifdef _OPENMP
321  /* Cannot access these errors after the join,
322  so dump them now. :-(((((((((((((((((((( */
323  cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
324  cpl_errorstate_set(cleanstate);
325 #pragma omp critical(visir_util_clip)
326 #endif
327  didfail = errori;
328  }
329  }
330  }
331 
332  error_if(didfail, didfail, "Failed to clip %d frame(s)", (int)n);
333 
334  end_skip;
335 
336  irplib_framelist_delete(allframes);
337  irplib_framelist_delete(rawframes);
338  irplib_framelist_delete(bpmframes);
339  cpl_free(prnok);
340  prnok = NULL;
341 
342  return cpl_error_get_code();
343 }
344 
345 
346 /*----------------------------------------------------------------------------*/
358 /*----------------------------------------------------------------------------*/
359 static cpl_error_code visir_util_clip_one(cpl_frameset * framelist,
360  irplib_framelist * rawframes,
361  irplib_framelist * bpmframes,
362  const cpl_mask * static_mask,
363  int iframe, cpl_boolean bshared,
364  const cpl_parameterlist * parlist)
365 {
366 
367  cpl_frameset * products = cpl_frameset_new();
368  cpl_frameset * usedframes = cpl_frameset_new();
369 
370  char * bpmname = cpl_sprintf(RECIPE_STRING "_bpm_%03d" CPL_DFS_FITS, iframe);
371  char * mapname = cpl_sprintf(RECIPE_STRING "_map_%03d" CPL_DFS_FITS, iframe);
372  char * errname = cpl_sprintf(RECIPE_STRING "_error_%03d" CPL_DFS_FITS, iframe);
373 
374  const int n = irplib_framelist_get_size(rawframes);
375  cpl_frameset * rawone = cpl_frameset_new();
376  cpl_frameset * bpmone = cpl_frameset_new();
377  cpl_frame * rawframe =
378  cpl_frame_duplicate(irplib_framelist_get_const(rawframes, iframe));
379  cpl_frame * bpmframe = bpmframes ?
380  cpl_frame_duplicate(irplib_framelist_get_const(bpmframes,
381  bshared ? 0 : iframe))
382  : NULL;
383  const cpl_error_code errr = cpl_frameset_insert(rawone, rawframe);
384  const cpl_error_code errb = bpmframe ?
385  cpl_frameset_insert(bpmone, bpmframe) : CPL_ERROR_NONE;
386 
387  const char * serr = irplib_parameterlist_get_string(parlist, PACKAGE,
388  RECIPE_STRING,
389  "error-out-type");
390  cpl_boolean berr = serr && strcasecmp(serr, "none") != 0;
391 
392  const cpl_boolean bshifts = irplib_parameterlist_get_bool(parlist, PACKAGE,
393  RECIPE_STRING,
394  "shift-beams");
395 
396  const double badimage = irplib_parameterlist_get_double(parlist, PACKAGE,
397  RECIPE_STRING,
398  "badimage");
399 
400  const char * serr_src =
401  irplib_parameterlist_get_string(parlist, PACKAGE, RECIPE_STRING,
402  "error-source");
403 
404  cpl_imagelist * devlist = cpl_imagelist_new();
405  cpl_imagelist * rawlist =
406  cpl_imagelist_load_frameset(rawone, CPL_TYPE_UNSPECIFIED, 0, -1);
407  cpl_imagelist * bpmlist = bpmframe ?
408  cpl_imagelist_load_frameset(bpmone, CPL_TYPE_INT, 0, -1) : NULL;
409 
410  cpl_mask * bpm = NULL;
411  cpl_image * map = NULL;
412  cpl_propertylist * qclist = cpl_propertylist_new();
413  cpl_propertylist * xtlist = cpl_propertylist_new();
414 
415  const int m = rawlist ? cpl_imagelist_get_size(rawlist) : 0;
416  const int nbpm = bpmlist ? cpl_imagelist_get_size(bpmlist) : 0;
417  int mapmax, mapmean, mapmedian;
418  int * shifts = cpl_calloc(m * 2, sizeof(int));
419  double fx = 0, fy = 0; /* avoid false uninit warning */
420 
421  const char * err_procatg = "ERROR_MAP";
422  visir_error_type terr = VISIR_ERROR;
423  visir_error_source err_src = VISIR_ERROR_SRC_IMG_STDEV;
424  if (berr && strcmp(serr, "variance") == 0) {
425  terr = VISIR_VARIANCE;
426  err_procatg = "VARIANCE_MAP";
427  }
428  else if (berr && strcmp(serr, "weight") == 0) {
429  terr = VISIR_WEIGHT;
430  err_procatg = "WEIGHT_MAP";
431  }
432 
433  if (serr_src && !strcmp(serr_src, "img-stdev"))
434  err_src = VISIR_ERROR_SRC_IMG_STDEV;
435  else if (serr_src && !strcmp(serr_src, "timeseries"))
436  err_src = VISIR_ERROR_SRC_TIMESERIES;
437  else if (serr_src && !strcasecmp(serr_src, "none"))
438  berr = CPL_FALSE;
439  else if (serr)
440  error_if(1, CPL_ERROR_ILLEGAL_INPUT, "Unknown error-source: %s",
441  serr_src);
442 
443  skip_if(0);
444 
445  for (int e = 0; bshifts && e < m; e++) {
446  const cpl_propertylist * plist;
447  double crpix1, crpix2;
448  cpl_errorstate prestate = cpl_errorstate_get();
449 
450  irplib_framelist_load_propertylist(rawframes, iframe, e + 1, "^("
451  IRPLIB_PFITS_WCS_REGEXP ")$",
452  CPL_FALSE);
453  plist = irplib_framelist_get_propertylist_const(rawframes, iframe);
454  if (!cpl_propertylist_has(plist, "CRPIX1") ||
455  !cpl_propertylist_has(plist, "CRPIX2")) {
456  cpl_errorstate_set(prestate);
457  break;
458  }
459 
460  crpix1 = irplib_pfits_get_double(plist, "CRPIX1");
461  crpix2 = irplib_pfits_get_double(plist, "CRPIX2");
462 
463  if (e == 0) {
464  shifts[0] = 0;
465  shifts[1] = 0;
466  fx = crpix1;
467  fy = crpix2;
468  } else {
469  shifts[e * 2] = visir_round_to_int(-(fx - crpix1));
470  shifts[e * 2 + 1] = visir_round_to_int(-(fy - crpix2));
471  }
472  cpl_msg_debug(cpl_func, "CRPIX shifts %d %d, %f %f", shifts[e * 2],
473  shifts[e * 2 + 1], crpix1 - fx, crpix2 - fy);
474  }
475 
476  skip_if(rawlist == NULL);
477 
478  bug_if(errr);
479  bug_if(errb);
480 
481  error_if(nbpm != 1 && nbpm != m && nbpm != 0, CPL_ERROR_INCOMPATIBLE_INPUT,
482  "Frame-pair %d/%d: %d image(s) <=> %d bad pixel map(s)",
483  1+iframe, n, m, (int)cpl_imagelist_get_size(bpmlist));
484 
485  bug_if(cpl_frameset_insert(usedframes, cpl_frame_duplicate(rawframe)));
486  if (bpmframe)
487  bug_if(cpl_frameset_insert(usedframes, cpl_frame_duplicate(bpmframe)));
488 
489  for (int j = 0; bpmframe && j < m; j++) {
490  const cpl_image * bpmimg =
491  cpl_imagelist_get_const(bpmlist, nbpm > 1 ? j : 0);
492  cpl_image * rawimg = cpl_imagelist_get(rawlist, j);
493 
494  cpl_mask_delete(bpm);
495  bpm = cpl_mask_threshold_image_create(bpmimg, 0.5, FLT_MAX);
496 
497  /* merge static mask */
498  if (static_mask)
499  cpl_mask_or(bpm, static_mask);
500 
501  bug_if(cpl_image_reject_from_mask(rawimg, bpm));
502 
503  }
504 
505 
506  skip_if(visir_util_clip_kappa_sigma(rawlist, devlist, parlist, shifts));
507  /* reject whole image if too many pixels clipped,
508  * assumes number of rejected frames low, so no recomputing of stddev */
509  {
510  cpl_image * img = cpl_imagelist_get(rawlist, 0);
511  const int total_size =
512  cpl_image_get_size_x(img) * cpl_image_get_size_y(img);
513  cpl_mask * allbad = cpl_mask_new(cpl_image_get_size_x(img),
514  cpl_image_get_size_y(img));
515  cpl_mask_not(allbad);
516 
517  for (cpl_size i = 0; i < cpl_imagelist_get_size(rawlist); i++) {
518  cpl_mask * mask = cpl_image_get_bpm(cpl_imagelist_get(rawlist, i));
519  img = cpl_imagelist_get(rawlist, i);
520  if (badimage < (double)cpl_mask_count(mask) / total_size)
521  cpl_image_reject_from_mask(img, allbad);
522  }
523 
524  cpl_mask_delete(allbad);
525  }
526 
527  /* Must have two st.dev images */
528  bug_if(cpl_imagelist_get_size(devlist) != 2);
529 
530  map = cpl_image_new_from_accepted(rawlist);
531  mapmax = cpl_image_get_max(map);
532  mapmean = cpl_image_get_mean(map);
533  mapmedian = cpl_image_get_median(map);
534  bug_if(cpl_propertylist_append_int(qclist, VISIR_UTIL_CLIP_QC_MAP_MAX,
535  mapmax));
536  bug_if(cpl_propertylist_append_int(qclist, VISIR_UTIL_CLIP_QC_MAP_MEAN,
537  mapmean));
538  bug_if(cpl_propertylist_append_int(qclist, VISIR_UTIL_CLIP_QC_MAP_MEDIAN,
539  mapmedian));
540  bug_if(cpl_propertylist_set_comment(qclist, VISIR_UTIL_CLIP_QC_MAP_MAX,
541  "The maximum contribution on a pixel"));
542  bug_if(cpl_propertylist_set_comment(qclist, VISIR_UTIL_CLIP_QC_MAP_MEAN,
543  "The mean contribution on a pixel"));
544  bug_if(cpl_propertylist_set_comment(qclist, VISIR_UTIL_CLIP_QC_MAP_MEDIAN,
545  "The median contribution on a pixel"));
546 
547  skip_if(irplib_dfs_save_propertylist(products, parlist, usedframes,
548  RECIPE_STRING,
549  VISIR_IMG_CLIPPED_PROCATG, qclist,
550  NULL, visir_pipe_id, bpmname));
551 
552  if (berr)
553  skip_if(irplib_dfs_save_propertylist(products, parlist, usedframes,
554  RECIPE_STRING,
555  err_procatg, qclist,
556  NULL, visir_pipe_id, errname));
557 
558  for (int j = 0; j < m; j++) {
559  cpl_image * rawimg = cpl_imagelist_get(rawlist, j);
560  const cpl_mask * newbpm = cpl_image_get_bpm_const(rawimg);
561  const cpl_size npix =
562  cpl_image_get_size_x(rawimg) * cpl_image_get_size_y(rawimg);
563  cpl_image * err;
564 
565  skip_if(cpl_mask_save(newbpm, bpmname, NULL, CPL_IO_EXTEND));
566 
567  if (berr == CPL_FALSE)
568  continue;
569 
570  if (err_src == VISIR_ERROR_SRC_IMG_STDEV) {
571  double bkgsigma;
572  err = cpl_image_new(cpl_image_get_size_x(rawimg),
573  cpl_image_get_size_y(rawimg),
574  CPL_TYPE_FLOAT);
575  if (cpl_mask_count(cpl_image_get_bpm_const(rawimg)) == npix)
576  bkgsigma = INFINITY;
577  else {
578  cpl_image * dupl = cpl_image_cast(rawimg, CPL_TYPE_FLOAT);
579  const double median = cpl_image_get_median(dupl);
580  const double sigma = cpl_image_get_stdev(dupl);
581  const double kappa =
582  irplib_parameterlist_get_double(parlist, PACKAGE,
583  RECIPE_STRING, "kappa");
584  /* mask out signal */
585  cpl_mask * mask =
586  cpl_mask_threshold_image_create(dupl, median - kappa * sigma,
587  median + kappa * sigma);
588  skip_if(0);
589  /* for zero image testcase ... */
590  if (!cpl_mask_is_empty(mask))
591  cpl_mask_not(mask);
592  cpl_mask_or(mask, cpl_image_get_bpm(dupl));
593  cpl_image_reject_from_mask(dupl, mask);
594  /* conversion mad -> stdev for gaussian noise */
595  bkgsigma = median_abs_dev(dupl) * 1.4826;
596  cpl_msg_debug(cpl_func, "%d: sigma %.4f", j, bkgsigma);
597  cpl_image_delete(dupl);
598  cpl_mask_delete(mask);
599  skip_if(0);
600  }
601  cpl_image_add_scalar(err, bkgsigma);
602  }
603  else if (err_src == VISIR_ERROR_SRC_TIMESERIES)
604  err = cpl_image_duplicate(cpl_imagelist_get_const(devlist, 1));
605  else
606  bug_if(1);
607 
608  cpl_image_reject_from_mask(err, newbpm);
609  if (terr == VISIR_ERROR)
610  cpl_image_fill_rejected(err, INFINITY);
611  else if (terr == VISIR_VARIANCE) {
612  cpl_image_power(err, 2);
613  cpl_image_fill_rejected(err, INFINITY);
614  }
615  else if (terr == VISIR_WEIGHT) {
616  cpl_image_power(err, -2);
617  cpl_image_fill_rejected(err, 0);
618  }
619  cpl_image_save(err, errname, CPL_TYPE_FLOAT, NULL, CPL_IO_EXTEND);
620  cpl_image_delete(err);
621  skip_if(0);
622  }
623 
624  skip_if(irplib_dfs_save_image(products, parlist, usedframes,
625  map, m < 256 ? CPL_BPP_8_UNSIGNED
626  : (m < 65536 ? CPL_BPP_16_UNSIGNED
627  : CPL_BPP_32_SIGNED), RECIPE_STRING,
628  VISIR_IMG_CLIPPED_MAP_PROCATG, qclist,
629  NULL, visir_pipe_id, mapname));
630 
631  bug_if(cpl_propertylist_append_string(xtlist, "EXTNAME", "NO CLIP STANDARD "
632  "DEVIATION MAP"));
633 
634  skip_if(cpl_image_save(cpl_imagelist_get_const(devlist, 0), mapname,
635  CPL_TYPE_FLOAT, xtlist, CPL_IO_EXTEND));
636 
637  bug_if(cpl_propertylist_update_string(xtlist, "EXTNAME", "CLIPPED STANDARD "
638  "DEVIATION MAP"));
639 
640  skip_if(cpl_image_save(cpl_imagelist_get_const(devlist, 1), mapname,
641  CPL_TYPE_FLOAT, xtlist, CPL_IO_EXTEND));
642 
643 #ifdef _OPENMP
644 #pragma omp critical(visir_util_clip_one)
645 #endif
646  FOR_EACH_FRAMESET_C(frame, products)
647  cpl_frameset_insert(framelist, cpl_frame_duplicate(frame));
648 
649  end_skip;
650 
651  cpl_free(bpmname);
652  cpl_free(mapname);
653  cpl_free(errname);
654  cpl_free(shifts);
655 
656  cpl_frameset_delete(rawone);
657  cpl_frameset_delete(bpmone);
658  cpl_frameset_delete(usedframes);
659  cpl_frameset_delete(products);
660 
661  cpl_propertylist_delete(qclist);
662  cpl_propertylist_delete(xtlist);
663 
664  cpl_mask_delete(bpm);
665  cpl_image_delete(map);
666  cpl_imagelist_delete(rawlist);
667  cpl_imagelist_delete(bpmlist);
668  cpl_imagelist_delete(devlist);
669 
670  return cpl_error_get_code();
671 
672 }
673 
674 
675 /*----------------------------------------------------------------------------*/
683 /*----------------------------------------------------------------------------*/
684 static
685 cpl_error_code visir_util_clip_kappa_sigma(cpl_imagelist * self,
686  cpl_imagelist * devlist,
687  const cpl_parameterlist * parlist,
688  const int * shifts)
689 {
690 
691  const double keepfrac = irplib_parameterlist_get_double(parlist, PACKAGE,
692  RECIPE_STRING,
693  "keepfrac");
694  const double kappa = irplib_parameterlist_get_double(parlist, PACKAGE,
695  RECIPE_STRING,
696  "kappa");
697  const int maxite = irplib_parameterlist_get_int(parlist, PACKAGE,
698  RECIPE_STRING,
699  "maxite");
700  const cpl_image * img = cpl_imagelist_get_const(self, 0);
701 
702  switch (cpl_image_get_type(img)) {
703  case CPL_TYPE_DOUBLE:
704  skip_if(visir_util_clip_kappa_sigma_double(self, devlist, keepfrac,
705  kappa, maxite, shifts));
706  break;
707  case CPL_TYPE_FLOAT:
708  skip_if(visir_util_clip_kappa_sigma_float(self, devlist, keepfrac,
709  kappa, maxite, shifts));
710  break;
711  case CPL_TYPE_INT:
712  skip_if(visir_util_clip_kappa_sigma_int(self, devlist, keepfrac,
713  kappa, maxite, shifts));
714  break;
715  default:
716  bug_if( 1 );
717  }
718 
719  end_skip;
720 
721  return cpl_error_get_code();
722 
723 }
724 
725 
726 /* These macros are needed for support of the different pixel types */
727 
728 #define CONCAT(a,b) a ## _ ## b
729 #define CONCAT2X(a,b) CONCAT(a,b)
730 
731 #define PIXEL_TYPE double
732 #define STDEV_TYPE CPL_TYPE_DOUBLE
733 #define PIXEL_TYPE_CPL CPL_TYPE_DOUBLE
734 #include "visir_util_clip_body.c"
735 #undef PIXEL_TYPE
736 #undef STDEV_TYPE
737 #undef PIXEL_TYPE_CPL
738 
739 #define PIXEL_TYPE float
740 #define PIXEL_TYPE_CPL CPL_TYPE_FLOAT
741 #define STDEV_TYPE CPL_TYPE_FLOAT
742 #include "visir_util_clip_body.c"
743 #undef PIXEL_TYPE
744 #undef STDEV_TYPE
745 #undef PIXEL_TYPE_CPL
746 
747 #define PIXEL_TYPE int
748 #define PIXEL_TYPE_CPL CPL_TYPE_INT
749 #define STDEV_TYPE CPL_TYPE_FLOAT
750 #include "visir_util_clip_body.c"
751 #undef PIXEL_TYPE
752 #undef STDEV_TYPE
753 #undef PIXEL_TYPE_CPL
cpl_error_code irplib_dfs_save_propertylist(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save a propertylist as a DFS-compliant pipeline product.
Definition: irplib_utils.c:240
irplib_framelist * irplib_framelist_extract_regexp(const irplib_framelist *self, const char *regexp, cpl_boolean invert)
Extract the frames with the given tag from a framelist.
const cpl_propertylist * irplib_framelist_get_propertylist_const(const irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
cpl_error_code irplib_dfs_save_image(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_image *image, cpl_type_bpp bpp, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save an image as a DFS-compliant pipeline product.
Definition: irplib_utils.c:192
int visir_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: visir_dfs.c:72
const cpl_frame * irplib_framelist_get_const(const irplib_framelist *self, int pos)
Get the specified frame from the framelist.
void irplib_framelist_delete(irplib_framelist *self)
Deallocate an irplib_framelist with its frames and properties.
cpl_error_code irplib_framelist_load_propertylist(irplib_framelist *self, int pos, int ind, const char *regexp, cpl_boolean invert)
Load the propertylist of the specified frame in the framelist.
irplib_framelist * irplib_framelist_cast(const cpl_frameset *frameset)
Create an irplib_framelist from a cpl_framelist.
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.