GIRAFFE Pipeline Reference Manual

gidark.c
1 /* $Id$
2  *
3  * This file is part of the GIRAFFE Pipeline
4  * Copyright (C) 2002-2006 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /*
22  * $Author$
23  * $Date$
24  * $Revision$
25  * $Name$
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
31 
32 #include <string.h>
33 #include <math.h>
34 
35 #include <cxlist.h>
36 
37 #include "gialias.h"
38 #include "giarray.h"
39 #include "girange.h"
40 #include "giwindow.h"
41 #include "gidark.h"
42 
43 
52 inline static cxint
53 _giraffe_halfrange_mode(cxdouble *mode, cxdouble* array, cxsize* size,
54  cxdouble portion, cxdouble epsilon)
55 {
56 
57  cxint status = 0;
58 
59  register cxsize i = 0;
60 
61  cxsize ndata = 0;
62  cxsize _size = *size;
63 
64  cxdouble tiny = CX_MAXDOUBLE;
65 
66 
67  for (i = 0; i < _size - 1; i++) {
68 
69  cxdouble t = array[i + 1] - array[i];
70 
71  if (t <= 0.) {
72  continue;
73  }
74 
75  if (t < tiny) {
76  tiny = t;
77  }
78  }
79 
80  tiny /= 2.;
81 
82  if (tiny <= epsilon) {
83  tiny = epsilon;
84  // return -1;
85  }
86 
87  if (_size < 3) {
88 
89  cxdouble _mode = 0.;
90 
91 
92  status = 0;
93 
94  switch (_size) {
95  case 2:
96  _mode = (array[0] + array[1]) / 2.;
97  break;
98 
99  case 1:
100  _mode = array[0];
101  break;
102 
103  default:
104  status = -2;
105  break;
106  }
107 
108  *mode = _mode;
109  return status;
110 
111  }
112  else {
113 
114  cxsize count = 0;
115 
116  cxdouble iwidth = array[_size - 1] - array[0];
117  cxdouble iweps = 0.;
118 
119  cx_list* intervals = NULL;
120 
121  GiRange* interval = NULL;
122 
123 
124  if (iwidth <= epsilon) {
125  *mode = giraffe_array_mean(array, _size);
126  return 0;
127  }
128 
129  iwidth *= portion;
130  iweps = iwidth + tiny;
131 
132  intervals = cx_list_new();
133 
134  i = 0;
135  while (i < _size) {
136 
137  register cxsize j = 0;
138  register cxssize k = -1;
139 
140  cxsize nvalues = 0;
141 
142  GiRange* _interval = giraffe_range_create(array[i] - tiny,
143  array[i] + iweps);
144 
145 
146  for (j = 0; j < _size; j++) {
147 
148  register cxdouble value = array[j];
149 
150 
151  if (value >= giraffe_range_get_max(_interval)) {
152  break;
153  }
154 
155  if (value <= giraffe_range_get_min(_interval)) {
156  continue;
157  }
158 
159  if (k < 0) {
160  giraffe_range_set_min(_interval, value - tiny);
161  k = j;
162  }
163 
164  }
165 
166  giraffe_range_set_max(_interval, array[j - 1] + tiny);
167  nvalues = j - k;
168 
169  if (nvalues > count) {
170 
171  cx_list_iterator position = cx_list_begin(intervals);
172  cx_list_const_iterator last = cx_list_end(intervals);
173 
174  count = nvalues;
175 
176  while (position != last) {
177  position =
178  cx_list_erase(intervals, position,
179  (cx_free_func)giraffe_range_delete);
180  }
181  cx_list_clear(intervals);
182 
183  cx_list_push_back(intervals, _interval);
184  _interval = NULL;
185 
186  }
187  else if (nvalues == count) {
188 
189  cx_list_push_back(intervals, _interval);
190  _interval = NULL;
191 
192  }
193  else {
194 
195  giraffe_range_delete(_interval);
196  _interval = NULL;
197 
198  }
199 
200  ++i;
201 
202  }
203 
204  if (cx_list_size(intervals) == 1) {
205 
206  GiRange* _interval = cx_list_front(intervals);
207 
208  cxdouble minimum = giraffe_range_get_min(_interval);
209  cxdouble maximum = giraffe_range_get_max(_interval);
210 
211  interval = giraffe_range_create(minimum, maximum);
212 
213  }
214  else {
215 
216  cxdouble minimum = 0.;
217  cxdouble maximum = 0.;
218 
219  cx_list_iterator position = cx_list_begin(intervals);
220 
221  cx_list_const_iterator last = cx_list_end(intervals);
222 
223 
224  iwidth = CX_MAXDOUBLE;
225 
226 
227  /*
228  * Find smallest intervals
229  */
230 
231  while (position != last) {
232 
233  GiRange* _interval = cx_list_get(intervals, position);
234 
235  cxdouble t = giraffe_range_get_max(_interval) -
236  giraffe_range_get_min(_interval);
237 
238 
239  if (t <= 0.) {
240  continue;
241  }
242 
243  if (t < iwidth) {
244  iwidth = t;
245  }
246 
247  position = cx_list_next(intervals, position);
248 
249  }
250 
251  iwidth += tiny;
252 
253 
254  /*
255  * Remove intervals with a larger width than iwidth.
256  */
257 
258  position = cx_list_begin(intervals);
259  last = cx_list_end(intervals);
260 
261  while (position != last) {
262 
263  GiRange* _interval = cx_list_get(intervals, position);
264 
265  cxdouble t = giraffe_range_get_max(_interval) -
266  giraffe_range_get_min(_interval);
267 
268 
269  if (t >= iwidth) {
270  position =
271  cx_list_erase(intervals, position,
272  (cx_free_func)giraffe_range_delete);
273  }
274  else {
275  position = cx_list_next(intervals, position);
276  }
277 
278  }
279 
280  minimum = giraffe_range_get_min(cx_list_front(intervals));
281  maximum = giraffe_range_get_max(cx_list_back(intervals));
282 
283  interval = giraffe_range_create(minimum, maximum);
284 
285  }
286 
287  cx_list_destroy(intervals, (cx_free_func)giraffe_range_delete);
288  intervals = NULL;
289 
290 
291  /*
292  * Discard data outside the intervals
293  */
294 
295  ndata = 0;
296 
297  for (i = 0; i < _size; i++) {
298 
299  if (array[i] < giraffe_range_get_min(interval)) {
300  continue;
301  }
302 
303  if (array[i] > giraffe_range_get_max(interval)) {
304  break;
305  }
306 
307  array[ndata++] = array[i];
308 
309  }
310 
311  giraffe_range_delete(interval);
312  interval = NULL;
313 
314 
315  if (ndata == _size) {
316 
317  cxdouble start = array[1] - array[0];
318  cxdouble end = array[ndata - 1] - array[ndata - 2];
319 
320 
321  if (fabs(start - end) < epsilon) {
322 
323  /* Remove the first and the last value */
324  ndata -=2;
325  memmove(array, &array[1], ndata * sizeof(cxdouble));
326 
327  }
328  else {
329 
330  if (start < end) {
331 
332  /* Remove last value */
333  --ndata;
334 
335  }
336  else {
337 
338  /* Remove first value */
339  --ndata;
340  memmove(array, &array[1], ndata * sizeof(cxdouble));
341 
342  }
343 
344  }
345 
346  }
347 
348  *size = ndata;
349 
350  status = _giraffe_halfrange_mode(mode, array, size, portion, epsilon);
351 
352  }
353 
354  return status;
355 
356 }
357 
358 
359 inline static cxdouble
360 _giraffe_dark_compute_mode(const cpl_image* image, const cpl_image* bpixel)
361 {
362 
363  register cxsize i = 0;
364 
365  cxint status = 0;
366 
367  cxsize ndata = cpl_image_get_size_x(image) * cpl_image_get_size_y(image);
368  cxsize count = 0;
369  cxsize nbuffer = 0;
370 
371  const cxdouble* _image = cpl_image_get_data_double_const(image);
372 
373  cxdouble mode = 0.;
374  cxdouble delta = 0.;
375  cxdouble* buffer = NULL;
376  cxdouble* sorted_image = NULL;
377 
378 
379  cx_assert(cpl_image_get_type(image) == CPL_TYPE_DOUBLE);
380 
381  sorted_image = cx_calloc(ndata, sizeof(cxdouble));
382  memcpy(sorted_image, _image, ndata * sizeof(cxdouble));
383 
384  if (bpixel != NULL) {
385 
386  const cxint* _bpixel = cpl_image_get_data_int_const(bpixel);
387 
388 
389  for (i = 0; i < ndata; i++) {
390 
391  if (_bpixel[i] == GI_BPIX_OK) {
392  sorted_image[count++] = _image[i];
393  }
394 
395  }
396 
397  }
398  else {
399  count = ndata;
400  }
401 
402  status = giraffe_array_sort(sorted_image, count);
403 
404  if (status != 0) {
405  return 0.;
406  }
407 
408 
409  buffer = cx_calloc(count, sizeof(cxdouble));
410 
411  for (i = 0; i < count; i += 1000) {
412  buffer[nbuffer++] = sorted_image[i];
413  }
414 
415 
416  // FIXME: Check whether _giraffe_halfrange_mode() needs to update the
417  // size of buffer on return!
418 
419  status = _giraffe_halfrange_mode(&mode, buffer, &nbuffer, 0.1, 1.e-9);
420 
421  delta = CX_MIN(mode / 10.,
422  (sorted_image[count - 1] - sorted_image[0]) / 2.);
423  nbuffer = count;
424 
425  while ((nbuffer > 50000) && (delta > 1.e-6)) {
426 
427  register cxsize j = 0;
428 
429  for (i = 0; i < count; i++) {
430 
431  if (sorted_image[i] < (mode - delta)) {
432  continue;
433  }
434 
435  if (sorted_image[i] > (mode + delta)) {
436  break;
437  }
438 
439  buffer[j++] = sorted_image[i];
440 
441  }
442 
443  delta /= 2.;
444 
445  if (j > 0) {
446  nbuffer = j;
447  }
448 
449  }
450 
451  if (delta > 1.e-6) {
452  status = _giraffe_halfrange_mode(&mode, buffer, &nbuffer, 0.5, 1.e-9);
453  }
454  else {
455  mode = giraffe_array_mean(buffer, nbuffer);
456  }
457 
458  cx_free(buffer);
459  buffer = NULL;
460 
461  cx_free(sorted_image);
462  sorted_image = NULL;
463 
464  return mode;
465 
466 }
467 
468 
485 cxint
486 giraffe_subtract_dark(GiImage* image, const GiImage* dark,
487  const GiImage* bpixel, GiDarkResults* data,
488  const GiDarkConfig* config)
489 {
490 
491  cxbool crop = FALSE;
492 
493  cxint nx = 0;
494  cxint ny = 0;
495 
496  cxdouble exptime = 0.;
497  cxdouble darktime = 0.;
498  cxdouble dark_max = 0.;
499  cxdouble dark_mode = 0.;
500  cxdouble dark_value = 0.;
501  cxdouble timescale = 1.;
502 
503  cpl_propertylist* properties = NULL;
504 
505  const cpl_image* _dark = NULL;
506  const cpl_image* _bpixel = NULL;
507 
508  cpl_image* _image = NULL;
509 
510 
511  if ((image == NULL) || (dark == NULL)) {
512  return -1;
513  }
514 
515  if (config == NULL) {
516  return -2;
517  }
518 
519  _image = giraffe_image_get(image);
520  _dark = giraffe_image_get(dark);
521 
522  nx = cpl_image_get_size_y(_image);
523  ny = cpl_image_get_size_x(_image);
524 
525  if ((nx != cpl_image_get_size_y(_dark)) ||
526  (ny != cpl_image_get_size_x(_dark))) {
527  return -3;
528  }
529 
530  if (bpixel != NULL) {
531 
532  GiWindow area = {1, 1, ny, nx};
533 
534  properties = giraffe_image_get_properties(bpixel);
535  _bpixel = giraffe_image_get(bpixel);
536 
537  if (cpl_propertylist_has(properties, GIALIAS_PRSCX) == TRUE) {
538  area.x0 += cpl_propertylist_get_int(properties, GIALIAS_PRSCX);
539  crop = TRUE;
540  }
541 
542  if (cpl_propertylist_has(properties, GIALIAS_PRSCY) == TRUE) {
543  area.y0 += cpl_propertylist_get_int(properties, GIALIAS_PRSCY);
544  crop = TRUE;
545  }
546 
547  if (cpl_propertylist_has(properties, GIALIAS_OVSCX) == TRUE) {
548  area.x1 = cpl_image_get_size_x(_bpixel) -
549  cpl_propertylist_get_int(properties, GIALIAS_OVSCX);
550  crop = TRUE;
551  }
552 
553  if (cpl_propertylist_has(properties, GIALIAS_OVSCY) == TRUE) {
554  area.y1 = cpl_image_get_size_y(_bpixel) -
555  cpl_propertylist_get_int(properties, GIALIAS_OVSCY);
556  crop = TRUE;
557  }
558 
559  if (crop == TRUE) {
560  _bpixel = cpl_image_extract(_bpixel, area.x0, area.y0,
561  area.x1, area.y1);
562  }
563 
564  }
565 
566 
567  /*
568  * Get the dark current time from the input image and the dark.
569  */
570 
571  properties = giraffe_image_get_properties(image);
572  cx_assert(properties != NULL);
573 
574  if (cpl_propertylist_has(properties, GIALIAS_EXPTIME) == FALSE) {
575  return 1;
576  }
577  else {
578  exptime = cpl_propertylist_get_double(properties, GIALIAS_EXPTIME);
579  }
580 
581  properties = giraffe_image_get_properties(dark);
582  cx_assert(properties != NULL);
583 
584  if (cpl_propertylist_has(properties, GIALIAS_EXPTIME) == FALSE) {
585  return 1;
586  }
587  else {
588  darktime = cpl_propertylist_get_double(properties, GIALIAS_EXPTIME);
589  }
590 
591 
592  /*
593  * Dark current scale factor
594  */
595 
596  timescale = exptime / darktime;
597 
598 
599  /*
600  * Compute mode and maximum of the dark.
601  */
602 
603  dark_max = cpl_image_get_max(_dark) * timescale;
604  dark_mode = _giraffe_dark_compute_mode(_dark, _bpixel) * timescale;
605 
606 
607  /*
608  * Correct the input image for the dark current
609  */
610 
611  switch (config->method) {
612  case GIDARK_METHOD_UNIFORM:
613 
614  if (dark_max < config->threshold) {
615 
616  /* No dark subtraction */
617 
618  dark_value = 0.;
619 
620  }
621  else {
622 
623  dark_value = dark_mode;
624  cpl_image_subtract_scalar(_image, dark_value);
625 
626  }
627  break;
628 
629  case GIDARK_METHOD_ZMASTER:
630  {
631 
632  register cxint i = 0;
633 
634  cxdouble* pximage = NULL;
635  cxdouble* pxdark = NULL;
636 
637  cpl_image* scaled_dark = cpl_image_duplicate(_dark);
638 
639  pximage = cpl_image_get_data_double(_image);
640  pxdark = cpl_image_get_data_double(scaled_dark);
641 
642  if (_bpixel == NULL) {
643 
644  register cxint j = 0;
645  register cxint n = nx * ny;
646 
647  for (j = 0; j < n; j++) {
648 
649  pxdark[j] *= timescale;
650 
651  if (pxdark[j] < config->threshold) {
652  pxdark[j] = dark_mode;
653  }
654 
655  }
656 
657  }
658  else {
659 
660  register cxint j = 0;
661  register cxint n = nx * ny;
662 
663  const cxint* pxmask = cpl_image_get_data_int_const(_bpixel);
664 
665 
666  for (j = 0; j < n; j++) {
667 
668  if ((pxmask[j] & GI_M_PIX_SET) == 0x0) {
669  pxdark[j] *= timescale;
670  }
671  else {
672  pxdark[j] = dark_mode;
673  }
674 
675  }
676 
677  }
678 
679 
680  for (i = 0; i < nx; i++) {
681 
682  register cxint j = 0;
683  register cxint base = i * ny;
684 
685  for (j = 0; j < ny; j++) {
686 
687  register cxint offset = base + j;
688 
689  pximage[offset] -= pxdark[offset];
690 
691  }
692 
693  }
694 
695  dark_mode = _giraffe_dark_compute_mode(scaled_dark, _bpixel);
696  dark_value = dark_mode;
697 
698  cpl_image_delete(scaled_dark);
699  scaled_dark = NULL;
700 
701  }
702  break;
703 
704  case GIDARK_METHOD_MASTER:
705  default:
706  {
707 
708  register cxint i = 0;
709 
710  const cxdouble* pxdark = NULL;
711 
712  cxdouble* pximage = NULL;
713 
714  pximage = cpl_image_get_data_double(_image);
715  pxdark = cpl_image_get_data_double_const(_dark);
716 
717  for (i = 0; i < nx; i++) {
718 
719  register cxint j = 0;
720  register cxint base = i * ny;
721 
722  for (j = 0; j < ny; j++) {
723 
724  register cxint offset = base + j;
725 
726  pximage[offset] -= pxdark[offset] * timescale;
727 
728  }
729 
730  }
731  }
732  break;
733 
734  }
735 
736 
737  /*
738  * Update the properties of the corrected image.
739  */
740 
741  properties = giraffe_image_get_properties(image);
742 
743  cpl_propertylist_update_double(properties, GIALIAS_DARKVALUE,
744  dark_value / timescale);
745  cpl_propertylist_set_comment(properties, GIALIAS_DARKVALUE,
746  "Used dark current [ADU/s]");
747  cpl_propertylist_update_double(properties, GIALIAS_DARKEXPECT,
748  dark_mode / timescale);
749  cpl_propertylist_set_comment(properties, GIALIAS_DARKEXPECT,
750  "Expected dark current [ADU/s]");
751 
752 
753  /*
754  * Update dark results data
755  */
756 
757  if (data != NULL) {
758  data->value = dark_value;
759  data->expected = dark_mode;
760  data->mode = dark_mode / timescale;
761  data->maximum = dark_max / timescale;
762  }
763 
764 
765  /*
766  * Cleanup
767  */
768 
769  if (crop == TRUE) {
770  cpl_image_delete((cpl_image*)_bpixel);
771  _bpixel = NULL;
772  }
773 
774 
775  return 0;
776 
777 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.12.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Mon Mar 24 2014 11:43:52 by doxygen 1.8.2 written by Dimitri van Heesch, © 1997-2004