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 #ifdef HAVE_CONFIG_H
00028 #include <config.h>
00029 #endif
00030
00031
00038
00041
00042
00043
00044 #include <math.h>
00045 #include <xsh_utils.h>
00046 #include <xsh_drl.h>
00047 #include <xsh_pfits.h>
00048 #include <xsh_error.h>
00049 #include <xsh_msg.h>
00050 #include <xsh_badpixelmap.h>
00051 #include <xsh_utils_image.h>
00052 #include <xsh_data_order.h>
00053 #include <xsh_data_grid.h>
00054
00055
00056
00057
00058
00059
00060
00061
00062 static cpl_error_code
00063 subtract_background(cpl_image *image, cpl_image *background_im,
00064 const polynomial *background_pol);
00065
00066 static cpl_image*
00067 xsh_background_poly(cpl_image* image, xsh_grid* grid);
00068
00069
00070
00071
00072
00073
00090 cpl_frame*
00091 xsh_subtract_bias( cpl_frame *frame,
00092 cpl_frame *bias,
00093 xsh_instrument* instr,
00094 const char * type,
00095 const int pre_overscan_corr)
00096 {
00097
00098 cpl_frame * result = NULL;
00099
00100 xsh_pre* xframe = NULL;
00101 xsh_pre* xbias = NULL;
00102
00103 char resultname[256];
00104 int binx=0;
00105 int biny=0;
00106 char tag[80];
00107 double avg=0;
00108
00109
00110 XSH_ASSURE_NOT_NULL( frame);
00111 XSH_ASSURE_NOT_NULL( bias);
00112 XSH_ASSURE_NOT_NULL( instr);
00113
00114
00115 check( xframe = xsh_pre_load( frame, instr));
00116 check( xbias = xsh_pre_load( bias, instr));
00117
00118 check(binx=xsh_pfits_get_binx(xbias->data_header));
00119 check(biny=xsh_pfits_get_biny(xbias->data_header));
00120
00121 if(pre_overscan_corr==0) {
00122 check( xsh_pre_subtract( xframe, xbias));
00123 } else {
00124 check(avg=cpl_image_get_mean(xbias->data));
00125 check(xsh_pre_subtract_scalar(xbias,avg));
00126 check( xsh_pre_subtract( xframe, xbias));
00127 }
00128
00129 sprintf(tag,"%sON_%s",type,xsh_instrument_arm_tostring (instr));
00130
00131
00132
00133
00134 sprintf(resultname,"%s.fits",tag);
00135
00136 check( xsh_pfits_set_pcatg( xframe->data_header, tag));
00137 check( result = xsh_pre_save ( xframe, resultname, tag,1));
00138 check( cpl_frame_set_tag( result,tag));
00139
00140 cleanup:
00141 if ( cpl_error_get_code() != CPL_ERROR_NONE) {
00142 xsh_free_frame( &result);
00143 }
00144 xsh_pre_free( &xframe);
00145 xsh_pre_free( &xbias);
00146 return result;
00147 }
00148
00149
00150
00151
00160
00161 cpl_frameset* xsh_subtract_nir_on_off(cpl_frameset* on, cpl_frameset* off,
00162 xsh_instrument* instr){
00163
00164 cpl_frameset * result = NULL;
00165
00166 cpl_frame* res = NULL;
00167
00168 char resultname[256];
00169 int i = 0, size_on = 0, size_off = 0;
00170
00171
00172 XSH_ASSURE_NOT_NULL(on);
00173 XSH_ASSURE_NOT_NULL(off);
00174 XSH_ASSURE_NOT_NULL(instr);
00175
00176 check(size_on = cpl_frameset_get_size(on));
00177 check(size_off = cpl_frameset_get_size(off));
00178
00179 XSH_ASSURE_NOT_ILLEGAL(size_on == size_off);
00180
00181 XSH_NEW_FRAMESET(result);
00182
00183
00184 for ( i=0; i< size_on; i++) {
00185 cpl_frame* on_f = NULL;
00186 cpl_frame* off_f = NULL;
00187
00188 check( on_f = cpl_frameset_get_frame(on,i));
00189 check( off_f = cpl_frameset_get_frame(off,i));
00190 sprintf(resultname, "ON-OFF_%d.fits",i);
00191
00192 check( res = xsh_subtract_dark(on_f, off_f, resultname, instr));
00193 check(cpl_frameset_insert(result, res));
00194 }
00195
00196 cleanup:
00197 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00198 xsh_free_frameset(&result);
00199 xsh_free_frame(&res);
00200 }
00201 return result;
00202 }
00203
00212
00213 cpl_frame * xsh_subtract_dark(cpl_frame * frame,cpl_frame * dark,
00214 const char* filename, xsh_instrument* instr)
00215 {
00216
00217 cpl_frame * result = NULL;
00218
00219 xsh_pre* xframe = NULL;
00220 xsh_pre* xdark = NULL;
00221
00222 double exptime = 0.0;
00223 const char* tag=NULL;
00224
00225
00226 XSH_ASSURE_NOT_NULL(frame);
00227 XSH_ASSURE_NOT_NULL(dark);
00228 XSH_ASSURE_NOT_NULL(filename);
00229 XSH_ASSURE_NOT_NULL(instr);
00230
00231
00232 check(xframe = xsh_pre_load(frame, instr));
00233 check(xdark = xsh_pre_load(dark, instr));
00234
00235
00236 if (xsh_instrument_get_arm(instr) != XSH_ARM_NIR) {
00237 exptime = xframe->exptime;
00238 assure(exptime > 0,CPL_ERROR_ILLEGAL_INPUT,
00239 "EXPTIME must be greater than 0 : %f",exptime);
00240 check(xsh_pre_multiply_scalar(xdark,exptime));
00241 }
00242
00243 check(xsh_pre_subtract(xframe,xdark));
00244
00245 tag=cpl_frame_get_tag(frame);
00246 check(result = xsh_pre_save (xframe, filename, tag,1));
00247 check(cpl_frame_set_tag (result,tag));
00248
00249 cleanup:
00250 if (cpl_error_get_code () != CPL_ERROR_NONE) {
00251 xsh_free_frame(&result);
00252 }
00253 xsh_pre_free(&xframe);
00254 xsh_pre_free(&xdark);
00255 return result;
00256 }
00257
00258
00277
00278 cpl_frame* xsh_subtract_background( cpl_frame *frame,
00279 cpl_frame *edges_order_tab_frame,
00280 xsh_background_param *background_par,
00281 xsh_instrument *instr,
00282 const char *prefix,
00283 cpl_frame **grid_frame,
00284 cpl_frame **backg_frame)
00285 {
00286
00287 cpl_frame *result = NULL;
00288
00289 xsh_order_list *orderlist = NULL;
00290 xsh_pre *pre = NULL;
00291 xsh_grid *grid = NULL;
00292 cpl_image *background_img = NULL;
00293
00294 float *data = NULL;
00295 int incr = 0, i = 0, y =0, lost = 0;
00296 int grid_size_x =0, grid_size_y =0;
00297 double *tab = NULL;
00298 int x = 0;
00299 float x1 = 0, x2 =0, dx = 0;
00300 double medflux = 0.0;
00301 char *fname = NULL;
00302 char *pcatg = NULL;
00303 cpl_image *background_smo = NULL;
00304 int smooth_x = -1;
00305 int smooth_y = -1;
00306 cpl_propertylist *plist = NULL;
00307 cpl_table *grid_tbl = NULL;
00308 cpl_image* ima=NULL;
00309
00310
00311 XSH_ASSURE_NOT_NULL( instr);
00312 XSH_ASSURE_NOT_NULL( frame);
00313 XSH_ASSURE_NOT_NULL( edges_order_tab_frame);
00314 XSH_ASSURE_NOT_NULL( background_par);
00315
00316
00317
00318
00319
00320 XSH_ASSURE_NOT_ILLEGAL(background_par->sampley > 0);
00321 XSH_ASSURE_NOT_ILLEGAL(background_par->radius_x >= 0);
00322 XSH_ASSURE_NOT_ILLEGAL(background_par->radius_y >= 0);
00323
00324
00325
00326
00327 check( pre = xsh_pre_load(frame, instr));
00328 check( orderlist = xsh_order_list_load( edges_order_tab_frame, instr));
00329 xsh_order_list_set_bin_x( orderlist, pre->binx);
00330 xsh_order_list_set_bin_y( orderlist, pre->biny);
00331 check( data = cpl_image_get_data_float(pre->data));
00332
00333
00334 grid_size_x = orderlist->size+5;
00335 grid_size_y = background_par->sampley+2;
00336
00337 smooth_x = background_par->smooth_x;
00338 smooth_y = background_par->smooth_y;
00339
00340 check( grid = xsh_grid_create( grid_size_x*grid_size_y));
00341
00342
00343 XSH_MALLOC(tab,double,(2*background_par->radius_x+1)*(2*background_par->radius_y+1));
00344
00345
00346 incr = (int)ceil((float)pre->ny/(float)background_par->sampley);
00347
00348
00349 for( y=1; y <= (pre->ny-1+incr); y += incr){
00350 int sizey = 2 * background_par->radius_y+1;
00351 int oy = -background_par->radius_y;
00352
00353
00354 if( (y+incr) > pre->ny){
00355 y = pre->ny;
00356 }
00357
00358
00359 if((y == 1) || (y == pre->ny)){
00360 sizey = background_par->radius_y+1;
00361 oy = 0;
00362 }
00363
00364
00365 check( medflux = xsh_pre_data_window_sample_flux_pa(pre,
00366 1, y+oy,
00367 2 * background_par->radius_x+1,
00368 sizey,
00369 tab,
00370 background_par->method,
00371 background_par->min_frac_grid));
00372
00373 if ( xsh_instrument_get_arm(instr) == XSH_ARM_NIR){
00374 if ( (y <= orderlist->list[orderlist->size-2].starty) ||
00375 y >= orderlist->list[orderlist->size-2].endy){
00376
00377 check( xsh_grid_add(grid, 1, y, medflux));
00378 }
00379 }
00380 else{
00381 check( xsh_grid_add(grid, 1, y, medflux));
00382 }
00383
00384
00385 for( i=orderlist->size-1; i > 0; i--){
00386 int starty, endy;
00387
00388 starty = orderlist->list[i-1].starty;
00389 endy = orderlist->list[i-1].endy;
00390
00391
00392 if(starty == -999 ) {
00393
00394
00395
00396
00397
00398 xsh_msg("PROBLEMS");
00399 check(xsh_grid_add(grid, 0, y, 0.));
00400 background_par->method="poly";
00401 lost++;
00402 break;
00403 }
00404
00405 check( x1 = xsh_order_list_eval( orderlist,
00406 orderlist->list[i].edguppoly, y));
00407 check( x2 = xsh_order_list_eval( orderlist,
00408 orderlist->list[i-1].edglopoly, y));
00409
00410 x = floor( (x1+x2)/2.0+0.5);
00411 dx = (x2-x1)/2.0;
00412 xsh_msg_dbg_high("x %d dx %f", x, dx);
00413
00414 if ( xsh_instrument_get_arm(instr) == XSH_ARM_NIR){
00415 if ( y <= starty || y >= endy){
00416 if (x >1 && x <= pre->nx){
00417 check(xsh_grid_add(grid, x, y, 0.0));
00418 }
00419 continue;
00420 }
00421 }
00422
00423 if ( (x > (background_par->radius_x+1)) && ((2*background_par->radius_x+1)< dx)){
00424
00425 check(medflux = xsh_pre_data_window_sample_flux_pa(pre,
00426 x-background_par->radius_x,
00427 y+oy ,
00428 2*background_par->radius_x+1,
00429 sizey,
00430 tab,
00431 background_par->method,
00432 background_par->min_frac_grid));
00433 check( xsh_grid_add(grid, x, y, medflux));
00434 }
00435 else{
00436 lost++;
00437 }
00438
00439 if ( i == (orderlist->size-1)){
00440 check( x2 = xsh_order_list_eval( orderlist,
00441 orderlist->list[i].edglopoly, y));
00442
00443 x = x2-dx;
00444
00445 if(dx<0) {
00446 xsh_msg("Monitor dx=%d x=%g y=%d",x,dx,y);
00447 }
00448
00449
00450 if ( (x > (background_par->radius_x+1)) ){
00451 check(medflux = xsh_pre_data_window_sample_flux_pa(pre,
00452 x-background_par->radius_x,
00453 y+oy ,
00454 2*background_par->radius_x+1,
00455 sizey,
00456 tab,
00457 background_par->method,
00458 background_par->min_frac_grid));
00459 check(xsh_grid_add(grid, x, y, medflux));
00460 }
00461 }
00462 else{
00463 lost++;
00464 }
00465
00466 if ( i == 1){
00467 check( x1 = xsh_order_list_eval( orderlist,
00468 orderlist->list[0].edguppoly, y));
00469
00470 if ( xsh_instrument_get_arm(instr) == XSH_ARM_VIS){
00471 check( x2 = xsh_order_list_eval( orderlist,
00472 orderlist->list[0].edglopoly, y));
00473 x = x1+(x1-x2)*1.2;
00474 }
00475 else{
00476 x=x1+dx;
00477 }
00478 if ( (x > (background_par->radius_x+1)) && (x+background_par->radius_x < pre->nx) ){
00479 check(medflux = xsh_pre_data_window_sample_flux_pa(pre,
00480 x-background_par->radius_x,
00481 y+oy ,
00482 2*background_par->radius_x+1,
00483 sizey,
00484 tab,
00485 background_par->method,
00486 background_par->min_frac_grid));
00487 check(xsh_grid_add(grid, x, y, medflux));
00488 }
00489 else {
00490 lost++;
00491 }
00492 }
00493
00494 }
00495
00496 check(medflux = xsh_pre_data_window_sample_flux_pa(pre,
00497 pre->nx-background_par->radius_x,
00498 y+oy,
00499 background_par->radius_x+1,
00500 sizey,
00501 tab,
00502 background_par->method,
00503 background_par->min_frac_grid));
00504
00505 check(xsh_grid_add(grid, pre->nx, y, medflux));
00506 }
00507
00508 xsh_msg_dbg_low("Nb of lost points %d ",lost);
00509 xsh_msg_dbg_low("Nb of grid points %d ",xsh_grid_get_index(grid));
00510
00511
00512 check( xsh_grid_sort(grid));
00513
00514
00515 if(strcmp(background_par->method,"minimum")==0) {
00516
00517 xsh_msg("generate background image: spline");
00518 check( background_img = cpl_image_new( pre->nx, pre->ny, CPL_TYPE_DOUBLE));
00519 check(xsh_image_fit_spline(background_img, grid));
00520 } else if(strcmp(background_par->method,"median")==0) {
00521
00522 xsh_msg("generate background image: spline");
00523 check( background_img = cpl_image_new( pre->nx, pre->ny, CPL_TYPE_DOUBLE));
00524 check(xsh_image_fit_spline(background_img, grid));
00525 } else if (strcmp(background_par->method,"poly")==0) {
00526 xsh_msg("generate background image: poly");
00527 check(ima=cpl_image_cast(pre->data,CPL_TYPE_DOUBLE));
00528 check( background_img = xsh_background_poly( ima, grid));
00529 xsh_free_image(&ima);
00530
00531
00532
00533
00534 }
00535
00536 if( smooth_y>0) {
00537 check( background_smo = xsh_image_smooth_mean_y( background_img,
00538 smooth_y));
00539
00540
00541
00542
00543 xsh_free_image( &background_img);
00544 background_img= cpl_image_duplicate( background_smo);
00545 xsh_free_image( &background_smo);
00546 }
00547
00548 if( smooth_x>0) {
00549 check(background_smo = xsh_image_smooth_mean_x( background_img,
00550 smooth_x));
00551
00552
00553
00554
00555 xsh_free_image( &background_img);
00556 background_img = cpl_image_duplicate( background_smo);
00557 xsh_free_image( &background_smo);
00558 }
00559
00560
00561 XSH_NAME_PREFIX_LAMP_MODE_ARM( pcatg, prefix, "_BACK", "", instr);
00562 XSH_NAME_PREFIX_LAMP_MODE_ARM( fname, prefix, "_BACK", ".fits", instr);
00563 plist=cpl_propertylist_new();
00564 check( xsh_pfits_set_pcatg( plist, pcatg));
00565
00566 check( cpl_image_save( background_img, fname, CPL_BPP_IEEE_FLOAT,
00567 plist, CPL_IO_DEFAULT));
00568 xsh_free_propertylist( &plist);
00569
00570 check( *backg_frame = xsh_frame_product( fname, pcatg,
00571 CPL_FRAME_TYPE_IMAGE, CPL_FRAME_GROUP_CALIB,
00572 CPL_FRAME_LEVEL_FINAL));
00573
00574
00575 check( cpl_image_subtract( pre->data, background_img));
00576
00577 XSH_FREE( fname);
00578 XSH_FREE( pcatg);
00579 XSH_NAME_PREFIX_LAMP_MODE_ARM( fname, prefix, "_SUB_BACK", ".fits", instr);
00580 XSH_NAME_PREFIX_LAMP_MODE_ARM( pcatg, prefix, "_SUB_BACK", "", instr);
00581
00582 check( xsh_pfits_set_pcatg( pre->data_header, pcatg));
00583
00584 check( result = xsh_pre_save( pre, fname, pcatg, 1));
00585 check(cpl_frame_set_tag (result, pcatg));
00586 check(cpl_frame_set_type (result, CPL_FRAME_TYPE_IMAGE));
00587 check(cpl_frame_set_group (result, CPL_FRAME_GROUP_CALIB));
00588 check(cpl_frame_set_level (result, CPL_FRAME_LEVEL_FINAL));
00589
00590 grid_tbl = xsh_grid2table(grid);
00591
00592 XSH_FREE( fname);
00593 XSH_FREE( pcatg);
00594 XSH_NAME_PREFIX_LAMP_MODE_ARM( fname, prefix, "_GRID_BACK", ".fits", instr);
00595 XSH_NAME_PREFIX_LAMP_MODE_ARM( pcatg, prefix, "_GRID_BACK", "", instr);
00596
00597 plist = cpl_propertylist_new();
00598 check( xsh_pfits_set_pcatg( plist, pcatg));
00599 check( cpl_table_save( grid_tbl, plist, NULL, fname, CPL_IO_DEFAULT));
00600 xsh_free_propertylist( &plist);
00601 xsh_free_table( &grid_tbl);
00602 *grid_frame =xsh_frame_product(fname,pcatg,CPL_FRAME_TYPE_TABLE,
00603 CPL_FRAME_GROUP_CALIB,CPL_FRAME_LEVEL_FINAL);
00604
00605 cleanup:
00606 if (cpl_error_get_code () != CPL_ERROR_NONE) {
00607 xsh_free_frame(&result);
00608 }
00609 xsh_free_propertylist(&plist);
00610 xsh_order_list_free( &orderlist);
00611 XSH_FREE( tab);
00612 XSH_FREE( fname);
00613 XSH_FREE( pcatg);
00614 xsh_grid_free( &grid);
00615 xsh_pre_free( &pre);
00616 xsh_free_image( &background_img);
00617 return result;
00618 }
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00641
00642
00643 static cpl_error_code
00644 subtract_background(cpl_image *image, cpl_image *background_im,
00645 const polynomial *background_pol)
00646 {
00647 int nx, ny;
00648 int x, y;
00649
00650 double *image_data;
00651 double *background_data = NULL;
00652 passure(image != NULL, " ");
00653
00654
00655
00656
00657 assure(cpl_image_count_rejected(image) == 0,
00658 CPL_ERROR_UNSUPPORTED_MODE, "Input image contains bad pixels");
00659 assure(cpl_image_get_type(image) == CPL_TYPE_DOUBLE,
00660 CPL_ERROR_UNSUPPORTED_MODE,
00661 "Input image is of type %s. double expected",
00662 xsh_tostring_cpl_type(cpl_image_get_type(image)));
00663
00664
00665 image_data = cpl_image_get_data_double(image);
00666 background_data = cpl_image_get_data_double(background_im);
00667
00668 nx = cpl_image_get_size_x(image);
00669 ny = cpl_image_get_size_y(image);
00670
00671 for (y = 1; y <= ny; y++)
00672 {
00673 for (x = 1; x <= nx; x++)
00674 {
00675 double back;
00676 double flux, new_flux;
00677
00678
00679
00680 back = xsh_polynomial_evaluate_2d(background_pol,x,y);
00681
00682
00683 flux = image_data[(x-1) + (y-1) * nx];
00684 new_flux = flux-back;
00685 image_data[(x-1) + (y-1) * nx] = new_flux;
00686 background_data[(x-1)+(y-1)*nx]=xsh_max_double(0, flux - new_flux);
00687
00688 }
00689 }
00690
00691 cleanup:
00692 return cpl_error_get_code();
00693 }
00694
00695
00696
00697 #define DEGX 2
00698 #define DEGY 2
00699 #define KAPPA 4.
00700
00701 static cpl_image*
00702 xsh_background_poly(cpl_image* image, xsh_grid* grid)
00703 {
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713 polynomial* background=NULL;
00714 double mse=0, rmse=0;
00715 int total_clipped = 0;
00716 cpl_table* t=NULL;
00717 cpl_image* bkg_img=NULL;
00718
00719 check(t=xsh_grid2table(grid));
00720
00721
00722 {
00723 int n_clipped;
00724 do {
00725 assure( cpl_table_get_nrow(t) > (DEGX + 1)*(DEGY + 1),
00726 CPL_ERROR_ILLEGAL_OUTPUT,
00727 "Too few sample points available (%d point(s)) to make the fit "
00728 "(more than %d points needed). "
00729 "Increase number of sample points or increase kappa",
00730 cpl_table_get_nrow(t), (DEGX + 1)*(DEGY + 1));
00731
00732
00733 xsh_polynomial_delete(&background);
00734 check_msg( background = xsh_polynomial_regression_2d(
00735 t, "X", "Y", "INT", NULL,
00736 DEGX, DEGY, "INTfit", NULL, NULL, &mse,
00737 NULL, NULL, -1, -1),
00738 "Error fitting polynomial");
00739
00740
00741 cpl_table_duplicate_column(t, "Residual", t, "INT");
00742 cpl_table_subtract_columns(t, "Residual", "INTfit");
00743
00744
00745
00746
00747
00748
00749 cpl_table_subtract_scalar(t, "Residual",
00750 cpl_table_get_column_median(t, "Residual"));
00751 rmse = cpl_table_get_column_stdev(t, "Residual");
00752 xsh_msg_dbg_medium("rmse=%g",rmse);
00753
00754 if (KAPPA > 0)
00755 {
00756 check_msg( n_clipped = xsh_select_table_rows(
00757 t, "Residual", CPL_GREATER_THAN, KAPPA * rmse),
00758 "Error selecting rows");
00759 }
00760 else
00761 {
00762 n_clipped = 0;
00763 }
00764
00765 total_clipped += n_clipped;
00766
00767 xsh_msg_dbg_medium("RMS = %f. %d of %d points rejected in kappa-sigma clipping",
00768 rmse, n_clipped, cpl_table_get_nrow(t));
00769
00770 cpl_table_erase_selected(t);
00771
00772 if (n_clipped > 0)
00773 {
00774 cpl_table_erase_column(t, "INTfit");
00775 cpl_table_erase_column(t, "Residual");
00776 }
00777
00778 } while (n_clipped > 0);
00779 }
00780
00781
00782
00783
00784
00785 {
00786 double percentage =
00787 100.0 * ( (double)total_clipped ) / (total_clipped + cpl_table_get_nrow(t));
00788
00789 if (KAPPA > 0) {
00790 xsh_msg_dbg_medium("%d of %d points (%.2f %%) were rejected in "
00791 "kappa-sigma clipping. RMS = %.2f ADU",
00792 total_clipped,
00793 cpl_table_get_nrow(t) + total_clipped,
00794 percentage,
00795 sqrt(mse));
00796 }
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818 }
00819 bkg_img=cpl_image_duplicate(image);
00820
00821 check_msg( subtract_background(image,bkg_img, background),
00822 "Error subtracting background polynomial");
00823
00824 cleanup:
00825 xsh_free_table( &t);
00826 xsh_polynomial_delete(&background);
00827 return bkg_img;
00828
00829 }
00830
00831
00832