High-Level Data Reduction Library 1.6.0
High-Level data reduction routines for ESO pipelines
Loading...
Searching...
No Matches
hdrl_resample.c
Go to the documentation of this file.
1/*
2 * This file is part of the HDRL
3 * Copyright (C) 2020 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#include <cpl.h>
28#include <string.h>
29#include <math.h>
30
31#include "hdrl_resample.h"
32#include "hdrl_utils.h"
33
34#ifndef _OPENMP
35#define omp_get_max_threads() 1
36#define omp_get_thread_num() 0
37#else
38#include <omp.h>
39#endif
40
41#include <sys/time.h>
42
43/*-----------------------------------------------------------------------------
44 Defines
45 -----------------------------------------------------------------------------*/
46
47/* Not very elegant but it removes compiler warnings */
48#if !defined(_POSIX_C_SOURCE)
49#define _POSIX_C_SOURCE 200112L
50#elif (_POSIX_C_SOURCE - 0) < 200112L
51#undef _POSIX_C_SOURCE
52#define _POSIX_C_SOURCE 200112L
53#endif
54
55
56/* maximum keyword length for FITS headers, including '\0' */
57#define KEYWORD_LENGTH 81
58
59/* Default field margin (in percent), if the user does not specify any. 5
60 * percent is also used in the software package swarp */
61#define FIELDMARGIN 5.
62
63/* use bits 0-52 for the value (the pixel table row), this allows to convert
64 * pixel tables with up to 9e15 pixels into a pixel grid */
65#define PT_IDX_MASK 0x1FFFFFFFFFFFFFll
66
67/* use bits 53-62 to store the thread ID, this allows parallelization with up to
68 * 1024 cores */
69#define XMAP_BITMASK 0x3FFll /* 1023 */
70#define XMAP_LSHIFT 53ll
71
72typedef struct {
73 double crpix1, crpix2; /* the reference point */
74 double crval1, crval2; /* the coordinate values at the ref. point */
75 double cd11, cd12, cd21, cd22; /* the four elements of the CDi_j matrix */
76 double cddet; /* the determinant of the CDi_j matrix */
78
79typedef struct {
80 unsigned int npix; /* number of pixels in this grid point */
81 cpl_size *pix; /* the row number(s) in the pixel table */
83
84typedef struct {
85 /* The pixel grid array, elements can be:
86 0: empty
87 positive: row_number in the pixel table
88 negative: -(i_ext+1) in the extension array,
89 bits 53-62 contain the map index */
90 cpl_size *pix;
91 cpl_size nx; /* horizontal spatial size */
92 cpl_size ny; /* vertical spatial size */
93 cpl_size nz; /* size in dispersion direction */
94 unsigned short nmaps; /* number of extension maps */
95 cpl_size *nxmap; /* number of filled pixels in the extension maps */
96 cpl_size *nxalloc; /* number of allocated pixels in the extension maps */
97 hdrl_resample_pixels_ext **xmaps; /* the extension maps */
99
100/*----------------------------------------------------------------------------*/
153/*----------------------------------------------------------------------------*/
154
157/*----------------------------------------------------------------------------*/
176/*----------------------------------------------------------------------------*/
177
178/*----------------------------------------------------------------------------*/
197/*----------------------------------------------------------------------------*/
198
201/*-----------------------------------------------------------------------------
202 RESAMPLE Parameter Definition
203 -----------------------------------------------------------------------------*/
204
205typedef struct {
206 HDRL_PARAMETER_HEAD;
208 double delta_ra ; /* step size in right ascension [deg] */
209 double delta_dec ; /* step size in declination [deg] */
210 double delta_lambda ; /* step size in wavelength direction [m] */
211 const cpl_wcs* wcs ; /* World Coordinate System */
212 cpl_boolean recalc_limits;
213 double ra_min; /* Minimal Right ascension [deg] */
214 double ra_max; /* Maximal Right ascension [deg] */
215 double dec_min; /* Minimal Declination [deg] */
216 double dec_max; /* Maximal Declination [deg] */
217 double lambda_min; /* Minimal wavelength [m] */
218 double lambda_max; /* Maximal wavelength [m] */
219 double fieldmargin; /* Field margin to add [percent] */
220} hdrl_resample_outgrid_parameter;
221
222/* Parameter type */
223static hdrl_parameter_typeobj hdrl_resample_outgrid_parameter_type = {
224 HDRL_PARAMETER_RESAMPLE_OUTGRID, /* type */
225 (hdrl_alloc *)&cpl_malloc, /* fp_alloc */
226 (hdrl_free *)&cpl_free, /* fp_free */
227 NULL, /* fp_destroy */
228 sizeof(hdrl_resample_outgrid_parameter), /* obj_size */
229};
230
231typedef struct {
232 HDRL_PARAMETER_HEAD;
234 int loop_distance;
236 cpl_boolean use_errorweights;
240 double drizzle_pix_frac_x;
241 double drizzle_pix_frac_y;
242 double drizzle_pix_frac_lambda;
244 double renka_critical_radius;
246 int lanczos_kernel_size;
247} hdrl_resample_method_parameter;
248
249/* Parameter type */
250static hdrl_parameter_typeobj hdrl_resample_method_parameter_type = {
251 HDRL_PARAMETER_RESAMPLE_METHOD, /* type */
252 (hdrl_alloc *)&cpl_malloc, /* fp_alloc */
253 (hdrl_free *)&cpl_free, /* fp_free */
254 NULL, /* fp_destroy */
255 sizeof(hdrl_resample_method_parameter), /* obj_size */
256};
257
259/*-----------------------------------------------------------------------------
260 Functions
261 -----------------------------------------------------------------------------*/
262
264hdrl_resample_cube(const cpl_table *ResTable,
265 hdrl_resample_method_parameter *aParams_method,
266 hdrl_resample_outgrid_parameter *aParams_outputgrid,
267 hdrl_resample_pixgrid **aGrid);
268
269static cpl_error_code
270hdrl_resample_inputtable_verify(const cpl_table *ResTable);
271
272/*----------------------------------------------------------------------------*/
278/*----------------------------------------------------------------------------*/
279
280static cpl_error_code
281hdrl_resample_wcs_print(const cpl_wcs *wcs)
282{
283 cpl_ensure_code(wcs, CPL_ERROR_NULL_INPUT);
284
285 const cpl_array *crval = cpl_wcs_get_crval(wcs);
286 const cpl_array *crpix = cpl_wcs_get_crpix(wcs);
287 const cpl_array *ctype = cpl_wcs_get_ctype(wcs);
288 const cpl_array *cunit = cpl_wcs_get_cunit(wcs);
289
290 const cpl_matrix *cd = cpl_wcs_get_cd(wcs);
291 const cpl_array *dims = cpl_wcs_get_image_dims(wcs);
292 int naxis = cpl_wcs_get_image_naxis(wcs);
293
294 cpl_msg_debug(cpl_func, "NAXIS: %d", naxis);
295
296 int testerr = 0;
297
298 cpl_msg_indent_more();
299 /* Check NAXIS */
300 for (cpl_size i = 0; i < naxis; i++) {
301 cpl_msg_debug(cpl_func, "NAXIS%lld: %d", i + 1,
302 cpl_array_get_int(dims, i, &testerr));
303 }
304 cpl_msg_indent_less();
305
306 double cd11 = cpl_matrix_get(cd, 0, 0);
307 double cd12 = cpl_matrix_get(cd, 0, 1);
308 double cd21 = cpl_matrix_get(cd, 1, 0);
309 double cd22 = cpl_matrix_get(cd, 1, 1);
310 double crpix1 = cpl_array_get_double(crpix, 0, &testerr);
311 double crpix2 = cpl_array_get_double(crpix, 1, &testerr);
312 double crval1 = cpl_array_get_double(crval, 0, &testerr);
313 double crval2 = cpl_array_get_double(crval, 1, &testerr);
314
315 cpl_msg_debug(cpl_func, "1st and 2nd dimension");
316 cpl_msg_indent_more();
317 cpl_msg_debug(cpl_func, "CD1_1: %g", cd11);
318 cpl_msg_debug(cpl_func, "CD1_2: %g", cd12);
319 cpl_msg_debug(cpl_func, "CD2_1: %g", cd21);
320 cpl_msg_debug(cpl_func, "CD2_2: %g", cd22);
321
322 cpl_msg_debug(cpl_func, "CRPIX1: %g", crpix1);
323 cpl_msg_debug(cpl_func, "CRPIX2: %g", crpix2);
324 cpl_msg_debug(cpl_func, "CRVAL1: %g", crval1);
325 cpl_msg_debug(cpl_func, "CRVAL2: %g", crval2);
326 if (ctype) {
327 cpl_msg_debug(cpl_func, "CTYPE1: %s", cpl_array_get_string(ctype, 0));
328 cpl_msg_debug(cpl_func, "CTYPE2: %s", cpl_array_get_string(ctype, 1));
329 }
330
331 if (cunit) {
332 cpl_msg_debug(cpl_func, "CUNIT1: %s", cpl_array_get_string(cunit, 0));
333 cpl_msg_debug(cpl_func, "CUNIT2: %s", cpl_array_get_string(cunit, 1));
334 }
335 cpl_msg_indent_less();
336
337 /* Is it a 3D cube or a 2D image */
338 cpl_size cdncol = cpl_matrix_get_ncol(cd);
339 if (cdncol == 3) {
340
341 double cd13 = cpl_matrix_get(cd, 0, 2);
342 double cd23 = cpl_matrix_get(cd, 1, 2);
343 double cd31 = cpl_matrix_get(cd, 2, 0);
344 double cd32 = cpl_matrix_get(cd, 2, 1);
345 double cd33 = cpl_matrix_get(cd, 2, 2);
346 double crval3 = cpl_array_get_double(crval, 2, &testerr);
347 double crpix3 = cpl_array_get_double(crpix, 2, &testerr);
348
349 cpl_msg_debug(cpl_func, "3rd dimension");
350 cpl_msg_indent_more();
351 cpl_msg_debug(cpl_func, "CD1_3: %g", cd13);
352 cpl_msg_debug(cpl_func, "CD2_3: %g", cd23);
353 cpl_msg_debug(cpl_func, "CD3_1: %g", cd31);
354 cpl_msg_debug(cpl_func, "CD3_2: %g", cd32);
355 cpl_msg_debug(cpl_func, "CD3_3: %g", cd33);
356
357 cpl_msg_debug(cpl_func, "CRPIX3: %g", crpix3);
358 cpl_msg_debug(cpl_func, "CRVAL3: %g", crval3);
359
360 if (ctype) {
361 cpl_msg_debug(cpl_func, "CTYPE3: %s", cpl_array_get_string(ctype, 2));
362 }
363
364 if (cunit) {
365 cpl_msg_debug(cpl_func, "CUNIT3: %s", cpl_array_get_string(cunit, 2));
366 }
367
368 cpl_msg_indent_less();
369 }
370
371 return cpl_error_get_code();
372}
373
374/*----------------------------------------------------------------------------*/
380/*----------------------------------------------------------------------------*/
381static cpl_error_code
382hdrl_resample_outgrid_parameter_print(hdrl_resample_outgrid_parameter* p)
383{
384
385 cpl_ensure_code(p, CPL_ERROR_NULL_INPUT);
386 /* Content of the outgrid parameter structure */
387
388 cpl_msg_indent_more();
389 cpl_msg_debug(cpl_func, "delta_ra: %g", p->delta_ra);
390 cpl_msg_debug(cpl_func, "delta_dec: %g", p->delta_dec);
391 cpl_msg_debug(cpl_func, "delta_lambda: %g", p->delta_lambda);
392 cpl_msg_debug(cpl_func, "ra_min: %g", p->ra_min);
393 cpl_msg_debug(cpl_func, "ra_max: %g", p->ra_max);
394 cpl_msg_debug(cpl_func, "dec_min: %g", p->dec_min);
395 cpl_msg_debug(cpl_func, "dec_max: %g", p->dec_max);
396 cpl_msg_debug(cpl_func, "lambda_min: %g", p->lambda_min);
397 cpl_msg_debug(cpl_func, "lambda_max: %g", p->lambda_max);
398 cpl_msg_debug(cpl_func, "fieldmargin: %g", p->fieldmargin);
399 cpl_msg_debug(cpl_func, "recalc_limits: %d", p->recalc_limits);
400
401 /* World Coordinate System */
402 hdrl_resample_wcs_print(p->wcs);
403 cpl_msg_indent_less();
404 return cpl_error_get_code();
405
406}
407/*----------------------------------------------------------------------------*/
413/*----------------------------------------------------------------------------*/
414static cpl_error_code
415hdrl_resample_method_parameter_print(hdrl_resample_method_parameter* p)
416{
417 if (hdrl_resample_parameter_method_verify((hdrl_parameter*)p) != CPL_ERROR_NONE) {
418 return cpl_error_get_code();
419 }
420
421 /* Content of the outgrid parameter structure */
422
423 cpl_msg_indent_more();
424 if(p->method == HDRL_RESAMPLE_METHOD_NEAREST) {
425 cpl_msg_debug(cpl_func, "method: %s", "NEAREST" );
426 } else if (p->method == HDRL_RESAMPLE_METHOD_RENKA) {
427 cpl_msg_debug(cpl_func, "method: %s", "RENKA" );
428 cpl_msg_debug(cpl_func, "loop_distance: %d", p->loop_distance);
429 cpl_msg_debug(cpl_func, "use_errorweights: %s",
430 p->use_errorweights == CPL_TRUE ? "TRUE" : "FALSE");
431 cpl_msg_debug(cpl_func, "renka_critical_radius: %g", p->renka_critical_radius);
432 } else if (p->method == HDRL_RESAMPLE_METHOD_LINEAR) {
433 cpl_msg_debug(cpl_func, "method: %s", "LINEAR" );
434 cpl_msg_debug(cpl_func, "loop_distance: %d", p->loop_distance);
435 cpl_msg_debug(cpl_func, "use_errorweights: %s",
436 p->use_errorweights == CPL_TRUE ? "TRUE" : "FALSE");
437 } else if (p->method == HDRL_RESAMPLE_METHOD_QUADRATIC) {
438 cpl_msg_debug(cpl_func, "method: %s", "QUADRATIC)" );
439 cpl_msg_debug(cpl_func, "loop_distance: %d", p->loop_distance);
440 cpl_msg_debug(cpl_func, "use_errorweights: %s",
441 p->use_errorweights == CPL_TRUE ? "TRUE" : "FALSE");
442 } else if (p->method == HDRL_RESAMPLE_METHOD_DRIZZLE) {
443 cpl_msg_debug(cpl_func, "method: %s", "DRIZZLE" );
444 cpl_msg_debug(cpl_func, "loop_distance: %d", p->loop_distance);
445 cpl_msg_debug(cpl_func, "use_errorweights: %s",
446 p->use_errorweights == CPL_TRUE ? "TRUE" : "FALSE");
447 cpl_msg_debug(cpl_func, "drizzle_pix_frac_x: %g", p->drizzle_pix_frac_x);
448 cpl_msg_debug(cpl_func, "drizzle_pix_frac_y: %g", p->drizzle_pix_frac_y);
449 cpl_msg_debug(cpl_func, "drizzle_pix_frac_lambda: %g", p->drizzle_pix_frac_lambda);
450 } else if (p->method == HDRL_RESAMPLE_METHOD_LANCZOS) {
451 cpl_msg_debug(cpl_func, "method: %s", "LANCZOS" );
452 cpl_msg_debug(cpl_func, "loop_distance: %d", p->loop_distance);
453 cpl_msg_debug(cpl_func, "use_errorweights: %s",
454 p->use_errorweights == CPL_TRUE ? "TRUE" : "FALSE");
455 cpl_msg_debug(cpl_func, "lanczos_kernel_size: %d", p->lanczos_kernel_size);
456 }
457
458 cpl_msg_indent_less();
459 return cpl_error_get_code();
460}
461
462/*----------------------------------------------------------------------------*/
475/*----------------------------------------------------------------------------*/
476cpl_error_code
477hdrl_wcs_xy_to_radec(const cpl_wcs *wcs, double x, double y, double *ra,
478 double *dec) {
479 cpl_ensure_code(wcs && ra && dec, CPL_ERROR_NULL_INPUT);
480 double * xy = NULL;
481 double * radec = NULL;
482 cpl_matrix * from = NULL;
483 cpl_matrix * to = NULL;
484 cpl_array * status = NULL;
485
486 /* Load up the information */
487 int naxis = cpl_wcs_get_image_naxis(wcs);
488 from = cpl_matrix_new(1, naxis);
489 xy = cpl_matrix_get_data(from);
490 xy[0] = x;
491 xy[1] = y;
492
493 /* Call the conversion routine */
494
495 cpl_wcs_convert(wcs, from, &to, &status, CPL_WCS_PHYS2WORLD);
496
497 /* Pass it back now */
498
499 radec = cpl_matrix_get_data(to);
500 *ra = radec[0];
501 *dec = radec[1];
502
503 /* Tidy and exit */
504
505 cpl_matrix_delete(from);
506 cpl_matrix_delete(to);
507 cpl_array_delete(status);
508 return cpl_error_get_code();
509}
510
511
512/*----------------------------------------------------------------------------*/
521/*----------------------------------------------------------------------------*/
522static double
523hdrl_resample_pfits_get_crpix(const cpl_propertylist *aHeaders, unsigned int aAxis)
524{
525 cpl_errorstate prestate = cpl_errorstate_get();
526 cpl_ensure(aHeaders, CPL_ERROR_NULL_INPUT, 0);
527
528 char keyword[KEYWORD_LENGTH];
529 snprintf(keyword, KEYWORD_LENGTH, "CRPIX%u", aAxis);
530 const double value = cpl_propertylist_get_double(aHeaders, keyword);
531 /* default to 0.0 as per FITS Standard v3.0 */
532 cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
533 return value;
534}
535
536/*----------------------------------------------------------------------------*/
545/*----------------------------------------------------------------------------*/
546static double
547hdrl_resample_pfits_get_crval(const cpl_propertylist *aHeaders, unsigned int aAxis)
548{
549 cpl_errorstate prestate = cpl_errorstate_get();
550 cpl_ensure(aHeaders, CPL_ERROR_NULL_INPUT, 0);
551
552 char keyword[KEYWORD_LENGTH];
553 snprintf(keyword, KEYWORD_LENGTH, "CRVAL%u", aAxis);
554 const double value = cpl_propertylist_get_double(aHeaders, keyword);
555 /* default to 0.0 as per FITS Standard v3.0 */
556 cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
557 return value;
558}
559
560/*----------------------------------------------------------------------------*/
570/*----------------------------------------------------------------------------*/
571static double
572hdrl_resample_pfits_get_cd(const cpl_propertylist *aHeaders, unsigned int aAxisI,
573 unsigned int aAxisJ)
574{
575 cpl_errorstate prestate = cpl_errorstate_get();
576 cpl_ensure(aHeaders, CPL_ERROR_NULL_INPUT, 0);
577
578 char keyword[KEYWORD_LENGTH];
579 snprintf(keyword, KEYWORD_LENGTH, "CD%u_%u", aAxisI, aAxisJ);
580 const double value = cpl_propertylist_get_double(aHeaders, keyword);
581 /* default to 0.0 as per FITS Standard v3.0 */
582 cpl_ensure(cpl_errorstate_is_equal(prestate), cpl_error_get_code(), 0.0);
583 return value;
584}
585
586/*----------------------------------------------------------------------------*/
603/*----------------------------------------------------------------------------*/
605hdrl_resample_smallwcs_new(cpl_propertylist *aHeader)
606{
607
608 cpl_ensure(aHeader, CPL_ERROR_NULL_INPUT, NULL);
609 hdrl_resample_smallwcs *wcs = cpl_calloc(1, sizeof(hdrl_resample_smallwcs));
610
611 cpl_errorstate prestate = cpl_errorstate_get();
612 wcs->crpix1 = hdrl_resample_pfits_get_crpix(aHeader, 1);
613 wcs->crpix2 = hdrl_resample_pfits_get_crpix(aHeader, 2);
614 wcs->crval1 = hdrl_resample_pfits_get_crval(aHeader, 1);
615 wcs->crval2 = hdrl_resample_pfits_get_crval(aHeader, 2);
616 if (!cpl_errorstate_is_equal(prestate)) {
617 /* all these headers default to 0.0 following the FITS *
618 * Standard, so we can ignore any errors set here */
619 cpl_errorstate_set(prestate);
620 }
621
622 prestate = cpl_errorstate_get();
623 wcs->cd11 = hdrl_resample_pfits_get_cd(aHeader, 1, 1);
624 wcs->cd22 = hdrl_resample_pfits_get_cd(aHeader, 2, 2);
625 wcs->cd12 = hdrl_resample_pfits_get_cd(aHeader, 1, 2);
626 wcs->cd21 = hdrl_resample_pfits_get_cd(aHeader, 2, 1);
627 if (!cpl_errorstate_is_equal(prestate) &&
628 wcs->cd11 == 0. && wcs->cd12 == 0. && wcs->cd21 == 0. && wcs->cd22 == 0.) {
629 /* FITS Standard says to handle the CD matrix like the PC *
630 * matrix in this case, with 1 for the diagonal elements */
631 wcs->cd11 = wcs->cd22 = wcs->cddet = 1.;
632 cpl_errorstate_set(prestate); /* not a real error */
633 }
634 wcs->cddet = wcs->cd11 * wcs->cd22 - wcs->cd12 * wcs->cd21;
635 if (wcs->cddet == 0.) {
636 cpl_error_set(cpl_func, CPL_ERROR_SINGULAR_MATRIX);
637 }
638
639 return wcs;
640} /* hdrl_resample_smallwcs_new() */
641
642/*---------------------------------------------------------------------------*/
648/*---------------------------------------------------------------------------*/
649static void
650hdrl_resample_pixgrid_delete(hdrl_resample_pixgrid *aGrid)
651{
652 if (!aGrid) {
653 return;
654 }
655 cpl_free(aGrid->pix);
656 aGrid->pix = NULL;
657 /* clean up extension maps */
658 unsigned short ix;
659 for (ix = 0; ix < aGrid->nmaps; ix++) {
660 cpl_size iext; /* index in this extension map */
661 for (iext = 0; iext < aGrid->nxalloc[ix]; iext++) {
662 cpl_free(aGrid->xmaps[ix][iext].pix);
663 } /* for iext (all allocated pixels in this extension map) */
664
665 cpl_free(aGrid->xmaps[ix]);
666 } /* for ix (all extension maps) */
667 cpl_free(aGrid->xmaps);
668 aGrid->xmaps = NULL;
669 cpl_free(aGrid->nxmap);
670 aGrid->nxmap = NULL;
671 cpl_free(aGrid->nxalloc);
672 aGrid->nxalloc = NULL;
673 cpl_free(aGrid);
674} /* hdrl_resample_pixgrid_delete() */
675
676
677/*---------------------------------------------------------------------------*/
733/*---------------------------------------------------------------------------*/
735hdrl_resample_compute(const cpl_table *ResTable,
736 hdrl_parameter *method,
737 hdrl_parameter *outputgrid,
738 const cpl_wcs* wcs)
739{
740 cpl_ensure(ResTable && method, CPL_ERROR_NULL_INPUT, NULL);
741 cpl_ensure(wcs != NULL, CPL_ERROR_NULL_INPUT, NULL);
742
743 if (hdrl_resample_inputtable_verify(ResTable)) {
744 return NULL;
745 }
747 return NULL;
748 }
750 return NULL;
751 }
752
753 if (hdrl_resample_inputtable_verify(ResTable)) {
754 return NULL;
755 }
756
757 hdrl_resample_outgrid_parameter *aParams_outputgrid =
758 (hdrl_resample_outgrid_parameter *) outputgrid;
759 hdrl_resample_method_parameter *aParams_method =
760 (hdrl_resample_method_parameter *) method;
761
762 /*Assign the wcs*/
763 aParams_outputgrid->wcs = wcs;
764
765 /* Recalculate the limits if the user did not specify any */
766 cpl_boolean recalc_limits = aParams_outputgrid->recalc_limits;
767
768 if (recalc_limits == CPL_TRUE) {
769 double ramin = cpl_table_get_column_min(ResTable, HDRL_RESAMPLE_TABLE_RA);
770 double ramax = cpl_table_get_column_max(ResTable, HDRL_RESAMPLE_TABLE_RA);
771 double decmin = cpl_table_get_column_min(ResTable, HDRL_RESAMPLE_TABLE_DEC);
772 double decmax = cpl_table_get_column_max(ResTable, HDRL_RESAMPLE_TABLE_DEC);
773 double lmin = cpl_table_get_column_min(ResTable, HDRL_RESAMPLE_TABLE_LAMBDA);
774 double lmax = cpl_table_get_column_max(ResTable, HDRL_RESAMPLE_TABLE_LAMBDA);
775
776 /* We have the rare case that the image spans over ra = 0.*/
777 if(ramax - ramin > 180){
778 const double *ra = cpl_table_get_data_double_const(ResTable,
780
781 /* set to extreme values for a start */
782 ramin = 0.;
783 ramax = 360.;
784 cpl_size nrow = cpl_table_get_nrow(ResTable);
785
786 for (cpl_size i = 0; i < nrow; i++) {
787 if (ra[i] > ramin && ra[i] <= 180.) ramin = ra[i]; /* get the maximum */
788 if (ra[i] < ramax && ra[i] > 180.) ramax = ra[i]; /* get the minimum */
789 }
790 }
791
792 aParams_outputgrid->ra_min = ramin;
793 aParams_outputgrid->ra_max = ramax;
794 aParams_outputgrid->dec_min = decmin;
795 aParams_outputgrid->dec_max = decmax;
796 aParams_outputgrid->lambda_min = lmin;
797 aParams_outputgrid->lambda_max = lmax;
798 }
799
800 cpl_msg_debug(cpl_func, "Content of the outgrid parameter structure "
801 "hdrl_resample_outgrid_parameter when resampling starts:");
802 hdrl_resample_outgrid_parameter_print(aParams_outputgrid);
803
804 cpl_msg_debug(cpl_func, "Content of the method parameter structure "
805 "hdrl_resample_method_parameter when resampling starts:");
806 hdrl_resample_method_parameter_print(aParams_method);
807
808 /* create cube and cast to generic pointer to save code duplication */
809 hdrl_resample_result *cube = NULL;
810 hdrl_resample_pixgrid *grid = NULL;
811
812 cpl_msg_debug(cpl_func, "Resampling starts ...");
813 cpl_msg_indent_more();
814 cube = hdrl_resample_cube(ResTable,
815 (hdrl_resample_method_parameter *)aParams_method,
816 (hdrl_resample_outgrid_parameter *)aParams_outputgrid,
817 &grid);
818 cpl_msg_indent_less();
819 cpl_ensure(cube, CPL_ERROR_NULL_INPUT, NULL);
820 cpl_ensure(cube->header, CPL_ERROR_NULL_INPUT, NULL);
821 cpl_ensure(cube->himlist, CPL_ERROR_NULL_INPUT, NULL);
822
823 /* Cleanup wcs for 2D / 3D case */
824
825 if(hdrl_imagelist_get_size(cube->himlist) == 1) { /* 2D case */
826 cpl_propertylist *header = cpl_propertylist_new();
827 cpl_wcs* wcs_local = cpl_wcs_new_from_propertylist(cube->header);
828 hdrl_wcs_to_propertylist(wcs_local, header, CPL_TRUE);
829 cpl_wcs_delete(wcs_local);
830 cpl_propertylist_delete(cube->header);
831 cpl_propertylist_set_comment(header, "CTYPE1", "Gnomonic projection");
832 cpl_propertylist_set_comment(header, "CTYPE2", "Gnomonic projection");
833 cube->header = header;
834 }
835
836
837 hdrl_resample_pixgrid_delete(grid);
838 return cube;
839} /* hdrl_resample_compute() */
840
841/*---------------------------------------------------------------------------*/
846/*---------------------------------------------------------------------------*/
847void
849{
850 /* if the cube does not exists at all, we don't need to do anything */
851 if (!aCube) {
852 return;
853 }
854
855 /* checks for the existence of the sub-images *
856 * are done in the CPL functions */
857
859 aCube->himlist = NULL;
860 /* delete the FITS header, too */
861 cpl_propertylist_delete(aCube->header);
862 aCube->header = NULL;
863
864 cpl_free(aCube);
865} /* hdrl_resample_result_delete() */
866
867/*----------------------------------------------------------------------------*/
894/*----------------------------------------------------------------------------*/
895static cpl_error_code
896hdrl_resample_wcs_projplane_from_celestial(hdrl_resample_outgrid_parameter *
897 aParams_outputgrid, double aRA,
898 double aDEC, double *aX, double *aY)
899{
900 cpl_ensure_code(aParams_outputgrid && aX && aY, CPL_ERROR_NULL_INPUT);
901 /* make sure that the header represents TAN */
902 //const char * type1 = aParams_outputgrid->limits.ctype1;
903 //const char * type2 = aParams_outputgrid->limits.ctype2;
904 /*
905 cpl_ensure_code(type1 && type2 && !strncmp(type1, "RA---TAN", 9) &&
906 !strncmp(type2, "DEC--TAN", 9),
907 CPL_ERROR_UNSUPPORTED_MODE);
908 */
909
910 int err = 0;
911 const cpl_array *crval = cpl_wcs_get_crval(aParams_outputgrid->wcs);
912 double crval1 = cpl_array_get_double(crval, 0, &err);
913 double crval2 = cpl_array_get_double(crval, 1, &err);
914
915 /* spherical coordinate shift/translation */
916 double a = aRA / CPL_MATH_DEG_RAD, /* RA in radians */
917 d = aDEC / CPL_MATH_DEG_RAD, /* DEC in radians */
918 /* alpha_p and delta_p in Paper II (in radians) */
919 //ap = aParams_outputgrid->limits.crval1 / CPL_MATH_DEG_RAD,
920 //dp = aParams_outputgrid->limits.crval2 / CPL_MATH_DEG_RAD,
921 ap = crval1 / CPL_MATH_DEG_RAD,
922 dp = crval2 / CPL_MATH_DEG_RAD,
923 phi = atan2(-cos(d) * sin(a - ap),
924 sin(d) * cos(dp) - cos(d) * sin(dp) * cos(a-ap))
925 + 180 / CPL_MATH_DEG_RAD,
926 theta = asin(sin(d) * sin(dp) + cos(d) * cos(dp) * cos(a-ap)),
927 R_theta = CPL_MATH_DEG_RAD / tan(theta);
928 /* spherical deprojection */
929 *aX = R_theta * sin(phi),
930 *aY = -R_theta * cos(phi);
931
932 return CPL_ERROR_NONE;
933} /* hdrl_resample_wcs_projplane_from_celestial() */
934
935/*---------------------------------------------------------------------------*/
953/*---------------------------------------------------------------------------*/
954static inline void
955hdrl_resample_wcs_pixel_from_celestial_fast(hdrl_resample_smallwcs *aWCS,
956 double aRA, double aDEC, double *aX, double *aY)
957{
958 if(!aWCS) return;
959 /* spherical coordinate shift/translation */
960 /*Calabretta & Greisen 2002 A&A 395, 1077 (Paper II) */
961 /* aRA is alpha in Paper II, aDEC is delta, aWCS->crval1 is alpha_p, *
962 * aWCS->crval2 is delta_p, all of them in units of radians, eq (5), arg=atan2 */
963
964 double phi = atan2(-cos(aDEC) * sin(aRA - aWCS->crval1),
965 sin(aDEC) * cos(aWCS->crval2)
966 - cos(aDEC) * sin(aWCS->crval2) * cos(aRA - aWCS->crval1))
967 + 180 / CPL_MATH_DEG_RAD,
968 theta = asin(sin(aDEC) * sin(aWCS->crval2)
969 + cos(aDEC) * cos(aWCS->crval2) * cos(aRA - aWCS->crval1)),
970 R_theta = CPL_MATH_DEG_RAD / tan(theta);
971 /* spherical deprojection */
972 double x = R_theta * sin(phi),
973 y = -R_theta * cos(phi);
974 /* inverse linear transformation */
975 *aX = (aWCS->cd22 * x - aWCS->cd12 * y) / aWCS->cddet + aWCS->crpix1;
976 *aY = (aWCS->cd11 * y - aWCS->cd21 * x) / aWCS->cddet + aWCS->crpix2;
977} /* hdrl_resample_wcs_pixel_from_celestial_fast() */
978
979
980/*---------------------------------------------------------------------------*/
993/*---------------------------------------------------------------------------*/
994/* Forward declaration */
995static cpl_error_code
996hdrl_resample_wcs_get_scales(hdrl_resample_outgrid_parameter *aParams_outputgrid,
997 double *aXScale, double *aYScale);
998
999static cpl_error_code
1000hdrl_resample_compute_size(hdrl_resample_outgrid_parameter *aParams_outputgrid,
1001 int *aX, int *aY, int *aZ)
1002{
1003 cpl_ensure_code(aParams_outputgrid && aX && aY && aZ, CPL_ERROR_NULL_INPUT);
1004 const char func[] = "hdrl_resample_compute_size"; /* pretend to be in that fct... */
1005 double x1, y1, x2, y2;
1006
1007 /* Fix for PIPE-12792: Correct delta_ra/delta_dec if they appear incorrect.
1008 * When delta values are extracted using only diagonal CD matrix elements
1009 * (ignoring rotation), they can be orders of magnitude too small, leading
1010 * to unreasonably large grid dimensions. */
1011 if (aParams_outputgrid->wcs) {
1012 double wcs_delta_ra, wcs_delta_dec;
1013 if (hdrl_resample_wcs_get_scales(aParams_outputgrid, &wcs_delta_ra, &wcs_delta_dec)
1014 == CPL_ERROR_NONE) {
1015 /* Only correct if current delta is < 1% of correct value (orders of magnitude difference) */
1016 const double BUG_THRESHOLD = 0.01;
1017 if (fabs(wcs_delta_ra) > 1e-15 &&
1018 fabs(aParams_outputgrid->delta_ra) < BUG_THRESHOLD * fabs(wcs_delta_ra)) {
1019 aParams_outputgrid->delta_ra = wcs_delta_ra;
1020 }
1021 if (fabs(wcs_delta_dec) > 1e-15 &&
1022 fabs(aParams_outputgrid->delta_dec) < BUG_THRESHOLD * fabs(wcs_delta_dec)) {
1023 aParams_outputgrid->delta_dec = wcs_delta_dec;
1024 }
1025 }
1026 }
1027
1028 double ramin = aParams_outputgrid->ra_min;
1029 double ramax = aParams_outputgrid->ra_max;
1030 double decmin = aParams_outputgrid->dec_min;
1031 double decmax = aParams_outputgrid->dec_max;
1032 hdrl_resample_wcs_projplane_from_celestial(aParams_outputgrid, ramin, decmin,
1033 &x1, &y1);
1034 hdrl_resample_wcs_projplane_from_celestial(aParams_outputgrid, ramax, decmax,
1035 &x2, &y2);
1036 *aX = lround(fabs(x2 - x1) / aParams_outputgrid->delta_ra) + 1;
1037 *aY = lround(fabs(y2 - y1) / aParams_outputgrid->delta_dec) + 1;
1038
1039 double lmin = aParams_outputgrid->lambda_min;
1040 double lmax = aParams_outputgrid->lambda_max;
1041
1042 *aZ = (int)ceil((lmax - lmin) / aParams_outputgrid->delta_lambda) + 1;
1043
1044 cpl_msg_debug(func, "Output cube size %d x %d x %d (fit to data)",
1045 *aX, *aY, *aZ);
1046 return CPL_ERROR_NONE;
1047} /* hdrl_resample_compute_size() */
1048
1049/*---------------------------------------------------------------------------*/
1065/*---------------------------------------------------------------------------*/
1066static void
1067hdrl_resample_pixgrid_add(hdrl_resample_pixgrid *aGrid, cpl_size aIndex,
1068 cpl_size aRow, unsigned short aXIdx)
1069{
1070
1071 if (aIndex < 0 || aGrid == NULL) {
1072 return;
1073 }
1074
1075 if (aGrid->pix[aIndex] == 0 && aRow > 0) {
1076 /* First pixel is stored directly. */
1077 aGrid->pix[aIndex] = aRow;
1078 } else if (aGrid->pix[aIndex] == 0 && aRow == 0) {
1079 /* Special case: we cannot put "0" into the main map. */
1080 cpl_size iext = aGrid->nxmap[aXIdx]++;
1081 if (aGrid->nxmap[aXIdx] > aGrid->nxalloc[aXIdx]) {
1082 /* double the number of allocated entries */
1083 aGrid->nxalloc[aXIdx] = 2 * aGrid->nxmap[aXIdx];
1084 aGrid->xmaps[aXIdx] = cpl_realloc(aGrid->xmaps[aXIdx],
1085 aGrid->nxalloc[aXIdx]
1086 * sizeof(hdrl_resample_pixels_ext));
1087 }
1088 aGrid->xmaps[aXIdx][iext].npix = 1;
1089 aGrid->xmaps[aXIdx][iext].pix = cpl_malloc(sizeof(cpl_size));
1090 aGrid->xmaps[aXIdx][iext].pix[0] = aRow;
1091 aGrid->pix[aIndex] = -(iext + 1 + ((cpl_size)aXIdx << XMAP_LSHIFT));
1092 } else if (aGrid->pix[aIndex] > 0) {
1093 /* When a second pixel is added, put both to the extension map. */
1094 cpl_size iext = aGrid->nxmap[aXIdx]++;
1095 if (aGrid->nxmap[aXIdx] > aGrid->nxalloc[aXIdx]) {
1096 /* double the number of allocated entries */
1097 aGrid->nxalloc[aXIdx] = 2 * aGrid->nxmap[aXIdx];
1098 aGrid->xmaps[aXIdx] = cpl_realloc(aGrid->xmaps[aXIdx],
1099 aGrid->nxalloc[aXIdx]
1100 * sizeof(hdrl_resample_pixels_ext));
1101 }
1102 aGrid->xmaps[aXIdx][iext].npix = 2;
1103 aGrid->xmaps[aXIdx][iext].pix = cpl_malloc(2 * sizeof(cpl_size));
1104 aGrid->xmaps[aXIdx][iext].pix[0] = aGrid->pix[aIndex];
1105 aGrid->xmaps[aXIdx][iext].pix[1] = aRow;
1106 aGrid->pix[aIndex] = -(iext + 1 + ((cpl_size)aXIdx << XMAP_LSHIFT));
1107 } else {
1108 /* Append additional pixels to the extension map. */
1109 cpl_size iext = (-aGrid->pix[aIndex] - 1) & PT_IDX_MASK;
1110 /* index of the new entry in this grid point */
1111 unsigned int ipix = aGrid->xmaps[aXIdx][iext].npix;
1112 aGrid->xmaps[aXIdx][iext].npix++;
1113 aGrid->xmaps[aXIdx][iext].pix = cpl_realloc(aGrid->xmaps[aXIdx][iext].pix,
1114 (ipix + 1) * sizeof(cpl_size));
1115 aGrid->xmaps[aXIdx][iext].pix[ipix] = aRow;
1116 }
1117} /* hdrl_resample_pixgrid_add() */
1118
1119/*---------------------------------------------------------------------------*/
1128/*---------------------------------------------------------------------------*/
1129static inline cpl_size
1130hdrl_resample_pixgrid_get_count(hdrl_resample_pixgrid *aGrid, cpl_size aIndex)
1131{
1132 if (aIndex < 0 || aGrid == NULL) {
1133 return 0;
1134 }
1135 /* get entry in pixel grid */
1136 cpl_size p = aGrid->pix[aIndex];
1137 if (p == 0) { /* points nowhere --> no pixels */
1138 return 0;
1139 }
1140 if (p > 0) { /* points to pixel table --> 1 pixel */
1141 return 1;
1142 }
1143 /* p is negative, so points to an extension map, get its index */
1144 unsigned short ix = (-p >> XMAP_LSHIFT) & XMAP_BITMASK;
1145 p = (-p - 1) & PT_IDX_MASK;
1146 /* the npix component now gives the number of pixels in this grid index */
1147 return aGrid->xmaps[ix][p].npix;
1148} /* hdrl_resample_pixgrid_get_count() */
1149
1150/*---------------------------------------------------------------------------*/
1164/*---------------------------------------------------------------------------*/
1165static inline cpl_size
1166hdrl_resample_pixgrid_get_index(hdrl_resample_pixgrid *aGrid, cpl_size aX,
1167 cpl_size aY, cpl_size aZ, cpl_boolean aAllowOutside)
1168{
1169 if (aGrid == NULL) {
1170 return -1;
1171 }
1172 if (!aAllowOutside &&
1173 (aX < 0 || aX >= aGrid->nx || aY < 0 || aY >= aGrid->ny ||
1174 aZ < 0 || aZ >= aGrid->nz)) {
1175 return -1;
1176 }
1177 if (aX < 0) {
1178 aX = 0;
1179 }
1180 if (aX >= aGrid->nx) {
1181 aX = aGrid->nx - 1;
1182 }
1183 if (aY < 0) {
1184 aY = 0;
1185 }
1186 if (aY >= aGrid->ny) {
1187 aY = aGrid->ny - 1;
1188 }
1189 if (aZ < 0) {
1190 aZ = 0;
1191 }
1192 if (aZ >= aGrid->nz) {
1193 aZ = aGrid->nz - 1;
1194 }
1195 return aX + aGrid->nx * (aY + aGrid->ny * aZ);
1196} /* hdrl_resample_pixgrid_get_index() */
1197
1198/*---------------------------------------------------------------------------*/
1208/*---------------------------------------------------------------------------*/
1209static hdrl_resample_pixgrid *
1210hdrl_resample_pixgrid_new(cpl_size aSizeX, cpl_size aSizeY, cpl_size aSizeZ,
1211 unsigned short aNMaps)
1212{
1213 cpl_ensure(aSizeX > 0 && aSizeY > 0 && aSizeZ > 0 && aNMaps > 0,
1214 CPL_ERROR_ILLEGAL_INPUT, NULL);
1215 hdrl_resample_pixgrid *pixels = cpl_calloc(1, sizeof(hdrl_resample_pixgrid));
1216 pixels->nx = aSizeX;
1217 pixels->ny = aSizeY;
1218 pixels->nz = aSizeZ;
1219 pixels->pix = cpl_calloc(aSizeX * aSizeY * aSizeZ, sizeof(cpl_size));
1220 /* extension maps for possibly multiple threads */
1221 pixels->nmaps = aNMaps;
1222 pixels->nxalloc = cpl_calloc(aNMaps, sizeof(cpl_size));
1223 pixels->xmaps = cpl_calloc(aNMaps, sizeof(hdrl_resample_pixels_ext *));
1224 pixels->nxmap = cpl_calloc(aNMaps, sizeof(cpl_size));
1225 return pixels;
1226} /* hdrl_resample_pixgrid_new() */
1227
1228/*---------------------------------------------------------------------------*/
1261/*---------------------------------------------------------------------------*/
1262static hdrl_resample_pixgrid *
1263hdrl_resample_pixgrid_create(const cpl_table *ResTable, cpl_propertylist *aHeader,
1264 cpl_size aXSize, cpl_size aYSize, cpl_size aZSize)
1265{
1266 cpl_ensure(ResTable, CPL_ERROR_NULL_INPUT, NULL);
1267 cpl_ensure(aHeader, CPL_ERROR_NULL_INPUT, NULL);
1268 cpl_size nrow = cpl_table_get_nrow(ResTable);
1269 if (nrow == 0) {
1270 cpl_msg_error(cpl_func, "Invalid pixel table (no entries?)");
1271 cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
1272 return NULL;
1273 }
1274 cpl_ensure(aXSize > 0 && aYSize > 0 && aZSize > 0, CPL_ERROR_ILLEGAL_INPUT,
1275 NULL);
1276
1277
1278 double crval3 = hdrl_resample_pfits_get_crval(aHeader, 3),
1279 crpix3 = hdrl_resample_pfits_get_crpix(aHeader, 3),
1280 cd33 = hdrl_resample_pfits_get_cd(aHeader, 3, 3);
1281
1282 hdrl_resample_smallwcs *wcs = hdrl_resample_smallwcs_new(aHeader);
1283
1284 /* get all (relevant) table columns for easy pointer access */
1285
1286 const double *xpos = cpl_table_get_data_double_const(ResTable, HDRL_RESAMPLE_TABLE_RA),
1287 *ypos = cpl_table_get_data_double_const(ResTable, HDRL_RESAMPLE_TABLE_DEC),
1288 *lbda = cpl_table_get_data_double_const(ResTable, HDRL_RESAMPLE_TABLE_LAMBDA);
1289 if (!xpos || !ypos || !lbda) {
1290 cpl_msg_error(cpl_func, "Missing pixel table column (%p %p %p): %s",
1291 (void *)xpos, (void *)ypos, (void *)lbda,
1292 cpl_error_get_message());
1293 cpl_error_set(cpl_func, CPL_ERROR_DATA_NOT_FOUND);
1294 cpl_free(wcs);
1295 return NULL;
1296 }
1297
1298 wcs->crval1 /= CPL_MATH_DEG_RAD; /* convert to radians before calling... */
1299 wcs->crval2 /= CPL_MATH_DEG_RAD; /* ...hdrl_resample_wcs_pixel_from_celestial_fast() */
1300
1301 double timeinit = cpl_test_get_walltime(),
1302 timeprogress = timeinit,
1303 cpuinit = cpl_test_get_cputime();
1304 cpl_boolean showprogress = cpl_msg_get_level() == CPL_MSG_DEBUG
1305 || cpl_msg_get_log_level() == CPL_MSG_DEBUG;
1306
1307 /* check for the selected pixels in the pixel table, only those *
1308 * are used to construct the pixel grid; since constructing the *
1309 * array of selected pixels costs significant amounts of time, *
1310 * do that only when not all pixels are selected! */
1311 cpl_array *asel = NULL;
1312 const cpl_size *sel = NULL;
1313 cpl_size nsel = cpl_table_count_selected(ResTable);
1314 if (nsel < nrow) {
1315 asel = cpl_table_where_selected(ResTable);
1316 sel = cpl_array_get_data_cplsize_const(asel);
1317 }
1318
1319 /* can use at most XMAP_BITMASK threads so that the bitmask does not *
1320 * overflow, but ensure that we are not using more cores than available... */
1323 /* prepare the ranges for the different threads, store them in arrays */
1324 cpl_array *az1 = cpl_array_new(nth, CPL_TYPE_INT),
1325 *az2 = cpl_array_new(nth, CPL_TYPE_INT);
1326 if (aZSize < nth) {
1327 /* pre-fill arrays with values that cause the threads to do nothing */
1328 cpl_array_fill_window_int(az1, aZSize, nth, -1);
1329 cpl_array_fill_window_int(az2, aZSize, nth, -2);
1330 }
1331 /* now fill the (first) ones with real ranges */
1332 double base = nth > aZSize ? 1. : (double)aZSize / nth;
1333 cpl_size ith;
1334 for (ith = 0; ith < nth && ith < aZSize; ith++) {
1335 cpl_array_set_int(az1, ith, lround(base * ith));
1336 cpl_array_set_int(az2, ith, lround(base * (ith + 1) - 1));
1337 } /* for */
1338 /* make sure that we don't lose pixels at the edges of the wavelength *
1339 * range, put them into the extreme threads by making their ranges larger; *
1340 * set the relevant array entries to something close to the largest value, *
1341 * that we can still add as an integer (to compute the z-range) */
1342 cpl_array_set_int(az1, 0, -INT_MAX / 2 + 1);
1343 cpl_array_set_int(az2, ith - 1, INT_MAX / 2 - 1);
1344
1345 /* create the pixel grid with extension maps for threads */
1346 hdrl_resample_pixgrid *grid = hdrl_resample_pixgrid_new(aXSize, aYSize, aZSize, nth);
1347
1348 /* parallel region to fill the pixel grid */
1349
1350 struct timeval tv1, tv2;
1351
1352 cpl_msg_debug(cpl_func,"Starting parallel loop in hdrl_resample_pixgrid_create");
1353 gettimeofday(&tv1, NULL);
1354
1355#pragma omp parallel num_threads(nth) /* default(none) as req. by Ralf */ \
1356 shared(aXSize, aYSize, aZSize, az1, az2, cd33, crpix3, crval3, grid, \
1357 lbda, nsel, sel, showprogress, \
1358 timeinit, timeprogress, wcs, xpos, ypos)
1359
1360 {
1361 /* split the work up into threads, for non-overlapping wavelength ranges */
1362 unsigned short ithread = omp_get_thread_num(); /* index of this thread */
1363 int z1 = cpl_array_get_int(az1, ithread, NULL),
1364 z2 = cpl_array_get_int(az2, ithread, NULL),
1365 zrange = z2 - z1 + 1;
1366
1367 /* check if we actually need to enter the (parallel) loop, i.e. *
1368 * if the current thread is handling any wavelength planes */
1369
1370 /* now the actual parallel loop */
1371 cpl_size isel;
1372 for (isel = 0 ; zrange > 0 && isel < nsel; isel++) {
1373#pragma omp master /* only output progress from the master thread */
1374 if (showprogress && !((isel+1) % 1000000ll)) { /* output before every millionth entry */
1375 double timenow = cpl_test_get_walltime();
1376 if (timenow - timeprogress > 30.) { /* and more than half a minute passed */
1377 timeprogress = timenow;
1378 double percent = 100. * (isel + 1.) / nsel,
1379 elapsed = timeprogress - timeinit,
1380 remaining = (100. - percent) * elapsed / percent;
1381 /* overwritable only exists for INFO mode, but we check *
1382 * above that we want this only for DEBUG mode output... */
1383 cpl_msg_info_overwritable(cpl_func, "pixel grid creation is %.1f%% "
1384 "complete, %.1fs elapsed, ~%.1fs remaining",
1385 percent, elapsed, remaining);
1386 } /* if: 1/2 min passed */
1387 } /* if: want debug output */
1388
1389 /* either use the index from the array of selected rows *
1390 * or the row numberdirectly (for a fully selected table) */
1391 cpl_size n = sel ? sel[isel] : isel;
1392 int z = -1;
1393
1394 z = lround((lbda[n] - crval3) / cd33 + crpix3) - 1;
1395
1396 if (z < z1 || z > z2) {
1397 continue; /* skip this entry, one of the other threads handles it */
1398 }
1399
1400 /* determine the pixel coordinates in the grid (indices, starting at 0) */
1401 double xpx = 0., ypx = 0.;
1402
1403 hdrl_resample_wcs_pixel_from_celestial_fast(wcs, (xpos[n]) / CPL_MATH_DEG_RAD,
1404 (ypos[n]) / CPL_MATH_DEG_RAD,
1405 &xpx, &ypx);
1406
1407 int x = lround(xpx) - 1,
1408 y = lround(ypx) - 1;
1409 cpl_size idx = hdrl_resample_pixgrid_get_index(grid, x, y, z, CPL_TRUE);
1410
1411
1412 /* write the pixel values to the correct place in the grid */
1413 hdrl_resample_pixgrid_add(grid, idx, n, ithread);
1414 } /* for isel (all selected pixel table rows) */
1415
1416 /* Clean up the possibly too many allocations; this is not strictly *
1417 * needed but nice to only consume as much memory as we need. */
1418 grid->xmaps[ithread] = cpl_realloc(grid->xmaps[ithread],
1419 grid->nxmap[ithread]
1420 * sizeof(hdrl_resample_pixels_ext));
1421 grid->nxalloc[ithread] = grid->nxmap[ithread];
1422 } /* omp parallel */
1423
1424 gettimeofday(&tv2, NULL);
1425 cpl_msg_debug(cpl_func, "Wall time for hdrl_resample_pixgrid_create was %f seconds\n",
1426 (double) (tv2.tv_usec - tv1.tv_usec) / 1000000 +
1427 (double) (tv2.tv_sec - tv1.tv_sec));
1428
1429 cpl_array_delete(asel);
1430 cpl_free(wcs);
1431 cpl_array_delete(az1);
1432 cpl_array_delete(az2);
1433
1434
1435 cpl_size idx, npix = 0;
1436 for (idx = 0; idx < aXSize * aYSize * aZSize; idx++) {
1437 npix += hdrl_resample_pixgrid_get_count(grid, idx);
1438 }
1439 cpl_size nxmap = 0;
1440 for (idx = 0; idx < (cpl_size)grid->nmaps; idx++) {
1441 nxmap += grid->nxmap[idx];
1442 }
1443 if (npix != nsel) {
1444 char *msg = cpl_sprintf("Pixels got lost while creating the cube (input "
1445 "pixel table: %"CPL_SIZE_FORMAT", output pixel grid"
1446 ": %"CPL_SIZE_FORMAT")", nsel, npix);
1447 cpl_msg_error(cpl_func, "%s:", msg);
1448 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT, "%s!", msg);
1449 cpl_free(msg);
1450 }
1451 double timefini = cpl_test_get_walltime(),
1452 cpufini = cpl_test_get_cputime();
1453 cpl_msg_debug(cpl_func, "pixel grid: %dx%dx%d, %"CPL_SIZE_FORMAT" pixels "
1454 "total, %"CPL_SIZE_FORMAT" (%.1f%%) in %hu extension maps; took"
1455 " %gs (wall-clock) and %gs (CPU) to create", (int)grid->nx,
1456 (int)grid->ny, (int)grid->nz, npix, nxmap,
1457 (double)nxmap / npix * 100., grid->nmaps, timefini - timeinit,
1458 cpufini - cpuinit);
1459
1460 return grid;
1461} /* hdrl_resample_pixgrid_create() */
1462
1463/*----------------------------------------------------------------------------*/
1483/*----------------------------------------------------------------------------*/
1484static cpl_error_code
1485hdrl_resample_wcs_get_scales(hdrl_resample_outgrid_parameter *aParams_outputgrid,
1486 double *aXScale, double *aYScale)
1487{
1488 cpl_ensure_code(aParams_outputgrid && aXScale && aYScale, CPL_ERROR_NULL_INPUT);
1489
1490 cpl_errorstate prestate = cpl_errorstate_get();
1491
1492 const cpl_matrix *cd = cpl_wcs_get_cd(aParams_outputgrid->wcs);
1493 //double cd11 = aParams_outputgrid->limits.cd11;
1494 //double cd22 = aParams_outputgrid->limits.cd22;
1495 //double cd12 = aParams_outputgrid->limits.cd12;
1496 //double cd21 = aParams_outputgrid->limits.cd21;
1497 double cd11 = cpl_matrix_get(cd, 0, 0);
1498 double cd12 = cpl_matrix_get(cd, 0, 1);
1499 double cd21 = cpl_matrix_get(cd, 1, 0);
1500 double cd22 = cpl_matrix_get(cd, 1, 1);
1501
1502
1503 double det = cd11 * cd22 - cd12 * cd21;
1504 cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
1505
1506 if (det < 0.) {
1507 cd12 *= -1;
1508 cd11 *= -1;
1509 }
1510 if (cd12 == 0. && cd21 == 0.) { /* matrix without rotation */
1511 *aXScale = cd11;
1512 *aYScale = cd22;
1513 return CPL_ERROR_NONE;
1514 }
1515 *aXScale = sqrt(cd11*cd11 + cd12*cd12); /* only the absolute value */
1516 *aYScale = sqrt(cd22*cd22 + cd21*cd21);
1517 return CPL_ERROR_NONE;
1518} /* hdrl_resample_wcs_get_scales() */
1519/*---------------------------------------------------------------------------*/
1528/*---------------------------------------------------------------------------*/
1529static inline const cpl_size *
1530hdrl_resample_pixgrid_get_rows(hdrl_resample_pixgrid *aGrid, cpl_size aIndex)
1531{
1532
1533 cpl_ensure(aGrid , CPL_ERROR_NULL_INPUT, 0);
1534 cpl_ensure(aIndex >= 0 , CPL_ERROR_ILLEGAL_INPUT, 0);
1535 cpl_ensure(aIndex < aGrid->nx * aGrid->ny * aGrid->nz, CPL_ERROR_ILLEGAL_INPUT, 0);
1536 /* get entry in pixel grid */
1537 cpl_size p = aGrid->pix[aIndex];
1538 if (p == 0) { /* points nowhere --> no array */
1539 return NULL;
1540 }
1541 if (p > 0) { /* points to pixel table */
1542 return aGrid->pix + aIndex;
1543 }
1544 /* p is negative, so points to an extension map, get its array */
1545 unsigned short ix = (-p >> XMAP_LSHIFT) & XMAP_BITMASK;
1546 p = (-p - 1) & PT_IDX_MASK;
1547 /* the pix component provides the array of pixel table rows in this index */
1548 return aGrid->xmaps[ix][p].pix;
1549} /* hdrl_resample_pixgrid_get_rows() */
1550
1551
1552/*---------------------------------------------------------------------------*/
1569/*---------------------------------------------------------------------------*/
1570static cpl_error_code
1571hdrl_resample_cube_nearest(hdrl_resample_result *aCube, const cpl_table *ResTable,
1572 hdrl_resample_pixgrid *aGrid,
1573 hdrl_resample_outgrid_parameter *aParams_outputgrid)
1574{
1575 cpl_ensure_code(aCube && ResTable && aGrid && aParams_outputgrid,
1576 CPL_ERROR_NULL_INPUT);
1577 cpl_ensure_code(cpl_propertylist_has(aCube->header,"CRVAL3") == 1,
1578 CPL_ERROR_ILLEGAL_INPUT);
1579 cpl_ensure_code(cpl_propertylist_has(aCube->header,"CRPIX3") == 1,
1580 CPL_ERROR_ILLEGAL_INPUT);
1581 cpl_ensure_code(cpl_propertylist_has(aCube->header,"CD3_3") == 1,
1582 CPL_ERROR_ILLEGAL_INPUT);
1583
1584 double crval3 = hdrl_resample_pfits_get_crval(aCube->header, 3);
1585 double crpix3 = hdrl_resample_pfits_get_crpix(aCube->header, 3);
1586 double cd33 = hdrl_resample_pfits_get_cd(aCube->header, 3, 3);
1587 cpl_ensure_code(cd33 != 0, CPL_ERROR_ILLEGAL_INPUT);
1588
1589 cpl_wcs *wcscpl = cpl_wcs_new_from_propertylist(aCube->header);
1590
1591 if (hdrl_resample_inputtable_verify(ResTable)) {
1592 return CPL_ERROR_ILLEGAL_INPUT;
1593 }
1594
1595
1596 const double *xpos = cpl_table_get_data_double_const(ResTable, HDRL_RESAMPLE_TABLE_RA),
1597 *ypos = cpl_table_get_data_double_const(ResTable, HDRL_RESAMPLE_TABLE_DEC),
1598 *lbda = cpl_table_get_data_double_const(ResTable, HDRL_RESAMPLE_TABLE_LAMBDA),
1599 *data = cpl_table_get_data_double_const(ResTable, HDRL_RESAMPLE_TABLE_DATA),
1600 *stat = cpl_table_get_data_double_const(ResTable, HDRL_RESAMPLE_TABLE_ERRORS);
1601 const int *dq = cpl_table_get_data_int_const(ResTable, HDRL_RESAMPLE_TABLE_BPM);
1602
1603 /* If our data was astrometrically calibrated, we need to scale the *
1604 * data units to the pixel size in all three dimensions so that the *
1605 * radius computation works again. *
1606 * Otherwise dx~5.6e-5deg won't contribute to the weighting at all. */
1607
1608 double xnorm = 1., ynorm = 1., znorm = 1. ;
1609
1610
1611 hdrl_resample_wcs_get_scales(aParams_outputgrid, &xnorm, &ynorm);
1612 //TODO: we should check that xnorm, ynorm, znorm are not zero
1613 xnorm = 1. / xnorm;
1614 ynorm = 1. / ynorm;
1615 //znorm = 1. / aParams_outputgrid->limits.cd33;
1616 const cpl_matrix *cd = cpl_wcs_get_cd(aParams_outputgrid->wcs);
1617 if (cpl_matrix_get_ncol(cd) == 3) {
1618 znorm = 1. / cpl_matrix_get(cd, 2, 2);
1619 }
1620/*
1621 cpl_msg_debug(cpl_func, "Norm factors from wcs - xnorm: %g ynorm: %g znorm: %g",
1622 xnorm, ynorm, znorm);
1623 need to use the real coordinate offset for celestial spherical
1624 // We are now working with the full astrometric solution
1625 //ptxoff = hdrl_resample_pfits_get_crval(ResTable->header, 1);
1626 //ptyoff = hdrl_resample_pfits_get_crval(ResTable->header, 2);
1627*/
1628
1629 struct timeval tv1, tv2;
1630 cpl_msg_debug(cpl_func,"Starting parallel loop in hdrl_resample_cube_nearest");
1631 gettimeofday(&tv1, NULL);
1632
1633#pragma omp parallel for default(none) /* as req. by Ralf */ \
1634 shared(aCube, aGrid, cd33, crpix3, crval3, data, dq, lbda, \
1635 stat, stdout, wcscpl, \
1636 xnorm, xpos, ynorm, ypos, znorm) collapse(2)
1637
1638 for (cpl_size l = 0; l < aGrid->nz; l++) {
1639 for (cpl_size i = 0; i < aGrid->nx; i++) {
1640 double *pdata = cpl_image_get_data_double(hdrl_image_get_image(hdrl_imagelist_get(aCube->himlist, l)));
1641 double *pstat = cpl_image_get_data_double(hdrl_image_get_error(hdrl_imagelist_get(aCube->himlist, l)));
1642 cpl_binary *pdq = cpl_mask_get_data(hdrl_image_get_mask(hdrl_imagelist_get(aCube->himlist, l)));
1643 /* wavelength of center of current grid cell (l is index starting at 0) */
1644 double lambda = (l + 1. - crpix3) * cd33 + crval3;
1645
1646 cpl_size j;
1647 for (j = 0; j < aGrid->ny; j++) {
1648 cpl_size idx = hdrl_resample_pixgrid_get_index(aGrid, i, j, l, CPL_FALSE),
1649 n_rows = hdrl_resample_pixgrid_get_count(aGrid, idx);
1650 const cpl_size *rows = hdrl_resample_pixgrid_get_rows(aGrid, idx);
1651
1652 /* x and y position of center of current grid cell (i, j start at 0) */
1653 double x = 0., y = 0.;
1654
1655 // We are now working with the full astrometric solution
1656 // hdrl_resample_wcs_celestial_from_pixel_fast(wcs, i + 1, j + 1, &x, &y);
1657 hdrl_wcs_xy_to_radec(wcscpl, i + 1, j + 1, &x, &y);
1658
1659 if (n_rows == 1) {
1660 if ((cpl_binary)dq[rows[0]] == CPL_BINARY_0) {
1661 /* if there is only one pixel in the cell, just use it */
1662 pdata[i + j * aGrid->nx] = data[rows[0]];
1663 pstat[i + j * aGrid->nx] = stat[rows[0]];
1664 pdq[i + j * aGrid->nx] = (cpl_binary)dq[rows[0]];
1665 } else {
1666 pdq[i + j * aGrid->nx] = CPL_BINARY_1;
1667 }
1668 } else if (n_rows >= 2) {
1669 /* loop through all available values and take the closest one */
1670 cpl_size n, nbest = -1;
1671 double dbest = FLT_MAX; /* some unlikely large value to start with*/
1672 for (n = 0; n < n_rows; n++) {
1673 /* do not use bad pixels */
1674 if((cpl_binary)dq[rows[n]] != CPL_BINARY_0) {
1675 continue;
1676 }
1677 /* the differences for the cell center and the current pixel */
1678 double dx = fabs(x - xpos[rows[n]]) * xnorm,
1679 dy = fabs(y - ypos[rows[n]]) * ynorm,
1680 dlambda = fabs(lambda - lbda[rows[n]]) * znorm,
1681 dthis = sqrt(dx*dx + dy*dy + dlambda*dlambda);
1682
1683 /* Not strictly necessary for NN, but still scale the RA *
1684 * distance properly, see hdrl_resample_cube_weighted(). */
1685 dx *= cos(y * CPL_MATH_RAD_DEG);
1686
1687 if (dthis < dbest) {
1688 nbest = n;
1689 dbest = dthis;
1690 }
1691 }
1692 if (nbest >= 0) { /* We found a good nearest neighbor */
1693 pdata[i + j * aGrid->nx] = data[rows[nbest]];
1694 pstat[i + j * aGrid->nx] = stat[rows[nbest]];
1695 pdq[i + j * aGrid->nx] = (cpl_binary)dq[rows[nbest]];
1696 }
1697 } else {
1698 /* npix == 0: do nothing, pixel stays zero */
1699 pdq[i + j * aGrid->nx] = CPL_BINARY_1;
1700 }
1701 } /* for j (y direction) */
1702 } /* for i (x direction) */
1703 } /* for l (wavelength planes) */
1704
1705 gettimeofday(&tv2, NULL);
1706 cpl_msg_debug(cpl_func, "Wall time for hdrl_resample_cube_nearest was %f seconds\n",
1707 (double) (tv2.tv_usec - tv1.tv_usec) / 1000000 +
1708 (double) (tv2.tv_sec - tv1.tv_sec));
1709
1710 /* Make sure that the bpm of the image and the error are in sinc as we are
1711 * working with pointers */
1712 cpl_size size = hdrl_imagelist_get_size(aCube->himlist);
1713 for(cpl_size i = 0; i < size; i++){
1714 /* sync image and error bpm ignoring what is in error before */
1715 cpl_image_reject_from_mask(hdrl_image_get_error(hdrl_imagelist_get(aCube->himlist, i)),
1717 }
1718
1719 cpl_wcs_delete(wcscpl);
1720
1721 return CPL_ERROR_NONE;
1722} /* hdrl_resample_cube_nearest() */
1723
1724/*---------------------------------------------------------------------------*/
1737/*---------------------------------------------------------------------------*/
1738static inline double
1739hdrl_resample_weight_function_renka(double r, double r_c)
1740{
1741 if (r == 0) {
1742 return FLT_MAX;
1743 } else if (r >= r_c) {
1744 return DBL_MIN;
1745 } else {
1746 double p = (r_c - r) / (r_c * r);
1747 return p*p;
1748 }
1749} /* hdrl_resample_weight_function_renka() */
1750
1751/*---------------------------------------------------------------------------*/
1770/*---------------------------------------------------------------------------*/
1771static inline double
1772hdrl_resample_weight_function_drizzle(double xin, double yin, double zin,
1773 double xout, double yout, double zout,
1774 double dx, double dy, double dz)
1775{
1776 /* compute the three terms in the numerator: if the offset *
1777 * plus the output halfsize is less than the input halfsize, *
1778 * then that side is fully contained in the input pixel */
1779 double x = (dx + xout / 2.) <= xin / 2. ? xout : (xin + xout) / 2. - dx,
1780 y = (dy + yout / 2.) <= yin / 2. ? yout : (yin + yout) / 2. - dy,
1781 z = (dz + zout / 2.) <= zin / 2. ? zout : (zin + zout) / 2. - dz;
1782 /* any negative value means that the input pixel is completely *
1783 * outside the target voxel, so it doesn't contribute */
1784 if (x <= 0 || y <= 0 || z <= 0) {
1785 return 0.;
1786 }
1787 /* any value > input size means this dimension of the input pixel *
1788 * is completely inside the target voxel, so that's the limit! */
1789 return (x > xin ? xin : x) * (y > yin ? yin : y) * (z > zin ? zin : z)
1790 / (xin * yin * zin);
1791} /* hdrl_resample_weight_function_drizzle() */
1792
1793
1794/*---------------------------------------------------------------------------*/
1805/*---------------------------------------------------------------------------*/
1806static inline double
1807hdrl_resample_weight_function_linear(double r)
1808{
1809 return r == 0 ? FLT_MAX : 1. / r;
1810} /* hdrl_resample_weight_function_linear() */
1811
1812/*---------------------------------------------------------------------------*/
1823/*---------------------------------------------------------------------------*/
1824static inline double
1825hdrl_resample_weight_function_quadratic(double r2)
1826{
1827 return r2 == 0 ? FLT_MAX : 1. / r2;
1828} /* hdrl_resample_weight_function_quadratic() */
1829
1830/*---------------------------------------------------------------------------*/
1837/*---------------------------------------------------------------------------*/
1838static inline double
1839hdrl_resample_weight_function_sinc(double r)
1840{
1841 return fabs(r) < DBL_EPSILON ? 1. : sin(CPL_MATH_PI * r) / (CPL_MATH_PI * r);
1842} /* hdrl_resample_weight_function_sinc() */
1843
1844/*---------------------------------------------------------------------------*/
1855/*---------------------------------------------------------------------------*/
1856static inline double
1857hdrl_resample_weight_function_lanczos(double dx, double dy, double dz,
1858 unsigned int ld, unsigned int lks)
1859{
1860 /* Adding 0.5 as for a loop distance of 0 the weight should only drop to 0 if
1861 * the distance is larger then half the pixel */
1862 return (fabs(dx) >= (ld + 0.5) || fabs(dy) >= (ld + 0.5) || fabs(dz) > (ld + 0.5)) ? 0.
1863 : hdrl_resample_weight_function_sinc(dx) * hdrl_resample_weight_function_sinc(dx / lks)
1864 * hdrl_resample_weight_function_sinc(dy) * hdrl_resample_weight_function_sinc(dy / lks)
1865 * hdrl_resample_weight_function_sinc(dz) * hdrl_resample_weight_function_sinc(dz / lks);
1866} /* hdrl_resample_weight_function_lanczos() */
1867
1868/*---------------------------------------------------------------------------*/
1890/*---------------------------------------------------------------------------*/
1891static cpl_error_code
1892hdrl_resample_cube_weighted(hdrl_resample_result *aCube,
1893 const cpl_table *ResTable,
1894 hdrl_resample_pixgrid *aGrid,
1895 hdrl_resample_method_parameter *aParams_method,
1896 hdrl_resample_outgrid_parameter *aParams_outputgrid)
1897{
1898
1899 cpl_ensure_code(aCube && ResTable && aGrid && aParams_method &&
1900 aParams_outputgrid, CPL_ERROR_NULL_INPUT);
1901 cpl_ensure_code(cpl_propertylist_has(aCube->header,"CRVAL3") == 1,
1902 CPL_ERROR_ILLEGAL_INPUT);
1903 cpl_ensure_code(cpl_propertylist_has(aCube->header,"CRPIX3") == 1,
1904 CPL_ERROR_ILLEGAL_INPUT);
1905 cpl_ensure_code(cpl_propertylist_has(aCube->header,"CD3_3") == 1,
1906 CPL_ERROR_ILLEGAL_INPUT);
1907
1908 double crval3 = hdrl_resample_pfits_get_crval(aCube->header, 3),
1909 crpix3 = hdrl_resample_pfits_get_crpix(aCube->header, 3),
1910 cd33 = hdrl_resample_pfits_get_cd(aCube->header, 3, 3);
1911
1912 hdrl_resample_smallwcs *wcs = hdrl_resample_smallwcs_new(aCube->header);
1913 cpl_wcs *wcscpl = cpl_wcs_new_from_propertylist(aCube->header);
1914
1915 const double *xpos = cpl_table_get_data_double_const(ResTable, HDRL_RESAMPLE_TABLE_RA),
1916 *ypos = cpl_table_get_data_double_const(ResTable, HDRL_RESAMPLE_TABLE_DEC),
1917 *lbda = cpl_table_get_data_double_const(ResTable, HDRL_RESAMPLE_TABLE_LAMBDA),
1918 *data = cpl_table_get_data_double_const(ResTable, HDRL_RESAMPLE_TABLE_DATA),
1919 *stat = cpl_table_get_data_double_const(ResTable, HDRL_RESAMPLE_TABLE_ERRORS);
1920 const int *dq = cpl_table_get_data_int_const(ResTable, HDRL_RESAMPLE_TABLE_BPM);
1921
1922 /* If our data was astrometrically calibrated, we need to scale the *
1923 * data units to the pixel size in all three dimensions so that the *
1924 * radius computation works again. *
1925 * Otherwise dx~5.6e-5deg won't contribute to the weighting at all. */
1926
1927 double xnorm = 1., ynorm = 1., znorm = 1. ;
1928
1929 hdrl_resample_wcs_get_scales(aParams_outputgrid, &xnorm, &ynorm);
1930 xnorm = 1. / xnorm;
1931 ynorm = 1. / ynorm;
1932 //znorm = 1. / aParams_outputgrid->limits.cd33;
1933 const cpl_matrix *cd = cpl_wcs_get_cd(aParams_outputgrid->wcs);
1934 if (cpl_matrix_get_ncol(cd) == 3) {
1935 znorm = 1. / cpl_matrix_get(cd, 2, 2);
1936 }
1937/*
1938 cpl_msg_debug(cpl_func, "Norm factors from wcs - xnorm: %g ynorm: %g znorm: %g",
1939 xnorm, ynorm, znorm);
1940 need to use the real coordinate offset for celestial spherical
1941 // We are now working with the full astrometric solution
1942 //ptxoff = hdrl_resample_pfits_get_crval(ResTable->header, 1);
1943 //ptyoff = hdrl_resample_pfits_get_crval(ResTable->header, 2);
1944*/
1945
1946
1947 /* scale the input critical radius by the voxel radius */
1948 double renka_rc = aParams_method->renka_critical_radius /*beware of rotation! */
1949 * sqrt((wcs->cd11*xnorm)*(wcs->cd11*xnorm)
1950 + (wcs->cd22*ynorm)*(wcs->cd22*ynorm)
1951 + (cd33*znorm)*(cd33*znorm));
1952
1953 /* loop distance (to take into account surrounding pixels) verification */
1954 int ld = aParams_method->loop_distance;
1955 if (ld < 0) {
1956 ld = 0;
1957 cpl_msg_debug(cpl_func, "Overriding loop distance ld=%d", ld);
1958 }
1959
1960 /* Lankzos kernel size (lks) verification */
1961 int lks = aParams_method->lanczos_kernel_size;
1962 if (lks <= 0) {
1963 lks = 1;
1964 cpl_msg_debug(cpl_func, "Overriding lanczos kernel size lks=%d", lks);
1965 }
1966
1967 /* Should 1/variance be used as an additional weight */
1968 cpl_boolean wght = aParams_method->use_errorweights;
1969
1970 /* pixel sizes in all three directions, scaled by pixfrac, and *
1971 * output pixel sizes (absolute values), as needed for drizzle */
1972 double xsz = aParams_method->drizzle_pix_frac_x / xnorm,
1973 ysz = aParams_method->drizzle_pix_frac_y / ynorm,
1974 zsz = aParams_method->drizzle_pix_frac_lambda / znorm,
1975 xout = fabs(wcs->cd11), yout = fabs(wcs->cd22), zout = fabs(cd33);
1976
1977 struct timeval tv1, tv2;
1978 cpl_msg_debug(cpl_func,"Starting parallel loop in hdrl_resample_cube_weighted");
1979 gettimeofday(&tv1, NULL);
1980
1981#pragma omp parallel for default(none) /* as req. by Ralf */ \
1982 shared(aCube, aParams_method, aParams_outputgrid, aGrid, ResTable, cd33, crpix3, crval3, data, \
1983 dq, lbda, ld, lks, renka_rc, stat, \
1984 stdout, wcs, wcscpl, wght, xnorm, xout, xpos, xsz, ynorm, yout,\
1985 ypos, ysz, znorm, zout, zsz) collapse(2)
1986
1987 for (cpl_size l = 0; l < aGrid->nz; l++) {
1988 for (cpl_size i = 0; i < aGrid->nx; i++) {
1989 double *pdata = cpl_image_get_data_double(hdrl_image_get_image(hdrl_imagelist_get(aCube->himlist, l)));
1990 double *pstat = cpl_image_get_data_double(hdrl_image_get_error(hdrl_imagelist_get(aCube->himlist, l)));
1991 cpl_binary *pdq = cpl_mask_get_data(hdrl_image_get_mask(hdrl_imagelist_get(aCube->himlist, l)));
1992
1993 /* wavelength of center of current grid cell (l is index starting at 0) */
1994 double lambda = (l + 1. - crpix3) * cd33 + crval3;
1995 double zout2 = zout; /* correct the output pixel size for log-lambda */
1996
1997 for (cpl_size j = 0; j < aGrid->ny; j++) {
1998 /* x and y position of center of current grid cell (i, j start at 0) */
1999 double x, y;
2000
2001 // We are now working with the full astrometric solution
2002 // hdrl_resample_wcs_celestial_from_pixel_fast(wcs, i + 1, j + 1, &x, &y);
2003 hdrl_wcs_xy_to_radec(wcscpl, i + 1, j + 1, &x, &y);
2004 //cpl_msg_debug(cpl_func,"case1 i %d j %d x %10.7f y %10.7f ",i+1,j+1,x,y);
2005
2006 double sumdata = 0, sumstat = 0, sumweight = 0;
2007 cpl_size npoints = 0;
2008
2009 /* loop through surrounding cells and their contained pixels */
2010 cpl_size i2;
2011 for (i2 = i - ld; i2 <= i + ld; i2++) {
2012 cpl_size j2;
2013 for (j2 = j - ld; j2 <= j + ld; j2++) {
2014 cpl_size l2;
2015 for (l2 = l - ld; l2 <= l + ld; l2++) {
2016 cpl_size idx2 = hdrl_resample_pixgrid_get_index(aGrid, i2, j2, l2, CPL_FALSE);
2017 if (idx2 < 0) continue;
2018 cpl_size n_rows2 = hdrl_resample_pixgrid_get_count(aGrid, idx2);
2019
2020 const cpl_size *rows2 = hdrl_resample_pixgrid_get_rows(aGrid, idx2);
2021 cpl_size n;
2022 for (n = 0; n < n_rows2; n++) {
2023 if (dq[rows2[n]]) { /* exclude all bad pixels */
2024
2025 continue;
2026 }
2027
2028 double dx = fabs(x - (xpos[rows2[n]])),
2029 dy = fabs(y - (ypos[rows2[n]])),
2030 dlambda = fabs(lambda - lbda[rows2[n]]),
2031 r2 = 0;
2032
2033 /* Since the distances of RA in degrees get larger the *
2034 * closer we get to the celestial pole, we have to *
2035 * compensate for that by multiplying the distance in *
2036 * RA by cos(delta), to make it comparable to the *
2037 * distances in pixels for the different kernels below. */
2038
2039 // We are now working with the full astrometric solution
2040 dx *= cos(y * CPL_MATH_RAD_DEG);
2041
2042 if (aParams_method->method != HDRL_RESAMPLE_METHOD_DRIZZLE) {
2043 dx *= xnorm;
2044 dy *= ynorm;
2045 dlambda *= znorm;
2046 r2 = dx * dx + dy * dy + dlambda * dlambda;
2047 //cpl_msg_debug(cpl_func,"n %lld dx %10.7f dy %10.7f dlambda %10.7f",n,dx,dy,dlambda);
2048 }
2049 double weight = 0.;
2050 if (aParams_method->method == HDRL_RESAMPLE_METHOD_RENKA) {
2051 weight = hdrl_resample_weight_function_renka(sqrt(r2), renka_rc);
2052 } else if (aParams_method->method == HDRL_RESAMPLE_METHOD_DRIZZLE) {
2053 weight = hdrl_resample_weight_function_drizzle(xsz, ysz, zsz,
2054 xout, yout, zout2,
2055 dx, dy, dlambda);
2056 } else if (aParams_method->method == HDRL_RESAMPLE_METHOD_LINEAR) {
2057
2058 weight = hdrl_resample_weight_function_linear(sqrt(r2));
2059 //cpl_msg_debug(cpl_func,"r2=%10.7f weight=%10.7f",r2,weight);
2060 } else if (aParams_method->method == HDRL_RESAMPLE_METHOD_QUADRATIC) {
2061 weight = hdrl_resample_weight_function_quadratic(r2);
2062 } else if (aParams_method->method == HDRL_RESAMPLE_METHOD_LANCZOS) {
2063 weight = hdrl_resample_weight_function_lanczos(dx, dy,
2064 dlambda, ld, lks);
2065 }
2066
2067 if (wght && stat[rows2[n]] > 0.) { /* User wants to weight by 1/variance */
2068 /* apply it on top of the weight computed here */
2069 weight /= (stat[rows2[n]] * stat[rows2[n]]);
2070 }
2071
2072 sumweight += weight;
2073 sumdata += data[rows2[n]] * weight;
2074 sumstat += stat[rows2[n]] * stat[rows2[n]] * weight * weight;
2075 npoints++;
2076
2077 } /* for n (all pixels in grid cell) */
2078 } /* for l2 (lambda direction) */
2079 } /* for j2 (y direction) */
2080 } /* for i2 (x direction) */
2081
2082
2083 /* if no points were found, we cannot divide by the summed weight *
2084 * and don't need to set the output pixel value (it's 0 already), *
2085 * only set the relevant Euro3D bad pixel flag
2086 * In some cases only sumweight * sumweight is really zero so this
2087 * check was additionally added for the error propagation part*/
2088
2089 if (!npoints || !isnormal(sumweight) || !isnormal(sumweight * sumweight)) {
2090 pdq[i + j * aGrid->nx] = CPL_BINARY_1;
2091 continue;
2092 }
2093
2094 /* divide results by weight of summed pixels */
2095 sumdata /= sumweight;
2096 sumstat /= sumweight * sumweight;
2097
2098 pdata[i + j * aGrid->nx] = sumdata;
2099 /* Going back from variance to errors */
2100 pstat[i + j * aGrid->nx] = sqrt(sumstat);
2101 pdq[i + j * aGrid->nx] = CPL_BINARY_0; /* now we can mark it as good */
2102
2103 } /* for j (y direction) */
2104 } /* for i (x direction) */
2105 } /* for l (wavelength planes) */
2106
2107 gettimeofday(&tv2, NULL);
2108 cpl_msg_debug(cpl_func, "Wall time for hdrl_resample_cube_weighted was %f seconds\n",
2109 (double) (tv2.tv_usec - tv1.tv_usec) / 1000000 +
2110 (double) (tv2.tv_sec - tv1.tv_sec));
2111
2112 /* Make sure that the bpm of the image and the error are in sinc as we are
2113 * working with pointers */
2114 cpl_size size = hdrl_imagelist_get_size(aCube->himlist);
2115 for(cpl_size i = 0; i < size; i++){
2116 /* sync image and error bpm ignoring what is in error before */
2117 cpl_image_reject_from_mask(hdrl_image_get_error(hdrl_imagelist_get(aCube->himlist, i)),
2119 }
2120
2121 cpl_free(wcs);
2122 cpl_wcs_delete(wcscpl);
2123
2124 return CPL_ERROR_NONE;
2125} /* hdrl_resample_cube_weighted() */
2126/*---------------------------------------------------------------------------*/
2145/*---------------------------------------------------------------------------*/
2146static cpl_error_code hdrl_resampling_set_outputgrid (
2147 int xsize, int ysize, int zsize, hdrl_resample_result *cube,
2148 hdrl_resample_outgrid_parameter *aParams_outputgrid)
2149{
2150 cpl_ensure_code(xsize > 0, CPL_ERROR_ILLEGAL_INPUT);
2151 cpl_ensure_code(ysize > 0,CPL_ERROR_ILLEGAL_INPUT);
2152 cpl_ensure_code(zsize >= 0, CPL_ERROR_ILLEGAL_INPUT);
2153
2154 cpl_ensure_code(cube && aParams_outputgrid, CPL_ERROR_NULL_INPUT);
2155 /* TODO: cube->header may be already allocated. In this case why a new and
2156 * not an over-write of the content?
2157 */
2158 cube->header = cpl_propertylist_new ();
2159 hdrl_wcs_to_propertylist (aParams_outputgrid->wcs, cube->header,
2160 FALSE);
2161
2162 cpl_propertylist_update_string (cube->header, "CTYPE1", "RA---TAN");
2163 cpl_propertylist_update_string (cube->header, "CTYPE2", "DEC--TAN");
2164 cpl_propertylist_set_comment(cube->header, "CTYPE1", "Gnomonic projection");
2165 cpl_propertylist_set_comment(cube->header, "CTYPE2", "Gnomonic projection");
2166
2167
2168
2169 /* set NAXIS for later handling of the WCS */
2170 cpl_propertylist_update_int (cube->header, "NAXIS", 3);
2171 cpl_propertylist_update_int (cube->header, "NAXIS1", xsize);
2172 cpl_propertylist_update_int (cube->header, "NAXIS2", ysize);
2173 cpl_propertylist_update_int (cube->header, "NAXIS3", zsize);
2174 /* if pixel table was astrometrically calibrated, use its WCS headers *
2175 * Axis 1: x or RA, axis 2: y or DEC, axis 3: lambda
2176 *
2177 * */
2178 cpl_propertylist_update_double (cube->header, "CD1_1",
2179 -aParams_outputgrid->delta_ra);
2180 cpl_propertylist_update_double (cube->header, "CD2_2",
2181 aParams_outputgrid->delta_dec);
2182 cpl_propertylist_update_double (cube->header, "CD1_2", 0.);
2183 cpl_propertylist_update_double (cube->header, "CD2_1", 0.);
2184
2185 double ramin = aParams_outputgrid->ra_min;
2186 double ramax = aParams_outputgrid->ra_max;
2187 double decmin = aParams_outputgrid->dec_min;
2188 double decmax = aParams_outputgrid->dec_max;
2189
2190 /* Following swarp we put CRPIX and CRVAL to the center of the field */
2191 cpl_propertylist_update_double(cube->header, "CRPIX1", (double)((xsize + 1) / 2.));
2192 cpl_propertylist_update_double(cube->header, "CRPIX2", (double)((ysize + 1) / 2.));
2193
2194 if(ramax - ramin < 180) {
2195 /* To be checked: Both values are in 0 - 180 or 180 - 360 */
2196 cpl_propertylist_update_double(cube->header, "CRVAL1", (ramin + ramax) / 2.);
2197 } else {
2198 double diff1 = 360. - ramax;
2199 double diff2 = ramin - 0.;
2200 if (diff1 < diff2) {
2201 cpl_propertylist_update_double(cube->header, "CRVAL1", ramin - (diff1 + diff2) / 2);
2202 } else {
2203 cpl_propertylist_update_double(cube->header, "CRVAL1", ramax + (diff1 + diff2) / 2.);
2204 }
2205 }
2206 cpl_propertylist_update_double(cube->header, "CRVAL2", (decmin + decmax) / 2.);
2207 cpl_propertylist_update_double (cube->header, "CD3_3",
2208 aParams_outputgrid->delta_lambda);
2209 cpl_propertylist_update_double (cube->header, "CRPIX3", 1.);
2210 cpl_propertylist_update_double (cube->header, "CRVAL3",
2211 aParams_outputgrid->lambda_min);
2212 /* fill in empty cross-terms of the CDi_j matrix */
2213 cpl_propertylist_update_double (cube->header, "CD1_3", 0.);
2214 cpl_propertylist_update_double (cube->header, "CD2_3", 0.);
2215 cpl_propertylist_update_double (cube->header, "CD3_1", 0.);
2216 cpl_propertylist_update_double (cube->header, "CD3_2", 0.);
2217
2218 return cpl_error_get_code();
2219}
2220
2221/*---------------------------------------------------------------------------*/
2275/*---------------------------------------------------------------------------*/
2276static hdrl_resample_result *
2277hdrl_resample_cube(const cpl_table *ResTable,
2278 hdrl_resample_method_parameter *aParams_method,
2279 hdrl_resample_outgrid_parameter *aParams_outputgrid,
2280 hdrl_resample_pixgrid **aGrid)
2281{
2282 cpl_ensure(ResTable && aParams_method && aParams_outputgrid && aGrid,
2283 CPL_ERROR_NULL_INPUT, NULL);
2284
2285 /* compute or set the size of the output grid depending on *
2286 * the inputs and the data available in the pixel table */
2287
2288
2289 /* compute output sizes; wavelength is different in that it is *
2290 * more useful to contain partly empty areas within the field *
2291 * for the extreme ends, so use ceil() */
2292 int xsize = 0, ysize = 0, zsize = 0;
2293
2294 hdrl_resample_compute_size(aParams_outputgrid, &xsize, &ysize, &zsize);
2295
2296 /* Following swarp for x and y : Add a margin in field size */
2297
2298 xsize *= (100. + aParams_outputgrid->fieldmargin)/100.;
2299 ysize *= (100. + aParams_outputgrid->fieldmargin)/100.;
2300
2301 cpl_ensure(xsize > 0 && ysize > 0 && zsize > 0, CPL_ERROR_ILLEGAL_OUTPUT,
2302 NULL);
2303
2304 double time = cpl_test_get_walltime();
2305
2306 /* create the structure for the output datacube */
2307 hdrl_resample_result *cube = cpl_calloc(1, sizeof(hdrl_resample_result));
2308
2309 hdrl_resampling_set_outputgrid (xsize, ysize, zsize, cube, aParams_outputgrid);
2310
2311 if (aParams_method->method < HDRL_RESAMPLE_METHOD_NONE) {
2312 /* fill the cube for the data */
2313 cube->himlist = hdrl_imagelist_new();
2314
2315 for (cpl_size i = 0; i < zsize; i++) {
2316 hdrl_image * image = hdrl_image_new(xsize, ysize);
2317
2318 /* Set all pixels a priori to bad - do not use pointers to keep the
2319 * bpm of the data and error image in sync*/
2320 for (cpl_size j = 1; j <= xsize; j++) {
2321 for (cpl_size k = 1; k <= ysize; k++) {
2322 hdrl_image_reject(image, j, k);
2323 }
2324 }
2325
2326 hdrl_imagelist_set(cube->himlist, image, i);
2327 } /* for i (all wavelength planes) */
2328 } /* if method not HDRL_RESAMPLE_METHOD_NONE */
2329
2330 /* convert the pixel table into a pixel grid */
2331 hdrl_resample_pixgrid *grid = hdrl_resample_pixgrid_create(ResTable, cube->header,
2332 xsize, ysize, zsize);
2333 if (!grid) {
2335 cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND, "Could not create"
2336 " pixel grid!");
2337 if (aGrid) {
2338 *aGrid = NULL;
2339 }
2340 return NULL;
2341 } /* if not grid */
2342
2343 double timeinit = cpl_test_get_walltime(),
2344 cpuinit = cpl_test_get_cputime();
2345
2346 /* do the resampling */
2347 cpl_error_code rc = CPL_ERROR_NONE;
2348 switch (aParams_method->method) {
2350 cpl_msg_debug(cpl_func, "Starting resampling, using method \"nearest\"");
2351 rc = hdrl_resample_cube_nearest(cube, ResTable, grid, aParams_outputgrid);
2352 break;
2354 cpl_msg_debug(cpl_func, "Starting resampling, using method \"renka\" "
2355 "(critical radius rc=%f, loop distance ld=%d)",
2356 aParams_method->renka_critical_radius,
2357 aParams_method->loop_distance);
2358 rc = hdrl_resample_cube_weighted(cube, ResTable, grid, aParams_method,
2359 aParams_outputgrid);
2360 break;
2364 cpl_msg_debug(cpl_func, "Starting resampling, using method \"%s\" (loop "
2365 "distance ld=%d)",
2366 aParams_method->method == HDRL_RESAMPLE_METHOD_LINEAR
2367 ? "linear"
2368 : (aParams_method->method == HDRL_RESAMPLE_METHOD_QUADRATIC
2369 ? "quadratic"
2370 : "lanczos"),
2371 aParams_method->loop_distance);
2372 rc = hdrl_resample_cube_weighted(cube, ResTable, grid, aParams_method,
2373 aParams_outputgrid);
2374 break;
2376 cpl_msg_debug(cpl_func, "Starting resampling, using method \"drizzle\" "
2377 "(pixfrac f=%.3f,%.3f,%.3f, loop distance ld=%d)",
2378 aParams_method->drizzle_pix_frac_x,
2379 aParams_method->drizzle_pix_frac_y,
2380 aParams_method->drizzle_pix_frac_lambda,
2381 aParams_method->loop_distance);
2382 rc = hdrl_resample_cube_weighted(cube, ResTable, grid,
2383 aParams_method,
2384 aParams_outputgrid);
2385 break;
2387 /* cpl_msg_debug(cpl_func, "Method %d (no resampling)", aParams_method->method); */
2388 break;
2389 default:
2390 cpl_msg_error(cpl_func, "Don't know this resampling method: %d",
2391 aParams_method->method);
2392 cpl_error_set(cpl_func, CPL_ERROR_UNSUPPORTED_MODE);
2393 rc = CPL_ERROR_UNSUPPORTED_MODE;
2394 }
2395
2396 double timefini = cpl_test_get_walltime(),
2397 cpufini = cpl_test_get_cputime();
2398
2399 /* now that we have resampled we can either remove the pixel grid or save it */
2400 if (aGrid) {
2401 *aGrid = grid;
2402 } else {
2403 hdrl_resample_pixgrid_delete(grid);
2404 }
2405
2406 cpl_msg_debug(cpl_func, "resampling took %.3fs (wall-clock) and %.3fs "
2407 "(%.3fs CPU, %d CPUs) for hdrl_resample_cube*() alone",
2408 timefini - time, timefini - timeinit, cpufini - cpuinit,
2410 if (rc != CPL_ERROR_NONE) {
2411 cpl_msg_error(cpl_func, "resampling failed: %s", cpl_error_get_message());
2413 return NULL;
2414 }
2415
2416 return cube;
2417} /* hdrl_resample_cube() */
2418
2419/*---------------------------------------------------------------------------*/
2429/*---------------------------------------------------------------------------*/
2430cpl_error_code
2431hdrl_wcs_to_propertylist(const cpl_wcs * wcs, cpl_propertylist * header,
2432 cpl_boolean only2d)
2433{
2434 cpl_ensure_code(wcs && header, CPL_ERROR_NULL_INPUT);
2435 int err = 0;
2436 const cpl_array *crval = cpl_wcs_get_crval(wcs);
2437 const cpl_array *crpix = cpl_wcs_get_crpix(wcs);
2438 const cpl_array *ctype = cpl_wcs_get_ctype(wcs);
2439 const cpl_array *cunit = cpl_wcs_get_cunit(wcs);
2440
2441 const cpl_matrix *cd = cpl_wcs_get_cd(wcs);
2442
2443 const cpl_array *dims = cpl_wcs_get_image_dims(wcs);
2444 int naxis = cpl_wcs_get_image_naxis(wcs);
2445
2446
2447 /* Check NAXIS */
2448 for (cpl_size i = 0; i < naxis; i++) {
2449 if (i == 0) {
2450 cpl_propertylist_update_int(header, "NAXIS", naxis);
2451 }
2452 char * buf = cpl_sprintf("NAXIS%lld", i + 1);
2453 cpl_propertylist_update_int(header, buf,
2454 cpl_array_get_int(dims, i, &err));
2455 cpl_free(buf);
2456 }
2457
2458/* Make sure to have the right NAXIS keywords if 2D is forced */
2459 if (only2d == TRUE) {
2460 cpl_propertylist_update_int(header, "NAXIS", 2);
2461
2462 if(cpl_propertylist_has(header, "NAXIS3")){
2463 cpl_propertylist_erase(header, "NAXIS3");
2464 }
2465 }
2466
2467 /* for 2D images */
2468 if (crval) {
2469 cpl_propertylist_update_double(header, "CRVAL1",
2470 cpl_array_get_double(crval, 0, &err));
2471 cpl_propertylist_update_double(header, "CRVAL2",
2472 cpl_array_get_double(crval, 1, &err));
2473 }
2474
2475 if (crpix) {
2476 cpl_propertylist_update_double(header, "CRPIX1",
2477 cpl_array_get_double(crpix, 0, &err));
2478 cpl_propertylist_update_double(header, "CRPIX2",
2479 cpl_array_get_double(crpix, 1, &err));
2480 }
2481
2482 if (ctype) {
2483 cpl_propertylist_update_string(header, "CTYPE1",
2484 cpl_array_get_string(ctype, 0));
2485 cpl_propertylist_update_string(header, "CTYPE2",
2486 cpl_array_get_string(ctype, 1));
2487 }
2488
2489 if (cunit) {
2490 cpl_propertylist_update_string(header, "CUNIT1",
2491 cpl_array_get_string(cunit, 0));
2492 cpl_propertylist_update_string(header, "CUNIT2",
2493 cpl_array_get_string(cunit, 1));
2494 }
2495
2496 if (cd) {
2497 double cd11 = cpl_matrix_get(cd, 0, 0);
2498 double cd12 = cpl_matrix_get(cd, 0, 1);
2499 double cd21 = cpl_matrix_get(cd, 1, 0);
2500 double cd22 = cpl_matrix_get(cd, 1, 1);
2501 cpl_propertylist_update_double(header, "CD1_1", cd11);
2502 cpl_propertylist_update_double(header, "CD1_2", cd12);
2503 cpl_propertylist_update_double(header, "CD2_1", cd21);
2504 cpl_propertylist_update_double(header, "CD2_2", cd22);
2505 }
2506
2507 /* for 3D cubes */
2508 if (only2d == FALSE && cpl_array_get_size(crval) > 2) {
2509
2510 if (crval) {
2511 cpl_propertylist_update_double(header, "CRVAL3",
2512 cpl_array_get_double(crval, 2, &err));
2513 }
2514
2515 if (crpix) {
2516 cpl_propertylist_update_double(header, "CRPIX3",
2517 cpl_array_get_double(crpix, 2, &err));
2518 }
2519
2520 if (ctype) {
2521 cpl_propertylist_update_string(header, "CTYPE3",
2522 cpl_array_get_string(ctype, 2));
2523 }
2524
2525 if (cunit) {
2526 cpl_propertylist_update_string(header, "CUNIT3",
2527 cpl_array_get_string(cunit, 2));
2528 }
2529
2530 if (cd) {
2531 double cd13 = cpl_matrix_get(cd, 0, 2);
2532 double cd23 = cpl_matrix_get(cd, 1, 2);
2533 double cd31 = cpl_matrix_get(cd, 2, 0);
2534 double cd32 = cpl_matrix_get(cd, 2, 1);
2535 double cd33 = cpl_matrix_get(cd, 2, 2);
2536 cpl_propertylist_update_double(header, "CD1_3", cd13);
2537 cpl_propertylist_update_double(header, "CD2_3", cd23);
2538 cpl_propertylist_update_double(header, "CD3_1", cd31);
2539 cpl_propertylist_update_double(header, "CD3_2", cd32);
2540 cpl_propertylist_update_double(header, "CD3_3", cd33);
2541 }
2542 } /* if 3D */
2543 return CPL_ERROR_NONE;
2544}
2545
2546/*----------------------------------------------------------------------------*/
2553/*----------------------------------------------------------------------------*/
2554
2555static cpl_error_code
2556hdrl_resample_create_table(cpl_table** tab, const cpl_size size)
2557{
2558
2559 cpl_ensure_code(tab, CPL_ERROR_NULL_INPUT);
2560 cpl_ensure_code(size > 0 , CPL_ERROR_ILLEGAL_INPUT);
2561
2562 *tab = cpl_table_new(size);
2563 /*
2564 * MUSE_PIXTABLE_XPOS "xpos" *< x-position column of a MUSE pixel table
2565 * MUSE_PIXTABLE_YPOS "ypos" *< y-position column of a MUSE pixel table
2566 * MUSE_PIXTABLE_LAMBDA "lambda" *< wavelength column of a MUSE pixel table
2567 * MUSE_PIXTABLE_DATA "data" *< data column of a MUSE pixel table
2568 * MUSE_PIXTABLE_DQ "dq" *< data quality column of a MUSE pixel table
2569 * MUSE_PIXTABLE_STAT "stat" *< error column of a MUSE pixel table
2570 */
2571 cpl_table_new_column(*tab,
2573 cpl_table_new_column(*tab,
2575 cpl_table_new_column(*tab,
2577 cpl_table_new_column(*tab,
2579 cpl_table_new_column(*tab,
2581 cpl_table_new_column(*tab,
2583
2584 /* init column values */
2585 cpl_table_fill_column_window_double(*tab, HDRL_RESAMPLE_TABLE_RA, 0, size, 0.);
2586 cpl_table_fill_column_window_double(*tab, HDRL_RESAMPLE_TABLE_DEC, 0, size, 0.);
2587 cpl_table_fill_column_window_double(*tab, HDRL_RESAMPLE_TABLE_LAMBDA,0, size, 0.);
2588 cpl_table_fill_column_window_double(*tab, HDRL_RESAMPLE_TABLE_DATA, 0, size, 0.);
2589 cpl_table_fill_column_window_int(*tab, HDRL_RESAMPLE_TABLE_BPM, 0, size, 0);
2590 cpl_table_fill_column_window_double(*tab, HDRL_RESAMPLE_TABLE_ERRORS,0, size, 0.);
2591
2592 return cpl_error_get_code();
2593}
2594
2595/*----------------------------------------------------------------------------*/
2603/*----------------------------------------------------------------------------*/
2604cpl_table*
2605hdrl_resample_image_to_table(const hdrl_image * hima, const cpl_wcs* wcs)
2606{
2607 cpl_ensure(hima, CPL_ERROR_NULL_INPUT, NULL);
2608 cpl_ensure(wcs, CPL_ERROR_NULL_INPUT, NULL);
2609 cpl_msg_debug(cpl_func, "Converting Data to table");
2610 hdrl_imagelist* ilist = NULL;
2611 cpl_table* tab;
2612 ilist = hdrl_imagelist_new();
2613 hdrl_imagelist_set(ilist, (hdrl_image *)hima, 0);
2614
2615 tab = hdrl_resample_imagelist_to_table(ilist, wcs);
2616
2617 /* cleanup memory */
2618 hdrl_imagelist_unset(ilist, 0);
2619 hdrl_imagelist_delete(ilist);
2620
2621
2622 return tab;
2623}
2624
2625/*----------------------------------------------------------------------------*/
2633/*----------------------------------------------------------------------------*/
2634cpl_table*
2636 const cpl_wcs* wcs)
2637{
2638
2639 cpl_ensure(himlist, CPL_ERROR_NULL_INPUT, NULL);
2640 cpl_ensure(wcs, CPL_ERROR_NULL_INPUT, NULL);
2641
2642 cpl_msg_debug(cpl_func, "Converting Dataset to table");
2643
2644 cpl_size naxis1 = hdrl_imagelist_get_size_x(himlist);
2645 cpl_size naxis2 = hdrl_imagelist_get_size_y(himlist);
2646 cpl_size naxis3 = hdrl_imagelist_get_size(himlist);
2647
2648 cpl_msg_debug(cpl_func,"Dataset dimentions (x, y, l): (%lld, %lld, %lld)",
2649 naxis1, naxis2, naxis3);
2650
2651 const cpl_array *crval = cpl_wcs_get_crval(wcs);
2652 const cpl_array *crpix = cpl_wcs_get_crpix(wcs);
2653 const cpl_matrix *cd = cpl_wcs_get_cd(wcs);
2654
2655 int testerr = 0;
2656 double crpix3 = 0.;
2657 double crval3 = 0.;
2658 double cdelt3 = 0.;
2659
2660 if (naxis3 > 1) { /* We have a cube */
2661 crpix3 = cpl_array_get_double(crpix, 2, &testerr);
2662 crval3 = cpl_array_get_double(crval, 2, &testerr);
2663 cdelt3 = cpl_matrix_get(cd, 2, 2); /* CD3_3 */
2664/*
2665 cpl_msg_debug(cpl_func,"crpix3: %g crval3: %g cdelt3: %g", crpix3,
2666 crval3, cdelt3);
2667*/
2668 }
2669
2670 cpl_size tab_size = naxis1 * naxis2 * naxis3;
2671 cpl_table* tab = NULL;
2672 /* Prefill the full table */
2673 hdrl_resample_create_table(&tab, tab_size);
2674
2675 double* ptabxpos = cpl_table_get_data_double(tab, HDRL_RESAMPLE_TABLE_RA);
2676 double* ptabypos = cpl_table_get_data_double(tab, HDRL_RESAMPLE_TABLE_DEC);
2677 double* ptablambda = cpl_table_get_data_double(tab, HDRL_RESAMPLE_TABLE_LAMBDA);
2678 double* ptabdata = cpl_table_get_data_double(tab, HDRL_RESAMPLE_TABLE_DATA);
2679 int* ptabbpm = cpl_table_get_data_int(tab, HDRL_RESAMPLE_TABLE_BPM);
2680 double* ptaberr = cpl_table_get_data_double(tab, HDRL_RESAMPLE_TABLE_ERRORS);
2681
2682 struct timeval tv1, tv2;
2683 cpl_msg_debug(cpl_func,"Starting parallel loop in hdrl_imagelist_to_table");
2684 gettimeofday(&tv1, NULL);
2685
2686 HDRL_OMP(omp parallel for collapse(2))
2687 for(cpl_size k = 0; k < naxis3; k++) {
2688 for(cpl_size j = 0; j < naxis2; j++) {
2689 const double* pimaerr = NULL;
2690 const cpl_binary * pimabpm = NULL;
2691
2692 /* Fill the data */
2693 const hdrl_image* hima = hdrl_imagelist_get_const(himlist, k);
2694 const cpl_image* imadata = hdrl_image_get_image_const(hima);
2695 const cpl_image* imaerrs = hdrl_image_get_error_const(hima);
2696 const cpl_mask* imamask = hdrl_image_get_mask_const(hima);
2697 const double* pimadata = cpl_image_get_data_double_const(imadata);
2698
2699 if (imaerrs) { /* Fill the errors */
2700 pimaerr = cpl_image_get_data_double_const(imaerrs);
2701 }
2702 if (imamask) { /* Fill the bpm */
2703 pimabpm = cpl_mask_get_data_const(imamask);
2704 }
2705
2706 cpl_size k_naxis1_naxis2 = naxis1 * naxis2 * k;
2707 cpl_size j_naxis1 = j * naxis1;
2708 for(cpl_size i = 0; i < naxis1; i++) {
2709 cpl_size raw = k_naxis1_naxis2 + j_naxis1 + i;
2710 hdrl_wcs_xy_to_radec(wcs, i+1 , j+1 , &ptabxpos[raw],
2711 &ptabypos[raw]);
2712 ptabdata[raw] = pimadata[j_naxis1 + i];
2713 if (naxis3 > 1) ptablambda[raw] = crval3 + cdelt3 * (k - crpix3 + 1.);
2714 if (imaerrs) ptaberr[raw] = pimaerr[j_naxis1 + i];
2715 if (imamask) ptabbpm[raw] = pimabpm[j_naxis1 + i];
2716 /* Insert only good pixels */
2717 if (!isfinite(pimadata[j_naxis1 + i]) ||
2718 ptabbpm[raw] != CPL_BINARY_0 ){
2719 ptabbpm[raw] = CPL_BINARY_1;
2720
2721 }
2722 }
2723 }
2724 }
2725
2726 gettimeofday(&tv2, NULL);
2727 cpl_msg_debug(cpl_func, "Wall time for hdrl_imagelist_to_table was %f seconds\n",
2728 (double) (tv2.tv_usec - tv1.tv_usec) / 1000000 +
2729 (double) (tv2.tv_sec - tv1.tv_sec));
2730
2731 return tab;
2732}
2733
2734/*----------------------------------------------------------------------------*/
2755/*----------------------------------------------------------------------------*/
2758 const double delta_dec)
2759{
2760
2761 hdrl_resample_outgrid_parameter * p = (hdrl_resample_outgrid_parameter *)
2762 hdrl_parameter_new(&hdrl_resample_outgrid_parameter_type);
2763 p->method = HDRL_RESAMPLE_OUTGRID_2D;
2764 p->delta_ra = delta_ra;
2765 p->delta_dec = delta_dec;
2766
2767 p->recalc_limits = CPL_TRUE;
2768
2769 /* This function asks to recalculate the limits in the hdrl_resample_compute
2770 * function - therefore we put dummy values for the moment. */
2771
2772 p->dec_min = 0.1;
2773 p->dec_max = 0.2;
2774 p->ra_min = 0.1;
2775 p->ra_max = 0.2;
2776
2777 /* in case of 2D sets some defaults dummy values for 3rd dimension */
2778 p->lambda_min = 0;
2779 p->lambda_max = 0;
2780 p->delta_lambda = 1;
2781
2782 /* Default field margin in percent taken from swarp. */
2783 p->fieldmargin = FIELDMARGIN;
2784
2785 p->wcs = NULL;
2786
2787 if (hdrl_resample_parameter_outgrid_verify((hdrl_parameter*)p) != CPL_ERROR_NONE) {
2788 cpl_free(p);
2789 return NULL;
2790 }
2791 return (hdrl_parameter *)p;
2792
2793}
2794
2795/*----------------------------------------------------------------------------*/
2817/*----------------------------------------------------------------------------*/
2820 const double delta_dec, const double delta_lambda)
2821{
2822
2823 hdrl_resample_outgrid_parameter * p = (hdrl_resample_outgrid_parameter *)
2824 hdrl_parameter_new(&hdrl_resample_outgrid_parameter_type);
2825 p->method = HDRL_RESAMPLE_OUTGRID_3D;
2826 p->delta_ra = delta_ra;
2827 p->delta_dec = delta_dec;
2828 p->delta_lambda = delta_lambda;
2829
2830 p->recalc_limits = CPL_TRUE;
2831 /* This function asks to recalculate the limits in the hdrl_resample_compute
2832 * function - therefore we put dummy values for the moment. */
2833
2834 p->dec_min = 0.1;
2835 p->dec_max = 0.2;
2836 p->ra_min = 0.1;
2837 p->ra_max = 0.2;
2838 p->lambda_min = 0.;
2839 p->lambda_max = 0.;
2840
2841 /* Default field margin in percent taken from swarp. */
2842 p->fieldmargin = FIELDMARGIN;
2843
2844 p->wcs = NULL;
2845
2846 if (hdrl_resample_parameter_outgrid_verify((hdrl_parameter*)p) != CPL_ERROR_NONE) {
2847 cpl_free(p);
2848 return NULL;
2849 }
2850 return (hdrl_parameter *)p;
2851
2852}
2853
2854/*----------------------------------------------------------------------------*/
2877/*----------------------------------------------------------------------------*/
2880 const double delta_dec,
2881 const double ra_min,
2882 const double ra_max,
2883 const double dec_min,
2884 const double dec_max,
2885 const double fieldmargin)
2886{
2887
2888 hdrl_resample_outgrid_parameter * p = (hdrl_resample_outgrid_parameter *)
2889 hdrl_parameter_new(&hdrl_resample_outgrid_parameter_type);
2890 p->method = HDRL_RESAMPLE_OUTGRID_2D;
2891 p->delta_ra = delta_ra;
2892 p->delta_dec = delta_dec;
2893
2894
2895 p->recalc_limits = CPL_FALSE; /*This function takes the limits from the user*/
2896 p->dec_min = dec_min;
2897 p->dec_max = dec_max;
2898 p->ra_min = ra_min;
2899 p->ra_max = ra_max;
2900
2901 /* in case of 2D sets some defaults dummy values for 3rd dimension */
2902 p->lambda_min = 0.;
2903 p->lambda_max = 0.;
2904 p->delta_lambda = 1.;
2905
2906 p->fieldmargin = fieldmargin;
2907
2908 p->wcs = NULL;
2909
2910 if (hdrl_resample_parameter_outgrid_verify((hdrl_parameter*)p) != CPL_ERROR_NONE) {
2911 cpl_free(p);
2912 return NULL;
2913 }
2914 return (hdrl_parameter *)p;
2915
2916}
2917
2918/*----------------------------------------------------------------------------*/
2946/*----------------------------------------------------------------------------*/
2949 const double delta_dec,
2950 const double delta_lambda,
2951 const double ra_min,
2952 const double ra_max,
2953 const double dec_min,
2954 const double dec_max,
2955 const double lambda_min,
2956 const double lambda_max,
2957 const double fieldmargin)
2958{
2959
2960 hdrl_resample_outgrid_parameter * p = (hdrl_resample_outgrid_parameter *)
2961 hdrl_parameter_new(&hdrl_resample_outgrid_parameter_type);
2962 p->method = HDRL_RESAMPLE_OUTGRID_3D;
2963 p->delta_ra = delta_ra;
2964 p->delta_dec = delta_dec;
2965 p->delta_lambda = delta_lambda;
2966
2967 p->recalc_limits = CPL_FALSE; /*This function takes the limits from the user*/
2968
2969 p->dec_min = dec_min;
2970 p->dec_max = dec_max;
2971 p->ra_min = ra_min;
2972 p->ra_max = ra_max;
2973
2974 p->lambda_min = lambda_min;
2975 p->lambda_max = lambda_max;
2976
2977 p->fieldmargin = fieldmargin;
2978
2979 p->wcs = NULL;
2980
2981 if (hdrl_resample_parameter_outgrid_verify((hdrl_parameter*)p) != CPL_ERROR_NONE) {
2982 cpl_free(p);
2983 return NULL;
2984 }
2985 return (hdrl_parameter *)p;
2986
2987}
2988
2989/*----------------------------------------------------------------------------*/
3011/*----------------------------------------------------------------------------*/
3014 cpl_boolean use_errorweights,
3015 const double critical_radius)
3016{
3017
3018 hdrl_resample_method_parameter * p = (hdrl_resample_method_parameter *)
3019 hdrl_parameter_new(&hdrl_resample_method_parameter_type);
3020
3021 p->method = HDRL_RESAMPLE_METHOD_RENKA;
3022 p->loop_distance = loop_distance;
3023 p->use_errorweights = use_errorweights;
3024 p->renka_critical_radius = critical_radius;
3025
3026 /* fill rest with dummy input */
3027 p->drizzle_pix_frac_x = 0.1;
3028 p->drizzle_pix_frac_y = 0.1;
3029 p->drizzle_pix_frac_lambda = 0.1;
3030 p->lanczos_kernel_size = 2;
3031
3032 if (hdrl_resample_parameter_method_verify((hdrl_parameter*)p) != CPL_ERROR_NONE) {
3033 cpl_free(p);
3034 return NULL;
3035 }
3036 return (hdrl_parameter*) p;
3037}
3038
3039/*----------------------------------------------------------------------------*/
3058/*----------------------------------------------------------------------------*/
3061 cpl_boolean use_errorweights)
3062{
3063
3064 hdrl_resample_method_parameter * p = (hdrl_resample_method_parameter *)
3065 hdrl_parameter_new(&hdrl_resample_method_parameter_type);
3066
3067
3068 p->method = HDRL_RESAMPLE_METHOD_LINEAR;
3069 p->loop_distance = loop_distance;
3070 p->use_errorweights = use_errorweights;
3071
3072 /* fill rest with dummy input */
3073 p->renka_critical_radius = 0.1;
3074 p->drizzle_pix_frac_x = 0.1;
3075 p->drizzle_pix_frac_y = 0.1;
3076 p->drizzle_pix_frac_lambda = 0.1;
3077 p->lanczos_kernel_size = 2;
3078
3079 if (hdrl_resample_parameter_method_verify((hdrl_parameter*)p) != CPL_ERROR_NONE) {
3080 cpl_free(p);
3081 return NULL;
3082 }
3083 return (hdrl_parameter*) p;
3084}
3085
3086/*----------------------------------------------------------------------------*/
3106/*----------------------------------------------------------------------------*/
3109 cpl_boolean use_errorweights)
3110{
3111
3112 hdrl_resample_method_parameter * p = (hdrl_resample_method_parameter *)
3113 hdrl_parameter_new(&hdrl_resample_method_parameter_type);
3114
3116 p->loop_distance = loop_distance;
3117 p->use_errorweights = use_errorweights;
3118
3119 /* fill rest with dummy input */
3120 p->renka_critical_radius = 0.1;
3121 p->drizzle_pix_frac_x = 0.1;
3122 p->drizzle_pix_frac_y = 0.1;
3123 p->drizzle_pix_frac_lambda = 0.1;
3124 p->lanczos_kernel_size = 2;
3125
3126 if (hdrl_resample_parameter_method_verify((hdrl_parameter*)p) != CPL_ERROR_NONE) {
3127 cpl_free(p);
3128 return NULL;
3129 }
3130 return (hdrl_parameter*) p;
3131}
3132
3133/*----------------------------------------------------------------------------*/
3148/*----------------------------------------------------------------------------*/
3151{
3152
3153 hdrl_resample_method_parameter * p = (hdrl_resample_method_parameter *)
3154 hdrl_parameter_new(&hdrl_resample_method_parameter_type);
3155
3156
3157 p->method = HDRL_RESAMPLE_METHOD_NEAREST;
3158 p->loop_distance = 0;
3159 p->use_errorweights = CPL_FALSE;
3160
3161 /* fill rest with dummy input */
3162 p->renka_critical_radius = 0.1;
3163 p->drizzle_pix_frac_x = 0.1;
3164 p->drizzle_pix_frac_y = 0.1;
3165 p->drizzle_pix_frac_lambda = 0.1;
3166 p->lanczos_kernel_size = 2;
3167
3168 if (hdrl_resample_parameter_method_verify((hdrl_parameter*)p) != CPL_ERROR_NONE) {
3169 cpl_free(p);
3170 return NULL;
3171 }
3172 return (hdrl_parameter*) p;
3173}
3174
3175/*----------------------------------------------------------------------------*/
3196/*----------------------------------------------------------------------------*/
3199 cpl_boolean use_errorweights,
3200 const int kernel_size)
3201{
3202
3203 hdrl_resample_method_parameter * p = (hdrl_resample_method_parameter *)
3204 hdrl_parameter_new(&hdrl_resample_method_parameter_type);
3205
3206 p->method = HDRL_RESAMPLE_METHOD_LANCZOS;
3207 p->loop_distance = loop_distance;
3208 p->use_errorweights = use_errorweights;
3209 p->lanczos_kernel_size = kernel_size;
3210 /* fill rest with dummy input */
3211 p->renka_critical_radius = 0.1;
3212 p->drizzle_pix_frac_x = 0.1;
3213 p->drizzle_pix_frac_y = 0.1;
3214 p->drizzle_pix_frac_lambda = 0.1;
3215
3216 if (hdrl_resample_parameter_method_verify((hdrl_parameter*)p) != CPL_ERROR_NONE) {
3217 cpl_free(p);
3218 return NULL;
3219 }
3220 return (hdrl_parameter*) p;
3221}
3222
3223/*----------------------------------------------------------------------------*/
3251/*----------------------------------------------------------------------------*/
3254 cpl_boolean use_errorweights,
3255 const double pix_frac_x,
3256 const double pix_frac_y,
3257 const double pix_frac_lambda)
3258{
3259
3260 hdrl_resample_method_parameter * p = (hdrl_resample_method_parameter *)
3261 hdrl_parameter_new(&hdrl_resample_method_parameter_type);
3262
3263 p->method = HDRL_RESAMPLE_METHOD_DRIZZLE;
3264 p->loop_distance = loop_distance;
3265 p->use_errorweights = use_errorweights;
3266 p->drizzle_pix_frac_x = pix_frac_x;
3267 p->drizzle_pix_frac_y = pix_frac_y;
3268 p->drizzle_pix_frac_lambda = pix_frac_lambda;
3269
3270 /* fill rest with dummy input */
3271 p->renka_critical_radius = 0.1;
3272 p->lanczos_kernel_size = 2;
3273
3274 if (hdrl_resample_parameter_method_verify((hdrl_parameter*)p) != CPL_ERROR_NONE) {
3275 cpl_free(p);
3276 return NULL;
3277 }
3278 return (hdrl_parameter*) p;
3279
3280}
3281/*----------------------------------------------------------------------------*/
3290/*----------------------------------------------------------------------------*/
3291cpl_error_code
3293
3294 const hdrl_resample_outgrid_parameter * param_loc =
3295 (const hdrl_resample_outgrid_parameter *)hp ;
3296
3297 cpl_error_ensure(hp != NULL, CPL_ERROR_NULL_INPUT,
3298 return CPL_ERROR_NULL_INPUT, "NULL Input Parameters");
3299
3300 cpl_error_ensure(hdrl_resample_parameter_outgrid_check(hp),
3301 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3302 "Here we expect a resample outgrid parameter") ;
3303
3304 cpl_error_ensure(
3305 param_loc->recalc_limits == CPL_TRUE ||
3306 param_loc->recalc_limits == CPL_FALSE,
3307 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3308 "Unsupported resample recalc_limits value");
3309
3310/*
3311 * The wcs is filled later on by the compute function so it can not be checked
3312 * at this stage
3313 *
3314 cpl_error_ensure(param_loc->wcs != NULL, CPL_ERROR_NULL_INPUT,
3315 return CPL_ERROR_NULL_INPUT, "WCS must be defined");
3316*/
3317
3318
3319 cpl_error_ensure(param_loc->delta_ra > 0, CPL_ERROR_ILLEGAL_INPUT,
3320 return CPL_ERROR_ILLEGAL_INPUT, "right ascension "
3321 "stepsize must be > 0");
3322
3323 cpl_error_ensure(param_loc->delta_dec > 0, CPL_ERROR_ILLEGAL_INPUT,
3324 return CPL_ERROR_ILLEGAL_INPUT, "declination stepsize "
3325 "must be > 0");
3326
3327 cpl_error_ensure(param_loc->delta_lambda > 0, CPL_ERROR_ILLEGAL_INPUT,
3328 return CPL_ERROR_ILLEGAL_INPUT, "wavelength stepsize "
3329 "must be > 0");
3330
3331
3332 cpl_error_ensure(param_loc->ra_min >= 0,
3333 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3334 "Minimum right ascension must be >= 0");
3335
3336 cpl_error_ensure(param_loc->ra_max >= 0,
3337 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3338 "Maximum right ascension must be >= 0");
3339
3340
3341 cpl_error_ensure(param_loc->lambda_min >= 0,
3342 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3343 "Minimum wavelength must be >= 0");
3344
3345 cpl_error_ensure(param_loc->lambda_max >= 0,
3346 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3347 "Maximum wavelength must be >= 0");
3348
3349 cpl_error_ensure(param_loc->fieldmargin >= 0., CPL_ERROR_ILLEGAL_INPUT,
3350 return CPL_ERROR_ILLEGAL_INPUT, "The field margin must"
3351 " be >= 0.");
3352
3353 cpl_error_ensure(param_loc->ra_max >= param_loc->ra_min ,
3354 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3355 "The maximum right ascension must be >= "
3356 "the minimum right ascension");
3357 cpl_error_ensure(param_loc->dec_max >= param_loc->dec_min ,
3358 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3359 "The maximum declination must be >= "
3360 "the minimum declination");
3361
3362 cpl_error_ensure(param_loc->lambda_max >= param_loc->lambda_min ,
3363 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3364 "The maximum wavelength must be >= "
3365 "the minimum wavelength");
3366
3367 return CPL_ERROR_NONE ;
3368}
3369
3370/*----------------------------------------------------------------------------*/
3379/*----------------------------------------------------------------------------*/
3380cpl_error_code
3382
3383 const hdrl_resample_method_parameter * param_loc =
3384 (const hdrl_resample_method_parameter *)hp ;
3385 cpl_error_ensure(hp != NULL, CPL_ERROR_NULL_INPUT,
3386 return CPL_ERROR_NULL_INPUT, "NULL Input Parameters");
3387
3388 cpl_error_ensure(hdrl_resample_parameter_method_check(hp),
3389 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3390 "Here we expect a resample method parameter") ;
3391
3392 /* checks on parameter methods */
3393 cpl_error_ensure(
3394 param_loc->method == HDRL_RESAMPLE_METHOD_NEAREST ||
3395 param_loc->method == HDRL_RESAMPLE_METHOD_LINEAR ||
3396 param_loc->method == HDRL_RESAMPLE_METHOD_QUADRATIC ||
3397 param_loc->method == HDRL_RESAMPLE_METHOD_LANCZOS ||
3398 param_loc->method == HDRL_RESAMPLE_METHOD_DRIZZLE ||
3399 param_loc->method == HDRL_RESAMPLE_METHOD_RENKA,
3400 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3401 "Unsupported resample method");
3402
3403 /* checks on common parameter elements */
3404 cpl_error_ensure(param_loc->loop_distance >= 0, CPL_ERROR_ILLEGAL_INPUT,
3405 return CPL_ERROR_ILLEGAL_INPUT, "The loop distance must "
3406 "be >=0");
3407
3408 cpl_error_ensure(param_loc->use_errorweights == CPL_TRUE ||
3409 param_loc->use_errorweights == CPL_FALSE,
3410 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3411 "Unsupported resample use_errorweights value");
3412
3413 switch (param_loc->method) {
3418 break;
3420 /* checks on peculiar parameter elements */
3421 cpl_error_ensure(param_loc->renka_critical_radius > 0.,
3422 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3423 "Critical radius of the Renka method must be > 0");
3424 break ;
3425
3427 /* checks on peculiar parameter elements */
3428 cpl_error_ensure(param_loc->drizzle_pix_frac_x > 0.,
3429 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3430 "Drizzle down-scaling factor in x direction "
3431 "must be > 0");
3432
3433 cpl_error_ensure(param_loc->drizzle_pix_frac_y > 0.,
3434 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3435 "Drizzle down-scaling factor in y direction "
3436 "must be > 0");
3437
3438 cpl_error_ensure(param_loc->drizzle_pix_frac_lambda > 0.,
3439 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3440 "Drizzle down-scaling factor in z/lambda direction "
3441 "must be > 0");
3442 break;
3443
3445 /* checks on peculiar parameter elements */
3446 cpl_error_ensure(param_loc->lanczos_kernel_size > 0,
3447 CPL_ERROR_ILLEGAL_INPUT, return CPL_ERROR_ILLEGAL_INPUT,
3448 "The kernel size of the Lanczos method must be > 0");
3449 break;
3450 }
3451
3452 return CPL_ERROR_NONE ;
3453}
3454/*----------------------------------------------------------------------------*/
3463/*----------------------------------------------------------------------------*/
3464int
3466 /* Check if the method is of proper type */
3467 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
3468
3469 return hdrl_parameter_check_type(self, &hdrl_resample_outgrid_parameter_type);
3470}
3471/*----------------------------------------------------------------------------*/
3480/*----------------------------------------------------------------------------*/
3481int
3483 /* Check if the method is of proper type */
3484 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
3485 return hdrl_parameter_check_type(self, &hdrl_resample_method_parameter_type);
3486}
3487
3488
3489/*----------------------------------------------------------------------------*/
3496/*----------------------------------------------------------------------------*/
3497static cpl_error_code
3498hdrl_resample_inputtable_verify(const cpl_table *ResTable){
3499
3500 cpl_error_ensure(ResTable != NULL, CPL_ERROR_NULL_INPUT,
3501 return CPL_ERROR_NULL_INPUT, "No Table as input");
3502
3503 /* Check the existence of all columns */
3504 cpl_error_ensure(cpl_table_has_column(ResTable, HDRL_RESAMPLE_TABLE_DATA )
3505 == 1, CPL_ERROR_INCOMPATIBLE_INPUT,
3506 return CPL_ERROR_INCOMPATIBLE_INPUT,
3507 "Missing data table column");
3508 cpl_error_ensure(cpl_table_has_column(ResTable, HDRL_RESAMPLE_TABLE_BPM )
3509 == 1, CPL_ERROR_INCOMPATIBLE_INPUT,
3510 return CPL_ERROR_INCOMPATIBLE_INPUT,
3511 "Missing bpm table column");
3512 cpl_error_ensure(cpl_table_has_column(ResTable, HDRL_RESAMPLE_TABLE_ERRORS)
3513 == 1, CPL_ERROR_INCOMPATIBLE_INPUT,
3514 return CPL_ERROR_INCOMPATIBLE_INPUT,
3515 "Missing error table column");
3516 cpl_error_ensure(cpl_table_has_column(ResTable, HDRL_RESAMPLE_TABLE_RA )
3517 == 1, CPL_ERROR_INCOMPATIBLE_INPUT,
3518 return CPL_ERROR_INCOMPATIBLE_INPUT,
3519 "Missing right ascension table column");
3520 cpl_error_ensure(cpl_table_has_column(ResTable, HDRL_RESAMPLE_TABLE_DEC )
3521 == 1, CPL_ERROR_INCOMPATIBLE_INPUT,
3522 return CPL_ERROR_INCOMPATIBLE_INPUT,
3523 "Missing declination table column");
3524 cpl_error_ensure(cpl_table_has_column(ResTable, HDRL_RESAMPLE_TABLE_LAMBDA)
3525 == 1, CPL_ERROR_INCOMPATIBLE_INPUT,
3526 return CPL_ERROR_INCOMPATIBLE_INPUT,
3527 "Missing wavelength table column");
3528
3529 /* Check the format of all columns */
3530 cpl_error_ensure(cpl_table_get_column_type(ResTable, HDRL_RESAMPLE_TABLE_DATA )
3531 == HDRL_RESAMPLE_TABLE_DATA_TYPE, CPL_ERROR_INCOMPATIBLE_INPUT,
3532 return CPL_ERROR_INCOMPATIBLE_INPUT,
3533 "Data table column has wrong format");
3534 cpl_error_ensure(cpl_table_get_column_type(ResTable, HDRL_RESAMPLE_TABLE_BPM )
3535 == HDRL_RESAMPLE_TABLE_BPM_TYPE, CPL_ERROR_INCOMPATIBLE_INPUT,
3536 return CPL_ERROR_INCOMPATIBLE_INPUT,
3537 "Bpm table column has wrong format");
3538 cpl_error_ensure(cpl_table_get_column_type(ResTable, HDRL_RESAMPLE_TABLE_ERRORS)
3539 == HDRL_RESAMPLE_TABLE_ERRORS_TYPE, CPL_ERROR_INCOMPATIBLE_INPUT,
3540 return CPL_ERROR_INCOMPATIBLE_INPUT,
3541 "Error table column has wrong format");
3542 cpl_error_ensure(cpl_table_get_column_type(ResTable, HDRL_RESAMPLE_TABLE_RA )
3543 == HDRL_RESAMPLE_TABLE_RA_TYPE, CPL_ERROR_INCOMPATIBLE_INPUT,
3544 return CPL_ERROR_INCOMPATIBLE_INPUT,
3545 "Right ascension table column has wrong format");
3546 cpl_error_ensure(cpl_table_get_column_type(ResTable, HDRL_RESAMPLE_TABLE_DEC )
3547 == HDRL_RESAMPLE_TABLE_DEC_TYPE, CPL_ERROR_INCOMPATIBLE_INPUT,
3548 return CPL_ERROR_INCOMPATIBLE_INPUT,
3549 "Declination table column has wrong format");
3550 cpl_error_ensure(cpl_table_get_column_type(ResTable, HDRL_RESAMPLE_TABLE_LAMBDA)
3551 == HDRL_RESAMPLE_TABLE_LAMBDA_TYPE, CPL_ERROR_INCOMPATIBLE_INPUT,
3552 return CPL_ERROR_INCOMPATIBLE_INPUT,
3553 "Wavelength table column has wrong format");
3554
3555 return cpl_error_get_code();
3556}
3558/* EOF */
3559
hdrl_resample_outgrid
Definition hdrl_resample.h:67
@ HDRL_RESAMPLE_OUTGRID_3D
Definition hdrl_resample.h:69
@ HDRL_RESAMPLE_OUTGRID_2D
Definition hdrl_resample.h:68
#define HDRL_RESAMPLE_TABLE_DATA_TYPE
Definition hdrl_resample.h:51
#define HDRL_RESAMPLE_TABLE_RA_TYPE
Definition hdrl_resample.h:45
#define HDRL_RESAMPLE_TABLE_LAMBDA_TYPE
Definition hdrl_resample.h:49
#define HDRL_RESAMPLE_TABLE_DATA
Definition hdrl_resample.h:40
#define HDRL_RESAMPLE_TABLE_RA
Definition hdrl_resample.h:37
#define HDRL_RESAMPLE_TABLE_DEC
Definition hdrl_resample.h:38
#define HDRL_RESAMPLE_TABLE_ERRORS_TYPE
Definition hdrl_resample.h:55
hdrl_resample_method
Definition hdrl_resample.h:57
@ HDRL_RESAMPLE_METHOD_NONE
Definition hdrl_resample.h:64
@ HDRL_RESAMPLE_METHOD_RENKA
Definition hdrl_resample.h:59
@ HDRL_RESAMPLE_METHOD_DRIZZLE
Definition hdrl_resample.h:62
@ HDRL_RESAMPLE_METHOD_LANCZOS
Definition hdrl_resample.h:63
@ HDRL_RESAMPLE_METHOD_LINEAR
Definition hdrl_resample.h:60
@ HDRL_RESAMPLE_METHOD_QUADRATIC
Definition hdrl_resample.h:61
@ HDRL_RESAMPLE_METHOD_NEAREST
Definition hdrl_resample.h:58
#define HDRL_RESAMPLE_TABLE_BPM_TYPE
Definition hdrl_resample.h:53
#define HDRL_RESAMPLE_TABLE_LAMBDA
Definition hdrl_resample.h:39
#define HDRL_RESAMPLE_TABLE_DEC_TYPE
Definition hdrl_resample.h:47
#define HDRL_RESAMPLE_TABLE_ERRORS
Definition hdrl_resample.h:42
#define HDRL_RESAMPLE_TABLE_BPM
Definition hdrl_resample.h:41
void *() hdrl_alloc(size_t)
Definition hdrl_types.h:38
void() hdrl_free(void *)
Definition hdrl_types.h:39
#define HDRL_OMP(x)
Definition hdrl_cat_def.h:35
#define XMAP_BITMASK
Definition hdrl_resample.c:69
#define FIELDMARGIN
Definition hdrl_resample.c:61
#define omp_get_max_threads()
Definition hdrl_resample.c:35
#define XMAP_LSHIFT
Definition hdrl_resample.c:70
#define omp_get_thread_num()
Definition hdrl_resample.c:36
#define KEYWORD_LENGTH
Definition hdrl_resample.c:57
#define PT_IDX_MASK
Definition hdrl_resample.c:65
struct _hdrl_parameter_ hdrl_parameter
Definition hdrl_parameter.h:27
cpl_mask * hdrl_image_get_mask(hdrl_image *himg)
get cpl bad pixel mask from image
Definition hdrl_image.c:157
cpl_image * hdrl_image_get_error(hdrl_image *himg)
get error as cpl image
Definition hdrl_image.c:131
const cpl_mask * hdrl_image_get_mask_const(const hdrl_image *himg)
get cpl bad pixel mask from image
Definition hdrl_image.c:175
const cpl_image * hdrl_image_get_error_const(const hdrl_image *himg)
get error as cpl image
Definition hdrl_image.c:144
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
Definition hdrl_image.c:105
cpl_error_code hdrl_image_reject(hdrl_image *self, cpl_size xpos, cpl_size ypos)
mark pixel as bad
Definition hdrl_image.c:427
const cpl_image * hdrl_image_get_image_const(const hdrl_image *himg)
get data as cpl image
Definition hdrl_image.c:118
hdrl_image * hdrl_image_new(cpl_size nx, cpl_size ny)
create new zero filled hdrl image
Definition hdrl_image.c:311
hdrl_image * hdrl_imagelist_unset(hdrl_imagelist *himlist, cpl_size pos)
Remove an image from an imagelist.
Definition hdrl_imagelist_io.c:347
cpl_error_code hdrl_imagelist_set(hdrl_imagelist *himlist, hdrl_image *himg, cpl_size pos)
Insert an image into an imagelist.
Definition hdrl_imagelist_io.c:274
cpl_size hdrl_imagelist_get_size_y(const hdrl_imagelist *himlist)
Get number of rows of images in the imagelist.
Definition hdrl_imagelist_io.c:188
void hdrl_imagelist_delete(hdrl_imagelist *himlist)
Free all memory used by a hdrl_imagelist object including the images.
Definition hdrl_imagelist_io.c:384
const hdrl_image * hdrl_imagelist_get_const(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
Definition hdrl_imagelist_io.c:229
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.
Definition hdrl_imagelist_io.c:148
hdrl_imagelist * hdrl_imagelist_new(void)
Create an empty imagelist.
Definition hdrl_imagelist_io.c:84
cpl_size hdrl_imagelist_get_size_x(const hdrl_imagelist *himlist)
Get number of colums of images in the imagelist.
Definition hdrl_imagelist_io.c:168
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.
Definition hdrl_imagelist_io.c:210
hdrl_resample_result * hdrl_resample_compute(const cpl_table *ResTable, hdrl_parameter *method, hdrl_parameter *outputgrid, const cpl_wcs *wcs)
High level resampling function.
Definition hdrl_resample.c:735
void hdrl_resample_result_delete(hdrl_resample_result *aCube)
Deallocates the memory associated to a hdrl_resample_result object.
Definition hdrl_resample.c:848
cpl_table * hdrl_resample_image_to_table(const hdrl_image *hima, const cpl_wcs *wcs)
Convert a hdrl image into a cpl table that can be given as input to hdrl_resample_compute()
Definition hdrl_resample.c:2605
cpl_table * hdrl_resample_imagelist_to_table(const hdrl_imagelist *himlist, const cpl_wcs *wcs)
Convert a hdrl imagelist into a cpl table that can be given as input to hdrl_resample_compute().
Definition hdrl_resample.c:2635
hdrl_parameter * hdrl_resample_parameter_create_nearest(void)
Creates a resample nearest neighbor hdrl parameter object. The algorithm does not use any weighting f...
Definition hdrl_resample.c:3150
cpl_error_code hdrl_resample_parameter_method_verify(const hdrl_parameter *hp)
verify parameters have proper values
Definition hdrl_resample.c:3381
int hdrl_resample_parameter_method_check(const hdrl_parameter *self)
check method is of proper type
Definition hdrl_resample.c:3482
hdrl_parameter * hdrl_resample_parameter_create_renka(const int loop_distance, cpl_boolean use_errorweights, const double critical_radius)
Creates a resample renka hdrl parameter object. The algorithm uses a modified Shepard-like distance w...
Definition hdrl_resample.c:3013
hdrl_parameter * hdrl_resample_parameter_create_lanczos(const int loop_distance, cpl_boolean use_errorweights, const int kernel_size)
Creates a resample Lanczos hdrl parameter object. The algorithm uses a restricted SINC distance weigh...
Definition hdrl_resample.c:3198
hdrl_parameter * hdrl_resample_parameter_create_drizzle(const int loop_distance, cpl_boolean use_errorweights, const double pix_frac_x, const double pix_frac_y, const double pix_frac_lambda)
Creates a resample drizzle hdrl parameter object. The algorithm uses a drizzle-like distance weightin...
Definition hdrl_resample.c:3253
hdrl_parameter * hdrl_resample_parameter_create_quadratic(const int loop_distance, cpl_boolean use_errorweights)
Creates a resample quadratic hdrl parameter object. The algorithm uses a quadratic inverse distance w...
Definition hdrl_resample.c:3108
hdrl_parameter * hdrl_resample_parameter_create_linear(const int loop_distance, cpl_boolean use_errorweights)
Creates a resample linear hdrl parameter object. The algorithm uses a linear inverse distance weighti...
Definition hdrl_resample.c:3060
hdrl_parameter * hdrl_resample_parameter_create_outgrid3D(const double delta_ra, const double delta_dec, const double delta_lambda)
Creates a resample_outgrid hdrl parameter object for a 3 dimensional interpolation,...
Definition hdrl_resample.c:2819
hdrl_parameter * hdrl_resample_parameter_create_outgrid3D_userdef(const double delta_ra, const double delta_dec, const double delta_lambda, const double ra_min, const double ra_max, const double dec_min, const double dec_max, const double lambda_min, const double lambda_max, const double fieldmargin)
Creates a resample_outgrid hdrl parameter object for a 3 dimensional interpolation,...
Definition hdrl_resample.c:2948
int hdrl_resample_parameter_outgrid_check(const hdrl_parameter *self)
check method is of proper type
Definition hdrl_resample.c:3465
hdrl_parameter * hdrl_resample_parameter_create_outgrid2D(const double delta_ra, const double delta_dec)
Creates a resample_outgrid hdrl parameter object for a 2 dimensional interpolation,...
Definition hdrl_resample.c:2757
hdrl_parameter * hdrl_resample_parameter_create_outgrid2D_userdef(const double delta_ra, const double delta_dec, const double ra_min, const double ra_max, const double dec_min, const double dec_max, const double fieldmargin)
Creates a resample_outgrid hdrl parameter object for a 2 dimensional interpolation,...
Definition hdrl_resample.c:2879
cpl_error_code hdrl_resample_parameter_outgrid_verify(const hdrl_parameter *hp)
verify parameters have proper values
Definition hdrl_resample.c:3292
Definition hdrl_image_defs.h:40
Definition hdrl_imagelist_defs.h:42
Definition hdrl_resample.c:72
double crval1
Definition hdrl_resample.c:74
double cd22
Definition hdrl_resample.c:75
double cd12
Definition hdrl_resample.c:75
double crval2
Definition hdrl_resample.c:74
double crpix1
Definition hdrl_resample.c:73
double cddet
Definition hdrl_resample.c:76
double cd21
Definition hdrl_resample.c:75
double crpix2
Definition hdrl_resample.c:73
double cd11
Definition hdrl_resample.c:75
Definition hdrl_resample.c:79
unsigned int npix
Definition hdrl_resample.c:80
cpl_size * pix
Definition hdrl_resample.c:81
Definition hdrl_resample.c:84
unsigned short nmaps
Definition hdrl_resample.c:94
cpl_size * pix
Definition hdrl_resample.c:90
cpl_size nx
Definition hdrl_resample.c:91
cpl_size nz
Definition hdrl_resample.c:93
cpl_size * nxalloc
Definition hdrl_resample.c:96
cpl_size * nxmap
Definition hdrl_resample.c:95
cpl_size ny
Definition hdrl_resample.c:92
hdrl_resample_pixels_ext ** xmaps
Definition hdrl_resample.c:97
Definition hdrl_resample.h:72
hdrl_imagelist * himlist
Definition hdrl_resample.h:74
cpl_propertylist * header
Definition hdrl_resample.h:73