00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include <math.h>
00037 #include <string.h>
00038 #include "irplib_mkmaster.h"
00039
00040
00044
00045
00047
00054
00055
00056
00068
00069 static cpl_vector *
00070 irplib_imagelist_get_clean_mean_levels(const cpl_imagelist* iml,
00071 const double kappa,
00072 const int nclip,
00073 const double tolerance)
00074 {
00075
00076 const cpl_image* img=NULL;
00077 int size=0;
00078 int i=0;
00079 cpl_vector* levels=NULL;
00080 double* pval=NULL;
00081 double mean=0;
00082 double stdev=0;
00083
00084
00085 cpl_error_ensure(iml != NULL, CPL_ERROR_NULL_INPUT, return(levels),
00086 "Null input image list");
00087 cpl_error_ensure(kappa >= 0, CPL_ERROR_ILLEGAL_INPUT, return(levels),
00088 "Must be kappa>0");
00089
00090 size=cpl_imagelist_get_size(iml);
00091 levels=cpl_vector_new(size);
00092 pval=cpl_vector_get_data(levels);
00093
00094 for(i=0;i<size;i++) {
00095 img=cpl_imagelist_get_const(iml,i);
00096 irplib_ksigma_clip(img,1,1,
00097 cpl_image_get_size_x(img),
00098 cpl_image_get_size_y(img),
00099 nclip,kappa,tolerance,&mean,&stdev);
00100 cpl_msg_info(cpl_func,"Ima %d mean level: %g",i+1,mean);
00101 pval[i]=mean;
00102 }
00103
00104
00105 return levels;
00106 }
00107
00108
00116
00117 static cpl_error_code
00118 irplib_imagelist_subtract_values(cpl_imagelist** iml, cpl_vector* values)
00119 {
00120
00121 cpl_image* img=NULL;
00122 int size=0;
00123 int i=0;
00124 double* pval=NULL;
00125
00126 size=cpl_imagelist_get_size(*iml);
00127 pval=cpl_vector_get_data(values);
00128
00129 for(i=0;i<size;i++) {
00130 img=cpl_imagelist_get(*iml,i);
00131 cpl_image_subtract_scalar(img,pval[i]);
00132 cpl_imagelist_set(*iml,img,i);
00133 }
00134
00135 return cpl_error_get_code();
00136 }
00137
00138
00151
00152 static double
00153 irplib_vector_ksigma(cpl_vector *values,
00154 const double klow, const double khigh, int kiter)
00155 {
00156 cpl_vector *accepted;
00157 double mean = 0.0;
00158 double sigma = 0.0;
00159 double *data = cpl_vector_get_data(values);
00160 int n = cpl_vector_get_size(values);
00161 int ngood = n;
00162 int count = 0;
00163 int i;
00164
00165
00166
00167
00168
00169
00170 mean = cpl_vector_get_median(values);
00171
00172 for (i = 0; i < n; i++) {
00173 sigma += (mean - data[i]) * (mean - data[i]);
00174 }
00175 sigma = sqrt(sigma / (n - 1));
00176
00177 while (kiter) {
00178 count = 0;
00179 for (i = 0; i < ngood; i++) {
00180 if (data[i]-mean < khigh*sigma && mean-data[i] < klow*sigma) {
00181 data[count] = data[i];
00182 ++count;
00183 }
00184 }
00185
00186 if (count == 0)
00187 break;
00188
00189
00190
00191
00192
00193
00194
00195 accepted = cpl_vector_wrap(count, data);
00196 mean = cpl_vector_get_mean(accepted);
00197 if(count>1) {
00198 sigma = cpl_vector_get_stdev(accepted);
00199 }
00200 cpl_vector_unwrap(accepted);
00201
00202 if (count == ngood) {
00203 break;
00204 }
00205 ngood = count;
00206 --kiter;
00207 }
00208
00209 return mean;
00210 }
00211
00212
00231 static cpl_image *
00232 irplib_imagelist_ksigma_stack(const cpl_imagelist *imlist,
00233 double klow, double khigh, int kiter)
00234 {
00235 int ni, nx, ny, npix;
00236 cpl_image *out_ima=NULL;
00237 cpl_imagelist *loc_iml=NULL;
00238 double *pout_ima=NULL;
00239 cpl_image *image=NULL;
00240 const double **data=NULL;
00241 double *med=NULL;
00242 cpl_vector *time_line=NULL;
00243
00244 double *ptime_line=NULL;
00245 int i, j;
00246 double mean_of_medians=0;
00247
00248 cpl_error_ensure(imlist != NULL, CPL_ERROR_NULL_INPUT, return(out_ima),
00249 "Null input image list");
00250
00251 ni = cpl_imagelist_get_size(imlist);
00252 loc_iml = cpl_imagelist_duplicate(imlist);
00253 image = cpl_imagelist_get(loc_iml, 0);
00254 nx = cpl_image_get_size_x(image);
00255 ny = cpl_image_get_size_y(image);
00256 npix = nx * ny;
00257
00258 out_ima = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00259 pout_ima = cpl_image_get_data_double(out_ima);
00260
00261 time_line = cpl_vector_new(ni);
00262
00263 ptime_line = cpl_vector_get_data(time_line);
00264
00265 data = cpl_calloc(sizeof(double *), ni);
00266 med = cpl_calloc(sizeof(double), ni);
00267
00268 for (i = 0; i < ni; i++) {
00269 image = cpl_imagelist_get(loc_iml, i);
00270 med[i]=cpl_image_get_median(image);
00271 cpl_image_subtract_scalar(image,med[i]);
00272 data[i] = cpl_image_get_data_double(image);
00273 mean_of_medians+=med[i];
00274 }
00275 mean_of_medians/=ni;
00276
00277 for (i = 0; i < npix; i++) {
00278 for (j = 0; j < ni; j++) {
00279 ptime_line[j] = data[j][i];
00280 }
00281 pout_ima[i] = irplib_vector_ksigma(time_line, klow, khigh, kiter);
00282 }
00283
00284 cpl_image_add_scalar(out_ima,mean_of_medians);
00285
00286
00287 cpl_free(data);
00288 cpl_free(med);
00289 cpl_vector_delete(time_line);
00290 cpl_imagelist_delete(loc_iml);
00291
00292 return out_ima;
00293
00294 }
00295
00296
00297
00298
00299
00311
00312 cpl_image*
00313 irplib_mkmaster_mean(cpl_imagelist* images,const double kappa, const int nclip, const double tolerance,const double klow,const double khigh,const int niter)
00314 {
00315
00316 cpl_image* master=NULL;
00317 cpl_vector* levels=NULL;
00318 double mean=0;
00319 cpl_imagelist* iml=NULL;
00320
00321 cpl_msg_info(cpl_func,"method mean");
00322 iml=cpl_imagelist_duplicate(images);
00323 levels=irplib_imagelist_get_clean_mean_levels(iml,kappa,nclip,tolerance);
00324 mean=cpl_vector_get_mean(levels);
00325 cpl_msg_info(cpl_func,"Master mean level: %g",mean);
00326
00327 irplib_imagelist_subtract_values(&iml,levels);
00328
00329 master = irplib_imagelist_ksigma_stack(iml,klow,khigh,niter);
00330 cpl_image_add_scalar(master,mean);
00331
00332 cpl_vector_delete(levels);
00333 cpl_imagelist_delete(iml);
00334 return master;
00335
00336 }
00337
00338
00350
00351 cpl_image*
00352 irplib_mkmaster_median(cpl_imagelist* images,const double kappa, const int nclip, const double tolerance)
00353 {
00354
00355 cpl_image* master=NULL;
00356 cpl_vector* levels=NULL;
00357 double mean=0;
00358 cpl_imagelist* iml=NULL;
00359
00360 cpl_msg_info(cpl_func,"method median");
00361 iml=cpl_imagelist_duplicate(images);
00362 levels=irplib_imagelist_get_clean_mean_levels(iml,kappa,nclip,tolerance);
00363
00364 mean=cpl_vector_get_mean(levels);
00365 cpl_msg_info(cpl_func,"Master mean level: %g",mean);
00366 irplib_imagelist_subtract_values(&iml,levels);
00367
00368 master = cpl_imagelist_collapse_median_create(iml);
00369
00370 cpl_image_add_scalar(master,mean);
00371
00372 cpl_vector_delete(levels);
00373 cpl_imagelist_delete(iml);
00374
00375 return master;
00376
00377 }
00378
00379
00380 static cpl_error_code
00381 irplib_mkmaster_dark_qc(const cpl_imagelist* raw_images,
00382 cpl_imagelist* preproc_images,
00383 const cpl_parameterlist* parameters,
00384 const int pr_num_x, const int pr_num_y,
00385 const int pr_box_sx, const int pr_box_sy, const char* recipe_id,
00386 cpl_table* qclog) {
00387
00388 cpl_ensure_code(qclog !=NULL, CPL_ERROR_NULL_INPUT);
00389 cpl_ensure_code(recipe_id !=NULL, CPL_ERROR_NULL_INPUT);
00390 cpl_ensure_code(parameters !=NULL, CPL_ERROR_NULL_INPUT);
00391
00392 int i = 0;
00393 cpl_image* current_dark = 0;
00394 if (pr_num_x != 0 && pr_num_y != 0 && pr_box_sx != 0 && pr_box_sy != 0) {
00395 for (i = 0; i < cpl_imagelist_get_size(raw_images); i++) {
00396 current_dark = cpl_image_duplicate(
00397 cpl_imagelist_get_const(preproc_images, i));
00398 cpl_msg_info(cpl_func, "Calculating QC parameters on raw dark frame %d",
00399 i);
00400
00401
00402
00403
00404
00405 cpl_image_delete(current_dark);
00406 }
00407 }
00408 return cpl_error_get_code();
00409 }
00410
00411
00421
00422 static double
00423 irplib_head_get_exptime(const cpl_propertylist * plist) {
00424 double result = 0;
00425
00426 result=cpl_propertylist_get_double(plist, "EXPTIME");
00427 cpl_ensure_code(result >= 0, CPL_ERROR_ILLEGAL_OUTPUT);
00428
00429 return result;
00430 }
00431
00432
00440
00441 static cpl_error_code
00442 irplib_head_set_exptime(cpl_propertylist *plist, double exptime)
00443 {
00444 cpl_propertylist_update_double(plist, "EXPTIME", exptime);
00445 cpl_propertylist_set_comment(plist, "EXPTIME", "Total integration time");
00446
00447 return cpl_error_get_code();
00448 }
00449
00450 static cpl_imagelist*
00451 irplib_mkmaster_dark_fill_imagelist(const cpl_imagelist* raw_images,
00452 cpl_propertylist** raw_headers, const cpl_image* master_bias,
00453 double* mean_exptime) {
00454
00455
00456
00457 cpl_imagelist* preproc_images = NULL;
00458 int i = 0;
00459 cpl_image* current_dark = NULL;
00460 double min_exptime = 0;
00461 double max_exptime = 0;
00462
00463 preproc_images = cpl_imagelist_new();
00464 for (i = 0; i < cpl_imagelist_get_size(raw_images); i++) {
00465 double exposure_time = 0.0;
00466 const cpl_propertylist *current_header;
00467
00468 current_dark = cpl_image_duplicate(cpl_imagelist_get_const(raw_images, i));
00469 current_header = raw_headers[i];
00470
00471
00472 if (master_bias != NULL) {
00473 cpl_msg_info(cpl_func, "Subtracting master bias");
00474 cpl_image_subtract(current_dark, master_bias);
00475 } else {
00476 cpl_msg_info(cpl_func, "Skipping bias subtraction");
00477 }
00478
00479 exposure_time = irplib_head_get_exptime(current_header);
00480
00481
00482 if (i == 0 || exposure_time < min_exptime) {
00483 min_exptime = exposure_time;
00484 }
00485 if (i == 0 || exposure_time > max_exptime) {
00486 max_exptime = exposure_time;
00487 }
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 cpl_imagelist_set(preproc_images, current_dark, i);
00498
00499
00500
00501 current_dark = NULL;
00502 }
00503
00504
00505
00506 cpl_msg_info(cpl_func,
00507 "Exposure times range from %e s to %e s (%e %% variation)", min_exptime,
00508 max_exptime, 100 * (max_exptime - min_exptime) / min_exptime);
00509
00510 if ((max_exptime - min_exptime) / min_exptime > .001) {
00511 cpl_msg_warning(cpl_func, "Exposure times differ by %e %%",
00512 100 * (max_exptime - min_exptime) / min_exptime);
00513 }
00514
00515
00516 *mean_exptime=0.5 * (max_exptime + min_exptime);
00517 return preproc_images;
00518 }
00519
00520
00521 cpl_image *
00522 irplib_mdark_process_chip(const cpl_imagelist *raw_images,
00523 cpl_propertylist **raw_headers, const cpl_image *master_bias,
00524 cpl_propertylist *mdark_header, const cpl_parameterlist *parameters,
00525 const char* recipe_id, cpl_table* qclog, const int do_qc,
00526 const char* STACK_METHOD, const double STACK_KLOW, const double STACK_KHIGH,
00527 const int STACK_NITER,
00528 const int pr_num_x, const int pr_num_y,
00529 const int pr_box_sx, const int pr_box_sy) {
00530 cpl_image *master_dark = NULL;
00531 cpl_image *current_dark = NULL;
00532 cpl_imagelist *preproc_images = NULL;
00533 double mean_exptime = 0;
00534
00535
00536
00537 preproc_images = irplib_mkmaster_dark_fill_imagelist(raw_images, raw_headers,
00538 master_bias, &mean_exptime);
00539 if (do_qc) {
00540
00541 irplib_mkmaster_dark_qc(raw_images, preproc_images, parameters, pr_num_x,
00542 pr_num_y, pr_box_sx, pr_box_sy, recipe_id, qclog);
00543
00544 }
00545
00546 if (strcmp(STACK_METHOD, "MEDIAN") == 0) {
00547 cpl_msg_info(cpl_func, "Calculating stack median");
00548 master_dark = cpl_imagelist_collapse_median_create(preproc_images);
00549 } else {
00550 cpl_msg_info(cpl_func, "Calculating stack mean");
00551 master_dark = irplib_imagelist_ksigma_stack(preproc_images, STACK_KLOW,
00552 STACK_KHIGH, STACK_NITER);
00553
00554 }
00555 irplib_head_set_exptime(mdark_header, mean_exptime );
00556
00557 cpl_image_delete(current_dark);
00558 cpl_imagelist_delete(preproc_images);
00559 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00560 cpl_image_delete(master_dark);
00561 }
00562
00563 return master_dark;
00564 }
00565