00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include <config.h>
00024 #endif
00025
00026
00027
00028
00029 #include <stdio.h>
00030 #include <float.h>
00031 #include <math.h>
00032 #include <string.h>
00033 #include <cpl.h>
00034
00035 #include "muse_imagelist.h"
00036
00037 #include "muse_dfs.h"
00038 #include "muse_pfits.h"
00039 #include "muse_quadrants.h"
00040 #include "muse_quality.h"
00041 #include "muse_utils.h"
00042
00043
00049
00050
00053
00058
00059 muse_imagelist *
00060 muse_imagelist_new(void)
00061 {
00062 muse_imagelist *images = cpl_calloc(sizeof(muse_imagelist), 1);
00063
00064 return images;
00065 }
00066
00067
00076
00077 void
00078 muse_imagelist_delete(muse_imagelist *aList)
00079 {
00080 if (!aList) {
00081 return;
00082 }
00083 unsigned int k;
00084 for (k = 0; k < aList->size; k++) {
00085 muse_image_delete(aList->list[k]);
00086 }
00087 cpl_free(aList->list);
00088 aList->list = NULL;
00089 aList->size = 0;
00090 cpl_free(aList);
00091 }
00092
00093
00101
00102 unsigned int
00103 muse_imagelist_get_size(muse_imagelist *aList)
00104 {
00105 cpl_ensure(aList, CPL_ERROR_NULL_INPUT, 0);
00106 return aList->size;
00107 }
00108
00109
00124
00125 muse_image *
00126 muse_imagelist_get(muse_imagelist *aList, unsigned int aIdx)
00127 {
00128 cpl_ensure(aList, CPL_ERROR_NULL_INPUT, NULL);
00129 cpl_ensure(aIdx < aList->size, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
00130
00131 return aList->list[aIdx];
00132 }
00133
00134
00154
00155 cpl_error_code
00156 muse_imagelist_set(muse_imagelist *aList, muse_image *aImage, unsigned int aIdx)
00157 {
00158 cpl_ensure_code(aList && aImage, CPL_ERROR_NULL_INPUT);
00159
00160 unsigned int k;
00161 for (k = 0; k < aList->size; k++) {
00162
00163 cpl_ensure_code(aList->list[k] != aImage, CPL_ERROR_ILLEGAL_INPUT);
00164 }
00165
00166 if (aIdx >= aList->size || aList->list == NULL) {
00167 aList->list = (muse_image **)cpl_realloc(aList->list,
00168 sizeof(muse_image *) * (aIdx+1));
00169
00170 for (k = aList->size; k <= aIdx; k++) {
00171 aList->list[k] = NULL;
00172 }
00173 aList->size = aIdx + 1;
00174 }
00175
00176 muse_image_delete(aList->list[aIdx]);
00177 aList->list[aIdx] = aImage;
00178 return CPL_ERROR_NONE;
00179 }
00180
00181
00198
00199 muse_image *
00200 muse_imagelist_unset(muse_imagelist *aList, unsigned int aIdx)
00201 {
00202 cpl_ensure(aList, CPL_ERROR_NULL_INPUT, NULL);
00203 cpl_ensure(aIdx < aList->size, CPL_ERROR_ACCESS_OUT_OF_RANGE, NULL);
00204
00205
00206 muse_image *image = aList->list[aIdx];
00207
00208
00209 unsigned int k;
00210 for (k = aIdx; k < aList->size - 1; k++) {
00211 aList->list[k] = aList->list[k + 1];
00212 }
00213
00214 aList->list[aList->size - 1] = NULL;
00215
00216 aList->size--;
00217
00218 return image;
00219 }
00220
00221
00238
00239 int
00240 muse_imagelist_is_uniform(muse_imagelist *aList)
00241 {
00242 cpl_ensure(aList, CPL_ERROR_NULL_INPUT, -1);
00243 if (!aList->size) {
00244 return 1;
00245 }
00246
00247
00248 int nx = cpl_image_get_size_x(muse_imagelist_get(aList, 0)->data),
00249 ny = cpl_image_get_size_y(muse_imagelist_get(aList, 0)->data);
00250 unsigned int k;
00251 for (k = 1; k < aList->size; k++) {
00252 if (cpl_image_get_size_x(muse_imagelist_get(aList, k)->data) != nx ||
00253 cpl_image_get_size_y(muse_imagelist_get(aList, k)->data) != ny) {
00254 return k+1;
00255 }
00256 }
00257 return 0;
00258 }
00259
00260
00267
00268 void
00269 muse_imagelist_dump_statistics(muse_imagelist *aList)
00270 {
00271 if (!aList) {
00272 return;
00273 }
00274 double t0 = muse_pfits_get_exptime(muse_imagelist_get(aList, 0)->header);
00275 cpl_msg_info(__func__, " index median mean stdev scale");
00276 unsigned int k;
00277 for (k = 0; k < aList->size; k++) {
00278 muse_image *image = muse_imagelist_get(aList, k);
00279 if (!image) {
00280 const char *empty = "----------";
00281 cpl_msg_info(__func__, "%5d %10s %10s %10s %10s" , k,
00282 empty, empty, empty, empty);
00283 continue;
00284 }
00285 double t = muse_pfits_get_exptime(image->header),
00286 scale = t0 / t;
00287 cpl_msg_info(__func__, "%5d %10.2f %10.2f %10.2f %10.2f", k,
00288 cpl_image_get_median(image->data),
00289 cpl_image_get_mean(image->data),
00290 cpl_image_get_stdev(image->data), scale);
00291 }
00292 }
00293
00294
00306
00307 cpl_error_code
00308 muse_imagelist_scale_exptime(muse_imagelist *aList)
00309 {
00310 cpl_ensure_code(aList, CPL_ERROR_NULL_INPUT);
00311 double t0 = muse_pfits_get_exptime(muse_imagelist_get(aList, 0)->header);
00312 cpl_msg_info(__func__, "Scale all images to %7.2fs exposure time",
00313 t0);
00314 cpl_msg_debug(__func__, "Image EXPTIME scale");
00315 cpl_msg_debug(__func__, " 1 %7.2fs 1.000", t0);
00316 unsigned int k;
00317 for (k = 1; k < aList->size; k++) {
00318 muse_image *image = muse_imagelist_get(aList, k);
00319 double t = muse_pfits_get_exptime(image->header),
00320 scale = t0 / t;
00321 cpl_msg_debug(__func__, "%4d %7.2fs %6.3f", k+1, t, scale);
00322 muse_image_scale(image, scale);
00323 cpl_propertylist_update_double(image->header, "EXPTIME", t0);
00324 }
00325 return CPL_ERROR_NONE;
00326 }
00327
00328
00362
00363 cpl_bivector *
00364 muse_imagelist_compute_ron(muse_imagelist *aList, int aHalfsize, int aNSamples)
00365 {
00366 cpl_ensure(aList, CPL_ERROR_NULL_INPUT, NULL);
00367 unsigned int nvalues = aList->size;
00368 cpl_ensure(nvalues > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
00369 nvalues -= 1;
00370 unsigned char ifu = muse_utils_get_ifu(aList->list[0]->header);
00371
00372
00373
00374 cpl_image *ronimage = cpl_image_new(4 * 2, nvalues, CPL_TYPE_DOUBLE);
00375
00376
00377 unsigned int k;
00378 unsigned char n;
00379 for (k = 0; k < nvalues; k++) {
00380
00381 cpl_image *diff = cpl_image_subtract_create(aList->list[k]->data,
00382 aList->list[k+1]->data);
00383 for (n = 1; n <= 4; n++) {
00384
00385 double gain = muse_pfits_get_gain(aList->list[k]->header, n);
00386 cpl_size *window = muse_quadrants_get_window(aList->list[k], n);
00387 #if 0
00388 cpl_stats *s = cpl_stats_new_from_image_window(diff, CPL_STATS_ALL,
00389 window[0], window[2],
00390 window[1], window[3]);
00391 cpl_msg_debug(__func__, "Quadrant %hhu stats: %f+/-%f %f %f..%f\n", n,
00392 cpl_stats_get_mean(s), cpl_stats_get_stdev(s),
00393 cpl_stats_get_median(s),
00394 cpl_stats_get_min(s), cpl_stats_get_max(s));
00395 cpl_stats_delete(s);
00396 #endif
00397 double ron = 100., ronerr = 1000.;
00398 unsigned int niter = 0;
00399 #pragma omp critical (cpl_flux_get_noise)
00400 do {
00401 srand(niter++ * 100 + 1);
00402 cpl_flux_get_noise_window(diff, window, aHalfsize, aNSamples,
00403 &ron, &ronerr);
00404 } while (ronerr > 0.1 * ron && niter < 5);
00405 #if 0
00406 cpl_msg_debug(__func__, "--> intermediate RON=%f+/-%f (GAIN=%f)",
00407 ron, ronerr, gain);
00408 #endif
00409
00410 ron *= gain / sqrt(2);
00411 ronerr *= gain / sqrt(2);
00412 cpl_image_set(ronimage, n, k+1, ron);
00413 cpl_image_set(ronimage, n+4, k+1, ronerr);
00414 cpl_free(window);
00415 }
00416 cpl_image_delete(diff);
00417 }
00418
00419
00420 cpl_vector *ron = cpl_vector_new(4),
00421 *ronerr = cpl_vector_new(4);
00422 for (n = 1; n <= 4; n++) {
00423 #if 0
00424 cpl_stats *ronstats, *ronerrstats;
00425 ronstats = cpl_stats_new_from_image_window(ronimage, CPL_STATS_ALL,
00426 n, 1, n, nvalues);
00427 ronerrstats = cpl_stats_new_from_image_window(ronimage, CPL_STATS_ALL,
00428 n+4, 1, n+4, nvalues);
00429 cpl_msg_debug(__func__, "IFU %hhu, quadrant %hhu RON: %f+/-%f %f %f..%f\n",
00430 ifu, n, cpl_stats_get_mean(ronstats),
00431 cpl_stats_get_stdev(ronstats),
00432 cpl_stats_get_median(ronstats),
00433 cpl_stats_get_min(ronstats),
00434 cpl_stats_get_max(ronstats));
00435 cpl_msg_debug(__func__, "IFU %hhu, quadrant %hhu RONERR: %f+/-%f %f %f..%f\n",
00436 ifu, n, cpl_stats_get_mean(ronerrstats),
00437 cpl_stats_get_stdev(ronerrstats),
00438 cpl_stats_get_median(ronerrstats),
00439 cpl_stats_get_min(ronerrstats),
00440 cpl_stats_get_max(ronerrstats));
00441 cpl_stats_delete(ronstats);
00442 cpl_stats_delete(ronerrstats);
00443 #endif
00444
00445 double ronmean = cpl_image_get_mean_window(ronimage, n, 1, n, nvalues),
00446 ronmeanerr = cpl_image_get_mean_window(ronimage, n+4, 1, n+4, nvalues);
00447 cpl_vector_set(ron, n - 1, ronmean);
00448 cpl_vector_set(ronerr, n - 1, ronmeanerr);
00449
00450
00451 double ronheader = muse_pfits_get_ron(aList->list[0]->header, n);
00452 if (ronmean < 1. || ronmean > 5.) {
00453 cpl_msg_warning(__func__, "The RON value computed for quadrant %hhu in "
00454 "IFU %hhu is likely wrong (outside the range 1..5 count: "
00455 "%.2f +/- %.2f count; the raw header says %.2f count)", n,
00456 ifu, ronmean, ronmeanerr, ronheader);
00457 }
00458 }
00459 cpl_image_delete(ronimage);
00460
00461
00462 nvalues = muse_imagelist_get_size(aList);
00463 for (k = 0; k < nvalues; k++) {
00464 for (n = 1; n <= 4; n++) {
00465 double gain = muse_pfits_get_gain(aList->list[k]->header, n);
00466
00467
00468
00469
00470 double variance = (1. + 1. / (pow(2 * aHalfsize + 1, 2) * aNSamples))
00471 * pow(cpl_vector_get(ron, n-1)/gain, 2);
00472 if (k == 0) {
00473 cpl_msg_info(__func__, "IFU %hhu, quadrant %hhu: RON = %.3f +/- %.3f "
00474 "count ==> variance = %.4f adu**2 (1st value of image "
00475 "series)", ifu, n, cpl_vector_get(ron, n-1),
00476 cpl_vector_get(ronerr, n-1), variance);
00477 }
00478
00479 cpl_size *window = muse_quadrants_get_window(aList->list[k], n);
00480
00481 cpl_image_fill_window(aList->list[k]->stat, window[0], window[2],
00482 window[1], window[3], variance);
00483 cpl_free(window);
00484 }
00485 }
00486
00487 return cpl_bivector_wrap_vectors(ron, ronerr);
00488 }
00489