CR2RE Pipeline Reference Manual 1.7.0
hdrl_utils.c
1/*
2 * This file is part of the HDRL
3 * Copyright (C) 2012,2013 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26-----------------------------------------------------------------------------*/
27#if !defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE - 0) < 500
28#define _XOPEN_SOURCE 500 /* posix 2001, mkstemp */
29#endif
30
31#include "hdrl_utils.h"
32#include "hdrl_types.h"
33#include "hdrl_elemop.h"
34#include "hdrl_prototyping.h"
35#include "hdrl_imagelist.h"
36#include <string.h>
37#include <assert.h>
38#include <stdlib.h>
39#include <unistd.h>
40#include <errno.h>
41#include <math.h>
42#include <stdarg.h>
43
44/*-----------------------------------------------------------------------------
45 Static
46 -----------------------------------------------------------------------------*/
47
48/*----------------------------------------------------------------------------*/
55/*----------------------------------------------------------------------------*/
56
58
59/*----------------------------------------------------------------------------*/
67/*----------------------------------------------------------------------------*/
68const char * hdrl_get_license(void)
69{
70 static const char * hdrl_license =
71 "This file is part of the HDRL Instrument Pipeline\n"
72 "Copyright (C) 2012,2013 European Southern Observatory\n"
73 "\n"
74 "This program is free software; you can redistribute it and/or modify\n"
75 "it under the terms of the GNU General Public License as published by\n"
76 "the Free Software Foundation; either version 2 of the License, or\n"
77 "(at your option) any later version.\n"
78 "\n"
79 "This program is distributed in the hope that it will be useful,\n"
80 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
81 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
82 "GNU General Public License for more details.\n"
83 "\n"
84 "You should have received a copy of the GNU General Public License\n"
85 "along with this program; if not, write to the Free Software\n"
86 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, \n"
87 "MA 02110-1301 USA";
88
89 return hdrl_license;
90}
91
92#define EOP_LINE_SIZE 188
93
94/*----------------------------------------------------------------------------*/
110/*----------------------------------------------------------------------------*/
111
112cpl_table * hdrl_eop_data_totable (const char * eop_data, cpl_size data_length)
113{
114 cpl_ensure (eop_data, CPL_ERROR_NULL_INPUT, NULL);
115
116 if(!((data_length) % EOP_LINE_SIZE == 0))
117 {
118 cpl_error_set_message(cpl_func, CPL_ERROR_NULL_INPUT,
119 "Raw data doesn't have a fixed record width");
120 return 0;
121 }
122
123 /* Create tables */
124 cpl_size n_entries = (data_length) / EOP_LINE_SIZE;
125 cpl_table * eop_table = cpl_table_new (n_entries);
126 cpl_msg_debug (cpl_func, " EOP data has a total of %"CPL_SIZE_FORMAT" entries", n_entries);
127
128 /* Create columns */
129 cpl_table_new_column (eop_table, "MJD", CPL_TYPE_DOUBLE);
130 cpl_table_new_column (eop_table, "PMX", CPL_TYPE_DOUBLE);
131 cpl_table_new_column (eop_table, "PMY", CPL_TYPE_DOUBLE);
132 cpl_table_new_column (eop_table, "DUT", CPL_TYPE_DOUBLE);
133 cpl_table_new_column (eop_table, "FLAG", CPL_TYPE_STRING);
134
135 /* Set units */
136 cpl_table_set_column_unit (eop_table, "MJD", "d");
137 cpl_table_set_column_unit (eop_table, "PMX", "arcsec");
138 cpl_table_set_column_unit (eop_table, "PMY", "arcsec");
139 cpl_table_set_column_unit (eop_table, "DUT", "s");
140
141 /* Fill the columns from the string buffer */
142 for(cpl_size i=0; i<n_entries; i++)
143 {
144 char flag[2];
145 strncpy(flag, eop_data+i*EOP_LINE_SIZE+16, 1);
146 flag[1] = '\0';
147 cpl_table_set_string(eop_table, "FLAG", i, flag);
148
149 cpl_table_set_double(eop_table, "MJD", i, atof(eop_data+i*EOP_LINE_SIZE+7));
150 if(!strncmp(flag, "I", 1) || !strncmp(flag, "P", 1))
151 {
152 cpl_table_set_double(eop_table, "PMX", i, atof(eop_data+i*EOP_LINE_SIZE+18));
153 cpl_table_set_double(eop_table, "PMY", i, atof(eop_data+i*EOP_LINE_SIZE+37));
154 cpl_table_set_double(eop_table, "DUT", i, atof(eop_data+i*EOP_LINE_SIZE+58));
155 }
156 }
157
158 /* Remove the NULL columns */
159 cpl_table_unselect_all (eop_table);
160 cpl_table_or_selected_invalid (eop_table, "PMX");
161 cpl_table_or_selected_invalid (eop_table, "PMY");
162 cpl_table_or_selected_invalid (eop_table, "DUT");
163 cpl_msg_debug (cpl_func,"Found %lld invalid", cpl_table_count_selected (eop_table));
164 cpl_table_erase_selected (eop_table);
165
166 return eop_table;
167}
168
169
170/*-----------------------------------------------------------------------------
171 Rectangular Region Parameters Definition
172 -----------------------------------------------------------------------------*/
173
175typedef struct {
176 HDRL_PARAMETER_HEAD;
177 cpl_size llx ;
178 cpl_size lly ;
179 cpl_size urx ;
180 cpl_size ury ;
181} hdrl_rect_region_parameter;
182
183/* Parameter type */
184static hdrl_parameter_typeobj hdrl_rect_region_parameter_type = {
185 HDRL_PARAMETER_RECT_REGION, /* type */
186 (hdrl_alloc *)&cpl_malloc, /* fp_alloc */
187 (hdrl_free *)&cpl_free, /* fp_free */
188 NULL, /* fp_destroy */
189 sizeof(hdrl_rect_region_parameter), /* obj_size */
190};
191
192
193/*----------------------------------------------------------------------------*/
204/*----------------------------------------------------------------------------*/
205
206cpl_matrix *
207hdrl_maglim_kernel_create(const cpl_size kernel_sx, const cpl_size kernel_sy,
208 const double fwhm){
209
210 cpl_ensure(kernel_sx > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
211 cpl_ensure(kernel_sy > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
212 cpl_ensure(fwhm > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
213
214 cpl_matrix * kernel = cpl_matrix_new(kernel_sx, kernel_sy);
215
216 double* pkernel = cpl_matrix_get_data(kernel);
217
218 double arg_exp;
219 double x;
220 double y;
221
222 double sigma_to_fwhm = sqrt( 4. * log(4) ); //log=natural log; log10 = bas 10
223
224 double factor = (fwhm / sigma_to_fwhm);
225 factor *= factor;
226 factor = 2.0 * factor ;
227
228 //double sum = 0.;
229 double dx = 1;
230 double dy = 1;
231
232 for(cpl_size j = 0; j < kernel_sy; j++) {
233 y = j * dy - 0.5 * (kernel_sy - 1);
234
235 for(cpl_size i = 0; i < kernel_sx; i++) {
236 x = i * dx - 0.5 * (kernel_sx - 1);
237
238 arg_exp = (x * x + y * y) / factor;
239 pkernel[kernel_sx * j + i] = exp( -arg_exp );
240
241 }
242 }
243
244 return kernel;
245}
246
247
248
266cpl_image*
267hdrl_extend_image(const cpl_image* image, const cpl_size border_nx,
268 const cpl_size border_ny,
269 const hdrl_image_extend_method image_extend_method)
270{
271 cpl_ensure(image != NULL, CPL_ERROR_NULL_INPUT, NULL);
272 cpl_ensure(border_nx > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
273 cpl_ensure(border_ny > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
274
275 cpl_ensure(image_extend_method == HDRL_IMAGE_EXTEND_NEAREST ||
276 image_extend_method == HDRL_IMAGE_EXTEND_MIRROR, CPL_ERROR_ILLEGAL_INPUT, NULL);
277
278 cpl_type type = cpl_image_get_type(image);
279 cpl_size input_sx = cpl_image_get_size_x(image);
280 cpl_size input_sy = cpl_image_get_size_y(image);
281
282 cpl_ensure(2 * border_nx <= input_sx, CPL_ERROR_ILLEGAL_INPUT, NULL);
283 cpl_ensure(2 * border_ny <= input_sy, CPL_ERROR_ILLEGAL_INPUT, NULL);
284
285 cpl_size output_sx = input_sx + 2 * border_nx;
286 cpl_size output_sy = input_sy + 2 * border_ny;
287
288 cpl_msg_debug(cpl_func, "Extend image:");
289 cpl_msg_indent_more();
290 cpl_msg_debug(cpl_func, "Border sizes (x, y): (%lld, %lld)", border_nx, border_ny);
291 cpl_msg_debug(cpl_func, "Input image (x, y): (%lld, %lld)", input_sx, input_sy);
292 cpl_msg_debug(cpl_func, "Output image (x, y): (%lld, %lld)", output_sx, output_sy);
293 cpl_msg_indent_less();
294
295 cpl_image* output_image = cpl_image_new(output_sx, output_sy, type);
296 double value = 0;
297 int status = 0;
298
299 if ( image_extend_method == HDRL_IMAGE_EXTEND_NEAREST ) {
300
301 /* copy central image into the extended image*/
302 cpl_image_copy(output_image, image, border_nx + 1, border_ny + 1 );
303
304 /* fill left-right values at position of central image */
305 for(cpl_size j = 1; j <= input_sy; j++) {
306 /* left most tail */
307 value = cpl_image_get(image, 1, j, &status);
308 cpl_image_fill_window(output_image, 1, border_ny +j,
309 border_nx, border_ny + j, value);
310 /* right most tail */
311 value = cpl_image_get(image, input_sx, j, &status);
312 cpl_image_fill_window(output_image, input_sx + border_nx, border_ny +j,
313 output_sx, border_ny + j, value);
314 }
315
316 /* fill bottom-up values at any position */
317 for(cpl_size i = 1; i <= output_sx; i++) {
318 /* lower part */
319 value = cpl_image_get(output_image, i, border_ny + 1, &status);
320 cpl_image_fill_window(output_image, i, 1, i, border_ny, value);
321
322 /* upper part */
323 value = cpl_image_get(output_image, i, border_ny + input_sy, &status);
324 cpl_image_fill_window(output_image, i, border_ny + input_sy, i,
325 output_sy, value);
326 }
327
328 } else if ( image_extend_method == HDRL_IMAGE_EXTEND_MIRROR ) {
329
330 /* Insert input image into expanded image */
331 cpl_image_copy(output_image, image, border_nx + 1, border_ny + 1);
332
333 /* do left */
334 cpl_image* image_ex = cpl_image_extract(image, 1, 1, border_nx, input_sy);
335 cpl_image_flip(image_ex, 2);
336 cpl_image_copy(output_image, image_ex, 1, border_ny + 1);
337 cpl_image_delete(image_ex);
338
339 /* do right */
340 image_ex = cpl_image_extract(image, input_sx- border_nx + 1, 1, input_sx,
341 input_sy);
342 cpl_image_flip(image_ex, 2);
343 cpl_image_copy(output_image, image_ex, input_sx + border_nx + 1,
344 border_ny + 1);
345 cpl_image_delete(image_ex);
346
347 /* do upper */
348 image_ex = cpl_image_extract(output_image, 1, input_sy, output_sx,
349 input_sy + border_ny);
350 cpl_image_flip(image_ex, 0);
351 cpl_image_copy(output_image, image_ex, 1, input_sy + border_ny + 1);
352 cpl_image_delete(image_ex);
353
354 /* do lower */
355 image_ex = cpl_image_extract(output_image, 1, border_ny + 1, output_sx,
356 2 * border_ny);
357 cpl_image_flip(image_ex, 0);
358 cpl_image_copy(output_image, image_ex, 1, 1);
359 cpl_image_delete(image_ex);
360
361 }
362
363 return output_image;
364
365}
366
367
368/*----------------------------------------------------------------------------*/
383/*----------------------------------------------------------------------------*/
384cpl_image *
385hdrl_image_convolve(const cpl_image * input_image, const cpl_matrix * kernel,
386 const hdrl_image_extend_method image_extend_method)
387{
388 cpl_image * expanded_image;
389 cpl_image * filtered_image;
390 cpl_image * expanded_filtered_image;
391
392 /* Check Entries */
393 cpl_ensure(input_image != NULL, CPL_ERROR_NULL_INPUT, NULL);
394 cpl_ensure(kernel != NULL, CPL_ERROR_NULL_INPUT, NULL);
395 cpl_ensure(image_extend_method == HDRL_IMAGE_EXTEND_NEAREST ||
396 image_extend_method == HDRL_IMAGE_EXTEND_MIRROR, CPL_ERROR_ILLEGAL_INPUT, NULL);
397
398 cpl_size kernel_nx = cpl_matrix_get_ncol(kernel);
399 cpl_size kernel_ny = cpl_matrix_get_nrow(kernel);
400 cpl_ensure(kernel_nx >= 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
401 cpl_ensure(kernel_ny >= 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
402
403 /* Only odd-sized masks allowed */
404 cpl_ensure((kernel_nx&1) == 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
405 cpl_ensure((kernel_ny&1) == 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
406
407 const int border_nx = (int)((kernel_nx - 1)/2.);
408 const int border_ny = (int)((kernel_ny - 1)/2.);
409
410 expanded_image =
411 hdrl_extend_image(input_image, border_nx, border_ny, image_extend_method);
412
413
414 /* Use parallel filter as faster */
415 expanded_filtered_image =
416 hdrl_parallel_filter_image(expanded_image, kernel, NULL,
417 CPL_FILTER_LINEAR);
418
419
420 if(expanded_filtered_image == NULL) {
421 cpl_image_delete(expanded_filtered_image);
422 cpl_image_delete(expanded_image);
423 return NULL;
424 }
425
426 /* Extract the original mask from the expanded mask */
427 cpl_msg_debug(cpl_func, "Extract original image from expanded mask, region "\
428 "[llx: %lld, lly: %lld, urx: %lld, ury: %lld",
429 kernel_nx+1, kernel_ny + 1,
430 cpl_image_get_size_x(input_image) + kernel_nx,
431 cpl_image_get_size_y(input_image) + kernel_ny);
432
433 filtered_image = cpl_image_extract(expanded_filtered_image, border_nx + 1,
434 border_ny + 1,
435 cpl_image_get_size_x(input_image) + border_nx,
436 cpl_image_get_size_y(input_image) + border_ny);
437
438 /* Free memory */
439 cpl_image_delete(expanded_filtered_image);
440 cpl_image_delete(expanded_image);
441
442 return filtered_image;
443}
444
445
446
448
449/*----------------------------------------------------------------------------*/
458/*----------------------------------------------------------------------------*/
460 cpl_size llx,
461 cpl_size lly,
462 cpl_size urx,
463 cpl_size ury)
464{
465 hdrl_rect_region_parameter * p = (hdrl_rect_region_parameter *)
466 hdrl_parameter_new(&hdrl_rect_region_parameter_type);
467 p->llx = llx ;
468 p->lly = lly ;
469 p->urx = urx ;
470 p->ury = ury ;
471 return (hdrl_parameter *)p;
472}
473
474/*----------------------------------------------------------------------------*/
484/*----------------------------------------------------------------------------*/
486 hdrl_parameter * rect_region,
487 cpl_size llx,
488 cpl_size lly,
489 cpl_size urx,
490 cpl_size ury)
491{
492 hdrl_rect_region_parameter * p = (hdrl_rect_region_parameter *)rect_region ;
493 p->llx = llx ;
494 p->lly = lly ;
495 p->urx = urx ;
496 p->ury = ury ;
497 return hdrl_rect_region_parameter_verify(rect_region, -1, -1);
498}
499
500/*----------------------------------------------------------------------------*/
505/*----------------------------------------------------------------------------*/
506cpl_boolean hdrl_rect_region_parameter_check(const hdrl_parameter * self)
507{
508 return hdrl_parameter_check_type(self, &hdrl_rect_region_parameter_type);
509}
510
511/*-----------------------------------------------------------------------------
512 Rect Region Parameters Accessors
513 -----------------------------------------------------------------------------*/
514
518cpl_size hdrl_rect_region_get_llx(const hdrl_parameter * p)
519{
520 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1) ;
521 return ((const hdrl_rect_region_parameter *)p)->llx;
522}
523
527cpl_size hdrl_rect_region_get_lly(const hdrl_parameter * p)
528{
529 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1) ;
530 return ((const hdrl_rect_region_parameter *)p)->lly;
531}
532
536cpl_size hdrl_rect_region_get_urx(const hdrl_parameter * p)
537{
538 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1) ;
539 return ((const hdrl_rect_region_parameter *)p)->urx;
540}
541
545cpl_size hdrl_rect_region_get_ury(const hdrl_parameter * p)
546{
547 cpl_ensure(p, CPL_ERROR_NULL_INPUT, -1) ;
548 return ((const hdrl_rect_region_parameter *)p)->ury;
549}
550
551/*----------------------------------------------------------------------------*/
559/*----------------------------------------------------------------------------*/
561 const hdrl_parameter * param,
562 const cpl_size max_x,
563 const cpl_size max_y)
564{
565 const hdrl_rect_region_parameter * param_loc =
566 (const hdrl_rect_region_parameter *)param ;
567
568 cpl_error_ensure(param != NULL, CPL_ERROR_NULL_INPUT,
569 return CPL_ERROR_NULL_INPUT, "NULL Input Parameters");
570 cpl_error_ensure(hdrl_rect_region_parameter_check(param),
571 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
572 "Expected Rect Region parameter") ;
573 cpl_error_ensure(param_loc->llx >= 1 && param_loc->lly >= 1 &&
574 param_loc->urx >= 1 && param_loc->ury >= 1, CPL_ERROR_ILLEGAL_INPUT,
575 return CPL_ERROR_ILLEGAL_INPUT,
576 "Coordinates must be strictly positive");
577
578 cpl_error_ensure(param_loc->urx >= param_loc->llx, CPL_ERROR_ILLEGAL_INPUT,
579 return CPL_ERROR_ILLEGAL_INPUT,
580 "urx (%ld) must be larger equal than llx (%ld)",
581 (long)param_loc->urx, (long)param_loc->llx);
582 cpl_error_ensure(param_loc->ury >= param_loc->lly, CPL_ERROR_ILLEGAL_INPUT,
583 return CPL_ERROR_ILLEGAL_INPUT,
584 "ury (%ld) must be larger equal than lly (%ld)",
585 (long)param_loc->ury, (long)param_loc->lly);
586 if (max_x > 0)
587 cpl_error_ensure(param_loc->urx <= max_x, CPL_ERROR_ILLEGAL_INPUT,
588 return CPL_ERROR_ILLEGAL_INPUT,
589 "urx %zu larger than maximum %zu",
590 (size_t)param_loc->urx, (size_t)max_x);
591 if (max_y > 0)
592 cpl_error_ensure(param_loc->ury <= max_y, CPL_ERROR_ILLEGAL_INPUT,
593 return CPL_ERROR_ILLEGAL_INPUT,
594 "ury %zu larger than maximum %zu",
595 (size_t)param_loc->ury, (size_t)max_y);
596 return CPL_ERROR_NONE;
597}
598
599/* ---------------------------------------------------------------------------*/
614/* ---------------------------------------------------------------------------*/
616 const char *base_context,
617 const char *prefix,
618 const char *name_prefix,
619 const hdrl_parameter *defaults)
620{
621 cpl_ensure(base_context && prefix && name_prefix && defaults,
622 CPL_ERROR_NULL_INPUT, NULL);
623
624 cpl_ensure(hdrl_rect_region_parameter_check(defaults),
625 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
626
627 cpl_parameterlist *parlist = cpl_parameterlist_new();
628
629 /* --prefix.llx */
630 hdrl_setup_vparameter(parlist, prefix, ".", name_prefix,
631 "llx", base_context,
632 "Lower left x pos. (FITS) defining the region",
633 CPL_TYPE_INT, (int)hdrl_rect_region_get_llx(defaults));
634 /* --prefix.lly */
635 hdrl_setup_vparameter(parlist, prefix, ".", name_prefix,
636 "lly", base_context,
637 "Lower left y pos. (FITS) defining the region",
638 CPL_TYPE_INT, (int)hdrl_rect_region_get_lly(defaults));
639
640 /* --prefix.urx */
641 hdrl_setup_vparameter(parlist, prefix, ".", name_prefix,
642 "urx", base_context,
643 "Upper right x pos. (FITS) defining the region",
644 CPL_TYPE_INT, (int)hdrl_rect_region_get_urx(defaults));
645
646 /* --prefix.ury */
647 hdrl_setup_vparameter(parlist, prefix, ".", name_prefix,
648 "ury", base_context,
649 "Upper right y pos. (FITS) defining the region",
650 CPL_TYPE_INT, (int)hdrl_rect_region_get_ury(defaults));
651
652 if (cpl_error_get_code()) {
653 cpl_parameterlist_delete(parlist);
654 return NULL;
655 }
656
657 return parlist;
658}
659
660/* ---------------------------------------------------------------------------*/
673/* ---------------------------------------------------------------------------*/
675 const cpl_parameterlist * parlist,
676 const char * base_context,
677 const char * name_prefix)
678{
679 cpl_size llx, lly, urx, ury ;
680 cpl_error_ensure(base_context && parlist, CPL_ERROR_NULL_INPUT,
681 return NULL, "NULL Input Parameters");
682 const char * sep = strlen(base_context) > 0 ? "." : "";
683 const char * points[] = {"llx", "lly", "urx", "ury"};
684 cpl_size * dest[] = {&llx, &lly, &urx, &ury};
685 for (size_t i = 0; i < 4; i++) {
686 char * name = cpl_sprintf("%s%s%s%s", base_context, sep,
687 name_prefix, points[i]);
688 const cpl_parameter * par = cpl_parameterlist_find_const(parlist, name);
689 *(dest[i]) = cpl_parameter_get_int(par);
690 cpl_free(name);
691 }
692
693 if (cpl_error_get_code()) {
694 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
695 "Error while parsing parameterlist "
696 "with base_context %s", base_context);
697 return NULL;
698 }
699
700 return hdrl_rect_region_parameter_create(llx, lly, urx, ury) ;
701}
702
703/*----------------------------------------------------------------------------*/
714/*----------------------------------------------------------------------------*/
716 hdrl_parameter * rect_region,
717 const cpl_size nx,
718 const cpl_size ny)
719{
720 hdrl_rect_region_parameter * rr_loc =
721 (hdrl_rect_region_parameter *)rect_region ;
722
723 cpl_error_ensure(rect_region != 0, CPL_ERROR_NULL_INPUT,
724 return CPL_ERROR_NULL_INPUT, "region input must not be NULL");
725 cpl_error_ensure(hdrl_rect_region_parameter_check(rect_region),
726 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
727 "Expected Rect Region parameter") ;
728
729 if (nx > 0 && rr_loc->llx < 1) rr_loc->llx += nx;
730 if (ny > 0 && rr_loc->lly < 1) rr_loc->lly += ny;
731 if (nx > 0 && rr_loc->urx < 1) rr_loc->urx += nx;
732 if (ny > 0 && rr_loc->ury < 1) rr_loc->ury += ny;
733
734 return hdrl_rect_region_parameter_verify(rect_region, nx, ny);
735}
736
737/* ---------------------------------------------------------------------------*/
744/* ---------------------------------------------------------------------------*/
745cpl_boolean hdrl_is_strictly_monotonic_increasing(const double * x, cpl_size l){
746
747 if(x == NULL || l <= 1) return CPL_TRUE;
748
749 for(cpl_size i = 0; i < l - 1; i++){
750 if(x[i] >= x[i + 1]) return CPL_FALSE;
751 }
752 return CPL_TRUE;
753}
754
755/* ---------------------------------------------------------------------------*/
764/* ---------------------------------------------------------------------------*/
765void hdrl_sort_on_x(double * x, double * y1, double * y2,
766 const cpl_size sample_len, const cpl_boolean sort_decreasing){
767
768 cpl_propertylist * col_list = cpl_propertylist_new();
769
770 cpl_propertylist_append_bool(col_list, "x", sort_decreasing);
771
772 cpl_table * tb = cpl_table_new(sample_len);
773
774 cpl_table_wrap_double(tb, x, "x");
775
776 if(y1)
777 cpl_table_wrap_double(tb, y1, "y1");
778
779 if(y2)
780 cpl_table_wrap_double(tb, y2, "y2");
781
782 cpl_table_sort(tb, col_list);
783
784 cpl_table_unwrap(tb, "x");
785
786 if(y1)
787 cpl_table_unwrap(tb, "y1");
788
789 if(y2)
790 cpl_table_unwrap(tb, "y2");
791
792 cpl_table_delete(tb);
793 cpl_propertylist_delete(col_list);
794}
795
796
797/* ---------------------------------------------------------------------------*/
809/* ---------------------------------------------------------------------------*/
810char * hdrl_join_string(const char * sep_, int n, ...)
811{
812 va_list vl;
813 char * res = NULL;
814 const char * sep = sep_ ? sep_ : "";
815 cpl_ensure(n > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
816
817 va_start(vl, n);
818 for (int i = 0; i < n; i++) {
819 char * tmp = res;
820 char * val = va_arg(vl, char *);
821 if (val == NULL || strlen(val) == 0) {
822 continue;
823 }
824 if (!res) {
825 res = cpl_strdup(val);
826 }
827 else {
828 res = cpl_sprintf("%s%s%s", res, sep, val);
829 }
830 cpl_free(tmp);
831 }
832 va_end(vl);
833
834 return res;
835}
836
837
839
840/* ---------------------------------------------------------------------------*/
850/* ---------------------------------------------------------------------------*/
851int hdrl_get_tempfile(const char * dir, cpl_boolean unlink)
852{
853 /* options in decreasing preference */
854 const char * tmpdirs[] = {
855 /* user override */
856 getenv("TMPDIR"),
857 /* large file temp */
858 "/var/tmp/",
859 /* small file temp, may be tmpfs */
860 "/tmp/"
861 };
862 const size_t ndirs = sizeof(tmpdirs) / sizeof(tmpdirs[0]);
863 const char * tmpdir = NULL;
864
865 if (dir && access(dir, W_OK) == 0) {
866 tmpdir = dir;
867 }
868 else {
869 for (size_t i = 0; i < ndirs; i++) {
870 if (tmpdirs[i] && access(tmpdirs[i], W_OK) == 0) {
871 tmpdir = tmpdirs[i];
872 break;
873 }
874 }
875 }
876
877 {
878 /* try $PWD if no tmpdir found */
879 char * template = hdrl_join_string("/", 2, tmpdir, "hdrl_tmp_XXXXXX");
880 int fd = mkstemp(template);
881 if (fd == -1) {
882 cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
883 "Temporary file creation failed: %s",
884 strerror(errno));
885 cpl_free(template);
886 return -1;
887 }
888
889 cpl_msg_debug(cpl_func, "Created tempfile %s", template);
890
891 if (unlink) {
892 remove(template);
893 }
894 cpl_free(template);
895
896 return fd;
897 }
898}
899
900
901/* ---------------------------------------------------------------------------*/
906/* ---------------------------------------------------------------------------*/
907char * hdrl_get_cwd(void)
908{
909 size_t n = 4096;
910 char * buf;
911 errno = 0;
912 /* if only we could use sane GNU functions instead of this posix crap */
913 while (1) {
914 buf = cpl_malloc(n);
915 if (getcwd(buf, n) != 0) {
916 break;
917 }
918 else if (errno == ERANGE) {
919 /* increase buffer, repeat */
920 errno = 0;
921 n *= 2;
922 cpl_free(buf);
923 }
924 else {
925 cpl_free(buf);
926 cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
927 "Could not determine current working "
928 "directory: %s", strerror(errno));
929 return NULL;
930 }
931 }
932
933 return buf;
934}
935
936/* ---------------------------------------------------------------------------*/
966/* ---------------------------------------------------------------------------*/
967cpl_error_code
968hdrl_normalize_imagelist_by_vector(const cpl_vector * scale,
969 const cpl_vector * scale_e,
970 const hdrl_scale_type scale_type,
971 cpl_imagelist * data,
972 cpl_imagelist * errors)
973{
974 cpl_ensure_code(scale, CPL_ERROR_NULL_INPUT);
975 cpl_ensure_code(scale_e, CPL_ERROR_NULL_INPUT);
976 cpl_ensure_code(data, CPL_ERROR_NULL_INPUT);
977 cpl_ensure_code(errors, CPL_ERROR_NULL_INPUT);
978 cpl_ensure_code(cpl_vector_get_size(scale) == cpl_imagelist_get_size(data),
979 CPL_ERROR_ILLEGAL_INPUT);
980 cpl_ensure_code(cpl_vector_get_size(scale_e) == cpl_vector_get_size(scale),
981 CPL_ERROR_ILLEGAL_INPUT);
982 cpl_ensure_code(cpl_imagelist_get_size(errors) ==
983 cpl_imagelist_get_size(data), CPL_ERROR_ILLEGAL_INPUT);
984
985 for (size_t i = 1; i < (size_t)cpl_imagelist_get_size(data); i++) {
986 const hdrl_data_t dfirst = cpl_vector_get(scale, 0);
987 const hdrl_error_t efirst = cpl_vector_get(scale_e, 0);
988 cpl_image * dimg = cpl_imagelist_get(data, i);
989 cpl_image * eimg = cpl_imagelist_get(errors, i);
990 if (scale_type == HDRL_SCALE_ADDITIVE) {
991 hdrl_data_t dscale_o = cpl_vector_get(scale, i);
992 hdrl_error_t escale_o = cpl_vector_get(scale_e, i);
993
994 /* dscale = dfirst - dscale_o */
995 hdrl_data_t dscale = dfirst;
996 hdrl_error_t escale = efirst;
997 hdrl_elemop_sub(&dscale, &escale, 1, &dscale_o, &escale_o, 1, NULL);
998
999 /* dimg = dimg + dscale */
1000 hdrl_elemop_image_add_scalar(dimg, eimg, dscale, escale);
1001 }
1002 else if (scale_type == HDRL_SCALE_MULTIPLICATIVE) {
1003 hdrl_data_t dscale_o = cpl_vector_get(scale, i);
1004 hdrl_error_t escale_o = cpl_vector_get(scale_e, i);
1005
1006 if (dscale_o == 0.) {
1007 cpl_msg_warning(cpl_func, "scale factor of image %zu is "
1008 "not a number", i);
1009 cpl_image_add_scalar(dimg, NAN);
1010 cpl_image_add_scalar(eimg, NAN);
1011 cpl_image_reject_value(dimg, CPL_VALUE_NAN);
1012 cpl_image_reject_value(eimg, CPL_VALUE_NAN);
1013 continue;
1014 }
1015
1016 /* dscale = dfirst / dscale_o */
1017 hdrl_data_t dscale = dfirst;
1018 hdrl_error_t escale = efirst;
1019 hdrl_elemop_div(&dscale, &escale, 1, &dscale_o, &escale_o, 1, NULL);
1020
1021 /* dimg = dimg * dscale */
1022 hdrl_elemop_image_mul_scalar(dimg, eimg, dscale, escale);
1023 }
1024 else {
1025 return cpl_error_set_message(cpl_func, CPL_ERROR_UNSUPPORTED_MODE,
1026 "Unsupported scale type");
1027 }
1028
1029 if (cpl_error_get_code())
1030 break;
1031 }
1032
1033 return cpl_error_get_code();
1034}
1035
1036
1037/* ---------------------------------------------------------------------------*/
1067/* ---------------------------------------------------------------------------*/
1068cpl_error_code
1069hdrl_normalize_imagelist_by_imagelist(const cpl_imagelist * scale,
1070 const cpl_imagelist * scale_e,
1071 const hdrl_scale_type scale_type,
1072 cpl_imagelist * data,
1073 cpl_imagelist * errors)
1074{
1075 cpl_ensure_code(scale, CPL_ERROR_NULL_INPUT);
1076 cpl_ensure_code(scale_e, CPL_ERROR_NULL_INPUT);
1077 cpl_ensure_code(data, CPL_ERROR_NULL_INPUT);
1078 cpl_ensure_code(errors, CPL_ERROR_NULL_INPUT);
1079 cpl_ensure_code(cpl_imagelist_get_size(scale) ==
1080 cpl_imagelist_get_size(data), CPL_ERROR_ILLEGAL_INPUT);
1081 cpl_ensure_code(cpl_imagelist_get_size(scale_e) ==
1082 cpl_imagelist_get_size(scale), CPL_ERROR_ILLEGAL_INPUT);
1083 cpl_ensure_code(cpl_imagelist_get_size(errors) ==
1084 cpl_imagelist_get_size(data), CPL_ERROR_ILLEGAL_INPUT);
1085
1086 for (size_t i = 1; i < (size_t)cpl_imagelist_get_size(data); i++) {
1087 cpl_image * dscale =
1088 cpl_image_duplicate(cpl_imagelist_get_const(scale, 0));
1089 cpl_image * escale =
1090 cpl_image_duplicate(cpl_imagelist_get_const(scale_e, 0));
1091 cpl_image * dimg = cpl_imagelist_get(data, i);
1092 cpl_image * eimg = cpl_imagelist_get(errors, i);
1093 const cpl_image * dscale_o = cpl_imagelist_get_const(scale, i);
1094 const cpl_image * escale_o = cpl_imagelist_get_const(scale_e, i);
1095
1096 if (scale_type == HDRL_SCALE_ADDITIVE) {
1097 /* dscale = dfirst - dscale_o */
1098 hdrl_elemop_image_sub_image(dscale, escale, dscale_o, escale_o);
1099
1100 /* dimg = dimg + dscale */
1101 hdrl_elemop_image_add_image(dimg, eimg, dscale, escale);
1102 }
1103 else if (scale_type == HDRL_SCALE_MULTIPLICATIVE) {
1104 /* dscale = dfirst / dscale_o */
1105 hdrl_elemop_image_div_image(dscale, escale, dscale_o, escale_o);
1106
1107 /* dimg = dimg * dscale */
1108 hdrl_elemop_image_mul_image(dimg, eimg, dscale, escale);
1109 }
1110 else {
1111 cpl_image_delete(dscale);
1112 cpl_image_delete(escale);
1113 return cpl_error_set_message(cpl_func, CPL_ERROR_UNSUPPORTED_MODE,
1114 "Unsupported scale type");
1115 }
1116
1117 cpl_image_delete(dscale);
1118 cpl_image_delete(escale);
1119
1120 if (cpl_error_get_code())
1121 break;
1122 }
1123
1124 return cpl_error_get_code();
1125}
1126
1128
1129
1131
1132/*----------------------------------------------------------------------------*/
1141/*----------------------------------------------------------------------------*/
1142cpl_vector * hdrl_image_to_vector(
1143 const cpl_image * source,
1144 const cpl_mask * bpm)
1145{
1146 cpl_ensure(source != NULL, CPL_ERROR_NULL_INPUT, NULL);
1147 cpl_vector * vec_source = NULL;
1148 /* only cast if required, extra copying of non double data is still
1149 * faster than a loop with cpl_image_get */
1150
1151 CPL_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
1152 cpl_image * d_img = cpl_image_get_type(source) == CPL_TYPE_DOUBLE ?
1153 (cpl_image *)source : cpl_image_cast(source, CPL_TYPE_DOUBLE);
1154 CPL_DIAG_PRAGMA_POP;
1155
1156 const cpl_size naxis1 = cpl_image_get_size_x(source);
1157 const cpl_size naxis2 = cpl_image_get_size_y(source);
1158
1159 /* get raw data */
1160 const double * restrict sdata = cpl_image_get_data_double_const(d_img);
1161 const cpl_binary * restrict bpmd = NULL;
1162
1163 /* allocate output buffer */
1164 double * restrict ddata = cpl_malloc(naxis1 * naxis2 *
1165 sizeof(ddata[0]));
1166 long j = 0;
1167
1168 if (bpm)
1169 bpmd = cpl_mask_get_data_const(bpm);
1170 else if (cpl_image_get_bpm_const(source) != NULL)
1171 bpmd = cpl_mask_get_data_const(cpl_image_get_bpm_const(source));
1172
1173 if (bpmd == NULL) {
1174 memcpy(ddata, sdata, naxis1 * naxis2 * sizeof(ddata[0]));
1175 j = naxis1 * naxis2;
1176 }
1177 else {
1178 /* copy only good pixels */
1179 for (long i = 0; i < naxis1 * naxis2; i++) {
1180 if (bpmd[i] == CPL_BINARY_0) {
1181 ddata[j] = sdata[i];
1182 j++;
1183 }
1184 }
1185 }
1186
1187 assert(j == naxis1 * naxis2 -
1188 (bpm ? cpl_mask_count(bpm) : cpl_image_count_rejected(source)));
1189
1190 if (j > 0) {
1191 vec_source = cpl_vector_wrap(j, ddata);
1192 }
1193 else {
1194 cpl_free(ddata);
1195 }
1196
1197 if (d_img != source) cpl_image_delete(d_img);
1198
1199 return vec_source;
1200}
1201
1202typedef struct {
1203 size_t available; /* number of cached pointers */
1204 size_t nspace; /* max cache pointers */
1205 void ** ptrs;
1206} cache_bucket;
1207
1208struct hdrl_vector_cache_ {
1209 cpl_size nbuckets;
1210 cache_bucket buckets[];
1211};
1212
1213/* ---------------------------------------------------------------------------*/
1237/* ---------------------------------------------------------------------------*/
1238hdrl_vector_cache * hdrl_vector_cache_new(cpl_size max_cached_size,
1239 cpl_size ncached_entries)
1240{
1241 /* for largish vectors a cache is not worthwhile, save the memory */
1242 if (max_cached_size > 50)
1243 return NULL;
1244 hdrl_vector_cache * c = cpl_malloc(sizeof(hdrl_vector_cache) +
1245 sizeof(cache_bucket) * (max_cached_size + 1));
1246 c->nbuckets = max_cached_size + 1;
1247 for (cpl_size i = 0; i < c->nbuckets; i++) {
1248 c->buckets[i].available = 0;
1249 c->buckets[i].nspace = ncached_entries;
1250 c->buckets[i].ptrs = cpl_calloc(ncached_entries, sizeof(cpl_vector*));
1251 }
1252 return c;
1253}
1254
1255/* ---------------------------------------------------------------------------*/
1261/* ---------------------------------------------------------------------------*/
1262void hdrl_vector_cache_delete(hdrl_vector_cache * cache)
1263{
1264 if (!cache)
1265 return;
1266 for (cpl_size i = 0; i < cache->nbuckets; i++) {
1267 for (size_t j = 0; j < cache->buckets[i].available; j++) {
1268 cpl_vector_delete(cache->buckets[i].ptrs[j]);
1269 }
1270 cpl_free(cache->buckets[i].ptrs);
1271 }
1272 cpl_free(cache);
1273}
1274
1275/* ---------------------------------------------------------------------------*/
1291/* ---------------------------------------------------------------------------*/
1292cpl_vector * hdrl_cplvector_new_from_cache(hdrl_vector_cache * cache, cpl_size sz)
1293{
1294 if (!cache) {
1295 return cpl_vector_new(sz);
1296 }
1297 if (sz < cache->nbuckets) {
1298 if (cache->buckets[sz].available > 0) {
1299 return cache->buckets[sz].ptrs[--(cache->buckets[sz].available)];
1300 }
1301 }
1302 return cpl_vector_new(sz);
1303}
1304
1305/* ---------------------------------------------------------------------------*/
1315/* ---------------------------------------------------------------------------*/
1316void hdrl_cplvector_delete_to_cache(hdrl_vector_cache * cache, cpl_vector * v)
1317{
1318 if (!v) {
1319 return;
1320 }
1321 if (cache) {
1322 const cpl_size sz = cpl_vector_get_size(v);
1323 if (sz < cache->nbuckets) {
1324 if (cache->buckets[sz].available < cache->buckets[sz].nspace) {
1325 cache->buckets[sz].ptrs[(cache->buckets[sz].available)++] = v;
1326 return;
1327 }
1328 }
1329 }
1330 cpl_vector_delete(v);
1331}
1332
1333
1334/* internal if imgdatabuf and maskbuf are not NULL they are assumed to hold the
1335 * data buffers of the image in the list in order to save on cpl_image_get
1336 * calls, error and type checking must be done by caller */
1337static cpl_vector * imagelist_to_vector(const cpl_imagelist * list,
1338 const cpl_size nx,
1339 const cpl_size x,
1340 const cpl_size y,
1341 const double ** imgdatabuf,
1342 const cpl_binary ** maskbuf, hdrl_vector_cache * cache)
1343{
1344 const long nz = list ? cpl_imagelist_get_size(list) : -1;
1345 unsigned long j = 0;
1346 cpl_vector * vec = hdrl_cplvector_new_from_cache(cache, nz);
1347 double * restrict ddata = cpl_vector_get_data(vec);
1348
1349 if (imgdatabuf && maskbuf) {
1350 for (long k = 0; k < nz; k++) {
1351 double v = imgdatabuf[k][(y - 1) * nx + (x - 1)];
1352 cpl_binary rej = maskbuf[k] ?
1353 maskbuf[k][(y - 1) * nx + (x - 1)] : 0;
1354
1355 if (!rej) {
1356 ddata[j] = v;
1357 j++;
1358 }
1359 }
1360 }
1361 else {
1362 for (long k = 0; k < nz; k++) {
1363 int rej;
1364 const cpl_image * img = cpl_imagelist_get_const(list, k);
1365 double v = cpl_image_get(img, x, y, &rej);
1366
1367 if (!rej) {
1368 ddata[j] = v;
1369 j++;
1370 }
1371 }
1372 }
1373
1374 if (j > 0) {
1375 if ((cpl_size)j != nz) {
1376 cpl_vector_set_size(vec, j);
1377 }
1378 }
1379 else {
1380 hdrl_cplvector_delete_to_cache(cache, vec);
1381 vec = NULL;
1382 }
1383
1384 return vec;
1385}
1386
1387
1388/*----------------------------------------------------------------------------*/
1398/*----------------------------------------------------------------------------*/
1399cpl_vector * hdrl_imagelist_to_vector(const cpl_imagelist * list,
1400 const cpl_size x,
1401 const cpl_size y)
1402{
1403 cpl_size nx;
1404 const cpl_size nz = list ? cpl_imagelist_get_size(list) : -1;
1405 cpl_ensure(list != NULL, CPL_ERROR_NULL_INPUT, NULL);
1406 cpl_ensure(nz > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1407 cpl_ensure(x > 0, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
1408 cpl_ensure(y > 0, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
1409
1410 {
1411 const cpl_image * img = cpl_imagelist_get_const(list, 0);
1412 const cpl_size ny = cpl_image_get_size_y(img);
1413 nx = cpl_image_get_size_x(img);
1414 cpl_ensure(x <= nx, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
1415 cpl_ensure(y <= ny, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
1416 }
1417 return imagelist_to_vector(list, nx, x, y, NULL, NULL, NULL);
1418}
1419
1420
1421/*----------------------------------------------------------------------------*/
1436/*----------------------------------------------------------------------------*/
1437cpl_error_code hdrl_imagelist_to_vector_row(const cpl_imagelist * list,
1438 const cpl_size y,
1439 cpl_vector ** out,
1440 hdrl_vector_cache * cache)
1441{
1442 long nx;
1443 int isdouble;
1444 const long nz = list ? (long)cpl_imagelist_get_size(list) : 0;
1445 cpl_ensure_code(list != NULL, CPL_ERROR_NULL_INPUT);
1446 cpl_ensure_code(nz > 0, CPL_ERROR_ILLEGAL_INPUT);
1447 cpl_ensure_code(y > 0, CPL_ERROR_ACCESS_OUT_OF_RANGE);
1448
1449 {
1450 const cpl_image * img = cpl_imagelist_get_const(list, 0);
1451 const cpl_size ny = cpl_image_get_size_y(img);
1452 cpl_ensure_code(y <= ny, CPL_ERROR_ACCESS_OUT_OF_RANGE);
1453 nx = (long)cpl_image_get_size_x(img);
1454 isdouble = cpl_image_get_type(img) == CPL_TYPE_DOUBLE;
1455 }
1456
1457 const double * imgdatabuf[nz];
1458 const cpl_binary * maskbuf[nz];
1459 for (long i = 0; i < nz && isdouble; i++) {
1460 const cpl_image * img = cpl_imagelist_get_const(list, i);
1461 const cpl_mask * bpm = cpl_image_get_bpm_const(img);
1462 imgdatabuf[i] = cpl_image_get_data_double_const(img);
1463 if (bpm) {
1464 maskbuf[i] = cpl_mask_get_data_const(bpm);
1465 }
1466 else {
1467 maskbuf[i] = NULL;
1468 }
1469 }
1470 for (long x = 0; x < nx; x++) {
1471 if (isdouble) {
1472 out[x] = imagelist_to_vector(list, nx, x + 1, y,
1473 imgdatabuf, maskbuf, cache);
1474 }
1475 else {
1476 out[x] = imagelist_to_vector(list, nx, x + 1, y, NULL, NULL, cache);
1477 }
1478 }
1479 return cpl_error_get_code();
1480}
1481
1482/* ---------------------------------------------------------------------------*/
1494/* ---------------------------------------------------------------------------*/
1495cpl_error_code
1496hdrl_imagelist_to_cplwrap(const hdrl_imagelist * list,
1497 cpl_imagelist ** data,
1498 cpl_imagelist ** errs)
1499{
1500 cpl_ensure_code(list, CPL_ERROR_NULL_INPUT);
1501 if (data) {
1502 *data = cpl_imagelist_new();
1503 }
1504 if (errs) {
1505 *errs = cpl_imagelist_new();
1506 }
1507 for (cpl_size i = 0; i < hdrl_imagelist_get_size(list); i++) {
1508 hdrl_image * img = hdrl_imagelist_get(list, i);
1509 if (data) {
1510 cpl_imagelist_set(*data, hdrl_image_get_image(img), i);
1511 }
1512 if (errs) {
1513 cpl_imagelist_set(*errs, hdrl_image_get_error(img), i);
1514 }
1515 }
1516
1517 if (cpl_error_get_code()) {
1518 if (data) {
1519 cpl_imagelist_unwrap(*data);
1520 *data = NULL;
1521 }
1522 if (errs) {
1523 cpl_imagelist_unwrap(*errs);
1524 *errs = NULL;
1525 }
1526 }
1527 return cpl_error_get_code();
1528}
1529
1530/* ---------------------------------------------------------------------------*/
1542/* ---------------------------------------------------------------------------*/
1543cpl_image *
1544hdrl_medianfilter_image_grid(const cpl_image * ima, cpl_matrix * x, cpl_matrix * y,
1545 cpl_size filtersize_x, cpl_size filtersize_y)
1546{
1547 cpl_error_ensure(ima != NULL, CPL_ERROR_NULL_INPUT, return NULL,
1548 "NULL input image");
1549 cpl_error_ensure(filtersize_x > 0 && filtersize_y > 0 ,
1550 CPL_ERROR_INCOMPATIBLE_INPUT, return NULL,
1551 "All function parameters must be greater then Zero");
1552
1553 const cpl_size nx = cpl_image_get_size_x(ima);
1554 const cpl_size ny = cpl_image_get_size_y(ima);
1555 const cpl_size steps_x = cpl_matrix_get_nrow(x);
1556 const cpl_size steps_y = cpl_matrix_get_nrow(y);
1557
1558 cpl_image * ima_local = cpl_image_new(steps_x, steps_y, CPL_TYPE_DOUBLE);
1559
1560 for (cpl_size iy = 0; iy < steps_y; iy++) {
1561 cpl_size middlep_y = cpl_matrix_get(y, iy, 0);
1562 for (cpl_size ix = 0; ix < steps_x; ix++) {
1563 cpl_size middlep_x = cpl_matrix_get(x, ix, 0);
1564
1565 cpl_size lowerlimit_x = CX_MAX(middlep_x - filtersize_x, 1);
1566 cpl_size lowerlimit_y = CX_MAX(middlep_y - filtersize_y, 1);
1567 cpl_size upperlimit_x = CX_MIN(middlep_x + filtersize_x, nx);
1568 cpl_size upperlimit_y = CX_MIN(middlep_y + filtersize_y, ny);
1569
1570 double median = cpl_image_get_median_window(ima, lowerlimit_x,
1571 lowerlimit_y, upperlimit_x, upperlimit_y);
1572
1573 cpl_image_set(ima_local, ix + 1, iy + 1, median);
1574
1575 cpl_msg_debug(cpl_func, "middlep_x: %lld, middlep_y: %lld, median: "
1576 "%g", middlep_x, middlep_y, median);
1577 }
1578 }
1579 return ima_local;
1580}
1581
1582/* ---------------------------------------------------------------------------*/
1592/* ---------------------------------------------------------------------------*/
1593cpl_matrix * hdrl_matrix_linspace(
1594 cpl_size start,
1595 cpl_size stop,
1596 cpl_size step)
1597{
1598 cpl_matrix * x = cpl_matrix_new(stop / step, 1);
1599 for (intptr_t i = 0; start + i * step < stop && i < stop / step; i++) {
1600 cpl_matrix_set(x, i, 0, start + i * step);
1601 }
1602 return x;
1603}
1604
1605/* ---------------------------------------------------------------------------*/
1621/* ---------------------------------------------------------------------------*/
1622cpl_matrix * hdrl_fit_legendre(
1623 cpl_image * img,
1624 int order_x,
1625 int order_y,
1626 cpl_matrix * grid_x,
1627 cpl_matrix * grid_y,
1628 cpl_size orig_nx,
1629 cpl_size orig_ny)
1630{
1631 cpl_size nx2 = cpl_matrix_get_nrow(grid_x);
1632 cpl_size ny2 = cpl_matrix_get_nrow(grid_y);
1633 cpl_matrix * xpolys =
1634 hdrl_mime_legendre_polynomials_create(order_x + 1, 0, orig_nx - 1, grid_x);
1635 cpl_matrix * ypolys =
1636 hdrl_mime_legendre_polynomials_create(order_y + 1, 0, orig_ny - 1, grid_y);
1637 cpl_matrix * tensors =
1639 xpolys);
1640 cpl_matrix * mimage = cpl_matrix_wrap(nx2 * ny2, 1, cpl_image_get_data(img));
1641 cpl_matrix * coeffs = cpl_matrix_solve_normal(tensors, mimage);
1642 cpl_matrix_unwrap(mimage);
1643 cpl_matrix_delete(xpolys);
1644 cpl_matrix_delete(ypolys);
1645 cpl_matrix_delete(tensors);
1646
1647 return coeffs;
1648}
1649
1650/* ---------------------------------------------------------------------------*/
1662/* ---------------------------------------------------------------------------*/
1663cpl_image * hdrl_legendre_to_image(
1664 cpl_matrix * coeffs,
1665 int order_x,
1666 int order_y,
1667 cpl_size nx,
1668 cpl_size ny)
1669{
1670 /* evaluate on full image */
1671 /* TODO need grid of original fit here? */
1672 cpl_matrix * x = hdrl_matrix_linspace(0, nx, 1);
1673 cpl_matrix * y = hdrl_matrix_linspace(0, ny, 1);
1674 cpl_matrix * xpolys =
1675 hdrl_mime_legendre_polynomials_create(order_x + 1, 0, nx - 1, x);
1676 cpl_matrix * ypolys =
1677 hdrl_mime_legendre_polynomials_create(order_y + 1, 0, ny - 1, y);
1678 cpl_matrix * tensors =
1680 xpolys);
1681 cpl_matrix * result = cpl_matrix_product_create(tensors, coeffs);
1682 cpl_image * iresult = cpl_image_wrap(nx, ny, CPL_TYPE_DOUBLE,
1683 cpl_matrix_get_data(result));
1684 cpl_matrix_delete(x);
1685 cpl_matrix_delete(y);
1686 cpl_matrix_delete(xpolys);
1687 cpl_matrix_delete(ypolys);
1688 cpl_matrix_delete(tensors);
1689 cpl_matrix_unwrap(result);
1690
1691 return iresult;
1692}
1693/* ---------------------------------------------------------------------------*/
1701/* ---------------------------------------------------------------------------*/
1702int hdrl_check_maskequality(const cpl_mask * mask1, const cpl_mask * mask2)
1703{
1704 cpl_ensure(mask1, CPL_ERROR_NULL_INPUT, 1);
1705 cpl_ensure(mask2, CPL_ERROR_NULL_INPUT, 1);
1706
1707 cpl_size m1nx = cpl_mask_get_size_x(mask1);
1708 cpl_size m1ny = cpl_mask_get_size_y(mask1);
1709 cpl_size m2nx = cpl_mask_get_size_x(mask2);
1710 cpl_size m2ny = cpl_mask_get_size_y(mask2);
1711 cpl_ensure(m1nx == m2nx, CPL_ERROR_NONE, 1);
1712 cpl_ensure(m1ny == m2ny, CPL_ERROR_NONE, 1);
1713
1714 const cpl_binary * dm1bpm = cpl_mask_get_data_const(mask1);
1715 const cpl_binary * dm2bpm = cpl_mask_get_data_const(mask2);
1716 if (memcmp(dm1bpm, dm2bpm, m1nx * m1ny) != 0) {
1717 return 1;
1718 }
1719 else {
1720 return 0;
1721 }
1722}
1723
1724static const cpl_image *
1725image_const_row_view_create(const cpl_image * img,
1726 cpl_size ly,
1727 cpl_size uy)
1728{
1729 const size_t dsz = cpl_type_get_sizeof(cpl_image_get_type(img));
1730 const cpl_size nx = cpl_image_get_size_x(img);
1731 const char * d = cpl_image_get_data_const(img);
1732 size_t offset = (ly - 1) * nx;
1733 cpl_size nny = uy - ly + 1;
1734
1735 CPL_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
1736
1737 cpl_image * wimg = cpl_image_wrap(nx, nny, cpl_image_get_type(img),
1738 (char*)d + offset * dsz);
1739
1740 const cpl_mask * omask = cpl_image_get_bpm_const(img);
1741 if (omask) {
1742 cpl_mask * mask = cpl_mask_wrap(nx, nny,
1743 (cpl_binary*)cpl_mask_get_data_const(omask) + offset);
1744 cpl_mask_delete(hcpl_image_set_bpm(wimg, mask));
1745 }
1746
1747 CPL_DIAG_PRAGMA_POP;
1748
1749 return wimg;
1750}
1751
1752static void
1753image_const_row_view_delete(const cpl_image * img)
1754{
1755 CPL_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
1756
1757 cpl_mask_unwrap(cpl_image_unset_bpm((cpl_image*)(img)));
1758 cpl_image_unwrap((cpl_image *)img);
1759
1760 CPL_DIAG_PRAGMA_POP;
1761}
1762
1763/* ---------------------------------------------------------------------------*/
1779/* ---------------------------------------------------------------------------*/
1780cpl_image *
1781hdrl_parallel_filter_image(const cpl_image * img,
1782 const cpl_matrix * kernel,
1783 const cpl_mask * mask,
1784 const cpl_filter_mode mode)
1785{
1786 cpl_ensure(img, CPL_ERROR_NULL_INPUT, NULL);
1787 intptr_t nx = cpl_image_get_size_x(img);
1788 intptr_t ny = cpl_image_get_size_y(img);
1789 intptr_t ky, kx;
1790 /* TODO probably one can use all except COPY */
1791 const cpl_border_mode border = CPL_BORDER_FILTER;
1792 cpl_ensure((kernel && !mask) || (!kernel && mask),
1793 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
1794 if (kernel) {
1795 ky = cpl_matrix_get_nrow(kernel);
1796 kx = cpl_matrix_get_ncol(kernel);
1797 }
1798 else {
1799 ky = cpl_mask_get_size_y(mask);
1800 kx = cpl_mask_get_size_x(mask);
1801 }
1802 cpl_ensure(ky % 2 == 1, CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
1803 cpl_ensure(ny >= ky, CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
1804 cpl_ensure(nx >= kx, CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
1805
1806 intptr_t hk = (ky / 2);
1807 cpl_image * res = cpl_image_new(nx, ny, cpl_image_get_type(img));
1808 /* make sure image has a bpm to avoid creation races later */
1809 cpl_image_get_bpm(res);
1810
1811 /* filter first half-kernel rows (needs full kernel image) */
1812 if (hk) {
1813 const cpl_image * slice = image_const_row_view_create(img, 1, ky);
1814 cpl_image * slres = cpl_image_duplicate(slice);
1815 if (kernel) {
1816 cpl_image_filter(slres, slice, kernel, mode, border);
1817 }
1818 else {
1819 cpl_image_filter_mask(slres, slice, mask, mode, border);
1820 }
1821
1822 const cpl_image * slice2 = image_const_row_view_create(slres, 1, hk);
1823 cpl_image_copy(res, slice2, 1, 1);
1824 image_const_row_view_delete(slice2);
1825 image_const_row_view_delete(slice);
1826 cpl_image_delete(slres);
1827 }
1828 intptr_t y = hk;
1829 const intptr_t s = 200;
1830 /* filter s sized row chunks needs one kernel overlap */
1831HDRL_OMP(omp parallel for lastprivate(y) if (ny > s + ky))
1832 for (y = hk; y < ny - ky - (ny - ky) % s; y+=s) {
1833 intptr_t l = (y + 1) - hk;
1834 intptr_t u = (y + 1 + s) + hk - 1;
1835 const cpl_image * slice = image_const_row_view_create(img, l, u);
1836 cpl_image * slres = cpl_image_new(nx, u - l + 1,
1837 cpl_image_get_type(slice));
1838 if (kernel) {
1839 cpl_image_filter(slres, slice, kernel, mode, border);
1840 }
1841 else {
1842 cpl_image_filter_mask(slres, slice, mask, mode, border);
1843 }
1844 const cpl_image * slice2 =
1845 image_const_row_view_create(slres, hk + 1, hk + s);
1846 cpl_image_copy(res, slice2, 1, y + 1);
1847 image_const_row_view_delete(slice);
1848 image_const_row_view_delete(slice2);
1849 cpl_image_delete(slres);
1850 }
1851 /* filter remainder, needs half kernel overlap */
1852 if (y + 1 - hk < ny) {
1853 const cpl_image * slice = image_const_row_view_create(img, y + 1 - hk, ny);
1854 cpl_image * slres = cpl_image_duplicate(slice);
1855 if (kernel) {
1856 cpl_image_filter(slres, slice, kernel, mode, border);
1857 }
1858 else {
1859 cpl_image_filter_mask(slres, slice, mask, mode, border);
1860 }
1861 const cpl_image * slice2 =
1862 image_const_row_view_create(slres, hk + 1, cpl_image_get_size_y(slice));
1863 cpl_image_copy(res, slice2, 1, y + 1);
1864 image_const_row_view_delete(slice);
1865 image_const_row_view_delete(slice2);
1866 cpl_image_delete(slres);
1867 }
1868 return res;
1869}
1870
1871
1889 /* ---------------------------------------------------------------------------*/
1890cpl_error_code
1891hdrl_wcs_convert(const cpl_wcs *wcs, const cpl_matrix *from,
1892 cpl_matrix **to, cpl_array **status,
1893 cpl_wcs_trans_mode transform)
1894{
1895 size_t nr = cpl_matrix_get_nrow(from);
1896 size_t nc = cpl_matrix_get_ncol(from);
1897 const size_t s = 4000;
1898 size_t i;
1899 int * dstatus;
1900 cpl_ensure_code(to, CPL_ERROR_NULL_INPUT);
1901 cpl_ensure_code(status, CPL_ERROR_NULL_INPUT);
1902 cpl_ensure_code(wcs, CPL_ERROR_NULL_INPUT);
1903 cpl_ensure_code(from, CPL_ERROR_NULL_INPUT);
1904
1905 *status = cpl_array_new(nr, CPL_TYPE_INT);
1906 cpl_ensure_code(*status, CPL_ERROR_NULL_INPUT);
1907 dstatus = cpl_array_get_data_int(*status);
1908 *to = cpl_matrix_new(nr, nc);
1909 cpl_error_code err = CPL_ERROR_NONE;
1910
1911HDRL_OMP(omp parallel for if (nr > s))
1912 for (i = 0; i < nr; i+=s) {
1913 cpl_matrix * lfrom = cpl_matrix_extract(from, i, 0, 1, 1, CPL_MIN(s, nr - i), nc);
1914 cpl_matrix * lto = NULL;
1915 cpl_array * lstatus = NULL;
1916 cpl_error_code lerr = cpl_wcs_convert(wcs, lfrom, &lto, &lstatus, transform);
1917 if (lto != NULL) {
1918 cpl_matrix_copy(*to, lto, i, 0);
1919 }
1920 if (lstatus != NULL) {
1921 memcpy(&dstatus[i], cpl_array_get_data_int(lstatus),
1922 cpl_array_get_size(lstatus) * sizeof(*dstatus));
1923 }
1924 cpl_array_delete(lstatus);
1925 cpl_matrix_delete(lfrom);
1926 cpl_matrix_delete(lto);
1927 if (lerr != CPL_ERROR_NONE) {
1928HDRL_OMP(omp critical(hdrl_hdrlwcserror))
1929 err = lerr;
1930 }
1931 }
1932
1933 if (err == CPL_ERROR_UNSUPPORTED_MODE) {
1934 cpl_matrix_delete(*to);
1935 *to = NULL;
1936 cpl_array_delete(*status);
1937 *status = NULL;
1938 }
1939
1940 return cpl_error_set(cpl_func, err);
1941}
1942
1943/* cpl_image_set_bpm from cpl 6.4 which we can't require yet for VLTSW 2014 */
1944struct _cpl_image_ {
1945 /* Size of the image in x and y */
1946 cpl_size nx, ny;
1947 /* Type of the pixels used for the cpl_image */
1948 cpl_type type;
1949 /* Pointer to pixel buffer as a 1d buffer */
1950 void * pixels;
1951 /* Bad Pixels mask */
1952 cpl_mask * bpm;
1953};
1954
1955cpl_mask * hcpl_image_set_bpm(cpl_image * self, cpl_mask * bpm)
1956{
1957#if CPL_VERSION_CODE < CPL_VERSION(6, 4, 0)
1958 cpl_mask * oldbpm;
1959
1960 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
1961
1962 oldbpm = self->bpm;
1963 self->bpm = bpm;
1964
1965 return oldbpm;
1966#else
1967 return cpl_image_set_bpm(self, bpm);
1968#endif
1969}
1970
1971double hcpl_vector_get_mad_window(cpl_vector * vec,
1972 cpl_size llx,
1973 cpl_size urx,
1974 double * sigma)
1975{
1976 /* TODO use cpl directly when PIPE-4792 is fixed */
1977 struct _cpl_image_ img;
1978 img.pixels = cpl_vector_get_data(vec);
1979 img.nx = cpl_vector_get_size(vec);
1980 img.ny = 1;
1981 img.bpm = NULL;
1982 img.type = CPL_TYPE_DOUBLE;
1983 return cpl_image_get_mad_window(&img, llx, 1, urx, 1, sigma);
1984}
1985
1986double hcpl_gaussian_eval_2d(const cpl_array * self, double x, double y)
1987{
1988#if CPL_VERSION_CODE < CPL_VERSION(6, 4, 0)
1989 cpl_errorstate prestate = cpl_errorstate_get();
1990 const double B = cpl_array_get_double(self, 0, NULL);
1991 const double A = cpl_array_get_double(self, 1, NULL);
1992 const double R = cpl_array_get_double(self, 2, NULL);
1993 const double M_x = cpl_array_get_double(self, 3, NULL);
1994 const double M_y = cpl_array_get_double(self, 4, NULL);
1995 const double S_x = cpl_array_get_double(self, 5, NULL);
1996 const double S_y = cpl_array_get_double(self, 6, NULL);
1997
1998 double value = 0.0;
1999
2000 if (!cpl_errorstate_is_equal(prestate)) {
2001 (void)cpl_error_set_where(cpl_func);
2002 } else if (cpl_array_get_size(self) != 7) {
2003 (void)cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
2004 } else if (fabs(R) < 1.0 && S_x != 0.0 && S_y != 0.0) {
2005 const double x_n = (x - M_x) / S_x;
2006 const double y_n = (y - M_y) / S_y;
2007
2008 value = B + A / (CPL_MATH_2PI * S_x * S_y * sqrt(1 - R * R)) *
2009 exp(-0.5 / (1 - R * R) * ( x_n * x_n + y_n * y_n
2010 - 2.0 * R * x_n * y_n));
2011 } else if (fabs(R) > 1.0) {
2012 (void)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
2013 "fabs(R=%g) > 1", R);
2014 } else {
2015 (void)cpl_error_set_message(cpl_func, CPL_ERROR_DIVISION_BY_ZERO,
2016 "R=%g. Sigma=(%g, %g)", R, S_x, S_y);
2017 }
2018
2019 return value;
2020#else
2021 return cpl_gaussian_eval_2d(self, x, y);
2022#endif
2023}
2024
2025
2027
2028
2029/*----------------------------------------------------------------------------*/
2066/*----------------------------------------------------------------------------*/
2068 hdrl_value aRA, hdrl_value aDEC, hdrl_value aLST,
2069 hdrl_value aExptime, hdrl_value aLatitude,
2070 hdrl_airmass_approx type)
2071{
2072
2073 hdrl_value retErr = {-1.,0.};
2074 cpl_ensure( aRA.data >= 0. && aRA.data < 360. && aRA.error >= 0.
2075 && aDEC.data >= -90. && aDEC.data <= 90. && aDEC.error >= 0.
2076 && aLST.data >= 0. && aLST.data < 86400. && aLST.error >= 0.
2077 && aExptime.data >= 0. && aExptime.error >= 0.
2078 && aLatitude.data >= -90. && aLatitude.data <= 90. && aLatitude.error >= 0.
2079 && (type == HDRL_AIRMASS_APPROX_HARDIE || type == HDRL_AIRMASS_APPROX_YOUNG_IRVINE || type == HDRL_AIRMASS_APPROX_YOUNG),
2080 CPL_ERROR_ILLEGAL_INPUT,
2081 retErr);
2082
2083 /* Compute hour angle of the observation in degrees. */
2084 hdrl_value HA = {aLST.data * 15. / 3600. - aRA.data,
2085 aLST.error * fabs(15. / 3600.) + aRA.error * fabs(-1.)};
2086
2087 /* Range adjustments.Angle between line of sight and meridian is needed. */
2088 if (HA.data < -180.) HA.data += 360.;
2089 if (HA.data > 180.) HA.data -= 360.;
2090
2091 /* Convert angles from degrees to radians. */
2092
2093 hdrl_value delta = {aDEC.data * CPL_MATH_RAD_DEG,
2094 aDEC.error * fabs(CPL_MATH_RAD_DEG)};
2095
2096 hdrl_value latitude = {aLatitude.data * CPL_MATH_RAD_DEG,
2097 aLatitude.error * fabs(CPL_MATH_RAD_DEG)};
2098
2099 hdrl_value hourangle = {HA.data * CPL_MATH_RAD_DEG,
2100 HA.error * fabs(CPL_MATH_RAD_DEG)};
2101
2102
2103 /* Calculate airmass of the observation using the approximation given *
2104 * by Young (1994). For non-zero exposure times these airmass values are *
2105 * averaged using the weights given by Stetson. */
2106
2107 hdrl_value cosz = hdrl_get_zenith_distance(hourangle, delta, latitude);
2108 hdrl_value z = {0., cosz.error};
2109 double zlimit = 80.;
2110
2111 if (type == HDRL_AIRMASS_APPROX_HARDIE) {
2112
2113 z.data = acos(cosz.data) * CPL_MATH_DEG_RAD;
2114 z.error = cosz.error * fabs(-CPL_MATH_DEG_RAD / sqrt(1. + pow(cosz.data, 2)));
2115
2116 cpl_error_ensure(z.data <= zlimit, CPL_ERROR_ILLEGAL_OUTPUT, return retErr,
2117 "Zenith angle %f+-[%f] > %f!", z.data, z.error, zlimit);
2118 }
2119
2120 cpl_error_ensure(
2121 cosz.data != 0. && fabs(1./cosz.data) >= FLT_EPSILON && acos(cosz.data) <= CPL_MATH_PI_2,
2122 CPL_ERROR_ILLEGAL_OUTPUT,
2123 return retErr,
2124 "Airmass computation unsuccessful. Object is below the horizon at start (z = %f). Return the error",
2125 cosz.error * fabs(-CPL_MATH_DEG_RAD / sqrt(1. + pow(cosz.data, 2))) );
2126
2127 hdrl_value airmass = {0.,0.};
2128 hdrl_value secansZdist = {1. / cosz.data, cosz.error * fabs(-1. / pow(cosz.data, 2))};
2129
2130 switch(type){
2131 case HDRL_AIRMASS_APPROX_HARDIE:
2132 airmass = hdrl_get_airmass_hardie(secansZdist);
2133 break;
2134 case HDRL_AIRMASS_APPROX_YOUNG_IRVINE:
2135 airmass = hdrl_get_airmass_youngirvine(secansZdist);
2136 break;
2137 case HDRL_AIRMASS_APPROX_YOUNG:
2138 airmass = hdrl_get_airmass_young(cosz);
2139 break;
2140 }
2141
2142 /* if the exposure time is larger than zero, weight in airmass *
2143 * at mid and end exposure according to Stetson's weights (which *
2144 * are also used in IRAF/astcalc for the airmass function */
2145 if (aExptime.data > 0.) {
2146
2147 const double weights[] = {1./6., 2./3., 1./6.};
2148 const cpl_size nweights = sizeof(weights) / sizeof(double);
2149
2150 hdrl_value timeStep = {aExptime.data / (nweights - 1.) * 15. / 3600. * CPL_MATH_RAD_DEG, 0.};
2151 timeStep.error = aExptime.error * fabs( 1. / (nweights - 1.) * 15. / 3600. * CPL_MATH_RAD_DEG);
2152
2153 airmass.data *= weights[0];
2154 airmass.error *= fabs(weights[0]);
2155
2156 for (cpl_size i = 1; i < nweights; i++) {
2157
2158 hdrl_value aux_hourangle = { hourangle.data + i * timeStep.data,
2159 hourangle.error + i * timeStep.error };
2160
2161 cosz = hdrl_get_zenith_distance(aux_hourangle, delta, latitude);
2162
2163 if (type == HDRL_AIRMASS_APPROX_HARDIE) {
2164
2165 z = (hdrl_value){acos(cosz.data) * CPL_MATH_DEG_RAD, 0.};
2166 z.error = cosz.error * fabs(-CPL_MATH_DEG_RAD / sqrt(1. + pow(cosz.data, 2)));
2167
2168 cpl_error_ensure(z.data <= zlimit, CPL_ERROR_ILLEGAL_OUTPUT, return retErr,
2169 "Zenith angle %f+-[%f] > %f!", z.data, z.error, zlimit);
2170 }
2171
2172 cpl_error_ensure(
2173 cosz.data != 0. && fabs(1./cosz.data) >= FLT_EPSILON && acos(cosz.data) <= CPL_MATH_PI_2,
2174 CPL_ERROR_ILLEGAL_OUTPUT,
2175 return retErr,
2176 "timeStep. Object is below the horizon at %s exposure (z=%f).",
2177 i==1 ? "mid. Return the error" : "end. Return the error",
2178 cosz.error * fabs(-CPL_MATH_DEG_RAD / sqrt(1. + pow(cosz.data, 2))) );
2179
2180 hdrl_value weight = {0., 0.};
2181 secansZdist = (hdrl_value){1. / cosz.data, cosz.error * fabs(-1. / pow(cosz.data, 2))};
2182
2183 switch(type){
2184 case HDRL_AIRMASS_APPROX_HARDIE:
2185 weight = hdrl_get_airmass_hardie(secansZdist);
2186 break;
2187 case HDRL_AIRMASS_APPROX_YOUNG_IRVINE:
2188 weight = hdrl_get_airmass_youngirvine(secansZdist);
2189 break;
2190 case HDRL_AIRMASS_APPROX_YOUNG:
2191 weight = hdrl_get_airmass_young(cosz);
2192 break;
2193 }
2194 airmass.data += weights[i] *weight.data;
2195 airmass.error += weights[i] *weight.error;
2196 }
2197 }
2198
2199 if (type == HDRL_AIRMASS_APPROX_YOUNG_IRVINE) {
2200
2201 /* Accuracy limit for airmass approximation of Young & Irvine */
2202 const double airmasslimit = 4.;
2203
2204 cpl_error_ensure(airmass.data <= airmasslimit, CPL_ERROR_ILLEGAL_OUTPUT,
2205 return retErr, "Airmass larger than %f", airmasslimit);
2206 }
2207
2208 return airmass;
2209}
2210
2211/*----------------------------------------------------------------------------*/
2227/*----------------------------------------------------------------------------*/
2228hdrl_value hdrl_get_zenith_distance(
2229 hdrl_value aHourAngle, hdrl_value aDelta, hdrl_value aLatitude)
2230{
2231
2232 hdrl_value p0 = {sin(aLatitude.data) * sin(aDelta.data),
2233 aLatitude.error * fabs( cos(aLatitude.data) * sin(aDelta.data)
2234 + aDelta.error * fabs( sin(aLatitude.data) * cos(aDelta.data)))};
2235
2236 hdrl_value p1 = {cos(aLatitude.data) * cos(aDelta.data),
2237 aLatitude.error * fabs(-sin(aLatitude.data) * cos(aDelta.data)
2238 + aDelta.error * fabs(-cos(aLatitude.data) * sin(aDelta.data)))};
2239
2240 hdrl_value z = {p0.data + cos(aHourAngle.data) * p1.data,
2241 p0.error * fabs(1.)
2242 + aHourAngle.error * fabs(-sin(aHourAngle.data) * p1.data)
2243 + p1.error * fabs( cos(aHourAngle.data))};
2244
2245 return fabs(z.data) < FLT_EPSILON ? (hdrl_value){0.,0.} : z;
2246}
2247
2248/*----------------------------------------------------------------------------*/
2261/*----------------------------------------------------------------------------*/
2262hdrl_value hdrl_get_airmass_hardie(hdrl_value hvaSecZ)
2263{
2264 double aSecZ = hvaSecZ.data,
2265 aSecZErr = hvaSecZ.error;
2266
2267 hdrl_value secm1 = {aSecZ - 1, aSecZErr};
2268
2269 hdrl_value airmass = {aSecZ - 0.0018167 * secm1.data
2270 - 0.002875 * secm1.data * secm1.data
2271 - 0.0008083 * secm1.data * secm1.data * secm1.data,
2272 aSecZErr +secm1.error * fabs( - 0.0018167
2273 - 2. * 0.002875 * secm1.data
2274 - 3. * 0.0008083 * secm1.data * secm1.data)};
2275
2276 return airmass;
2277}
2278
2279/*----------------------------------------------------------------------------*/
2291/*----------------------------------------------------------------------------*/
2292hdrl_value hdrl_get_airmass_youngirvine(hdrl_value hvaSecZ)
2293{
2294 double aSecZ = hvaSecZ.data,
2295 aSecZErr = hvaSecZ.error;
2296
2297 hdrl_value airmass = {aSecZ * (1. - 0.0012 * (pow(aSecZ, 2) - 1.)),
2298 aSecZErr * fabs( (1. - 0.0012 * (pow(aSecZ, 2) - 1.)) - 2. * 0.0012 * pow(aSecZ, 2))};
2299
2300 return airmass;
2301}
2302
2303/*----------------------------------------------------------------------------*/
2317/*----------------------------------------------------------------------------*/
2318hdrl_value hdrl_get_airmass_young(hdrl_value hvaCosZt)
2319{
2320 double aCosZt = hvaCosZt.data,
2321 aCosZtErr = hvaCosZt.error;
2322
2323 hdrl_value airmass = {(1.002432 * aCosZt * aCosZt + 0.148386 * aCosZt + 0.0096467)
2324 / (aCosZt * aCosZt * aCosZt + 0.149864 * aCosZt * aCosZt + 0.0102963 * aCosZt
2325 + 0.000303978),
2326 aCosZtErr * fabs( ( (2. * 1.002432 * aCosZt + 0.148386) * (aCosZt * aCosZt * aCosZt + 0.149864 * aCosZt * aCosZt + 0.0102963 * aCosZt + 0.000303978)
2327 - (3. * aCosZt * aCosZt + 2. * 0.149864 * aCosZt + 0.0102963) * (1.002432 * aCosZt * aCosZt + 0.148386 * aCosZt + 0.0096467)
2328 ) / pow(aCosZt * aCosZt * aCosZt + 0.149864 * aCosZt * aCosZt + 0.0102963 * aCosZt + 0.000303978, 2) )};
2329
2330 return airmass;
2331}
2332
2333
cpl_image * hdrl_image_get_error(hdrl_image *himg)
get error as cpl image
Definition hdrl_image.c:131
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
Definition hdrl_image.c:105
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
cpl_matrix * hdrl_mime_linalg_pairwise_column_tensor_products_create(const cpl_matrix *mat1, const cpl_matrix *mat2)
Create selected pairwise tensor products of the columns of two matrices.
cpl_matrix * hdrl_mime_legendre_polynomials_create(int npoly, double a, double b, const cpl_matrix *x)
Create the Legendre polynomial basis on the interval (a,b).
const char * hdrl_get_license(void)
Get the pipeline copyright and license.
Definition hdrl_utils.c:68
void hdrl_sort_on_x(double *x, double *y1, double *y2, const cpl_size sample_len, const cpl_boolean sort_decreasing)
sort in increasing or decreasing order x. Keep aligned with y1 and y2.
Definition hdrl_utils.c:765
hdrl_value hdrl_utils_airmass(hdrl_value aRA, hdrl_value aDEC, hdrl_value aLST, hdrl_value aExptime, hdrl_value aLatitude, hdrl_airmass_approx type)
Compute the effective airmass of an observation. Takes in count the error propagation if you enter th...
cpl_boolean hdrl_is_strictly_monotonic_increasing(const double *x, cpl_size l)
returns CPL_TRUE if x is strictly monotonic increasing
Definition hdrl_utils.c:745
cpl_error_code hdrl_rect_region_parameter_verify(const hdrl_parameter *param, const cpl_size max_x, const cpl_size max_y)
Verify basic correctness of the parameters.
Definition hdrl_utils.c:560
cpl_table * hdrl_eop_data_totable(const char *eop_data, cpl_size data_length)
Export a raw string buffer containing EOP data to a CPL table.
Definition hdrl_utils.c:112
cpl_error_code hdrl_rect_region_parameter_update(hdrl_parameter *rect_region, cpl_size llx, cpl_size lly, cpl_size urx, cpl_size ury)
Update Rect Region Parameters object.
Definition hdrl_utils.c:485
cpl_parameterlist * hdrl_rect_region_parameter_create_parlist(const char *base_context, const char *prefix, const char *name_prefix, const hdrl_parameter *defaults)
Create parameter list for hdrl_rect_region.
Definition hdrl_utils.c:615
cpl_error_code hdrl_rect_region_fix_negatives(hdrl_parameter *rect_region, const cpl_size nx, const cpl_size ny)
wrap negative or zero coordinates around full image size
Definition hdrl_utils.c:715
hdrl_parameter * hdrl_rect_region_parameter_create(cpl_size llx, cpl_size lly, cpl_size urx, cpl_size ury)
Creates Rect Region Parameters object.
Definition hdrl_utils.c:459
cpl_size hdrl_rect_region_get_llx(const hdrl_parameter *p)
get lower left x coordinate of rectangual region
Definition hdrl_utils.c:518
cpl_size hdrl_rect_region_get_urx(const hdrl_parameter *p)
get upper right x coordinate of rectangular region
Definition hdrl_utils.c:536
cpl_size hdrl_rect_region_get_lly(const hdrl_parameter *p)
get lower left y coordinate of rectangual region
Definition hdrl_utils.c:527
char * hdrl_join_string(const char *sep_, int n,...)
join strings together
Definition hdrl_utils.c:810
cpl_size hdrl_rect_region_get_ury(const hdrl_parameter *p)
get upper right y coordinate of rectangual region
Definition hdrl_utils.c:545
hdrl_parameter * hdrl_rect_region_parameter_parse_parlist(const cpl_parameterlist *parlist, const char *base_context, const char *name_prefix)
parse parameterlist for rectangle parameters
Definition hdrl_utils.c:674
cpl_boolean hdrl_rect_region_parameter_check(const hdrl_parameter *self)
Check that the parameter is hdrl_rect_region parameter.
Definition hdrl_utils.c:506