CR2RE Pipeline Reference Manual 1.7.0
irplib_utils.c
1/*
2 * This file is part of the irplib package
3 * Copyright (C) 2002,2003,2014 European Southern Observatory
4 * 2004 Free Software Foundation, Inc.
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#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
25/*-----------------------------------------------------------------------------
26 Includes
27 -----------------------------------------------------------------------------*/
28#include "irplib_utils.h"
29
30#include <string.h>
31#include <assert.h>
32#include <stdlib.h>
33#include <errno.h>
34
35/*-----------------------------------------------------------------------------
36 Defines
37 -----------------------------------------------------------------------------*/
38
39#ifndef inline
40#define inline /* inline */
41#endif
42
43/*-----------------------------------------------------------------------------
44 Missing Function Prototypes
45 -----------------------------------------------------------------------------*/
46
47/*-----------------------------------------------------------------------------
48 Private Function Prototypes
49 -----------------------------------------------------------------------------*/
50
51inline static double irplib_data_get_double(const void *, cpl_type, int)
52#ifdef CPL_HAVE_GNUC_NONNULL
53 __attribute__((nonnull))
54#endif
55 ;
56
57inline static void irplib_data_set_double(void *, cpl_type, int, double)
58#ifdef CPL_HAVE_GNUC_NONNULL
59 __attribute__((nonnull))
60#endif
61 ;
62
63
64static void
65irplib_errorstate_dump_one_level(void (*)(const char *, const char *, ...)
66#ifdef __GNUC__
67 __attribute__((format(printf, 2, 3)))
68#endif
69 ,
70 unsigned,
71 unsigned,
72 unsigned);
73static double frame_get_exptime(const cpl_frame *pframe);
74static void quicksort(int *index, double *exptime, int left, int right);
75
76static cpl_error_code irplib_dfs_product_save(cpl_frameset *,
77 cpl_propertylist *,
78 const cpl_parameterlist *,
79 const cpl_frameset *,
80 const cpl_frame *,
81 const cpl_imagelist *,
82 const cpl_image *,
83 cpl_type,
84 const cpl_table *,
85 const cpl_propertylist *,
86 const char *,
87 const cpl_propertylist *,
88 const char *,
89 const char *,
90 const char *);
91
92/*----------------------------------------------------------------------------*/
96/*----------------------------------------------------------------------------*/
98
99
100/*----------------------------------------------------------------------------*/
112/*----------------------------------------------------------------------------*/
113void
114irplib_errorstate_dump_warning(unsigned self, unsigned first, unsigned last)
115{
116 irplib_errorstate_dump_one_level(&cpl_msg_warning, self, first, last);
117}
118
119static cpl_polynomial *
120irplib_polynomial_fit_1d_create_common(const cpl_vector *x_pos,
121 const cpl_vector *values,
122 int degree,
123 double *mse,
124 double *rechisq);
125
126/*----------------------------------------------------------------------------*/
136/*----------------------------------------------------------------------------*/
137void
138irplib_errorstate_dump_info(unsigned self, unsigned first, unsigned last)
139{
140 irplib_errorstate_dump_one_level(&cpl_msg_info, self, first, last);
141}
142
143
144/*----------------------------------------------------------------------------*/
154/*----------------------------------------------------------------------------*/
155void
156irplib_errorstate_dump_debug(unsigned self, unsigned first, unsigned last)
157{
158 irplib_errorstate_dump_one_level(&cpl_msg_debug, self, first, last);
159}
160
161
162/*----------------------------------------------------------------------------*/
183/*----------------------------------------------------------------------------*/
184cpl_error_code
185irplib_dfs_save_image(cpl_frameset *allframes,
186 const cpl_parameterlist *parlist,
187 const cpl_frameset *usedframes,
188 const cpl_image *image,
189 cpl_type_bpp bpp,
190 const char *recipe,
191 const char *procat,
192 const cpl_propertylist *applist,
193 const char *remregexp,
194 const char *pipe_id,
195 const char *filename)
196{
197 cpl_errorstate prestate = cpl_errorstate_get();
198 cpl_propertylist *prolist =
199 applist ? cpl_propertylist_duplicate(applist) : cpl_propertylist_new();
200
201 cpl_propertylist_update_string(prolist, CPL_DFS_PRO_CATG, procat);
202
203 irplib_dfs_save_image_(allframes, NULL, parlist, usedframes, NULL, image,
204 bpp, recipe, prolist, remregexp, pipe_id, filename);
205
206 cpl_propertylist_delete(prolist);
207
208 cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
209
210 return CPL_ERROR_NONE;
211}
212
213/*----------------------------------------------------------------------------*/
230/*----------------------------------------------------------------------------*/
231cpl_error_code
232irplib_dfs_save_propertylist(cpl_frameset *allframes,
233 const cpl_parameterlist *parlist,
234 const cpl_frameset *usedframes,
235 const char *recipe,
236 const char *procat,
237 const cpl_propertylist *applist,
238 const char *remregexp,
239 const char *pipe_id,
240 const char *filename)
241{
242 cpl_errorstate prestate = cpl_errorstate_get();
243 cpl_propertylist *prolist =
244 applist ? cpl_propertylist_duplicate(applist) : cpl_propertylist_new();
245
246 cpl_propertylist_update_string(prolist, CPL_DFS_PRO_CATG, procat);
247
248 cpl_dfs_save_propertylist(allframes, NULL, parlist, usedframes, NULL,
249 recipe, prolist, remregexp, pipe_id, filename);
250
251 cpl_propertylist_delete(prolist);
252
253 cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
254
255 return CPL_ERROR_NONE;
256}
257
258/*----------------------------------------------------------------------------*/
277/*----------------------------------------------------------------------------*/
278cpl_error_code
279irplib_dfs_save_imagelist(cpl_frameset *allframes,
280 const cpl_parameterlist *parlist,
281 const cpl_frameset *usedframes,
282 const cpl_imagelist *imagelist,
283 cpl_type_bpp bpp,
284 const char *recipe,
285 const char *procat,
286 const cpl_propertylist *applist,
287 const char *remregexp,
288 const char *pipe_id,
289 const char *filename)
290{
291 cpl_errorstate prestate = cpl_errorstate_get();
292 cpl_propertylist *prolist =
293 applist ? cpl_propertylist_duplicate(applist) : cpl_propertylist_new();
294
295 cpl_propertylist_update_string(prolist, CPL_DFS_PRO_CATG, procat);
296
297 cpl_dfs_save_imagelist(allframes, NULL, parlist, usedframes, NULL,
298 imagelist, bpp, recipe, prolist, remregexp, pipe_id,
299 filename);
300
301 cpl_propertylist_delete(prolist);
302
303 cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
304
305 return CPL_ERROR_NONE;
306}
307
308/*----------------------------------------------------------------------------*/
326/*----------------------------------------------------------------------------*/
327cpl_error_code
328irplib_dfs_save_table(cpl_frameset *allframes,
329 const cpl_parameterlist *parlist,
330 const cpl_frameset *usedframes,
331 const cpl_table *table,
332 const cpl_propertylist *tablelist,
333 const char *recipe,
334 const char *procat,
335 const cpl_propertylist *applist,
336 const char *remregexp,
337 const char *pipe_id,
338 const char *filename)
339{
340 cpl_errorstate prestate = cpl_errorstate_get();
341 cpl_propertylist *prolist =
342 applist ? cpl_propertylist_duplicate(applist) : cpl_propertylist_new();
343
344 cpl_propertylist_update_string(prolist, CPL_DFS_PRO_CATG, procat);
345
346 cpl_dfs_save_table(allframes, NULL, parlist, usedframes, NULL, table,
347 tablelist, recipe, prolist, remregexp, pipe_id,
348 filename);
349
350 cpl_propertylist_delete(prolist);
351
352 cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
353
354 return CPL_ERROR_NONE;
355}
356
357
358/*----------------------------------------------------------------------------*/
385/*----------------------------------------------------------------------------*/
386cpl_error_code
387irplib_dfs_save_image_(cpl_frameset *allframes,
388 cpl_propertylist *header,
389 const cpl_parameterlist *parlist,
390 const cpl_frameset *usedframes,
391 const cpl_frame *inherit,
392 const cpl_image *image,
393 cpl_type type,
394 const char *recipe,
395 const cpl_propertylist *applist,
396 const char *remregexp,
397 const char *pipe_id,
398 const char *filename)
399{
400 return irplib_dfs_product_save(allframes, header, parlist, usedframes,
401 inherit, NULL, image, type, NULL, NULL,
402 recipe, applist, remregexp, pipe_id,
403 filename)
404 ? cpl_error_set_where(cpl_func)
405 : CPL_ERROR_NONE;
406}
407
408
409/*----------------------------------------------------------------------------*/
433/*----------------------------------------------------------------------------*/
434
435static cpl_error_code
436irplib_dfs_product_save(cpl_frameset *allframes,
437 cpl_propertylist *header,
438 const cpl_parameterlist *parlist,
439 const cpl_frameset *usedframes,
440 const cpl_frame *inherit,
441 const cpl_imagelist *imagelist,
442 const cpl_image *image,
443 cpl_type type,
444 const cpl_table *table,
445 const cpl_propertylist *tablelist,
446 const char *recipe,
447 const cpl_propertylist *applist,
448 const char *remregexp,
449 const char *pipe_id,
450 const char *filename)
451{
452 const char *procat;
453 cpl_propertylist *plist;
454 cpl_frame *product_frame;
455 /* Inside this function the product-types are numbered:
456 0: imagelist
457 1: table
458 2: image
459 3: propertylist only
460 */
461 const unsigned pronum = imagelist != NULL ? 0
462 : table != NULL ? 1
463 : (image != NULL ? 2 : 3);
464 const char *proname[] = {"imagelist", "table", "image", "propertylist"};
465 /* FIXME: Define a frame type for an imagelist and when data-less */
466 const int protype[] = {CPL_FRAME_TYPE_ANY, CPL_FRAME_TYPE_TABLE,
467 CPL_FRAME_TYPE_IMAGE, CPL_FRAME_TYPE_ANY};
468 cpl_error_code error = CPL_ERROR_NONE;
469
470
471 /* No more than one of imagelist, table and image may be non-NULL */
472 /* tablelist may only be non-NULL when table is non-NULL */
473 if (imagelist != NULL) {
474 assert(pronum == 0);
475 assert(image == NULL);
476 assert(table == NULL);
477 assert(tablelist == NULL);
478 }
479 else if (table != NULL) {
480 assert(pronum == 1);
481 assert(imagelist == NULL);
482 assert(image == NULL);
483 }
484 else if (image != NULL) {
485 assert(pronum == 2);
486 assert(imagelist == NULL);
487 assert(table == NULL);
488 assert(tablelist == NULL);
489 }
490 else {
491 assert(pronum == 3);
492 assert(imagelist == NULL);
493 assert(table == NULL);
494 assert(tablelist == NULL);
495 assert(image == NULL);
496 }
497
498 cpl_ensure_code(allframes != NULL, CPL_ERROR_NULL_INPUT);
499 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
500 cpl_ensure_code(usedframes != NULL, CPL_ERROR_NULL_INPUT);
501 cpl_ensure_code(recipe != NULL, CPL_ERROR_NULL_INPUT);
502 cpl_ensure_code(applist != NULL, CPL_ERROR_NULL_INPUT);
503 cpl_ensure_code(pipe_id != NULL, CPL_ERROR_NULL_INPUT);
504 cpl_ensure_code(filename != NULL, CPL_ERROR_NULL_INPUT);
505
506 procat = cpl_propertylist_get_string(applist, CPL_DFS_PRO_CATG);
507
508 cpl_ensure_code(procat != NULL, cpl_error_get_code());
509
510 cpl_msg_info(cpl_func, "Writing FITS %s product(%s): %s", proname[pronum],
511 procat, filename);
512
513 product_frame = cpl_frame_new();
514
515 /* Create product frame */
516 error |= cpl_frame_set_filename(product_frame, filename);
517 error |= cpl_frame_set_tag(product_frame, procat);
518 error |= cpl_frame_set_type(product_frame, protype[pronum]);
519 error |= cpl_frame_set_group(product_frame, CPL_FRAME_GROUP_PRODUCT);
520 error |= cpl_frame_set_level(product_frame, CPL_FRAME_LEVEL_FINAL);
521
522 if (error) {
523 cpl_frame_delete(product_frame);
524 return cpl_error_set_where(cpl_func);
525 }
526
527 if (header != NULL) {
528 cpl_propertylist_empty(header);
529 plist = header;
530 }
531 else {
532 plist = cpl_propertylist_new();
533 }
534
535 /* Add any QC parameters here */
536 if (applist != NULL)
537 error = cpl_propertylist_copy_property_regexp(plist, applist, ".", 0);
538
539 /* Add DataFlow keywords */
540 if (!error)
541 error = cpl_dfs_setup_product_header(plist, product_frame, usedframes,
542 parlist, recipe, pipe_id,
543 "PRO-1.16", inherit);
544
545 if (remregexp != NULL && !error) {
546 cpl_errorstate prestate = cpl_errorstate_get();
547 (void)cpl_propertylist_erase_regexp(plist, remregexp, 0);
548 if (!cpl_errorstate_is_equal(prestate))
549 error = cpl_error_get_code();
550 }
551
552 if (!error) {
553 switch (pronum) {
554 case 0:
555 error = cpl_imagelist_save(imagelist, filename, type, plist,
556 CPL_IO_CREATE);
557 break;
558 case 1:
559 error = cpl_table_save(table, plist, tablelist, filename,
560 CPL_IO_CREATE);
561 break;
562 case 2:
563 error =
564 cpl_image_save(image, filename, type, plist, CPL_IO_CREATE);
565 break;
566 default:
567 /* case 3: */
568 error = cpl_propertylist_save(plist, filename, CPL_IO_CREATE);
569 }
570 }
571
572 if (!error) {
573 /* Insert the frame of the saved file in the input frameset */
574 error = cpl_frameset_insert(allframes, product_frame);
575 }
576 else {
577 cpl_frame_delete(product_frame);
578 }
579
580 if (plist != header)
581 cpl_propertylist_delete(plist);
582
583 cpl_ensure_code(!error, error);
584
585 return CPL_ERROR_NONE;
586}
587
588
589/*----------------------------------------------------------------------------*/
644/*----------------------------------------------------------------------------*/
645cpl_error_code
646irplib_image_split(const cpl_image *self,
647 cpl_image *im_low,
648 cpl_image *im_mid,
649 cpl_image *im_high,
650 double th_low,
651 cpl_boolean isleq_low,
652 double th_high,
653 cpl_boolean isgeq_high,
654 double alt_low,
655 double alt_high,
656 cpl_boolean isbad_low,
657 cpl_boolean isbad_mid,
658 cpl_boolean isbad_high)
659{
660 const void *selfdata = cpl_image_get_data_const(self);
661 /* hasbpm reduces check-overhead if self does not have a bpm, and if
662 self is also passed as an output image, that ends up with bad pixels */
663 /* FIXME: Need a proper way to know if a bpm has been allocated :-((((((( */
664 const cpl_boolean hasbpm =
665 cpl_image_count_rejected(self) ? CPL_TRUE : CPL_FALSE;
666 const cpl_binary *selfbpm =
667 hasbpm ? cpl_mask_get_data_const(cpl_image_get_bpm_const(self)) : NULL;
668 const cpl_type selftype = cpl_image_get_type(self);
669 const int nx = cpl_image_get_size_x(self);
670 const int ny = cpl_image_get_size_y(self);
671 const int npix = nx * ny;
672 const cpl_boolean do_low = im_low != NULL;
673 const cpl_boolean do_mid = im_mid != NULL;
674 const cpl_boolean do_high = im_high != NULL;
675 void *lowdata = NULL;
676 void *middata = NULL;
677 void *highdata = NULL;
678 cpl_binary *lowbpm = NULL;
679 cpl_binary *midbpm = NULL;
680 cpl_binary *highbpm = NULL;
681 const cpl_type lowtype =
682 do_low ? cpl_image_get_type(im_low) : CPL_TYPE_INVALID;
683 const cpl_type midtype =
684 do_mid ? cpl_image_get_type(im_mid) : CPL_TYPE_INVALID;
685 const cpl_type hightype =
686 do_high ? cpl_image_get_type(im_high) : CPL_TYPE_INVALID;
687 int i;
688
689
690 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
691 cpl_ensure_code(do_low || do_mid || do_high, CPL_ERROR_NULL_INPUT);
692 cpl_ensure_code(th_low <= th_high, CPL_ERROR_ILLEGAL_INPUT);
693
694 if (do_low) {
695 cpl_ensure_code(cpl_image_get_size_x(im_low) == nx,
696 CPL_ERROR_INCOMPATIBLE_INPUT);
697 cpl_ensure_code(cpl_image_get_size_y(im_low) == ny,
698 CPL_ERROR_INCOMPATIBLE_INPUT);
699 lowdata = cpl_image_get_data(im_low);
700 }
701
702 if (do_mid) {
703 cpl_ensure_code(cpl_image_get_size_x(im_mid) == nx,
704 CPL_ERROR_INCOMPATIBLE_INPUT);
705 cpl_ensure_code(cpl_image_get_size_y(im_mid) == ny,
706 CPL_ERROR_INCOMPATIBLE_INPUT);
707 middata = cpl_image_get_data(im_mid);
708 }
709
710 if (do_high) {
711 cpl_ensure_code(cpl_image_get_size_x(im_high) == nx,
712 CPL_ERROR_INCOMPATIBLE_INPUT);
713 cpl_ensure_code(cpl_image_get_size_y(im_high) == ny,
714 CPL_ERROR_INCOMPATIBLE_INPUT);
715 highdata = cpl_image_get_data(im_high);
716 }
717
718 /* From this point a failure would indicate a serious bug in CPL */
719
720 for (i = 0; i < npix; i++) {
721 const double value = irplib_data_get_double(selfdata, selftype, i);
722 cpl_boolean isalt_low = do_low;
723 cpl_boolean isalt_mid = do_mid;
724 cpl_boolean isalt_high = do_high;
725 cpl_boolean setbad_low = do_low;
726 cpl_boolean setbad_mid = do_mid;
727 cpl_boolean setbad_high = do_high;
728 const void *setdata = NULL;
729 double alt_mid = 0.0; /* Avoid (false) uninit warning */
730
731 if (isleq_low ? value <= th_low : value < th_low) {
732 if (do_low) {
733 isalt_low = CPL_FALSE;
734 irplib_data_set_double(lowdata, lowtype, i, value);
735 setbad_low = hasbpm && selfbpm[i];
736 setdata = lowdata;
737 }
738 alt_mid = alt_low;
739 }
740 else if (isgeq_high ? value >= th_high : value > th_high) {
741 if (do_high) {
742 isalt_high = CPL_FALSE;
743 irplib_data_set_double(highdata, hightype, i, value);
744 setbad_high = hasbpm && selfbpm[i];
745 setdata = highdata;
746 }
747 alt_mid = alt_high;
748 }
749 else if (do_mid) {
750 isalt_mid = CPL_FALSE;
751 irplib_data_set_double(middata, midtype, i, value);
752 setbad_mid = hasbpm && selfbpm[i];
753 setdata = middata;
754 }
755
756 if (isalt_low && lowdata != setdata) {
757 irplib_data_set_double(lowdata, lowtype, i, alt_low);
758 setbad_low = isbad_low;
759 }
760 if (isalt_mid && middata != setdata) {
761 irplib_data_set_double(middata, midtype, i, alt_mid);
762 setbad_mid = isbad_mid;
763 }
764 if (isalt_high && highdata != setdata) {
765 irplib_data_set_double(highdata, hightype, i, alt_high);
766 setbad_high = isbad_high;
767 }
768
769 if (setbad_low) {
770 if (lowbpm == NULL)
771 lowbpm = cpl_mask_get_data(cpl_image_get_bpm(im_low));
772 lowbpm[i] = CPL_BINARY_1;
773 }
774 if (setbad_mid) {
775 if (midbpm == NULL)
776 midbpm = cpl_mask_get_data(cpl_image_get_bpm(im_mid));
777 midbpm[i] = CPL_BINARY_1;
778 }
779 if (setbad_high) {
780 if (highbpm == NULL)
781 highbpm = cpl_mask_get_data(cpl_image_get_bpm(im_high));
782 highbpm[i] = CPL_BINARY_1;
783 }
784 }
785
786 return CPL_ERROR_NONE;
787}
788
789
790/*----------------------------------------------------------------------------*/
838/*----------------------------------------------------------------------------*/
839
840cpl_error_code
842 cpl_table *self,
843 cpl_frameset *allframes,
844 const cpl_frameset *useframes,
845 int maxlinelen,
846 char commentchar,
847 const char *product_name,
848 const char *procatg,
849 const cpl_parameterlist *parlist,
850 const char *recipe_name,
851 const cpl_propertylist *mainlist,
852 const cpl_propertylist *extlist,
853 const char *remregexp,
854 const char *instrume,
855 const char *pipe_id,
856 cpl_boolean (*table_set_row)(cpl_table *,
857 const char *,
858 int,
859 const cpl_frame *,
860 const cpl_parameterlist *),
861 cpl_error_code (*table_check)(cpl_table *,
862 const cpl_frameset *,
863 const cpl_parameterlist *))
864{
865 const char *filename;
866 cpl_propertylist *applist = NULL;
867 cpl_errorstate prestate = cpl_errorstate_get();
868 cpl_error_code error;
869 char *fallback_filename = NULL;
870
871 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
872 cpl_ensure_code(allframes != NULL, CPL_ERROR_NULL_INPUT);
873 cpl_ensure_code(useframes != NULL, CPL_ERROR_NULL_INPUT);
874 cpl_ensure_code(procatg != NULL, CPL_ERROR_NULL_INPUT);
875 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
876 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
877 cpl_ensure_code(instrume != NULL, CPL_ERROR_NULL_INPUT);
878 cpl_ensure_code(pipe_id != NULL, CPL_ERROR_NULL_INPUT);
879
880 cpl_ensure_code(!irplib_table_read_from_frameset(self, useframes,
881 maxlinelen, commentchar,
882 parlist, table_set_row),
883 cpl_error_get_code());
884
885 if (table_check != NULL && (table_check(self, useframes, parlist) ||
886 !cpl_errorstate_is_equal(prestate))) {
887 return cpl_error_set_message(cpl_func, cpl_error_get_code(),
888 "Consistency check of table failed");
889 }
890
891 fallback_filename = cpl_sprintf("%s" CPL_DFS_FITS, recipe_name);
892 filename = product_name != NULL ? product_name : fallback_filename;
893
894 applist = mainlist == NULL ? cpl_propertylist_new()
895 : cpl_propertylist_duplicate(mainlist);
896
897 error = cpl_propertylist_update_string(applist, "INSTRUME", instrume);
898
899 if (!error)
900 error = irplib_dfs_save_table(allframes, parlist, useframes, self,
901 extlist, recipe_name, procatg, applist,
902 remregexp, pipe_id, filename);
903
904 cpl_propertylist_delete(applist);
905 cpl_free(fallback_filename);
906
907 /* Propagate the error, if any */
908 cpl_ensure_code(!error, error);
909
910 return CPL_ERROR_NONE;
911}
912
913
914/*----------------------------------------------------------------------------*/
963/*----------------------------------------------------------------------------*/
964
965cpl_error_code
967 cpl_table *self,
968 const cpl_frameset *useframes,
969 int maxlinelen,
970 char commentchar,
971 const cpl_parameterlist *parlist,
972 cpl_boolean (*table_set_row)(cpl_table *,
973 const char *,
974 int,
975 const cpl_frame *,
976 const cpl_parameterlist *))
977{
978 const cpl_frame *rawframe;
979 char *linebuffer = NULL;
980 FILE *stream = NULL;
981 int nfiles = 0;
982 int nrow = cpl_table_get_nrow(self);
983 int irow = 0;
984 cpl_errorstate prestate = cpl_errorstate_get();
985 cpl_frameset_iterator *iterator = NULL;
986
987 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
988 cpl_ensure_code(useframes != NULL, CPL_ERROR_NULL_INPUT);
989 cpl_ensure_code(maxlinelen > 0, CPL_ERROR_ILLEGAL_INPUT);
990 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
991 cpl_ensure_code(table_set_row != NULL, CPL_ERROR_NULL_INPUT);
992
993 linebuffer = cpl_malloc(maxlinelen);
994
995 for (rawframe = irplib_frameset_get_first_const(&iterator, useframes);
996 rawframe != NULL;
997 rawframe = irplib_frameset_get_next_const(iterator), nfiles++) {
998 const char *rawfile = cpl_frame_get_filename(rawframe);
999 const char *done; /* Indicate when the reading is done */
1000 const int irowpre = irow;
1001 int iirow = 0;
1002 int ierror;
1003
1004 if (rawfile == NULL)
1005 break; /* Should not happen... */
1006
1007 stream = fopen(rawfile, "r");
1008
1009 if (stream == NULL) {
1010#if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
1011 cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
1012 "Could not "
1013 "open %s for reading",
1014 rawfile);
1015#else
1016 cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
1017 "Could not "
1018 "open file for reading");
1019#endif
1020 break;
1021 }
1022
1023 for (; (done = fgets(linebuffer, maxlinelen, stream)) != NULL;
1024 iirow++) {
1025 if (linebuffer[0] != commentchar) {
1026 cpl_boolean didset;
1027#if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
1028 const int prerow = irow;
1029#endif
1030
1031 if (irow == nrow) {
1032 nrow += nrow ? nrow : 1;
1033 if (cpl_table_set_size(self, nrow))
1034 break;
1035 }
1036
1037 didset =
1038 table_set_row(self, linebuffer, irow, rawframe, parlist);
1039 if (didset)
1040 irow++;
1041
1042 if (!cpl_errorstate_is_equal(prestate)) {
1043 if (didset)
1044#if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
1045 cpl_error_set_message(cpl_func, cpl_error_get_code(),
1046 "Failed to set table row %d "
1047 "using line %d from %d. file %s",
1048 1 + prerow, iirow + 1, nfiles + 1,
1049 rawfile);
1050 else
1051 cpl_error_set_message(cpl_func, cpl_error_get_code(),
1052 "Failure with line %d from %d. "
1053 "file %s",
1054 iirow + 1, nfiles + 1, rawfile);
1055#else
1056 cpl_error_set_message(cpl_func, cpl_error_get_code(),
1057 "Failed to set table row"
1058 "using catalogue line");
1059 else
1060 cpl_error_set_message(cpl_func, cpl_error_get_code(),
1061 "Failure with catalogue line");
1062#endif
1063
1064 break;
1065 }
1066 }
1067 }
1068 if (done != NULL)
1069 break;
1070
1071 ierror = fclose(stream);
1072 stream = NULL;
1073 if (ierror)
1074 break;
1075
1076
1077 if (irow == irowpre)
1078 cpl_msg_warning(cpl_func, "No usable lines in the %d. file: %s",
1079 1 + nfiles, rawfile);
1080 }
1081
1082 cpl_frameset_iterator_delete(iterator);
1083 cpl_free(linebuffer);
1084 if (stream != NULL)
1085 fclose(stream);
1086
1087 /* Check for premature end */
1088 cpl_ensure_code(rawframe == NULL, cpl_error_get_code());
1089
1090 if (irow == 0) {
1091#if defined CPL_HAVE_VA_ARGS && CPL_HAVE_VA_ARGS != 0
1092 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1093 "No usable lines in the %d input "
1094 "frame(s)",
1095 nfiles);
1096#else
1097 return cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
1098 "No usable lines in the input frame(s)");
1099#endif
1100 }
1101
1102 /* Resize the table to the actual number of rows set */
1103 cpl_ensure_code(!cpl_table_set_size(self, irow), cpl_error_get_code());
1104
1105 return CPL_ERROR_NONE;
1106}
1107
1108
1109/*----------------------------------------------------------------------------*/
1121/*----------------------------------------------------------------------------*/
1122void
1124{
1125 return;
1126}
1127
1128/*----------------------------------------------------------------------------*/
1135/*----------------------------------------------------------------------------*/
1136int
1137irplib_compare_tags(cpl_frame *frame1, cpl_frame *frame2)
1138{
1139 const char *v1;
1140 const char *v2;
1141
1142 /* Test entries */
1143 if (frame1 == NULL || frame2 == NULL)
1144 return -1;
1145
1146 /* Get the tags */
1147 if ((v1 = cpl_frame_get_tag(frame1)) == NULL)
1148 return -1;
1149 if ((v2 = cpl_frame_get_tag(frame2)) == NULL)
1150 return -1;
1151
1152 /* Compare the tags */
1153 if (strcmp(v1, v2))
1154 return 0;
1155 else
1156 return 1;
1157}
1158
1159/*----------------------------------------------------------------------------*/
1175/*----------------------------------------------------------------------------*/
1176const char *
1177irplib_frameset_find_file(const cpl_frameset *self, const char *tag)
1178{
1179 const cpl_frame *frame = cpl_frameset_find_const(self, tag);
1180
1181
1182 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
1183
1184 if (frame == NULL)
1185 return NULL;
1186
1187 if (cpl_frameset_find_const(self, NULL))
1188 cpl_msg_warning(cpl_func,
1189 "Frameset has more than one file with tag: %s", tag);
1190
1191 return cpl_frame_get_filename(frame);
1192}
1193
1194/*----------------------------------------------------------------------------*/
1204/*----------------------------------------------------------------------------*/
1205const cpl_frame *
1207 cpl_frame_group group)
1208{
1209 const cpl_frame *frame;
1210 cpl_frameset_iterator *iterator = NULL;
1211
1212 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
1213
1214 for (frame = irplib_frameset_get_first_const(&iterator, self);
1215 frame != NULL; frame = irplib_frameset_get_next_const(iterator)) {
1216 if (cpl_frame_get_group(frame) == group)
1217 break;
1218 }
1219 cpl_frameset_iterator_delete(iterator);
1220 return frame;
1221}
1222
1223/*----------------------------------------------------------------------------*/
1242/*----------------------------------------------------------------------------*/
1243cpl_error_code
1244irplib_apertures_find_max_flux(const cpl_apertures *self, int *ind, int nfind)
1245{
1246 const int nsize = cpl_apertures_get_size(self);
1247 int ifind;
1248
1249
1250 cpl_ensure_code(nsize > 0, cpl_error_get_code());
1251 cpl_ensure_code(ind, CPL_ERROR_NULL_INPUT);
1252 cpl_ensure_code(nfind > 0, CPL_ERROR_ILLEGAL_INPUT);
1253 cpl_ensure_code(nfind <= nsize, CPL_ERROR_ILLEGAL_INPUT);
1254
1255 for (ifind = 0; ifind < nfind; ifind++) {
1256 double maxflux = -1;
1257 int maxind = -1;
1258 int i;
1259 for (i = 1; i <= nsize; i++) {
1260 int k;
1261
1262 /* The flux has to be the highest among those not already found */
1263 for (k = 0; k < ifind; k++)
1264 if (ind[k] == i)
1265 break;
1266
1267 if (k == ifind) {
1268 /* i has not been inserted into ind */
1269 const double flux = cpl_apertures_get_flux(self, i);
1270
1271 if (maxind < 0 || flux > maxflux) {
1272 maxind = i;
1273 maxflux = flux;
1274 }
1275 }
1276 }
1277 ind[ifind] = maxind;
1278 }
1279
1280 return CPL_ERROR_NONE;
1281}
1282
1284
1285
1286/*----------------------------------------------------------------------------*/
1297/*----------------------------------------------------------------------------*/
1298inline static double
1299irplib_data_get_double(const void *self, cpl_type type, int i)
1300{
1301 double value;
1302
1303
1304 switch (type) {
1305 case CPL_TYPE_FLOAT: {
1306 const float *pself = (const float *)self;
1307 value = (double)pself[i];
1308 break;
1309 }
1310 case CPL_TYPE_INT: {
1311 const int *pself = (const int *)self;
1312 value = (double)pself[i];
1313 break;
1314 }
1315 default: /* case CPL_TYPE_DOUBLE */
1316 {
1317 const double *pself = (const double *)self;
1318 value = pself[i];
1319 break;
1320 }
1321 }
1322
1323 return value;
1324}
1325
1326
1327/*----------------------------------------------------------------------------*/
1338/*----------------------------------------------------------------------------*/
1339inline static void
1340irplib_data_set_double(void *self, cpl_type type, int i, double value)
1341{
1342 switch (type) {
1343 case CPL_TYPE_FLOAT: {
1344 float *pself = (float *)self;
1345 pself[i] = (float)value;
1346 break;
1347 }
1348 case CPL_TYPE_INT: {
1349 int *pself = (int *)self;
1350 pself[i] = (int)value;
1351 break;
1352 }
1353 default: /* case CPL_TYPE_DOUBLE */
1354 {
1355 double *pself = (double *)self;
1356 pself[i] = value;
1357 break;
1358 }
1359 }
1360}
1361
1362
1363/*----------------------------------------------------------------------------*/
1374/*----------------------------------------------------------------------------*/
1375static void
1376irplib_errorstate_dump_one_level(void (*messenger)(const char *,
1377 const char *,
1378 ...),
1379 unsigned self,
1380 unsigned first,
1381 unsigned last)
1382{
1383 const cpl_boolean is_reverse = first > last ? CPL_TRUE : CPL_FALSE;
1384 const unsigned newest = is_reverse ? first : last;
1385 const unsigned oldest = is_reverse ? last : first;
1386 const char *revmsg = is_reverse ? " in reverse order" : "";
1387
1388
1389 /*
1390 cx_assert( messenger != NULL );
1391 cx_assert( oldest <= self );
1392 cx_assert( newest >= self );
1393 */
1394
1395 if (newest == 0) {
1396 messenger(cpl_func, "No error(s) to dump");
1397 /* cx_assert( oldest == 0); */
1398 }
1399 else {
1400 /*
1401 cx_assert( oldest > 0);
1402 cx_assert( newest >= oldest);
1403 */
1404 if (self == first) {
1405 if (oldest == 1) {
1406 messenger(cpl_func, "Dumping all %u error(s)%s:", newest,
1407 revmsg);
1408 }
1409 else {
1410 messenger(cpl_func,
1411 "Dumping the %u most recent error(s) "
1412 "out of a total of %u errors%s:",
1413 newest - oldest + 1, newest, revmsg);
1414 }
1415 cpl_msg_indent_more();
1416 }
1417
1418 messenger(cpl_func, "[%u/%u] '%s' (%u) at %s", self, newest,
1419 cpl_error_get_message(), cpl_error_get_code(),
1420 cpl_error_get_where());
1421
1422 if (self == last)
1423 cpl_msg_indent_less();
1424 }
1425}
1426
1427cpl_polynomial *
1428irplib_polynomial_fit_1d_create_chiq(const cpl_vector *x_pos,
1429 const cpl_vector *values,
1430 int degree,
1431 double *rechisq)
1432{
1433 return irplib_polynomial_fit_1d_create_common(x_pos, values, degree, NULL,
1434 rechisq);
1435}
1436cpl_polynomial *
1437irplib_polynomial_fit_1d_create(const cpl_vector *x_pos,
1438 const cpl_vector *values,
1439 int degree,
1440 double *mse)
1441{
1442 return irplib_polynomial_fit_1d_create_common(x_pos, values, degree, mse,
1443 NULL);
1444}
1445static cpl_polynomial *
1446irplib_polynomial_fit_1d_create_common(const cpl_vector *x_pos,
1447 const cpl_vector *values,
1448 int degree,
1449 double *mse,
1450 double *rechisq)
1451{
1452 cpl_polynomial *fit1d = NULL;
1453 cpl_size loc_degree = (cpl_size)degree;
1454 int x_size = 0;
1455 fit1d = cpl_polynomial_new(1);
1456 x_size = cpl_vector_get_size(x_pos);
1457 if (fit1d != NULL && x_size > 1) {
1458 cpl_matrix *samppos = NULL;
1459 cpl_vector *fitresidual = NULL;
1460 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
1461 samppos = cpl_matrix_wrap(1, x_size,
1462 (double *)cpl_vector_get_data_const(x_pos));
1463 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
1464 fitresidual = cpl_vector_new(x_size);
1465 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
1466 cpl_polynomial_fit(fit1d, samppos, NULL, values, NULL, CPL_FALSE, NULL,
1467 &loc_degree);
1468 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
1469 cpl_vector_fill_polynomial_fit_residual(fitresidual, values, NULL,
1470 fit1d, samppos, rechisq);
1471 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
1472 if (mse) {
1473 *mse = cpl_vector_product(fitresidual, fitresidual) /
1474 cpl_vector_get_size(fitresidual);
1475 }
1476 cpl_matrix_unwrap(samppos);
1477 cpl_vector_delete(fitresidual);
1478 }
1479 return fit1d;
1480}
1481
1482static void
1483quicksort(int *iindex, double *exptime, int left, int right)
1484{
1485 int i = left;
1486 int j = right;
1487 int pivot = (i + j) / 2;
1488 double index_value = exptime[pivot];
1489 do {
1490 while (exptime[i] < index_value)
1491 i++;
1492 while (exptime[j] > index_value)
1493 j--;
1494 if (i <= j) {
1495 if (i < j) {
1496 int tmp = iindex[i];
1497 double dtmp = exptime[i];
1498 iindex[i] = iindex[j];
1499 iindex[j] = tmp;
1500 exptime[i] = exptime[j];
1501 exptime[j] = dtmp;
1502 }
1503 i++;
1504 j--;
1505 }
1506 } while (i <= j);
1507
1508 if (i < right) {
1509 quicksort(iindex, exptime, i, right);
1510 }
1511 if (left < j) {
1512 quicksort(iindex, exptime, left, j);
1513 }
1514}
1515cpl_error_code
1516irplib_frameset_sort(const cpl_frameset *self, int *iindex, double *exptime)
1517{
1518 int i = 0;
1519 const cpl_frame *tmp_frame = 0;
1520 cpl_error_code error = CPL_ERROR_NONE;
1521 int sz = cpl_frameset_get_size(self);
1522 cpl_frameset_iterator *iterator = NULL;
1523
1524 /* 1. get an array of frames */
1525 tmp_frame = irplib_frameset_get_first_const(&iterator, self);
1526 while (tmp_frame) {
1527 exptime[i] = frame_get_exptime(tmp_frame);
1528 iindex[i] = i;
1529 tmp_frame = irplib_frameset_get_next_const(iterator);
1530 i++;
1531 }
1532 cpl_frameset_iterator_delete(iterator);
1533 /* 2.sort */
1534 quicksort(iindex, exptime, 0, sz - 1);
1535
1536 return error;
1537}
1538
1539static double
1540frame_get_exptime(const cpl_frame *pframe)
1541{
1542 double dval = 0;
1543 cpl_propertylist *plist =
1544 cpl_propertylist_load_regexp(cpl_frame_get_filename(pframe), 0,
1545 "EXPTIME", CPL_FALSE);
1546 if (plist) {
1547 dval = cpl_propertylist_get_double(plist, "EXPTIME");
1548 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1549 cpl_msg_error(cpl_func,
1550 "error during reading EXPTIME key from "
1551 "the frame [%s]",
1552 cpl_frame_get_filename(pframe));
1553 }
1554 }
1555 /* Free and return */
1556 cpl_propertylist_delete(plist);
1557 return dval;
1558}
1559
1560
1561/*----------------------------------------------------------------------------*/
1575/*----------------------------------------------------------------------------*/
1576void *
1577irplib_aligned_malloc(size_t alignment, size_t size)
1578{
1579 if (alignment == 0)
1580 alignment = 1;
1581 /* Error if align is not a power of two. */
1582 if (alignment & (alignment - 1)) {
1583 errno = EINVAL;
1584 return NULL;
1585 }
1586 /* make size a multiple of alignment (required by C11) */
1587 if ((size % alignment) != 0) {
1588 size += alignment - (size % alignment);
1589 }
1590
1591#if defined HAVE_DECL_ALIGNED_ALLOC && defined HAVE_ALIGNED_ALLOC
1592 return aligned_alloc(alignment, size);
1593#elif defined HAVE_POSIX_MEMALIGN && defined HAVE_DECL_POSIX_MEMALIGN
1594 {
1595 void *ptr;
1596 if (alignment == 1)
1597 return malloc(size);
1598 if (alignment == 2 || (sizeof(void *) == 8 && alignment == 4))
1599 alignment = sizeof(void *);
1600 if (posix_memalign(&ptr, alignment, size) == 0)
1601 return ptr;
1602 else
1603 return NULL;
1604 }
1605#else
1606 /* copied from gmm_malloc.h in gcc-4.8 */
1607 {
1608 void *malloc_ptr;
1609 void *aligned_ptr;
1610
1611 if (size == 0)
1612 return NULL;
1613
1614 /* Assume malloc'd pointer is aligned at least to sizeof (void*).
1615 If necessary, add another sizeof (void*) to store the value
1616 returned by malloc. Effectively this enforces a minimum alignment
1617 of sizeof double. */
1618 if (alignment < 2 * sizeof(void *))
1619 alignment = 2 * sizeof(void *);
1620
1621 malloc_ptr = malloc(size + alignment);
1622 if (!malloc_ptr)
1623 return NULL;
1624
1625 /* Align We have at least sizeof (void *) space below malloc'd ptr. */
1626 aligned_ptr = (void *)(((size_t)malloc_ptr + alignment) &
1627 ~((size_t)(alignment)-1));
1628
1629 /* Store the original pointer just before p. */
1630 *(((void **)aligned_ptr) - 1) = malloc_ptr;
1631
1632 return aligned_ptr;
1633 }
1634#endif
1635}
1636
1637
1638/*----------------------------------------------------------------------------*/
1648/*----------------------------------------------------------------------------*/
1649void *
1650irplib_aligned_calloc(size_t alignment, size_t nelem, size_t nbytes)
1651{
1652 void *buffer = irplib_aligned_malloc(alignment, nelem * nbytes);
1653 if (buffer == NULL)
1654 return NULL;
1655 /* cast to aligned pointer helps compilers to emit better (builtin) code */
1656 memset((size_t *)buffer, 0, nelem * nbytes);
1657 return buffer;
1658}
1659
1660
1661/*----------------------------------------------------------------------------*/
1669/*----------------------------------------------------------------------------*/
1670void
1671irplib_aligned_free(void *aligned_ptr)
1672{
1673#if defined HAVE_DECL_ALIGNED_ALLOC && defined HAVE_ALIGNED_ALLOC
1674 free(aligned_ptr);
1675#elif defined HAVE_POSIX_MEMALIGN && defined HAVE_DECL_POSIX_MEMALIGN
1676 free(aligned_ptr);
1677#else
1678 if (aligned_ptr)
1679 free(*(((void **)aligned_ptr) - 1));
1680#endif
1681}
1682
1683
1684/*----------------------------------------------------------------------------*/
1697/*----------------------------------------------------------------------------*/
1698const cpl_frame *
1699irplib_frameset_get_first_const(cpl_frameset_iterator **iterator,
1700 const cpl_frameset *frameset)
1701{
1702 cpl_ensure(iterator != NULL, CPL_ERROR_NULL_INPUT, NULL);
1703 *iterator = cpl_frameset_iterator_new(frameset);
1704 return cpl_frameset_iterator_get_const(*iterator);
1705}
1706
1707/*----------------------------------------------------------------------------*/
1716/*----------------------------------------------------------------------------*/
1717const cpl_frame *
1718irplib_frameset_get_next_const(cpl_frameset_iterator *iterator)
1719{
1720 cpl_errorstate prestate = cpl_errorstate_get();
1721 cpl_error_code error = cpl_frameset_iterator_advance(iterator, 1);
1722 if (error == CPL_ERROR_ACCESS_OUT_OF_RANGE) {
1723 cpl_errorstate_set(prestate);
1724 return NULL;
1725 }
1726 else if (error != CPL_ERROR_NONE) {
1727 return NULL;
1728 }
1729 return cpl_frameset_iterator_get_const(iterator);
1730}
1731
1732
1733/*----------------------------------------------------------------------------*/
1755/*----------------------------------------------------------------------------*/
1756
1757void
1758irplib_vector_get_kth(cpl_vector *self, cpl_size k)
1759{
1760 cpl_size l = 0;
1761 cpl_size m = cpl_vector_get_size(self) - 1;
1762 cpl_size i = l;
1763 cpl_size j = m;
1764 double *pself = cpl_vector_get_data(self);
1765
1766 if (pself == NULL) {
1767 (void)cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
1768 return;
1769 }
1770 else if (k < 0) {
1771 (void)cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
1772 return;
1773 }
1774 else if (k > m) {
1775 (void)cpl_error_set(cpl_func, CPL_ERROR_ACCESS_OUT_OF_RANGE);
1776 return;
1777 }
1778
1779 while (l < m) {
1780 const double x = pself[k];
1781
1782 do {
1783 while (pself[i] < x)
1784 i++;
1785 while (x < pself[j])
1786 j--;
1787 if (i <= j) {
1788 IRPLIB_SWAP_DOUBLE(pself[i], pself[j]);
1789 i++;
1790 j--;
1791 }
1792 } while (i <= j);
1793
1794 assert(j < i);
1795
1796 /* The original implementation has two index comparisons and
1797 two, three or four index assignments. This has been reduced
1798 to one or two index comparisons and two index assignments.
1799 */
1800
1801 if (k <= j) {
1802 assert(k < i);
1803 m = j;
1804 i = l;
1805 }
1806 else {
1807 if (k < i) {
1808 m = j;
1809 }
1810 else {
1811 j = m;
1812 }
1813 l = i;
1814 }
1815 }
1816}
cpl_error_code irplib_dfs_save_image_(cpl_frameset *allframes, cpl_propertylist *header, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_frame *inherit, const cpl_image *image, cpl_type type, const char *recipe, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save an image as a DFS-compliant pipeline product.
void irplib_errorstate_dump_debug(unsigned self, unsigned first, unsigned last)
Dump a single CPL error at the CPL debug level.
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.
cpl_error_code irplib_dfs_table_convert(cpl_table *self, cpl_frameset *allframes, const cpl_frameset *useframes, int maxlinelen, char commentchar, const char *product_name, const char *procatg, const cpl_parameterlist *parlist, const char *recipe_name, const cpl_propertylist *mainlist, const cpl_propertylist *extlist, const char *remregexp, const char *instrume, const char *pipe_id, cpl_boolean(*table_set_row)(cpl_table *, const char *, int, const cpl_frame *, const cpl_parameterlist *), cpl_error_code(*table_check)(cpl_table *, const cpl_frameset *, const cpl_parameterlist *))
Create a DFS product with one table from one or more (ASCII) file(s)
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.
cpl_error_code irplib_table_read_from_frameset(cpl_table *self, const cpl_frameset *useframes, int maxlinelen, char commentchar, const cpl_parameterlist *parlist, cpl_boolean(*table_set_row)(cpl_table *, const char *, int, const cpl_frame *, const cpl_parameterlist *))
Set the rows of a table with data from one or more (ASCII) files.
cpl_error_code irplib_dfs_save_table(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_table *table, const cpl_propertylist *tablelist, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save a table as a DFS-compliant pipeline product.
cpl_error_code irplib_dfs_save_imagelist(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_imagelist *imagelist, 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 imagelist as a DFS-compliant pipeline product.
void irplib_errorstate_dump_warning(unsigned self, unsigned first, unsigned last)
Dump a single CPL error at the CPL warning level.
cpl_error_code irplib_image_split(const cpl_image *self, cpl_image *im_low, cpl_image *im_mid, cpl_image *im_high, double th_low, cpl_boolean isleq_low, double th_high, cpl_boolean isgeq_high, double alt_low, double alt_high, cpl_boolean isbad_low, cpl_boolean isbad_mid, cpl_boolean isbad_high)
Split the values in an image in three according to two thresholds.
void irplib_errorstate_dump_info(unsigned self, unsigned first, unsigned last)
Dump a single CPL error at the CPL info level.
const cpl_frame * irplib_frameset_get_first_from_group(const cpl_frameset *self, cpl_frame_group group)
Find the first frame belonging to the given group.
const char * irplib_frameset_find_file(const cpl_frameset *self, const char *tag)
Find the filename with the given tag in a frame set.
cpl_error_code irplib_apertures_find_max_flux(const cpl_apertures *self, int *ind, int nfind)
Find the aperture(s) with the greatest flux.
int irplib_compare_tags(cpl_frame *frame1, cpl_frame *frame2)
Comparison function to identify different input frames.
void irplib_reset(void)
Reset IRPLIB state.