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
00029
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033
00034 #include <cpl.h>
00035 #include <math.h>
00036 #include <string.h>
00037
00038 #include "vircam_sky.h"
00039 #include "vircam_mask.h"
00040 #include "vircam_fits.h"
00041 #include "vircam_mods.h"
00042 #include "vircam_utils.h"
00043 #include "vircam_stats.h"
00044 #include "vircam_wcsutils.h"
00045 #include "vircam_pfits.h"
00046
00047 typedef struct {
00048 vir_fits **in;
00049 int n;
00050 int nalloc;
00051 int status;
00052 vir_fits *xsky;
00053 } xsky_struct;
00054
00055 static void vircam_sky_mask_grow(cpl_image *dith, float rad);
00056 static float vircam_sky_med(vir_fits *sky);
00057
00058
00059 static void vircam_sky_joffs(vir_fits **inlist, int nfiles, float **xoffs,
00060 float **yoffs);
00061
00064
00109
00110
00111 extern int vircam_pawsky_mask(vir_fits **inlist, int nfiles, vir_fits *conf,
00112 vir_mask *mask, vir_fits **skyout, int niter,
00113 int ipix, float thresh, int nbsize, float smkern,
00114 int *status) {
00115 int i,nx,ny,nbad0,lastone,iter,*confdata,npts,nbad_init,nbad,dbad;
00116 int xx1,xx2,yy1,yy2;
00117 const char *fctid = "vircam_pawsky_mask";
00118 cpl_image *dith,*dithc,*skyim,*im,*newim,*outim;
00119 cpl_mask *cplmask,*dithmask,*newmask,*curmask;
00120 vir_fits **list_ss,*dithf,*dithcf;
00121 unsigned char *inbpm,*rejmask,*rejplus;
00122 float medsky,*xoffs,*yoffs,mindx,mindy,fbad;
00123 cpl_propertylist *p,*drs;
00124
00125
00126
00127 *skyout = NULL;
00128 if (*status != VIR_OK)
00129 return(*status);
00130
00131
00132
00133 if (nfiles == 0) {
00134 cpl_msg_error(fctid,"Sky correction impossible. No science frames");
00135 return(VIR_FATAL);
00136 }
00137
00138
00139
00140
00141 inbpm = vircam_mask_get_data(mask);
00142 nx = vircam_mask_get_size_x(mask);
00143 ny = vircam_mask_get_size_y(mask);
00144 cplmask = cpl_mask_wrap((cpl_size)nx,(cpl_size)ny,(cpl_binary *)inbpm);
00145 for (i = 0; i < nfiles; i++)
00146 cpl_image_reject_from_mask(vircam_fits_get_image(inlist[i]),cplmask);
00147 cpl_mask_unwrap(cplmask);
00148
00149
00150
00151
00152 vircam_imcombine(inlist,nfiles,1,1,0,2.0,&outim,&rejmask,
00153 &rejplus,&drs,status);
00154 *skyout = vircam_fits_wrap(outim,inlist[0],NULL,NULL);
00155 freespace(rejmask);
00156 freespace(rejplus);
00157 freepropertylist(drs);
00158
00159
00160
00161 (void)vircam_inpaint(*skyout,nbsize,status);
00162
00163
00164
00165 if (niter == 0)
00166 return(*status);
00167
00168
00169
00170 medsky = vircam_sky_med(*skyout);
00171
00172
00173
00174 vircam_sky_joffs(inlist,nfiles,&xoffs,&yoffs);
00175 mindx = xoffs[0];
00176 mindy = yoffs[0];
00177 for (i = 1; i < nfiles; i++) {
00178 mindx = min(mindx,xoffs[i]);
00179 mindy = min(mindy,yoffs[i]);
00180 }
00181
00182
00183
00184 list_ss = cpl_malloc(nfiles*sizeof(vir_fits *));
00185 skyim = vircam_fits_get_image(*skyout);
00186 for (i = 0; i < nfiles; i++) {
00187 im = vircam_fits_get_image(inlist[i]);
00188 newim = cpl_image_subtract_create(im,skyim);
00189 cpl_image_add_scalar(newim,(double)medsky);
00190 list_ss[i] = vircam_fits_wrap(newim,inlist[i],NULL,NULL);
00191 }
00192
00193
00194
00195 nbad0 = 0;
00196 lastone = 0;
00197 for (iter = 1; iter <= niter; iter++) {
00198 if (lastone)
00199 break;
00200 lastone = (iter == niter);
00201
00202
00203
00204 (void)vircam_imdither(list_ss,&conf,nfiles,1,5.0,5.0,&p,&dith,
00205 &dithc,status);
00206 cpl_propertylist_delete(p);
00207
00208
00209
00210 confdata = cpl_image_get_data_int(dithc);
00211 npts = (int)cpl_image_get_size_x(dithc)*(int)cpl_image_get_size_y(dithc);
00212 nbad_init = 0;
00213 for (i = 0; i < npts; i++)
00214 if (confdata[i] == 0)
00215 nbad_init++;
00216
00217
00218
00219 for (i = 0; i < nfiles; i++)
00220 vircam_fits_delete(list_ss[i]);
00221
00222
00223
00224 dithf = vircam_fits_wrap(dith,inlist[0],NULL,NULL);
00225 dithcf = vircam_fits_wrap(dithc,conf,NULL,NULL);
00226
00227
00228
00229 (void)vircam_opm(dithf,dithcf,ipix,thresh,nbsize,smkern,niter,status);
00230
00231
00232
00233
00234 nbad = (int)cpl_image_count_rejected((const cpl_image *)dith) - nbad_init;
00235 dbad = nbad - nbad0;
00236 fbad = (iter > 1 ? (float)abs(dbad)/(float)nbad0 : 10000.0);
00237 cpl_msg_info(fctid,
00238 " Iteration: %" CPL_SIZE_FORMAT ", Nreject: %" CPL_SIZE_FORMAT " %" CPL_SIZE_FORMAT,
00239 (cpl_size)iter,(cpl_size)nbad,(cpl_size)nbad0);
00240 if (fbad < 0.025 || dbad < 0) {
00241 lastone = 1;
00242 } else {
00243 nbad0 = nbad;
00244 }
00245
00246
00247
00248 vircam_sky_mask_grow(dith,2);
00249
00250
00251
00252
00253 dithmask = cpl_image_get_bpm(dith);
00254 for (i = 0; i < nfiles; i++) {
00255 xx1 = (int)(-mindx + xoffs[i] + 1.5);
00256 xx2 = xx1 + nx - 1;
00257 yy1 = (int)(-mindy + yoffs[i] + 1.5);
00258 yy2 = yy1 + ny - 1;
00259 newmask = cpl_mask_extract(dithmask,(cpl_size)xx1,(cpl_size)yy1,
00260 (cpl_size)xx2,(cpl_size)yy2);
00261 curmask = cpl_image_get_bpm(vircam_fits_get_image(inlist[i]));
00262 cpl_mask_or(curmask,newmask);
00263 cpl_mask_delete(newmask);
00264 }
00265
00266
00267
00268 vircam_fits_delete(dithf);
00269 vircam_fits_delete(dithcf);
00270
00271
00272
00273
00274 vircam_imcombine(inlist,nfiles,1,1,0,2.0,&outim,&rejmask,
00275 &rejplus,&drs,status);
00276 *skyout = vircam_fits_wrap(outim,inlist[0],NULL,NULL);
00277 freespace(rejmask);
00278 freespace(rejplus);
00279 freepropertylist(drs);
00280
00281
00282
00283 (void)vircam_inpaint(*skyout,nbsize,status);
00284
00285
00286
00287
00288 if (! lastone) {
00289 skyim = vircam_fits_get_image(*skyout);
00290 for (i = 0; i < nfiles; i++) {
00291 im = vircam_fits_get_image(inlist[i]);
00292 newim = cpl_image_subtract_create(im,skyim);
00293 cpl_image_add_scalar(newim,(double)medsky);
00294 list_ss[i] = vircam_fits_wrap(newim,inlist[i],NULL,NULL);
00295 }
00296 }
00297 }
00298
00299
00300
00301 freespace(xoffs);
00302 freespace(yoffs);
00303 freespace(list_ss);
00304 return(*status);
00305 }
00306
00307
00340
00341
00342 extern int vircam_tilesky(vir_fits **inlist, int nfiles, vir_mask *mask,
00343 vir_fits **skyout, int *status) {
00344 int i,njit,nx,ny,ji,ns,npts,j;
00345 unsigned char *inbpm,*rejmask,*rejplus;
00346 cpl_mask *cplmask;
00347 xsky_struct *xskys;
00348 cpl_propertylist *drs;
00349 cpl_image *outim;
00350 cpl_binary *immask;
00351 vir_fits **xsky_fits;
00352 float *test,skymed,*odata,*idata,skysig;
00353 const char *fctid = "vircam_tilesky";
00354
00355
00356
00357 *skyout = NULL;
00358 if (*status != VIR_OK)
00359 return(*status);
00360
00361
00362
00363 if (nfiles == 0) {
00364 cpl_msg_error(fctid,"Sky correction impossible. No science frames");
00365 return(VIR_FATAL);
00366 }
00367
00368
00369
00370
00371 inbpm = vircam_mask_get_data(mask);
00372 nx = vircam_mask_get_size_x(mask);
00373 ny = vircam_mask_get_size_y(mask);
00374 npts = nx*ny;
00375 cplmask = cpl_mask_wrap((cpl_size)nx,(cpl_size)ny,(cpl_binary *)inbpm);
00376 for (i = 0; i < nfiles; i++)
00377 cpl_image_reject_from_mask(vircam_fits_get_image(inlist[i]),cplmask);
00378 cpl_mask_unwrap(cplmask);
00379
00380
00381
00382
00383 test = cpl_malloc(nx*ny*sizeof(float));
00384 for (i = 0; i < nfiles; i++) {
00385 vircam_backmap(inlist[i],mask,64,&outim,&skymed);
00386 odata = cpl_image_get_data_float(outim);
00387 idata = cpl_image_get_data_float(vircam_fits_get_image(inlist[i]));
00388 for (j = 0; j < npts; j++)
00389 test[j] = idata[j] - odata[j];
00390 vircam_qmedsig(test,inbpm,(long)npts,3.0,2,-65535.0,65535.0,&skymed,
00391 &skysig);
00392 immask = cpl_mask_get_data(cpl_image_get_bpm(vircam_fits_get_image(inlist[i])));
00393 for (j = 0; j < npts; j++)
00394 if (test[j] > (skymed + 1.5*skysig))
00395 immask[j] = 1;
00396 cpl_image_delete(outim);
00397 }
00398 freespace(test);
00399
00400
00401
00402 (void)vircam_pfits_get_njsteps(vircam_fits_get_phu(inlist[0]),&njit);
00403
00404
00405
00406 xskys = cpl_malloc(njit*sizeof(xsky_struct));
00407 for (i = 0; i < njit; i++) {
00408 xskys[i].n = 0;
00409 xskys[i].in = cpl_malloc(8*sizeof(vir_fits *));
00410 xskys[i].nalloc = 8;
00411 xskys[i].xsky = NULL;
00412 xskys[i].status = VIR_OK;
00413 }
00414 xsky_fits = cpl_malloc(njit*sizeof(vir_fits *));
00415
00416
00417
00418
00419
00420
00421
00422 for (i = 0; i < nfiles; i++) {
00423 (void)vircam_pfits_get_jitteri(vircam_fits_get_phu(inlist[i]),&ji);
00424 ji--;
00425 if (xskys[ji].n == xskys[ji].nalloc) {
00426 xskys[ji].in = cpl_realloc(xskys[ji].in,
00427 (xskys[ji].nalloc+8)*sizeof(vir_fits *));
00428 xskys[ji].nalloc += 8;
00429 }
00430 xskys[ji].in[xskys[ji].n] = inlist[i];
00431 xskys[ji].n += 1;
00432 }
00433
00434
00435
00436
00437 ns = 0;
00438 for (i = 0; i < njit; i++) {
00439 *status = VIR_OK;
00440 if (xskys[i].n == 0) {
00441 xskys[i].xsky = NULL;
00442 continue;
00443 } else if (xskys[i].n == 1) {
00444 xskys[i].xsky = NULL;
00445 xsky_fits[ns++] = xskys[i].in[0];
00446 continue;
00447 }
00448 outim = NULL;
00449 (void)vircam_imcombine(xskys[i].in,xskys[i].n,1,1,0,1.0,&outim,&rejmask,
00450 &rejplus,&drs,status);
00451 freespace(rejmask);
00452 freespace(rejplus);
00453 freepropertylist(drs);
00454 if (*status == VIR_OK) {
00455 xskys[i].xsky = vircam_fits_wrap(outim,xskys[i].in[0],NULL,NULL);
00456 xsky_fits[ns++] = xskys[i].xsky;
00457 } else {
00458 freeimage(outim);
00459 }
00460 }
00461
00462
00463
00464 if (ns != 0) {
00465 outim = NULL;
00466 (void)vircam_imcombine(xsky_fits,ns,1,1,0,1.0,&outim,&rejmask,&rejplus,
00467 &drs,status);
00468 freespace(rejmask);
00469 freespace(rejplus);
00470 freepropertylist(drs);
00471 if (*status == VIR_OK) {
00472 *skyout = vircam_fits_wrap(outim,inlist[0],NULL,NULL);
00473 } else {
00474 freeimage(outim);
00475 *skyout = NULL;
00476 }
00477 } else {
00478 *skyout = NULL;
00479 }
00480
00481
00482
00483 freespace(xsky_fits);
00484 for (i = 0; i < njit; i++) {
00485 freespace(xskys[i].in);
00486 freefits(xskys[i].xsky);
00487 }
00488 freespace(xskys);
00489 return(*status);
00490 }
00491
00492
00493
00511
00512
00513 static void vircam_sky_mask_grow(cpl_image *dith, float rad) {
00514 cpl_binary *inmap,*outmap;
00515 int nx,ny,ir,i,j,indx,ixmin,ixmax,iymin,iymax,ii,jj,indx2;
00516 float dx,dy,radius;
00517
00518
00519
00520 inmap = cpl_mask_get_data(cpl_image_get_bpm(dith));
00521 nx = (int)cpl_image_get_size_x(dith);
00522 ny = (int)cpl_image_get_size_y(dith);
00523
00524
00525
00526 outmap = cpl_malloc(nx*ny*sizeof(*outmap));
00527 memmove(outmap,inmap,nx*ny*sizeof(*inmap));
00528
00529
00530
00531
00532 ir = vircam_nint(rad);
00533
00534
00535
00536
00537
00538
00539 for (j = 0; j < ny; j++) {
00540 for (i = 0; i < nx; i++) {
00541 indx = j*nx + i;
00542 if (! inmap[indx])
00543 continue;
00544 ixmin = max(0,i-ir);
00545 ixmax = min(nx-1,i+ir);
00546 iymin = max(0,j-ir);
00547 iymax = min(ny-1,j+ir);
00548 for (jj = iymin; jj <= iymax; jj++) {
00549 dy = (float)(jj - j);
00550 for (ii = ixmin; ii <= ixmax; ii++) {
00551 dx = (float)(ii - i);
00552 radius = (float)sqrt(pow(dx,2.0) + pow(dy,2.0));
00553 if (radius <= rad) {
00554 indx2 = jj*nx + ii;
00555 outmap[indx2] = 1;
00556 }
00557 }
00558 }
00559 }
00560 }
00561
00562
00563
00564
00565 memmove(inmap,outmap,nx*ny*sizeof(*inmap));
00566 cpl_free(outmap);
00567 }
00568
00569
00587
00588
00589 static float vircam_sky_med(vir_fits *sky) {
00590 int npts;
00591 float *data,med;
00592 unsigned char *bpm;
00593 cpl_image *skyim;
00594
00595
00596
00597 skyim = vircam_fits_get_image(sky);
00598 npts = (int)cpl_image_get_size_x(skyim)*(int)cpl_image_get_size_y(skyim);
00599
00600
00601
00602 data = cpl_image_get_data_float(skyim);
00603 bpm = (unsigned char *)cpl_mask_get_data(cpl_image_get_bpm(skyim));
00604
00605
00606
00607 med = vircam_med(data,bpm,(long)npts);
00608 return(med);
00609 }
00610
00611
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00745
00746
00747 static void vircam_sky_joffs(vir_fits **inlist, int nfiles, float **xoffs,
00748 float **yoffs) {
00749 float xoff,yoff;
00750 cpl_wcs *wcsref,*wcs;
00751 int refset,i,status;
00752 const double maxoffset = 2048;
00753 vir_fits *ff;
00754 const char *fctid = "vircam_sky_joffs";
00755
00756
00757
00758 *xoffs = cpl_malloc(nfiles*sizeof(float));
00759 *yoffs = cpl_malloc(nfiles*sizeof(float));
00760
00761
00762
00763 refset = 0;
00764 wcsref = NULL;
00765 for (i = 0; i < nfiles; i++) {
00766 ff = inlist[i];
00767 wcs = cpl_wcs_new_from_propertylist(vircam_fits_get_ehu(ff));
00768
00769
00770
00771
00772 if (wcs == NULL) {
00773 cpl_msg_warning(fctid,"Unable to get WCS for %s",
00774 vircam_fits_get_filename(ff));
00775 (*xoffs)[i] = 0.0;
00776 (*yoffs)[i] = 0.0;
00777 vircam_fits_set_error(ff,VIR_WARN);
00778 continue;
00779 }
00780
00781
00782
00783 if (! refset) {
00784 (*xoffs)[0] = 0.0;
00785 (*yoffs)[0] = 0.0;
00786 refset = 1;
00787 wcsref = wcs;
00788 continue;
00789 }
00790
00791
00792
00793 status = VIR_OK;
00794 (void)vircam_diffxywcs(wcs,wcsref,&xoff,&yoff,&status);
00795
00796
00797
00798 if (status != VIR_OK) {
00799 (*xoffs)[i] = 0.0;
00800 (*yoffs)[i] = 0.0;
00801 cpl_msg_warning(fctid,"Unable to WCS difference for %s",
00802 vircam_fits_get_filename(ff));
00803 } else if (fabs((double)xoff) > maxoffset ||
00804 fabs((double)yoff) > maxoffset) {
00805 vircam_fits_set_error(ff,VIR_FATAL);
00806 cpl_msg_error(fctid,"WCS offsets for %s are >%g: %g %g -- ignoring",
00807 vircam_fits_get_filename(ff),maxoffset,xoff,yoff);
00808 } else {
00809 (*xoffs)[i] = xoff;
00810 (*yoffs)[i] = yoff;
00811 }
00812 cpl_wcs_delete(wcs);
00813 }
00814 if (wcsref != NULL)
00815 cpl_wcs_delete(wcsref);
00816
00817
00818
00819 for (i = 0; i < nfiles; i++) {
00820 ff = inlist[i];
00821 cpl_propertylist_update_double(vircam_fits_get_ehu(ff),
00822 "ESO DRS XOFFDITHER",
00823 (double)(*xoffs)[i]);
00824 cpl_propertylist_update_double(vircam_fits_get_ehu(ff),
00825 "ESO DRS YOFFDITHER",
00826 (double)(*yoffs)[i]);
00827 }
00828 }
00829
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866