GIRAFFE Pipeline Reference Manual

gidark.c

00001 /* $Id: gidark.c,v 1.5 2008/02/18 09:41:02 rpalsa Exp $
00002  *
00003  * This file is part of the GIRAFFE Pipeline
00004  * Copyright (C) 2002-2006 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 /*
00022  * $Author: rpalsa $
00023  * $Date: 2008/02/18 09:41:02 $
00024  * $Revision: 1.5 $
00025  * $Name: giraffe-2_9 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #  include <config.h>
00030 #endif
00031 
00032 #include <string.h>
00033 #include <math.h>
00034 
00035 #include <cxlist.h>
00036 
00037 #include "gialias.h"
00038 #include "giarray.h"
00039 #include "girange.h"
00040 #include "giwindow.h"
00041 #include "gidark.h"
00042 
00043 
00052 inline static cxint
00053 _giraffe_halfrange_mode(cxdouble *mode, cxdouble* array, cxsize* size,
00054                         cxdouble portion, cxdouble epsilon)
00055 {
00056 
00057     cxint status = 0;
00058 
00059     register cxsize i = 0;
00060 
00061     cxsize ndata = 0;
00062     cxsize _size = *size;
00063 
00064     cxdouble tiny = CX_MAXDOUBLE;
00065 
00066 
00067     for (i = 0; i < _size - 1; i++) {
00068 
00069         cxdouble t = array[i + 1] - array[i];
00070 
00071         if (t <= 0.) {
00072             continue;
00073         }
00074 
00075         if (t < tiny) {
00076             tiny = t;
00077         }
00078     }
00079 
00080     tiny /= 2.;
00081 
00082     if (tiny <= epsilon) {
00083         tiny = epsilon;
00084         //        return -1;
00085     }
00086 
00087     if (_size < 3) {
00088 
00089         cxdouble _mode = 0.;
00090 
00091 
00092         status = 0;
00093 
00094         switch (_size) {
00095         case 2:
00096             _mode = (array[0] + array[1]) / 2.;
00097             break;
00098 
00099         case 1:
00100             _mode = array[0];
00101             break;
00102 
00103         default:
00104             status = -2;
00105             break;
00106         }
00107 
00108         *mode = _mode;
00109         return status;
00110 
00111     }
00112     else {
00113 
00114         cxsize count = 0;
00115 
00116         cxdouble iwidth = array[_size - 1] - array[0];
00117         cxdouble iweps = 0.;
00118 
00119         cx_list* intervals = NULL;
00120 
00121         GiRange* interval = NULL;
00122 
00123 
00124         if (iwidth <= epsilon) {
00125             *mode = giraffe_array_mean(array, _size);
00126             return 0;
00127         }
00128 
00129         iwidth *= portion;
00130         iweps = iwidth + tiny;
00131 
00132         intervals = cx_list_new();
00133 
00134         i = 0;
00135         while (i < _size) {
00136 
00137             register cxsize j = 0;
00138             register cxssize k = -1;
00139 
00140             cxsize nvalues = 0;
00141 
00142             GiRange* _interval = giraffe_range_create(array[i] - tiny,
00143                                                       array[i] + iweps);
00144 
00145 
00146             for (j = 0; j < _size; j++) {
00147 
00148                 register cxdouble value = array[j];
00149 
00150 
00151                 if (value >= giraffe_range_get_max(_interval)) {
00152                     break;
00153                 }
00154 
00155                 if (value <= giraffe_range_get_min(_interval)) {
00156                     continue;
00157                 }
00158 
00159                 if (k < 0) {
00160                     giraffe_range_set_min(_interval, value - tiny);
00161                     k = j;
00162                 }
00163 
00164             }
00165 
00166             giraffe_range_set_max(_interval, array[j - 1] + tiny);
00167             nvalues = j - k;
00168 
00169             if (nvalues > count) {
00170 
00171                 cx_list_iterator position = cx_list_begin(intervals);
00172                 cx_list_const_iterator last = cx_list_end(intervals);
00173 
00174                 count = nvalues;
00175 
00176                 while (position != last) {
00177                     position =
00178                         cx_list_erase(intervals, position,
00179                                       (cx_free_func)giraffe_range_delete);
00180                 }
00181                 cx_list_clear(intervals);
00182 
00183                 cx_list_push_back(intervals, _interval);
00184                 _interval = NULL;
00185 
00186             }
00187             else if (nvalues == count) {
00188 
00189                 cx_list_push_back(intervals, _interval);
00190                 _interval = NULL;
00191 
00192             }
00193             else {
00194 
00195                 giraffe_range_delete(_interval);
00196                 _interval = NULL;
00197 
00198             }
00199 
00200             ++i;
00201 
00202         }
00203 
00204         if (cx_list_size(intervals) == 1) {
00205 
00206             GiRange* _interval = cx_list_front(intervals);
00207 
00208             cxdouble minimum = giraffe_range_get_min(_interval);
00209             cxdouble maximum = giraffe_range_get_max(_interval);
00210 
00211             interval = giraffe_range_create(minimum, maximum);
00212 
00213         }
00214         else {
00215 
00216             cxdouble minimum = 0.;
00217             cxdouble maximum = 0.;
00218 
00219             cx_list_iterator position = cx_list_begin(intervals);
00220 
00221             cx_list_const_iterator last = cx_list_end(intervals);
00222 
00223 
00224             iwidth = CX_MAXDOUBLE;
00225 
00226 
00227             /*
00228              * Find smallest intervals
00229              */
00230 
00231             while (position != last) {
00232 
00233                 GiRange* _interval = cx_list_get(intervals, position);
00234 
00235                 cxdouble t = giraffe_range_get_max(_interval) -
00236                     giraffe_range_get_min(_interval);
00237 
00238 
00239                 if (t <= 0.) {
00240                     continue;
00241                 }
00242 
00243                 if (t < iwidth) {
00244                     iwidth = t;
00245                 }
00246 
00247                 position = cx_list_next(intervals, position);
00248 
00249             }
00250 
00251             iwidth += tiny;
00252 
00253 
00254             /*
00255              * Remove intervals with a larger width than iwidth.
00256              */
00257 
00258             position = cx_list_begin(intervals);
00259             last = cx_list_end(intervals);
00260 
00261             while (position != last) {
00262 
00263                 GiRange* _interval = cx_list_get(intervals, position);
00264 
00265                 cxdouble t = giraffe_range_get_max(_interval) -
00266                     giraffe_range_get_min(_interval);
00267 
00268 
00269                 if (t >= iwidth) {
00270                     position =
00271                         cx_list_erase(intervals, position,
00272                                       (cx_free_func)giraffe_range_delete);
00273                 }
00274                 else {
00275                     position = cx_list_next(intervals, position);
00276                 }
00277 
00278             }
00279 
00280             minimum = giraffe_range_get_min(cx_list_front(intervals));
00281             maximum = giraffe_range_get_max(cx_list_back(intervals));
00282 
00283             interval = giraffe_range_create(minimum, maximum);
00284 
00285         }
00286 
00287         cx_list_destroy(intervals, (cx_free_func)giraffe_range_delete);
00288         intervals = NULL;
00289 
00290 
00291         /*
00292          * Discard data outside the intervals
00293          */
00294 
00295         ndata = 0;
00296 
00297         for (i = 0; i < _size; i++) {
00298 
00299             if (array[i] < giraffe_range_get_min(interval)) {
00300                 continue;
00301             }
00302 
00303             if (array[i] > giraffe_range_get_max(interval)) {
00304                 break;
00305             }
00306 
00307             array[ndata++] = array[i];
00308 
00309         }
00310 
00311         giraffe_range_delete(interval);
00312         interval = NULL;
00313 
00314 
00315         if (ndata == _size) {
00316 
00317             cxdouble start = array[1] - array[0];
00318             cxdouble end = array[ndata - 1] - array[ndata - 2];
00319 
00320 
00321             if (fabs(start - end) < epsilon) {
00322 
00323                 /* Remove the first and the last value */
00324                 ndata -=2;
00325                 memmove(array, &array[1], ndata * sizeof(cxdouble));
00326 
00327             }
00328             else {
00329 
00330                 if (start < end) {
00331 
00332                     /* Remove last value */
00333                     --ndata;
00334 
00335                 }
00336                 else {
00337 
00338                     /* Remove first value */
00339                     --ndata;
00340                     memmove(array, &array[1], ndata * sizeof(cxdouble));
00341 
00342                 }
00343 
00344             }
00345 
00346         }
00347 
00348         *size = ndata;
00349 
00350         status = _giraffe_halfrange_mode(mode, array, size, portion, epsilon);
00351 
00352     }
00353 
00354     return status;
00355 
00356 }
00357 
00358 
00359 inline static cxdouble
00360 _giraffe_dark_compute_mode(const cpl_image* image, const cpl_image* bpixel)
00361 {
00362 
00363     register cxsize i = 0;
00364 
00365     cxint status = 0;
00366 
00367     cxsize ndata = cpl_image_get_size_x(image) * cpl_image_get_size_y(image);
00368     cxsize count = 0;
00369     cxsize nbuffer = 0;
00370 
00371     const cxdouble* _image = cpl_image_get_data_double_const(image);
00372 
00373     cxdouble mode = 0.;
00374     cxdouble delta = 0.;
00375     cxdouble* buffer = NULL;
00376     cxdouble* sorted_image = NULL;
00377 
00378 
00379     cx_assert(cpl_image_get_type(image) == CPL_TYPE_DOUBLE);
00380 
00381     sorted_image = cx_calloc(ndata, sizeof(cxdouble));
00382     memcpy(sorted_image, _image, ndata * sizeof(cxdouble));
00383 
00384     if (bpixel != NULL) {
00385 
00386         const cxint* _bpixel = cpl_image_get_data_int_const(bpixel);
00387 
00388 
00389         for (i = 0; i < ndata; i++) {
00390 
00391             if (_bpixel[i] == GI_BPIX_OK) {
00392                 sorted_image[count++] = _image[i];
00393             }
00394 
00395         }
00396 
00397     }
00398     else {
00399         count = ndata;
00400     }
00401 
00402     status = giraffe_array_sort(sorted_image, count);
00403 
00404     if (status != 0) {
00405         return 0.;
00406     }
00407 
00408 
00409     buffer = cx_calloc(count, sizeof(cxdouble));
00410 
00411     for (i = 0; i < count; i += 1000) {
00412         buffer[nbuffer++] = sorted_image[i];
00413     }
00414 
00415 
00416     // FIXME: Check whether _giraffe_halfrange_mode() needs to update the
00417     //        size of buffer on return!
00418 
00419     status = _giraffe_halfrange_mode(&mode, buffer, &nbuffer, 0.1, 1.e-9);
00420 
00421     delta = CX_MIN(mode / 10.,
00422                    (sorted_image[count - 1] - sorted_image[0]) / 2.);
00423     nbuffer = count;
00424 
00425     while ((nbuffer > 50000) && (delta > 1.e-6)) {
00426 
00427         register cxsize j = 0;
00428 
00429         for (i = 0; i < count; i++) {
00430 
00431             if (sorted_image[i] < (mode - delta)) {
00432                 continue;
00433             }
00434 
00435             if (sorted_image[i] > (mode + delta)) {
00436                 break;
00437             }
00438 
00439             buffer[j++] = sorted_image[i];
00440 
00441         }
00442 
00443         delta /= 2.;
00444 
00445         if (j > 0) {
00446             nbuffer = j;
00447         }
00448 
00449     }
00450 
00451     if (delta > 1.e-6) {
00452         status = _giraffe_halfrange_mode(&mode, buffer, &nbuffer, 0.5, 1.e-9);
00453     }
00454     else {
00455         mode = giraffe_array_mean(buffer, nbuffer);
00456     }
00457 
00458     cx_free(buffer);
00459     buffer = NULL;
00460 
00461     cx_free(sorted_image);
00462     sorted_image = NULL;
00463 
00464     return mode;
00465 
00466 }
00467 
00468 
00485 cxint
00486 giraffe_subtract_dark(GiImage* image, const GiImage* dark,
00487                       const GiImage* bpixel, GiDarkResults* data,
00488                       const GiDarkConfig* config)
00489 {
00490 
00491     cxbool crop = FALSE;
00492 
00493     cxint nx = 0;
00494     cxint ny = 0;
00495 
00496     cxdouble exptime = 0.;
00497     cxdouble darktime = 0.;
00498     cxdouble dark_max = 0.;
00499     cxdouble dark_mode = 0.;
00500     cxdouble dark_value = 0.;
00501     cxdouble timescale = 1.;
00502 
00503     cpl_propertylist* properties = NULL;
00504 
00505     const cpl_image* _dark = NULL;
00506     const cpl_image* _bpixel = NULL;
00507 
00508     cpl_image* _image = NULL;
00509 
00510 
00511     if ((image == NULL) || (dark == NULL)) {
00512         return -1;
00513     }
00514 
00515     if (config == NULL) {
00516         return -2;
00517     }
00518 
00519     _image = giraffe_image_get(image);
00520     _dark = giraffe_image_get(dark);
00521 
00522     nx = cpl_image_get_size_y(_image);
00523     ny = cpl_image_get_size_x(_image);
00524 
00525     if ((nx != cpl_image_get_size_y(_dark)) ||
00526         (ny != cpl_image_get_size_x(_dark))) {
00527             return -3;
00528     }
00529 
00530     if (bpixel != NULL) {
00531 
00532         GiWindow area = {1, 1, ny, nx};
00533 
00534         properties = giraffe_image_get_properties(bpixel);
00535         _bpixel = giraffe_image_get(bpixel);
00536 
00537         if (cpl_propertylist_has(properties, GIALIAS_PRSCX) == TRUE) {
00538             area.x0 += cpl_propertylist_get_int(properties, GIALIAS_PRSCX);
00539             crop = TRUE;
00540         }
00541 
00542         if (cpl_propertylist_has(properties, GIALIAS_PRSCY) == TRUE) {
00543             area.y0 += cpl_propertylist_get_int(properties, GIALIAS_PRSCY);
00544             crop = TRUE;
00545         }
00546 
00547         if (cpl_propertylist_has(properties, GIALIAS_OVSCX) == TRUE) {
00548             area.x1 = cpl_image_get_size_x(_bpixel) -
00549                 cpl_propertylist_get_int(properties, GIALIAS_OVSCX);
00550             crop = TRUE;
00551         }
00552 
00553         if (cpl_propertylist_has(properties, GIALIAS_OVSCY) == TRUE) {
00554             area.y1 = cpl_image_get_size_y(_bpixel) -
00555                 cpl_propertylist_get_int(properties, GIALIAS_OVSCY);
00556             crop = TRUE;
00557         }
00558 
00559         if (crop == TRUE) {
00560             _bpixel = cpl_image_extract(_bpixel, area.x0, area.y0,
00561                                         area.x1, area.y1);
00562         }
00563 
00564     }
00565 
00566 
00567     /*
00568      * Get the dark current time from the input image and the dark.
00569      */
00570 
00571     properties = giraffe_image_get_properties(image);
00572     cx_assert(properties != NULL);
00573 
00574     if (cpl_propertylist_has(properties, GIALIAS_EXPTIME) == FALSE) {
00575         return 1;
00576     }
00577     else {
00578         exptime = cpl_propertylist_get_double(properties, GIALIAS_EXPTIME);
00579     }
00580 
00581     properties = giraffe_image_get_properties(dark);
00582     cx_assert(properties != NULL);
00583 
00584     if (cpl_propertylist_has(properties, GIALIAS_EXPTIME) == FALSE) {
00585         return 1;
00586     }
00587     else {
00588         darktime = cpl_propertylist_get_double(properties, GIALIAS_EXPTIME);
00589     }
00590 
00591 
00592     /*
00593      * Dark current scale factor
00594      */
00595 
00596     timescale = exptime / darktime;
00597 
00598 
00599     /*
00600      * Compute mode and maximum of the dark.
00601      */
00602 
00603     dark_max = cpl_image_get_max(_dark) * timescale;
00604     dark_mode = _giraffe_dark_compute_mode(_dark, _bpixel) * timescale;
00605 
00606 
00607     /*
00608      * Correct the input image for the dark current
00609      */
00610 
00611     switch (config->method) {
00612     case GIDARK_METHOD_UNIFORM:
00613 
00614         if (dark_max < config->threshold) {
00615 
00616             /* No dark subtraction */
00617 
00618             dark_value = 0.;
00619 
00620         }
00621         else {
00622 
00623             dark_value = dark_mode;
00624             cpl_image_subtract_scalar(_image, dark_value);
00625 
00626         }
00627         break;
00628 
00629     case GIDARK_METHOD_ZMASTER:
00630         {
00631 
00632             register cxint i = 0;
00633 
00634             cxdouble* pximage = NULL;
00635             cxdouble* pxdark = NULL;
00636 
00637             cpl_image* scaled_dark = cpl_image_duplicate(_dark);
00638 
00639             pximage = cpl_image_get_data_double(_image);
00640             pxdark = cpl_image_get_data_double(scaled_dark);
00641 
00642             if (_bpixel == NULL) {
00643 
00644                 register cxint j = 0;
00645                 register cxint n = nx * ny;
00646 
00647                 for (j = 0; j < n; j++) {
00648 
00649                     pxdark[j] *= timescale;
00650 
00651                     if (pxdark[j] < config->threshold) {
00652                         pxdark[j] = dark_mode;
00653                     }
00654 
00655                 }
00656 
00657             }
00658             else {
00659 
00660                 register cxint j = 0;
00661                 register cxint n = nx * ny;
00662 
00663                 const cxint* pxmask = cpl_image_get_data_int_const(_bpixel);
00664 
00665 
00666                 for (j = 0; j < n; j++) {
00667 
00668                     if ((pxmask[j] & GI_M_PIX_SET) == 0x0) {
00669                         pxdark[j] *= timescale;
00670                     }
00671                     else {
00672                         pxdark[j] = dark_mode;
00673                     }
00674 
00675                 }
00676 
00677             }
00678 
00679 
00680             for (i = 0; i < nx; i++) {
00681 
00682                 register cxint j = 0;
00683                 register cxint base = i * ny;
00684 
00685                 for (j = 0; j < ny; j++) {
00686 
00687                     register cxint offset = base + j;
00688 
00689                     pximage[offset] -= pxdark[offset];
00690 
00691                 }
00692 
00693             }
00694 
00695             dark_mode = _giraffe_dark_compute_mode(scaled_dark, _bpixel);
00696             dark_value = dark_mode;
00697 
00698             cpl_image_delete(scaled_dark);
00699             scaled_dark = NULL;
00700 
00701         }
00702         break;
00703 
00704     case GIDARK_METHOD_MASTER:
00705     default:
00706         {
00707 
00708             register cxint i = 0;
00709 
00710             const cxdouble* pxdark = NULL;
00711 
00712             cxdouble* pximage = NULL;
00713 
00714             pximage = cpl_image_get_data_double(_image);
00715             pxdark = cpl_image_get_data_double_const(_dark);
00716 
00717             for (i = 0; i < nx; i++) {
00718 
00719                 register cxint j = 0;
00720                 register cxint base = i * ny;
00721 
00722                 for (j = 0; j < ny; j++) {
00723 
00724                     register cxint offset = base + j;
00725 
00726                     pximage[offset] -= pxdark[offset] * timescale;
00727 
00728                 }
00729 
00730             }
00731         }
00732         break;
00733 
00734     }
00735 
00736 
00737     /*
00738      * Update the properties of the corrected image.
00739      */
00740 
00741     properties = giraffe_image_get_properties(image);
00742 
00743     cpl_propertylist_update_double(properties, GIALIAS_DARKVALUE,
00744                                    dark_value / timescale);
00745     cpl_propertylist_set_comment(properties, GIALIAS_DARKVALUE,
00746                                  "Used dark current [ADU/s]");
00747     cpl_propertylist_update_double(properties, GIALIAS_DARKEXPECT,
00748                                    dark_mode / timescale);
00749     cpl_propertylist_set_comment(properties, GIALIAS_DARKEXPECT,
00750                                  "Expected dark current [ADU/s]");
00751 
00752 
00753     /*
00754      * Update dark results data
00755      */
00756 
00757     if (data != NULL) {
00758         data->value = dark_value;
00759         data->expected = dark_mode;
00760         data->mode = dark_mode / timescale;
00761         data->maximum = dark_max / timescale;
00762     }
00763 
00764 
00765     /*
00766      * Cleanup
00767      */
00768 
00769     if (crop == TRUE) {
00770         cpl_image_delete((cpl_image*)_bpixel);
00771         _bpixel = NULL;
00772     }
00773 
00774 
00775     return 0;
00776 
00777 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.9.0.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Jan 26 14:20:27 2012 by doxygen 1.6.3 written by Dimitri van Heesch, © 1997-2004