DETMON Pipeline Reference Manual  1.2.4
detmon_opt_lg_mr.c
1 /* $Id: detmon_opt_lg_mr.c,v 1.6 2013/08/07 09:32:50 jtaylor Exp $
2  *
3  * This file is part of the DETMON Pipeline
4  * Copyright (C) 2013 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/08/07 09:32:50 $
24  * $Revision: 1.6 $
25  * $Name: detmon-1_2_4 $
26  */
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 
31 /*----------------------------------------------------------------------------
32  Includes
33  ----------------------------------------------------------------------------*/
34 
35 
36 #include "detmon.h"
37 #include "detmon_lg.h"
38 #include "irplib_plugin.h"
39 #include <cpl.h>
40 
41 #include <string.h>
42 #include <errno.h>
43 #include <stdlib.h>
44 #include <assert.h>
45 #include <unistd.h> /* for chdir */
46 #include <sys/stat.h> /* for mkdir */
47 #include <sys/types.h> /* for mkdir */
48 #include <fcntl.h> /* for O_RDWR | S_IRWXU */
49 
50 #define RECIPE_NAME "detmon_opt_lg_mr"
51 
52 #define OPT FALSE
53 
54 /*----------------------------------------------------------------------------
55  Functions prototypes
56  ----------------------------------------------------------------------------*/
57 int
58 detmon_lg_dfs_set_groups(cpl_frameset * set,
59  const char *tag_on, const char *tag_off);
60 
61 CPL_RECIPE_DEFINE(detmon_opt_lg_mr, DETMON_BINARY_VERSION,
62  detmon_lg_fill_parlist_opt_default_mr(recipe->parameters,
63  "detmon_opt_lg_mr", "detmon"),
64  "Julian Taylor", "jtaylor@partner.eso.org", "2013",
65  "Linearity/Gain recipe for the optical domain, multi "
66  "region version",
67  detmon_lg_get_description("detmon_opt_lg_mr", "DETMON",
68  DETMON_LG_ON_RAW_NEW,
69  DETMON_LG_OFF_RAW_NEW,
70  DETMON_LG_ON_RAW_OLD,
71  DETMON_LG_OFF_RAW_OLD));
75 int compare_tags(const cpl_frame * a, const cpl_frame * b)
76 {
77  return strcmp(cpl_frame_get_tag(a), cpl_frame_get_tag(b)) == 0;
78 }
79 
80 
81 /* ---------------------------------------------------------------------------*/
92 /* ---------------------------------------------------------------------------*/
93 static cpl_error_code merge_keys(cpl_propertylist * mplist,
94  const cpl_propertylist * plist_,
95  const int pos,
96  const char * rmregexp)
97 {
98  char buffer[256];
99  /* no copy_regex, so duplicate and use erase_regex on the copy */
100  cpl_propertylist * plist = cpl_propertylist_duplicate(plist_);
101 
102  if (rmregexp) {
103  cpl_propertylist_erase_regexp(plist, rmregexp, 0);
104  cpl_propertylist_erase_regexp(mplist, rmregexp, 0);
105  }
106 
107  for (cpl_size i = 0; i < cpl_propertylist_get_size(plist); i++) {
108  cpl_property * p = cpl_propertylist_get(plist, i);
109  const char * key = cpl_property_get_name(p);
110  /* extend all qc keywords by a region prefix */
111  if (!strncmp(key, "ESO QC ", 7)) {
112  sprintf(buffer, "ESO QC REG%d %s", pos, key + 7);
113  cpl_msg_debug(cpl_func, "merging %s to %s", key, buffer);
114  if (cpl_property_get_type(p) == CPL_TYPE_INT) {
115  int val = cpl_property_get_int(p);
116  cpl_propertylist_append_int(mplist, buffer, val);
117  } else if (cpl_property_get_type(p) == CPL_TYPE_DOUBLE) {
118  double val = cpl_property_get_double(p);
119  cpl_propertylist_append_double(mplist, buffer, val);
120  } else if (cpl_property_get_type(p) == CPL_TYPE_STRING) {
121  const char * val = cpl_property_get_string(p);
122  cpl_propertylist_append_string(mplist, buffer, val);
123  }
124  else
125  bug_if(1);
126  const char * com = cpl_property_get_comment(p);
127  cpl_propertylist_set_comment(mplist, buffer, com);
128 
129  /* remove unprefixed key */
130  if (cpl_propertylist_has(mplist, key))
131  cpl_propertylist_erase(mplist, key);
132  }
133  }
134  skip_if(0);
135 
136  end_skip;
137  cpl_propertylist_delete(plist);
138 
139  return cpl_error_get_code();
140 }
141 
142 
143 /* ---------------------------------------------------------------------------*/
151 /* ---------------------------------------------------------------------------*/
152 static cpl_error_code
153 merge_images(cpl_imagelist * mimgl, const cpl_imagelist * img)
154 {
155  cpl_ensure_code(cpl_imagelist_get_size(img) ==
156  cpl_imagelist_get_size(mimgl), CPL_ERROR_ILLEGAL_INPUT);
157  for (int i = 0; i < cpl_imagelist_get_size(img); i++) {
158  cpl_image * mimg = cpl_imagelist_get(mimgl, i);
159  const cpl_image * part = cpl_imagelist_get_const(img, i);
160  cpl_image_add(mimg, part);
161  }
162 
163  return cpl_error_get_code();
164 }
165 
166 
167 /* ---------------------------------------------------------------------------*/
175 /* ---------------------------------------------------------------------------*/
176 static cpl_error_code
177 merge_table(cpl_table * mtab, cpl_table * tab, const int pos)
178 {
179  cpl_table_new_column(tab, "REGION", CPL_TYPE_INT);
180  cpl_table_fill_column_window(tab, "REGION", 0, cpl_table_get_nrow(tab), pos);
181  skip_if(cpl_table_insert(mtab, tab, cpl_table_get_nrow(mtab)));
182 
183  end_skip;
184 
185  return cpl_error_get_code();
186 }
187 
188 
189 static cpl_error_code
190 parse_token(const char * token, cpl_size * llx, cpl_size * lly,
191  cpl_size * urx, cpl_size * ury)
192 {
193  assert(sizeof(*llx) == 8);
194  if (sscanf(token, " %lld , %lld , %lld , %lld ", llx, lly, urx, ury) == 4) {
195  return CPL_ERROR_NONE;
196  }
197  return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
198  "Data not formated correctly: %s; "
199  "expecting: name,llx,lly,urx,ury",
200  token);
201 }
202 
203 
204 /* ---------------------------------------------------------------------------*/
217 /* ---------------------------------------------------------------------------*/
218 static cpl_error_code
219 read_regions_file(const char * filename, cpl_size ** rllx,
220  cpl_size ** rlly, cpl_size ** rurx, cpl_size ** rury,
221  cpl_size * n)
222 {
223  FILE * f = fopen(filename, "r");
224  char line[1024];
225  cpl_size i = 0;
226  cpl_size nmax = 100;
227  if (f == NULL) {
228  return cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
229  "Could not open file %s: %s", filename,
230  strerror(errno));
231  }
232  cpl_msg_info(cpl_func, "Reading %s", filename);
233 
234  *n = 0;
235  *rllx = cpl_malloc(sizeof(**rllx) * nmax);
236  *rlly = cpl_malloc(sizeof(**rllx) * nmax);
237  *rurx = cpl_malloc(sizeof(**rllx) * nmax);
238  *rury = cpl_malloc(sizeof(**rllx) * nmax);
239 
240  while (fgets(line, 1024, f) != NULL) {
241  const size_t nline = strlen(line);
242  if (line[nline - 1] != '\n') {
243  cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
244  "File %s contained too long line",
245  filename);
246  skip_if(0);
247  }
248 
249  if (line[0] == '#')
250  continue;
251 
252  skip_if(parse_token(line, &(*rllx)[i], &(*rlly)[i],
253  &(*rurx)[i], &(*rury)[i]));
254  *n = ++i;
255  if (i >= nmax) {
256  nmax *= 2;
257  *rllx = cpl_realloc(*rllx, sizeof(**rllx) * nmax);
258  *rlly = cpl_realloc(*rlly, sizeof(**rllx) * nmax);
259  *rurx = cpl_realloc(*rurx, sizeof(**rllx) * nmax);
260  *rury = cpl_realloc(*rury, sizeof(**rllx) * nmax);
261  skip_if(0);
262  }
263  }
264 
265  end_skip;
266  if (f)
267  fclose(f);
268  return CPL_ERROR_NONE;
269 }
270 
271 
272 /* ---------------------------------------------------------------------------*/
285 /* ---------------------------------------------------------------------------*/
286 static cpl_error_code
287 read_regions_str(const char * istr, cpl_size ** rllx,
288  cpl_size ** rlly, cpl_size ** rurx, cpl_size ** rury,
289  cpl_size * n)
290 {
291  cpl_size nmax = 100;
292  char * str_ = cpl_strdup(istr);
293  char * str = str_;
294  *n = 0;
295  *rllx = cpl_malloc(sizeof(**rllx) * nmax);
296  *rlly = cpl_malloc(sizeof(**rllx) * nmax);
297  *rurx = cpl_malloc(sizeof(**rllx) * nmax);
298  *rury = cpl_malloc(sizeof(**rllx) * nmax);
299 
300  for (int i = 0; ;i++) {
301  char * token = strtok(str, ":");
302  if (token == NULL)
303  break;
304 
305  skip_if(parse_token(token, &(*rllx)[i], &(*rlly)[i],
306  &(*rurx)[i], &(*rury)[i]));
307  (*n)++;
308  if (i >= nmax - 1) {
309  nmax *= 2;
310  *rllx = cpl_realloc(*rllx, sizeof(**rllx) * nmax);
311  *rlly = cpl_realloc(*rlly, sizeof(**rllx) * nmax);
312  *rurx = cpl_realloc(*rurx, sizeof(**rllx) * nmax);
313  *rury = cpl_realloc(*rury, sizeof(**rllx) * nmax);
314  skip_if(0);
315  }
316  str = NULL;
317  }
318 
319  end_skip;
320  cpl_free(str_);
321 
322  return CPL_ERROR_NONE;
323 }
324 
325 
326 /* ---------------------------------------------------------------------------*/
339 /* ---------------------------------------------------------------------------*/
340 static cpl_error_code
341 merge_lingain(cpl_propertylist * mplist[], cpl_table * mtab[],
342  const char * fn, const cpl_size next,
343  const char * rmregexp, int pos)
344 {
345  cpl_errorstate cleanstate = cpl_errorstate_get();
346 
347  {
348  cpl_propertylist * plist = cpl_propertylist_load(fn, 0);
349  skip_if(plist == NULL);
350  if (mplist[0] == NULL) {
351  mplist[0] = plist;
352  merge_keys(mplist[0], plist, pos, rmregexp);
353  }
354  else {
355  merge_keys(mplist[0], plist, pos, rmregexp);
356  cpl_propertylist_delete(plist);
357  }
358  }
359  skip_if(0);
360 
361  for (int e = 1; e < next + 1; e++) {
362  cpl_propertylist * plist = cpl_propertylist_load(fn, e);
363  cpl_table * tab = cpl_table_load(fn, e, 0);
364  /* empty extensions may exist */
365  if (tab == NULL) {
366  cpl_errorstate_set(cleanstate);
367  cpl_propertylist_delete(plist);
368  continue;
369  }
370  skip_if(plist == NULL);
371 
372  if (mplist[e] == NULL) {
373  merge_keys(plist, plist, pos, rmregexp);
374  cpl_table_new_column(tab, "REGION", CPL_TYPE_INT);
375  cpl_table_fill_column_window(tab, "REGION", 0,
376  cpl_table_get_nrow(tab), 1);
377  skip_if(0);
378  mplist[e] = plist;
379  mtab[e] = tab;
380  }
381  else {
382  merge_keys(mplist[e], plist, pos, rmregexp);
383  merge_table(mtab[e], tab, pos);
384  skip_if(0);
385  cpl_propertylist_delete(plist);
386  cpl_table_delete(tab);
387  }
388  skip_if(0);
389  }
390 
391  end_skip;
392 
393  return cpl_error_get_code();
394 }
395 
396 
397 /* ---------------------------------------------------------------------------*/
410 /* ---------------------------------------------------------------------------*/
411 static cpl_error_code
412 merge_bpmcoeff(cpl_propertylist * mplist[], cpl_imagelist * mimg[],
413  const char * fn, const cpl_size next,
414  const char * rmregexp, int pos)
415 {
416  cpl_errorstate cleanstate = cpl_errorstate_get();
417 
418  for (int e = 0; e < next + 1; e++) {
419  cpl_propertylist * plist = cpl_propertylist_load(fn, e);
420  cpl_imagelist * img = cpl_imagelist_load(fn, CPL_TYPE_UNSPECIFIED, e);
421  /* empty extensions may exist */
422  if (img == NULL) {
423  cpl_errorstate_set(cleanstate);
424  cpl_propertylist_delete(plist);
425  continue;
426  }
427  skip_if(plist == NULL);
428 
429  if (mimg[e] == NULL) {
430  merge_keys(plist, plist, pos, rmregexp);
431  mplist[e] = plist;
432  mimg[e] = img;
433  }
434  else {
435  merge_keys(mplist[e], plist, pos, rmregexp);
436  merge_images(mimg[e], img);
437  skip_if(0);
438  cpl_propertylist_delete(plist);
439  cpl_imagelist_delete(img);
440  }
441  skip_if(0);
442  }
443 
444  end_skip;
445 
446  return cpl_error_get_code();
447 }
448 
449 typedef enum {
450  DETMON_BP_MAP_NL_IDX = 0,
451  DETMON_LIN_INFO_IDX = 1,
452  DETMON_GAIN_INFO_IDX = 2,
453  DETMON_BPM_IDX = 3,
454  DETMON_COEFF_IDX = 4,
455  DETMON_MAX_IDX,
456 } detmon_idx;
457 
458 static cpl_error_code disable_contamination(cpl_parameterlist * parlist)
459 {
460  /* "disable" by setting it to a region of size 1 */
461  cpl_parameter * par;
462  for (int i = 1; i < 6; i++) {
463  char buffer[100];
464  sprintf(buffer, "detmon.detmon_opt_lg_mr.llx%d", i);
465  par = cpl_parameterlist_find(parlist, buffer);
466  cpl_parameter_set_int(par, 1);
467  sprintf(buffer, "detmon.detmon_opt_lg_mr.lly%d", i);
468  par = cpl_parameterlist_find(parlist, buffer);
469  cpl_parameter_set_int(par, 1);
470  sprintf(buffer, "detmon.detmon_opt_lg_mr.urx%d", i);
471  par = cpl_parameterlist_find(parlist, buffer);
472  cpl_parameter_set_int(par, 2);
473  sprintf(buffer, "detmon.detmon_opt_lg_mr.ury%d", i);
474  par = cpl_parameterlist_find(parlist, buffer);
475  cpl_parameter_set_int(par, 2);
476  }
477 
478  return cpl_error_get_code();
479 }
480 
481 /*---------------------------------------------------------------------------*/
482 /*
483  @brief Interpret the command line options and execute the data processing
484  @param frameset the frames list
485  @param parlist the parameters list
486  @return 0 if everything is ok
487  */
488 /*---------------------------------------------------------------------------*/
489 
490 static int detmon_opt_lg_mr(cpl_frameset * frameset,
491  const cpl_parameterlist * parlist_)
492 {
493  const char * tag_on=NULL;
494  const char * tag_off=NULL;
495  IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
496  cpl_parameterlist * parlist = (cpl_parameterlist *)parlist_;
497  IRPLIB_DIAG_PRAGMA_POP;
498  cpl_propertylist ** mplist[DETMON_MAX_IDX] = {NULL};
499  cpl_imagelist ** mimg[DETMON_MAX_IDX] = {NULL};
500  cpl_table ** mtab[DETMON_MAX_IDX] = {NULL};
501  cpl_size next[DETMON_MAX_IDX] = {0};
502  char * outname[DETMON_MAX_IDX] = {NULL};
503  char * outtag[DETMON_MAX_IDX] = {NULL};
504 
505  cpl_frameset * frameset_copy = NULL;
506 
507  cpl_propertylist * lintbl =
508  detmon_fill_prolist("DET_LIN_INFO", "REDUCED", "TECH", CPL_FALSE);
509 
510  cpl_propertylist * gaintbl =
511  detmon_fill_prolist("GAIN_INFO", "REDUCED", "TECH", CPL_FALSE);
512 
513  cpl_propertylist * coeffscube =
514  detmon_fill_prolist("COEFFS_CUBE", "REDUCED", "TECH", CPL_FALSE);
515 
516  cpl_propertylist * bpm =
517  detmon_fill_prolist("BP_MAP_NL", "REDUCED", "TECH", CPL_FALSE);
518 
519  cpl_propertylist * corr =
520  detmon_fill_prolist("AUTOCORR", "REDUCED", "TECH", CPL_FALSE);
521 
522  cpl_propertylist * diff_flat =
523  detmon_fill_prolist("DIFF_FLAT", "REDUCED", "TECH", CPL_FALSE);
524  const char * regions_file = NULL;
525  const char * regions_str = NULL;
526  cpl_error_code error = CPL_ERROR_NONE;
527  cpl_size * llx = NULL, * lly = NULL, * urx = NULL, * ury = NULL;
528  const cpl_parameter * p =
529  cpl_parameterlist_find_const(parlist, "detmon.detmon_opt_lg_mr.regions-file");
530  if (p) {
531  regions_file = cpl_parameter_get_string(p);
532  if (strlen(regions_file) == 0)
533  regions_file = NULL;
534  }
535  p = cpl_parameterlist_find_const(parlist,
536  "detmon.detmon_opt_lg_mr.regions");
537  if (p) {
538  regions_str = cpl_parameter_get_string(p);
539  if (strlen(regions_str) == 0)
540  regions_str = NULL;
541  else {
542  if (regions_file) {
543  return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
544  "Please only provide either "
545  "--regions or "
546  "--regions-file, not both");
547  }
548  }
549  }
550 
551  p = cpl_parameterlist_find_const(parlist,
552  "detmon.detmon_opt_lg_mr.intermediate");
553  if (p) {
554  error_if(cpl_parameter_get_bool(p), CPL_ERROR_UNSUPPORTED_MODE,
555  "--intermediate not supported by multi region recipe");
556  }
557 
558  skip_if (detmon_lg_set_tag(frameset, &tag_on, &tag_off));
559  skip_if (detmon_lg_dfs_set_groups(frameset, tag_on, tag_off));
560 
561  cpl_size nregions = 0;
562  if (regions_file) {
563  read_regions_file(regions_file, &llx, &lly, &urx, &ury,
564  &nregions);
565  }
566  else if (regions_str) {
567  read_regions_str(regions_str, &llx, &lly, &urx, &ury,
568  &nregions);
569  }
570  else {
571  return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
572  "Empty value in --regions or "
573  "--regions-file");
574  }
575  skip_if(0);
576 
577  /* contamination not supported */
578  skip_if(disable_contamination(parlist));
579 
580  /* additionally iterating on extensions would improve IO caching and
581  * reduce memory usage for pix2pix but requires checks if detmon really
582  * gives the same result in this case */
583  for (int i = 0; i < nregions; i++) {
584  cpl_parameter * par;
585  par = cpl_parameterlist_find(parlist, "detmon.detmon_opt_lg_mr.llx");
586  cpl_parameter_set_int(par, llx[i]);
587  par = cpl_parameterlist_find(parlist, "detmon.detmon_opt_lg_mr.lly");
588  cpl_parameter_set_int(par, lly[i]);
589  par = cpl_parameterlist_find(parlist, "detmon.detmon_opt_lg_mr.urx");
590  cpl_parameter_set_int(par, urx[i]);
591  par = cpl_parameterlist_find(parlist, "detmon.detmon_opt_lg_mr.ury");
592  cpl_parameter_set_int(par, ury[i]);
593  cpl_msg_info(cpl_func, "working on region %d/%d: %lld %lld, "
594  "%lld %lld", i + 1, (int)nregions,
595  llx[i], lly[i], urx[i], ury[i]);
596 
597  /* copy and throw away so we don't accumulate products
598  * for each call */
599  cpl_frameset_delete(frameset_copy);
600  frameset_copy = cpl_frameset_duplicate(frameset);
601  error = detmon_lg(frameset_copy,
602  parlist,
603  tag_on,
604  tag_off,
605  RECIPE_NAME,
606  PACKAGE_TARNAME,
607  REGEXP,
608  lintbl, gaintbl, coeffscube,
609  bpm, corr, diff_flat,
610  PACKAGE "/" PACKAGE_VERSION,
611  NULL, NULL, OPT);
612  skip_if(error);
613 
614  cpl_size nlabels;
615  cpl_size * selection = cpl_frameset_labelise(frameset_copy,
616  compare_tags, &nlabels);
617 
618  for (cpl_size j = 0; j < nlabels; j++) {
619  cpl_frameset * a = cpl_frameset_extract(frameset_copy, selection, j);
620  cpl_frame * frm = cpl_frameset_get_first(a);
621  const char * fn = cpl_frame_get_filename(frm);
622  int idx;
623 
624  if (strcmp(cpl_frame_get_tag(frm), "DET_LIN_INFO") == 0)
625  idx = DETMON_LIN_INFO_IDX;
626  else if (strcmp(cpl_frame_get_tag(frm), "GAIN_INFO") == 0)
627  idx = DETMON_GAIN_INFO_IDX;
628  else if (strcmp(cpl_frame_get_tag(frm), "BP_MAP_NL") == 0)
629  idx = DETMON_BPM_IDX;
630  else if (strcmp(cpl_frame_get_tag(frm), "COEFFS_CUBE") == 0)
631  idx = DETMON_COEFF_IDX;
632  else {
633  cpl_frameset_delete(a);
634  continue;
635  }
636 
637  /* prepare storage */
638  if (mplist[idx] == NULL) {
639  next[idx] = cpl_frame_get_nextensions(frm);
640  outname[idx] = cpl_strdup(cpl_frame_get_filename(frm));
641  outtag[idx] = cpl_strdup(cpl_frame_get_tag(frm));
642  mplist[idx] = cpl_calloc(sizeof(cpl_propertylist*), next[idx] + 1);
643  mimg[idx] = cpl_calloc(sizeof(cpl_imagelist*), next[idx] + 1);
644  mtab[idx] = cpl_calloc(sizeof(cpl_table*), next[idx] + 1);
645  }
646 
647  if (idx == DETMON_LIN_INFO_IDX) {
648  const char * rmregexp = "ESO QC CONTAM.*";
649  merge_lingain(mplist[idx], mtab[idx], fn, next[idx],
650  rmregexp, i + 1);
651  }
652  else if (idx == DETMON_GAIN_INFO_IDX) {
653  merge_lingain(mplist[idx], mtab[idx], fn, next[idx],
654  NULL, i + 1);
655  }
656  else if (idx == DETMON_BPM_IDX) {
657  merge_bpmcoeff(mplist[idx], mimg[idx], fn, next[idx],
658  NULL, i + 1);
659  }
660  else if (idx == DETMON_COEFF_IDX) {
661  merge_bpmcoeff(mplist[idx], mimg[idx], fn, next[idx],
662  NULL, i + 1);
663  }
664  skip_if(0);
665 
666  for (int e = 0; e < next[idx] + 1; e++) {
667  char buffer[300];
668  cpl_propertylist * copy_plist;
669  cpl_size len;
670  if (!mplist[idx][e])
671  continue;
672 
673  /* don't add region if extension has no QC parameters */
674  copy_plist = cpl_propertylist_duplicate(mplist[idx][e]);
675  cpl_propertylist_erase_regexp(copy_plist, "ESO QC.*", 1);
676  len = cpl_propertylist_get_size(copy_plist);
677  cpl_propertylist_delete(copy_plist);
678  if (len == 0) {
679  continue;
680  }
681 
682  sprintf(buffer, "ESO QC REG%d LLX", i + 1);
683  cpl_propertylist_append_int(mplist[idx][e], buffer, llx[i]);
684  cpl_propertylist_set_comment(mplist[idx][e], buffer,
685  "Lower left X of region");
686  sprintf(buffer, "ESO QC REG%d LLY", i + 1);
687  cpl_propertylist_append_int(mplist[idx][e], buffer, lly[i]);
688  cpl_propertylist_set_comment(mplist[idx][e], buffer,
689  "Lower left Y of region");
690  sprintf(buffer, "ESO QC REG%d URX", i + 1);
691  cpl_propertylist_append_int(mplist[idx][e], buffer, urx[i]);
692  cpl_propertylist_set_comment(mplist[idx][e], buffer,
693  "Upper right X of region");
694  sprintf(buffer, "ESO QC REG%d URY", i + 1);
695  cpl_propertylist_append_int(mplist[idx][e], buffer, ury[i]);
696  cpl_propertylist_set_comment(mplist[idx][e], buffer,
697  "Upper right Y of region");
698  }
699 
700  cpl_frameset_delete(a);
701  skip_if(0);
702  }
703  cpl_free(selection);
704  }
705 
706  {
707  cpl_frameset * usedframes = cpl_frameset_new();
708 
709  for (cpl_frame *frm = cpl_frameset_get_first(frameset); frm != NULL;
710  frm = cpl_frameset_get_next(frameset)) {
711  if (cpl_frame_get_group(frm) == CPL_FRAME_GROUP_RAW ||
712  cpl_frame_get_group(frm) == CPL_FRAME_GROUP_CALIB) {
713  cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm));
714  }
715  }
716  for (int idx = 0; idx < DETMON_MAX_IDX; idx++) {
717  if (!mplist[idx])
718  continue;
719  if (idx == DETMON_LIN_INFO_IDX || idx == DETMON_GAIN_INFO_IDX) {
720  irplib_dfs_save_propertylist(frameset, parlist, usedframes,
721  RECIPE_NAME, outtag[idx],
722  mplist[idx][0], NULL, PACKAGE "/"
723  PACKAGE_VERSION, outname[idx]);
724  skip_if(0);
725  for (cpl_size e = 1; e < next[idx] + 1; e++) {
726  if (mtab[idx][e]) {
727  cpl_table_save(mtab[idx][e], NULL, mplist[idx][e],
728  outname[idx], CPL_IO_EXTEND);
729  }
730  else {
731  cpl_propertylist_save(mplist[idx][e], outname[idx],
732  CPL_IO_EXTEND);
733  }
734  skip_if(0);
735  }
736  }
737  else if (idx == DETMON_BPM_IDX) {
738  if (!mimg[idx][0]) {
739  irplib_dfs_save_propertylist(frameset, parlist, usedframes,
740  RECIPE_NAME, outtag[idx],
741  mplist[idx][0], NULL, PACKAGE
742  "/" PACKAGE_VERSION,
743  outname[idx]);
744  }
745  else {
746  irplib_dfs_save_image(frameset, parlist, usedframes,
747  cpl_imagelist_get(mimg[idx][0], 0),
748  CPL_TYPE_UNSPECIFIED, RECIPE_NAME,
749  outtag[idx], mplist[idx][0], NULL,
750  PACKAGE "/" PACKAGE_VERSION,
751  outname[idx]);
752  cpl_imagelist_delete(mimg[idx][0]);
753  mimg[idx][0] = NULL;
754  }
755  skip_if(0);
756  for (cpl_size e = 1; e < next[idx] + 1; e++) {
757  if (mimg[idx][e]) {
758  cpl_image * img = cpl_imagelist_get(mimg[idx][e], 0);
759  cpl_image_save(img, outname[idx], CPL_TYPE_UNSPECIFIED,
760  mplist[idx][e],
761  CPL_IO_EXTEND);
762  cpl_imagelist_delete(mimg[idx][e]);
763  mimg[idx][e] = NULL;
764  }
765  else {
766  cpl_propertylist_save(mplist[idx][e], outname[idx],
767  CPL_IO_EXTEND);
768  }
769  skip_if(0);
770  }
771  }
772  else if (idx == DETMON_COEFF_IDX) {
773  if (!mimg[idx][0]) {
774  irplib_dfs_save_propertylist(frameset, parlist, usedframes,
775  RECIPE_NAME, outtag[idx],
776  mplist[idx][0], NULL, PACKAGE
777  "/" PACKAGE_VERSION,
778  outname[idx]);
779  }
780  else {
781  irplib_dfs_save_imagelist(frameset, parlist, usedframes,
782  mimg[idx][0],
783  CPL_TYPE_UNSPECIFIED,
784  RECIPE_NAME, outtag[idx],
785  mplist[idx][0], NULL, PACKAGE "/"
786  PACKAGE_VERSION, outname[idx]);
787  cpl_imagelist_delete(mimg[idx][0]);
788  mimg[idx][0] = NULL;
789  }
790  skip_if(0);
791  for (cpl_size e = 1; e < next[idx] + 1; e++) {
792  if (mimg[idx][e]) {
793  cpl_imagelist_save(mimg[idx][e], outname[idx],
794  CPL_TYPE_UNSPECIFIED,
795  mplist[idx][e], CPL_IO_EXTEND);
796  cpl_imagelist_delete(mimg[idx][e]);
797  mimg[idx][e] = NULL;
798  }
799  else {
800  cpl_propertylist_save(mplist[idx][e], outname[idx],
801  CPL_IO_EXTEND);
802  }
803  skip_if(0);
804  }
805  }
806  }
807 
808  cpl_frameset_delete(usedframes);
809  skip_if(0);
810  }
811 
812  end_skip;
813  cpl_frameset_delete(frameset_copy);
814  cpl_propertylist_delete(lintbl);
815  cpl_propertylist_delete(gaintbl);
816  cpl_propertylist_delete(coeffscube);
817  cpl_propertylist_delete(bpm);
818  cpl_propertylist_delete(corr);
819  cpl_propertylist_delete(diff_flat);
820  for (int i = 0; i < DETMON_MAX_IDX; i++) {
821  for (int e = 0; e < next[i] + 1; e++) {
822  if (mplist[i])
823  cpl_propertylist_delete(mplist[i][e]);
824  if (mimg[i])
825  cpl_imagelist_delete(mimg[i][e]);
826  if (mtab[i])
827  cpl_table_delete(mtab[i][e]);
828  }
829  cpl_free(mplist[i]);
830  cpl_free(mimg[i]);
831  cpl_free(mtab[i]);
832  cpl_free(outname[i]);
833  cpl_free(outtag[i]);
834  }
835  cpl_free(llx);
836  cpl_free(lly);
837  cpl_free(urx);
838  cpl_free(ury);
839 
840  return cpl_error_get_code();
841 }