High-Level Data Reduction Library 1.6.0
High-Level data reduction routines for ESO pipelines
Loading...
Searching...
No Matches
hdrl_persistence.c
Go to the documentation of this file.
1/*
2 * This file is part of the HDRL
3 * Copyright (C) 2016 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
28#include <math.h>
29#include <stdint.h>
30#include <stdbool.h>
31
32#include "hdrl_persistence.h"
33
34/*-----------------------------------------------------------------------------
35 Static
36 -----------------------------------------------------------------------------*/
37
38
39
69/*----------------------------------------------------------------------------*/
70
73/*-----------------------------------------------------------------------------
74 Persistence parameters Definition
75 -----------------------------------------------------------------------------*/
76
79/*-----------------------------------------------------------------------------
80 Function Prototypes
81 -----------------------------------------------------------------------------*/
82
83static void hdrl_persistence_verify_inputs(
84 const double gain,
85 const double det_turnover,
86 const double mean_trim,
87 const cpl_boolean cleanQ,
88 const cpl_array * dates_,
89 const cpl_array * exps_,
90 const hdrl_imagelist * illums_,
91 const cpl_imagelist * srcmasks_,
92 const cpl_image * maximum,
93 const cpl_image * density,
94 const cpl_image * fullwell,
95 const cpl_table * frac);
96
97static void hdrl_persistence_threshhold_img(
98 hdrl_image * input,
99 const hdrl_image * lower,
100 const hdrl_image * upper);
101
102static void hdrl_persistence_zero_flagged_pixels(
103 hdrl_image * hdrl_img,
104 const cpl_mask * mask,
105 const cpl_binary value);
106
107static void hdrl_persistence_compute_qi(
108 hdrl_imagelist * Q,
109 hdrl_imagelist * Qacc,
110 const double delt,
111 const hdrl_imagelist * hirhos,
112 const float * taud,
113 const double exptime,
114 const hdrl_image * hiillum,
115 const int n_tau,
116 const hdrl_imagelist * himaxs);
117
118static cpl_propertylist * hdrl_persistence_calc_stats(
119 const hdrl_image * Qtot,
120 const double trim_perc);
121
122static int hdrl_persistence_get_time_const(
123 const cpl_array * nus);
124
125static hdrl_imagelist * hdrl_persistence_calculate_rho(
126 const cpl_array * nus,
127 const hdrl_image * hiden,
128 const int n_tau);
129
130
131static const hdrl_imagelist * hdrl_persistence_convert_max_traps(
132 const cpl_array * nus,
133 const hdrl_image * himax,
134 const int n_tau);
135
136static void hdrl_persistence_sum_Qtots(
137 hdrl_image * Qtot1_n,
138 hdrl_imagelist * Qtot,
139 const hdrl_imagelist * Q,
140 const int n_tau);
141
142static hdrl_imagelist * hdrl_persistence_create_hilist(
143 const int n,
144 const cpl_size nx,
145 const cpl_size ny);
146
147/*----------------------------------------------------------------------------*/
151/*----------------------------------------------------------------------------*/
152static void hdrl_persistence_qc_dump(
153 cpl_propertylist * plist,
154 const char * qcname)
155{
156 cpl_error_ensure(plist && qcname, CPL_ERROR_NULL_INPUT, return, " ");
157
158 if (cpl_propertylist_has(plist, qcname)){
159
160 cpl_msg_debug(cpl_func,"Statistics: %s = %g",qcname,
161 cpl_propertylist_get_double(plist,qcname));
162 }
163
164}
165
166/*----------------------------------------------------------------------------*/
181/*----------------------------------------------------------------------------*/
182static void hdrl_persistence_verify_inputs(
183 const double gain,
184 const double det_turnover,
185 const double mean_trim,
186 const cpl_boolean cleanQ,
187 const cpl_array * dates_,
188 const cpl_array * exps_,
189 const hdrl_imagelist * illums_,
190 const cpl_imagelist * srcmasks_,
191 const cpl_image * maximum,
192 const cpl_image * density,
193 const cpl_image * fullwell,
194 const cpl_table * frac)
195{
196
197 cpl_error_ensure(gain > 0.0,
198 CPL_ERROR_ILLEGAL_INPUT, return, "gain has to be larger than zero");
199
200/* Dummy check in case we need to add a check in the future without changing api */
201 cpl_error_ensure(det_turnover < DBL_MAX,
202 CPL_ERROR_ILLEGAL_INPUT, return, "det_turnover exceeds range");
203
204 cpl_error_ensure(mean_trim >= 0.0 && mean_trim < 100.0,
205 CPL_ERROR_ILLEGAL_INPUT, return, "mean_trim < 0.0 or >= 100.0");
206
207 cpl_error_ensure(cleanQ == CPL_TRUE || cleanQ == CPL_FALSE,
208 CPL_ERROR_ILLEGAL_INPUT, return, "cleanQ isn't TRUE or FALSE");
209
210 // dates_ checks
211 cpl_error_ensure(dates_, CPL_ERROR_NULL_INPUT, return, "NULL 'dates' "
212 "input");
213 const cpl_size ndates = cpl_array_get_size(dates_);
214 cpl_error_ensure(ndates > 0, CPL_ERROR_DATA_NOT_FOUND, return, "Empty "
215 "'dates' input");
216 cpl_array_delete(cpl_array_cast(dates_, CPL_TYPE_DOUBLE));
217 cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(), return,
218 "'dates' input type must be numeric");
219
220 // exps_ checks
221 cpl_error_ensure(exps_, CPL_ERROR_NULL_INPUT, return, "NULL 'exps' input");
222 const cpl_size nexps = cpl_array_get_size(exps_);
223 cpl_error_ensure(nexps > 0, CPL_ERROR_DATA_NOT_FOUND, return, "Empty "
224 "'exps' input");
225 cpl_array_delete(cpl_array_cast(exps_, CPL_TYPE_DOUBLE));
226 cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(), return,
227 "'exps' input type must be numeric");
228 cpl_error_ensure(nexps == ndates - 1, CPL_ERROR_INCOMPATIBLE_INPUT, return,
229 "'dates' should be 1 larger than 'exps'");
230
231 // illums_ checks
232 cpl_error_ensure(illums_, CPL_ERROR_NULL_INPUT, return, "NULL 'illums' "
233 "input");
234 const cpl_size nillums = hdrl_imagelist_get_size(illums_);
235 cpl_error_ensure(nillums > 0, CPL_ERROR_DATA_NOT_FOUND, return, "Empty "
236 "'illums' input");
237 cpl_error_ensure(nillums == ndates - 1, CPL_ERROR_INCOMPATIBLE_INPUT,
238 return, "'dates' should be 1 larger than 'illums'");
239 const cpl_size illum_szx = hdrl_imagelist_get_size_x(illums_);
240 const cpl_size illum_szy = hdrl_imagelist_get_size_y(illums_);
241
242 // srcmasks_ checks
243 if (srcmasks_) {
244 const cpl_size nsrcmasks = cpl_imagelist_get_size(srcmasks_);
245 cpl_error_ensure(nsrcmasks == nillums, CPL_ERROR_INCOMPATIBLE_INPUT,
246 return, "The sizes of the 'srcmasks' & "
247 "'illum' inputs differ");
248
249 for (cpl_size i=0; i<nsrcmasks; ++i) {
250 const cpl_image * srcmask = cpl_imagelist_get_const(srcmasks_, i);
251 cpl_error_ensure(srcmask, CPL_ERROR_NULL_INPUT, return, "One of "
252 "the 'srcmasks' is NULL");
253 const cpl_size src_szx = cpl_image_get_size_x(srcmask);
254 const cpl_size src_szy = cpl_image_get_size_y(srcmask);
255 cpl_error_ensure(src_szx == illum_szx && src_szy == illum_szy,
256 CPL_ERROR_INCOMPATIBLE_INPUT, return, "The dimensions of "
257 "the 'srcmasks' & 'illum' inputs differ");
258 const cpl_type src_typ = cpl_image_get_type(srcmask);
259 cpl_error_ensure(src_typ == CPL_TYPE_INT, CPL_ERROR_INVALID_TYPE,
260 return, "One of the 'srcmasks' is not of type int");
261 }
262 }
263
264 // traps_ checks
265 // maximum, density, fullwell, and frac checks: they should be non-NULL but pt to NULL
266
267 cpl_error_ensure(maximum && density && fullwell && frac, CPL_ERROR_NULL_INPUT, return, " ");
268
269 cpl_error_ensure(cpl_image_get_size_x(maximum) == illum_szx &&
270 cpl_image_get_size_y(maximum) == illum_szy,
271 CPL_ERROR_INCOMPATIBLE_INPUT, return, "Dimensions of maximum "
272 "trap map & 'illums' input differ");
273
274
275 cpl_error_ensure(cpl_image_get_size_x(density) == illum_szx &&
276 cpl_image_get_size_y(density) == illum_szy ,
277 CPL_ERROR_INCOMPATIBLE_INPUT, return, "Dimensions of trap "
278 "density map & 'illums' input differ");
279
280
281 cpl_error_ensure(cpl_image_get_size_x(fullwell) == illum_szx &&
282 cpl_image_get_size_y(fullwell) == illum_szy ,
283 CPL_ERROR_INCOMPATIBLE_INPUT, return, "Dimensions of trap "
284 "fullwell map & 'illums' input differ");
285
286
287 cpl_error_ensure(cpl_table_has_column(frac, "TAU") &&
288 cpl_table_has_column(frac, "NU"), CPL_ERROR_INCOMPATIBLE_INPUT,
289 return, "Trap fraction table missing required columns");
290 cpl_error_ensure(6==cpl_table_get_nrow(frac), CPL_ERROR_INCOMPATIBLE_INPUT,
291 return, "Trap fraction table contains wrong number of rows");
292 const cpl_type tau_t = cpl_table_get_column_type(frac, "TAU");
293 const cpl_type nu_t = cpl_table_get_column_type(frac, "NU");
294 cpl_error_ensure(tau_t == CPL_TYPE_FLOAT && nu_t == CPL_TYPE_FLOAT,
295 CPL_ERROR_INVALID_TYPE, return, "Trap fraction table columns "
296 "are of the wrong type");
297
298}
299
302/*----------------------------------------------------------------------------*/
330/*----------------------------------------------------------------------------*/
331
333 const double gain,
334 const double turnover,
335 const double mean_trim,
336 const cpl_boolean cleanQ,
337 const cpl_array * dateobs,
338 const cpl_array * exptimes,
339 hdrl_imagelist * ilist_persistence,
340 const cpl_imagelist * ilist_obj,
341 const cpl_image * maximum,
342 const cpl_image * density,
343 const cpl_image * fullwell,
344 const cpl_table * frac,
345 hdrl_image ** persistence,
346 cpl_propertylist ** persistence_qc)
347{
348
349 hdrl_persistence_verify_inputs(gain, turnover, mean_trim, cleanQ, dateobs, exptimes, ilist_persistence,
350 ilist_obj, maximum, density, fullwell, frac);
351 cpl_error_ensure(!cpl_error_get_code(), cpl_error_get_code(), return cpl_error_get_code(),
352 " ");
353
354 // load the MTM (Maximum Trap Map)
355 hdrl_image * himax = hdrl_image_create(maximum, NULL); // no ERR plane!
356 // load the TDM (Trap Density Map)
357 hdrl_image * hiden = hdrl_image_create(density, NULL); // no ERR plane!
358
359 /* Now transform images from ADUs into electrons. */
360 cpl_msg_debug(cpl_func, "Converting frames from ADUs to electrons."
361 " For this a gain of %g is used", gain);
362
363 hdrl_imagelist_mul_scalar(ilist_persistence, (hdrl_value){gain, 0.});
364 hdrl_image_mul_scalar(himax, (hdrl_value){gain, 0.});
365
366 const cpl_size nx_0 = hdrl_imagelist_get_size_x(ilist_persistence);
367 const cpl_size ny_0 = hdrl_imagelist_get_size_y(ilist_persistence);
368
369
370 // get pointers to the nu & tau values
371 const cpl_size nrows = cpl_table_get_nrow(frac);
372 const float * taud = cpl_table_get_data_float_const(frac, "TAU");
373 const float * nud = cpl_table_get_data_float_const(frac, "NU");
374 cpl_array * nus = cpl_array_wrap_float((float *)nud, nrows);
375
376 // print a few params to screen/logfile
377 cpl_msg_debug(cpl_func, "cleanQ: %s", cleanQ ? "true" : "false");
378
379 // get a few size values
380 const cpl_size nimgs = hdrl_imagelist_get_size(ilist_persistence);
381 const int n_tau = hdrl_persistence_get_time_const(nus);
382
383 // create list of Qi, Qtoti, and Qacci frames, and the Qtot1_n frame that
384 // will be the final persistence map product
385 hdrl_imagelist * Q = hdrl_persistence_create_hilist(n_tau, nx_0, ny_0);
386 hdrl_imagelist * Qacc = hdrl_persistence_create_hilist(n_tau, nx_0, ny_0);
387 hdrl_imagelist * Qtot = hdrl_persistence_create_hilist(n_tau, nx_0, ny_0);
388 hdrl_image * Qtot1_n = hdrl_image_new(nx_0, ny_0);
389
390 const hdrl_image * hizero = hdrl_image_new(nx_0, ny_0);
391 const hdrl_imagelist * himaxs =
392 hdrl_persistence_convert_max_traps(nus, himax, n_tau);
393 hdrl_image_delete(himax);
394 himax = NULL;
395 const hdrl_imagelist * hirhos =
396 hdrl_persistence_calculate_rho(nus, hiden, n_tau);
397 cpl_array_unwrap(nus);
398 nus = NULL;
399
400 const double mjdobs = cpl_array_get(dateobs, 0, NULL);
401 for (int index=0; index<nimgs; index++) {
402 const double exptime = cpl_array_get(exptimes, index, NULL);
403 const double diff_ = mjdobs - cpl_array_get(dateobs, index+1, NULL);
404 const double diff = diff_ * 24.0 * 3600.0;
405 cpl_msg_debug(cpl_func, "illumination frame #%d taken %f secs before "
406 "the correction frame", index+1, diff);
407
408 hdrl_image * hiillum = hdrl_imagelist_get(ilist_persistence, index);
409
410
411 // new_4.2:
412 // Saturated pixels having the turn-over value defined in the persistence characterisation MEF (HIERARCH ESO SAT TURNOVER),
413 // are set to their full well value given in the full well map.
414
415 /*Working on data itself - no copy! */
416
417 size_t npix = hdrl_image_get_size_x(hiillum);
418 npix *= hdrl_image_get_size_y(hiillum);
419
420 cpl_image * img = hdrl_image_get_image(hiillum);
421 double * imgd = cpl_image_get_data_double(img);
422
423 const double * fullwell_vals = NULL;
424 if (cpl_image_get_type(fullwell) != CPL_TYPE_DOUBLE) {
425 cpl_image * fullwellnew = cpl_image_cast(fullwell, CPL_TYPE_DOUBLE);
426 fullwell_vals = cpl_image_get_data_double_const(fullwellnew);
427 for (size_t i=0; i<npix; i++) {
428 imgd[i] = (imgd[i] <= turnover ? fullwell_vals[i] : imgd[i]);
429 }
430 cpl_image_delete(fullwellnew);
431 } else {
432 fullwell_vals = cpl_image_get_data_double_const(fullwell);
433 for (size_t i=0; i<npix; i++) {
434 imgd[i] = (imgd[i] <= turnover ? fullwell_vals[i] : imgd[i]);
435 }
436 }
437
438
439 hdrl_persistence_compute_qi(
440 Q, Qacc, diff, hirhos, taud, exptime, hiillum, n_tau, himaxs);
441
442 if (cleanQ) {
443 // unlike Mark's Python prototype, we don't zero bad pixels here
444 // but rather further below (outside the loop) as the last step
445 for (int j=0; j<n_tau; j++) {
446 hdrl_image * qj = hdrl_imagelist_get(Q, j);
447 // threshholding below uses the image itself as the upper limit
448 hdrl_persistence_threshhold_img(qj, hizero, qj);
449 }
450 }
451
452 if (ilist_obj) {
453 for (int j=0; j<n_tau; j++) {
454 // note: offset i (*not* j) used below
455 const cpl_image * im = cpl_imagelist_get_const(ilist_obj, index);
456 cpl_mask * sm = cpl_mask_threshold_image_create(im, -0.5, 0.5);
457 hdrl_image * qj = hdrl_imagelist_get(Q, j);
458 hdrl_persistence_zero_flagged_pixels(qj, sm, CPL_BINARY_1);
459 cpl_mask_delete(sm);
460 }
461 }
462
463 hdrl_persistence_sum_Qtots(Qtot1_n, Qtot, Q, n_tau);
464 }
465
467 himaxs = NULL;
469 hirhos = NULL;
471 Qacc = NULL;
473 Q = NULL;
474
475 // Mark's latest script does not threshhold the final Qtot1_n frame even
476 // though the cleanQtot flag is still present
477 //if (p->cleanQtot) {
478 // hdrl_image * hi = hdrl_imagelist_get(Qtot1_n, n_tau - 1);
479 // hdrl_persistence_threshhold_img(hi, hizero, hiden);
480 //}
481
482 hdrl_image_delete((hdrl_image *)hizero);
483 hizero = NULL;
484 hdrl_image_delete(hiden);
485 hiden = NULL;
486
487 *persistence = Qtot1_n;
488 *persistence_qc = hdrl_persistence_calc_stats(Qtot1_n, mean_trim);
489
490 hdrl_persistence_qc_dump(*persistence_qc, "ESO QC PERSIST MEAN");
491 hdrl_persistence_qc_dump(*persistence_qc, "ESO QC PERSIST MEANERR");
492 hdrl_persistence_qc_dump(*persistence_qc, "ESO QC PERSIST MINMAX MEAN");
493 hdrl_persistence_qc_dump(*persistence_qc, "ESO QC PERSIST MINMAX MEANERR");
494 hdrl_persistence_qc_dump(*persistence_qc, "ESO QC PERSIST SIGCLIP MEAN");
495 hdrl_persistence_qc_dump(*persistence_qc, "ESO QC PERSIST SIGCLIP MEANERR");
496 hdrl_persistence_qc_dump(*persistence_qc, "ESO QC PERSIST WEIGHTED MEAN");
497 hdrl_persistence_qc_dump(*persistence_qc, "ESO QC PERSIST WEIGHTED MEANERR");
498 hdrl_persistence_qc_dump(*persistence_qc, "ESO QC PERSIST MEDIAN");
499 hdrl_persistence_qc_dump(*persistence_qc, "ESO QC PERSIST MEDIANERR");
500 hdrl_persistence_qc_dump(*persistence_qc, "ESO QC PERSIST STD");
501 hdrl_persistence_qc_dump(*persistence_qc, "ESO QC PERSIST MIN");
502 hdrl_persistence_qc_dump(*persistence_qc, "ESO QC PERSIST MAX");
503
504 // Calculate statistics
505 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
506 cpl_propertylist_save(NULL, "hdrl_debug_persistence_qtot.fits", CPL_IO_CREATE);
507 cpl_propertylist_save(NULL, "hdrl_debug_persistence_qtot_error.fits", CPL_IO_CREATE);
508
509 for (int i=0; i<n_tau; i++) {
510 hdrl_image * qtoti = hdrl_imagelist_get(Qtot, i);
511 cpl_image * qtoti_ima = hdrl_image_get_image(qtoti);
512 cpl_image * qtoti_err = hdrl_image_get_error(qtoti);
513
514 cpl_image_save(qtoti_ima,"hdrl_debug_persistence_qtot.fits", CPL_TYPE_DOUBLE, hdrl_persistence_calc_stats(qtoti, mean_trim), CPL_IO_EXTEND );
515 cpl_image_save(qtoti_err,"hdrl_debug_persistence_qtot_error.fits", CPL_TYPE_DOUBLE, hdrl_persistence_calc_stats(qtoti, mean_trim), CPL_IO_EXTEND );
516 }
517 }
519 Qtot = NULL;
520 return cpl_error_get_code();
521}
522
523/*----------------------------------------------------------------------------*/
533/*----------------------------------------------------------------------------*/
534static void hdrl_persistence_threshhold_img(
535 hdrl_image * input,
536 const hdrl_image * lower,
537 const hdrl_image * upper)
538{
539 cpl_error_ensure(
540 input && lower && upper, CPL_ERROR_NULL_INPUT, return," ");
541
542 size_t npix = hdrl_image_get_size_x(input);
543 npix *= hdrl_image_get_size_y(input);
544
545 cpl_image * img = hdrl_image_get_image(input);
546 double * imgd = cpl_image_get_data_double(img);
547
548 const cpl_image * up = hdrl_image_get_image_const(upper);
549 const double * upper_vals = cpl_image_get_data_double_const(up);
550 const cpl_image * low = hdrl_image_get_image_const(lower);
551 const double * lower_vals = cpl_image_get_data_double_const(low);
552 HDRL_OMP(omp parallel for)
553 for (size_t i=0; i<npix; i++) {
554 imgd[i] = (imgd[i] <= upper_vals[i] ? imgd[i] : upper_vals[i]);
555 imgd[i] = (imgd[i] >= lower_vals[i] ? imgd[i] : lower_vals[i]);
556 }
557}
558
559/*---------------------------------------------------------------------------*/
560/*
561 * @param
562 */
563/*---------------------------------------------------------------------------*/
564static void hdrl_persistence_sum_Qtots(
565 hdrl_image * Qtot1_n,
566 hdrl_imagelist * Qtot,
567 const hdrl_imagelist * Q,
568 const int n_tau)
569{
570 cpl_error_ensure(Qtot1_n && Qtot && Q, CPL_ERROR_NULL_INPUT, return, " ");
571 cpl_error_ensure(n_tau > -1, CPL_ERROR_ILLEGAL_INPUT, return, " ");
572
573 for (int i=0; i<n_tau; i++) {
574 const hdrl_image * qi = hdrl_imagelist_get_const(Q, i);
575 hdrl_image_add_image(Qtot1_n, qi);
576 }
577
578 for (int i=0; i<n_tau; i++) {
579 hdrl_image * qtoti = hdrl_imagelist_get(Qtot, i);
580 const hdrl_image * qi = hdrl_imagelist_get_const(Q, i);
581 hdrl_image_add_image(qtoti, qi);
582 }
583}
584
585
586/*----------------------------------------------------------------------------*/
596/*----------------------------------------------------------------------------*/
597static void hdrl_persistence_zero_flagged_pixels(
598 hdrl_image * hdrl_img,
599 const cpl_mask * mask,
600 const cpl_binary value)
601{
602 cpl_error_ensure(hdrl_img && mask, CPL_ERROR_NULL_INPUT, return, " ");
603 cpl_error_ensure(value == CPL_BINARY_0 || value == CPL_BINARY_1,
604 CPL_ERROR_ILLEGAL_INPUT, return, " ");
605
606 size_t npix = hdrl_image_get_size_x(hdrl_img);
607 npix *= hdrl_image_get_size_y(hdrl_img);
608
609 cpl_image * img = hdrl_image_get_image(hdrl_img);
610 double * imgd = cpl_image_get_data_double(img);
611
612 const cpl_binary * mskd = cpl_mask_get_data_const(mask);
613 HDRL_OMP(omp parallel for)
614 for (size_t i=0; i<npix; i++) {
615 imgd[i] = (mskd[i] == value ? 0.00 : imgd[i]);
616 }
617}
618
619/*----------------------------------------------------------------------------*/
632/*----------------------------------------------------------------------------*/
633static void hdrl_persistence_compute_qi(
634 hdrl_imagelist * Q,
635 hdrl_imagelist * Qacc,
636 const double delt,
637 const hdrl_imagelist * hirhos,
638 const float * taud,
639 const double exptime,
640 const hdrl_image * hiillum,
641 const int n_tau,
642 const hdrl_imagelist * himaxs)
643{
644 cpl_error_ensure(Q && Qacc && hirhos && taud && hiillum && himaxs,
645 CPL_ERROR_NULL_INPUT, return, " ");
646 cpl_error_ensure(n_tau > -1, CPL_ERROR_ILLEGAL_INPUT, return, " ");
647 cpl_error_ensure(exptime > -1, CPL_ERROR_ILLEGAL_INPUT, return, " ");
648
649 for (int i=0; i<n_tau; i++) {
650 /*ToDo AGA: Please verify statement as I inverted the logic and now
651 * I get the same result as the script from Mark! */
652
653 // compute new Qi using the old Qi & old Qacci ("Then, we allow ..." in
654 // Mark's script); use of the old Qacci is why the order of this step
655 // and the next is the reverse of what's in Mark's script: if we didn't
656 // reverse the order, then we'd overwrite the old Qacci before it could
657 // be used to generate the new Qi (Mark's script doesn't have this issue
658 // because he uses an array to store the value of Qacci for every file,
659 // whereas we only store 1 instance of Qacci in order to use less memory)
660
661 // compute new Qacci using illum & rho ("We first consider ..." in
662 // Mark's script)
663 {
664 hdrl_image * QacciC = hdrl_image_duplicate(hiillum); // "current"
665 hdrl_image_mul_image(QacciC, hdrl_imagelist_get(hirhos, i));
666 const hdrl_value val = { 1.0 - exp(-exptime/taud[i]), 0.0 };
667 hdrl_image_mul_scalar(QacciC, val);
668 const hdrl_image * himax = hdrl_imagelist_get_const(himaxs, i);
669 // threshholding below uses the image itself as the lower limit
670 hdrl_persistence_threshhold_img(QacciC, QacciC, himax);
671 hdrl_imagelist_set(Qacc, QacciC, i); // deallocates "previous" and
672 // replaces with "current"
673 }
674
675 {
676 const hdrl_image * QacciP = hdrl_imagelist_get(Qacc, i);
677 hdrl_image * tmp = hdrl_image_duplicate(QacciP);
678 hdrl_value val = (hdrl_value){ exp(-delt/taud[i]), 0.0 };
679 hdrl_image_mul_scalar(tmp, val);
680 hdrl_image * Qi = hdrl_imagelist_get(Q, i);
681 hdrl_image_sub_image(tmp, Qi);
682 val = (hdrl_value){ delt/taud[i], 0.0 };
683 hdrl_image_mul_scalar(tmp, val);
684 hdrl_image_add_image(Qi, tmp);
686 }
687 }
688}
689
690/*---------------------------------------------------------------------------*/
691/*
692 * @param
693 */
694/*---------------------------------------------------------------------------*/
695static hdrl_imagelist * hdrl_persistence_create_hilist(
696 const int n,
697 const cpl_size nx,
698 const cpl_size ny)
699{
701 for (int i=0; i<n; i++) {
702 hdrl_imagelist_set(list, hdrl_image_new(nx, ny), i);
703 }
704
705 return list;
706}
707
708/*---------------------------------------------------------------------------*/
709/*
710 * @param
711 */
712/*---------------------------------------------------------------------------*/
713static int hdrl_persistence_get_time_const(
714 const cpl_array * nus)
715{
716 int n_tau = 0;
717
718 for (int i=0; i<cpl_array_get_size(nus); i++) {
719 if (cpl_array_get(nus, i, NULL) > 0) {
720 n_tau = n_tau + 1;
721 }
722 }
723
724 return n_tau;
725}
726
727/*---------------------------------------------------------------------------*/
728/*
729 * @param
730 */
731/*---------------------------------------------------------------------------*/
732static const hdrl_imagelist * hdrl_persistence_convert_max_traps(
733 const cpl_array * nus,
734 const hdrl_image * himax,
735 const int n_tau)
736{
738
739 for (int i=0; i<n_tau; i++) {
740 hdrl_image * hinew = hdrl_image_duplicate(himax);
741 const double nu_i = cpl_array_get(nus, i, NULL);
742 hdrl_image_mul_scalar(hinew, (hdrl_value){nu_i, 0.0});
743 hdrl_imagelist_set(himaxs, hinew, i);
744 }
745
746 return himaxs;
747}
748
749/*---------------------------------------------------------------------------*/
750/*
751 * @param
752 */
753/*---------------------------------------------------------------------------*/
754static hdrl_imagelist * hdrl_persistence_calculate_rho(
755 const cpl_array * nus,
756 const hdrl_image * hiden,
757 const int n_tau)
758{
760
761 for (int i=0; i<n_tau; i++) {
762 hdrl_image * hinew = hdrl_image_duplicate(hiden);
763 const double nu_i = cpl_array_get(nus, i, NULL);
764 hdrl_image_mul_scalar(hinew, (hdrl_value){nu_i, 0.0});
765 hdrl_imagelist_set(hirhos, hinew, i);
766 }
767
768 return hirhos;
769}
770
771
772/*----------------------------------------------------------------------------*/
782/*----------------------------------------------------------------------------*/
783static cpl_propertylist * hdrl_persistence_calc_stats(
784 const hdrl_image * Qtot,
785 const double trim_perc)
786{
787 cpl_error_ensure(Qtot, CPL_ERROR_NULL_INPUT, return NULL, " ");
788 cpl_error_ensure(trim_perc >= 0.0 && trim_perc < 100.0,
789 CPL_ERROR_ILLEGAL_INPUT, return NULL, "0 <= trim_perc < 100");
790
791 hdrl_image * Qtot_local = hdrl_image_duplicate(Qtot);
792
793 cpl_mask * Qtot_local_mask = hdrl_image_get_mask(Qtot_local);
794 cpl_mask * mask_threshold =
795 cpl_mask_threshold_image_create(hdrl_image_get_image(Qtot_local), 0.0, DBL_MAX);
796 cpl_mask_not(mask_threshold);
797
798 cpl_mask_or(Qtot_local_mask, mask_threshold);
799 cpl_mask_delete(mask_threshold);
800
801 cpl_propertylist * qclist = cpl_propertylist_new();
802 const int nx_0 = hdrl_image_get_size_x(Qtot_local);
803 const int ny_0 = hdrl_image_get_size_y(Qtot_local);
804 double trim = (double)floor((nx_0*ny_0)* trim_perc/2.0);
805
806 const hdrl_value mean = hdrl_image_get_mean(Qtot_local);
807 const hdrl_value minmax_mean = hdrl_image_get_minmax_mean(Qtot_local, trim, trim);
808 const hdrl_value sigclip_mean = hdrl_image_get_sigclip_mean(Qtot_local, 3., 3., 100);
809 const hdrl_value weighted_mean = hdrl_image_get_weighted_mean(Qtot_local);
810 const hdrl_value median = hdrl_image_get_median(Qtot_local);
811
812 cpl_propertylist_append_double(qclist, "ESO QC PERSIST MEAN",
813 mean.data);
814 cpl_propertylist_append_double(qclist, "ESO QC PERSIST MEANERR",
815 mean.error);
816
817 cpl_propertylist_append_double(qclist, "ESO QC PERSIST MINMAX MEAN",
818 minmax_mean.data);
819 cpl_propertylist_append_double(qclist, "ESO QC PERSIST MINMAX MEANERR",
820 minmax_mean.error);
821
822 cpl_propertylist_append_double(qclist, "ESO QC PERSIST SIGCLIP MEAN",
823 sigclip_mean.data);
824 cpl_propertylist_append_double(qclist, "ESO QC PERSIST SIGCLIP MEANERR",
825 sigclip_mean.error);
826
827 cpl_propertylist_append_double(qclist, "ESO QC PERSIST WEIGHTED MEAN",
828 weighted_mean.data);
829 cpl_propertylist_append_double(qclist, "ESO QC PERSIST WEIGHTED MEANERR",
830 weighted_mean.error);
831
832 cpl_propertylist_append_double(qclist, "ESO QC PERSIST MEDIAN",
833 median.data);
834 cpl_propertylist_append_double(qclist, "ESO QC PERSIST MEDIANERR",
835 median.error);
836
837 cpl_propertylist_append_double(qclist, "ESO QC PERSIST STD",
838 hdrl_image_get_stdev(Qtot_local));
839 cpl_propertylist_append_double(qclist, "ESO QC PERSIST MIN",
840 cpl_image_get_min(hdrl_image_get_image_const(Qtot_local)));
841 cpl_propertylist_append_double(qclist, "ESO QC PERSIST MAX",
842 cpl_image_get_max(hdrl_image_get_image_const(Qtot_local)));
843
844 hdrl_image_delete(Qtot_local);
845 return qclist;
846}
847
#define HDRL_OMP(x)
Definition hdrl_cat_def.h:35
cpl_error_code hdrl_image_sub_image(hdrl_image *self, const hdrl_image *other)
Subtract two images, store the result in the first image.
Definition hdrl_image_math.c:137
hdrl_value hdrl_image_get_median(const hdrl_image *self)
computes the median and associated error of an image.
Definition hdrl_image_math.c:501
cpl_error_code hdrl_image_add_image(hdrl_image *self, const hdrl_image *other)
Add two images, store the result in the first image.
Definition hdrl_image_math.c:59
cpl_error_code hdrl_image_mul_scalar(hdrl_image *self, hdrl_value value)
Elementwise multiplication of an image with a scalar.
Definition hdrl_image_math.c:245
hdrl_image * hdrl_image_duplicate(const hdrl_image *himg)
copy hdrl_image
Definition hdrl_image.c:391
hdrl_value hdrl_image_get_minmax_mean(const hdrl_image *self, double nlow, double nhigh)
computes the minmax rejected mean and the associated error of an image.
Definition hdrl_image_math.c:448
hdrl_value hdrl_image_get_sigclip_mean(const hdrl_image *self, double kappa_low, double kappa_high, int niter)
computes the sigma-clipped mean and associated error of an image.
Definition hdrl_image_math.c:425
double hdrl_image_get_stdev(const hdrl_image *self)
computes the standard deviation of the data of an image
Definition hdrl_image_math.c:540
cpl_mask * hdrl_image_get_mask(hdrl_image *himg)
get cpl bad pixel mask from image
Definition hdrl_image.c:157
cpl_error_code hdrl_image_mul_image(hdrl_image *self, const hdrl_image *other)
Multiply two images, store the result in the first image.
Definition hdrl_image_math.c:201
cpl_image * hdrl_image_get_error(hdrl_image *himg)
get error as cpl image
Definition hdrl_image.c:131
hdrl_value hdrl_image_get_mean(const hdrl_image *self)
computes mean pixel value and associated error of an image.
Definition hdrl_image_math.c:402
cpl_size hdrl_image_get_size_y(const hdrl_image *self)
return size of Y dimension of image
Definition hdrl_image.c:540
cpl_size hdrl_image_get_size_x(const hdrl_image *self)
return size of X dimension of image
Definition hdrl_image.c:525
hdrl_value hdrl_image_get_weighted_mean(const hdrl_image *self)
computes the weighted mean and associated error of an image.
Definition hdrl_image_math.c:520
hdrl_image * hdrl_image_create(const cpl_image *image, const cpl_image *error)
create a new hdrl_image from to existing images by copying them
Definition hdrl_image.c:295
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
Definition hdrl_image.c:105
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
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
Definition hdrl_image.c:379
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
cpl_error_code hdrl_imagelist_mul_scalar(hdrl_imagelist *himlist, hdrl_value value)
Elementwise multiplication of a scalar to each image in the himlist.
Definition hdrl_imagelist_basic.c:330
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
cpl_error_code hdrl_persistence_compute(const double gain, const double turnover, const double mean_trim, const cpl_boolean cleanQ, const cpl_array *dateobs, const cpl_array *exptimes, hdrl_imagelist *ilist_persistence, const cpl_imagelist *ilist_obj, const cpl_image *maximum, const cpl_image *density, const cpl_image *fullwell, const cpl_table *frac, hdrl_image **persistence, cpl_propertylist **persistence_qc)
generate the persistence map
Definition hdrl_persistence.c:332
Definition hdrl_image_defs.h:40
Definition hdrl_imagelist_defs.h:42
Definition hdrl_types.h:77
hdrl_error_t error
Definition hdrl_types.h:79
hdrl_data_t data
Definition hdrl_types.h:78