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(nx,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 = cpl_image_get_size_x(dithc)*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 = 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," Iteration: %d, Nreject: %d %d",iter,nbad,
00238 nbad0);
00239 if (fbad < 0.025 || dbad < 0) {
00240 lastone = 1;
00241 } else {
00242 nbad0 = nbad;
00243 }
00244
00245
00246
00247 vircam_sky_mask_grow(dith,2);
00248
00249
00250
00251
00252 dithmask = cpl_image_get_bpm(dith);
00253 for (i = 0; i < nfiles; i++) {
00254 xx1 = (int)(-mindx + xoffs[i] + 1.5);
00255 xx2 = xx1 + nx - 1;
00256 yy1 = (int)(-mindy + yoffs[i] + 1.5);
00257 yy2 = yy1 + ny - 1;
00258 newmask = cpl_mask_extract(dithmask,xx1,yy1,xx2,yy2);
00259 curmask = cpl_image_get_bpm(vircam_fits_get_image(inlist[i]));
00260 cpl_mask_or(curmask,newmask);
00261 cpl_mask_delete(newmask);
00262 }
00263
00264
00265
00266 vircam_fits_delete(dithf);
00267 vircam_fits_delete(dithcf);
00268
00269
00270
00271
00272 vircam_imcombine(inlist,nfiles,1,1,0,2.0,&outim,&rejmask,
00273 &rejplus,&drs,status);
00274 *skyout = vircam_fits_wrap(outim,inlist[0],NULL,NULL);
00275 freespace(rejmask);
00276 freespace(rejplus);
00277 freepropertylist(drs);
00278
00279
00280
00281 (void)vircam_inpaint(*skyout,nbsize,status);
00282
00283
00284
00285
00286 if (! lastone) {
00287 skyim = vircam_fits_get_image(*skyout);
00288 for (i = 0; i < nfiles; i++) {
00289 im = vircam_fits_get_image(inlist[i]);
00290 newim = cpl_image_subtract_create(im,skyim);
00291 cpl_image_add_scalar(newim,(double)medsky);
00292 list_ss[i] = vircam_fits_wrap(newim,inlist[i],NULL,NULL);
00293 }
00294 }
00295 }
00296
00297
00298
00299 freespace(xoffs);
00300 freespace(yoffs);
00301 freespace(list_ss);
00302 return(*status);
00303 }
00304
00305
00338
00339
00340 extern int vircam_tilesky(vir_fits **inlist, int nfiles, vir_mask *mask,
00341 vir_fits **skyout, int *status) {
00342 int i,njit,nx,ny,ji,ns,npts,j;
00343 unsigned char *inbpm,*rejmask,*rejplus;
00344 cpl_mask *cplmask;
00345 xsky_struct *xskys;
00346 cpl_propertylist *drs;
00347 cpl_image *outim;
00348 cpl_binary *immask;
00349 vir_fits **xsky_fits;
00350 float *test,skymed,*odata,*idata,skysig;
00351 const char *fctid = "vircam_tilesky";
00352
00353
00354
00355 *skyout = NULL;
00356 if (*status != VIR_OK)
00357 return(*status);
00358
00359
00360
00361 if (nfiles == 0) {
00362 cpl_msg_error(fctid,"Sky correction impossible. No science frames");
00363 return(VIR_FATAL);
00364 }
00365
00366
00367
00368
00369 inbpm = vircam_mask_get_data(mask);
00370 nx = vircam_mask_get_size_x(mask);
00371 ny = vircam_mask_get_size_y(mask);
00372 npts = nx*ny;
00373 cplmask = cpl_mask_wrap(nx,ny,(cpl_binary *)inbpm);
00374 for (i = 0; i < nfiles; i++)
00375 cpl_image_reject_from_mask(vircam_fits_get_image(inlist[i]),cplmask);
00376 cpl_mask_unwrap(cplmask);
00377
00378
00379
00380
00381 test = cpl_malloc(nx*ny*sizeof(float));
00382 for (i = 0; i < nfiles; i++) {
00383 vircam_backmap(inlist[i],mask,64,&outim,&skymed);
00384 odata = cpl_image_get_data_float(outim);
00385 idata = cpl_image_get_data_float(vircam_fits_get_image(inlist[i]));
00386 for (j = 0; j < npts; j++)
00387 test[j] = idata[j] - odata[j];
00388 vircam_qmedsig(test,inbpm,(long)npts,3.0,2,-65535.0,65535.0,&skymed,
00389 &skysig);
00390 immask = cpl_mask_get_data(cpl_image_get_bpm(vircam_fits_get_image(inlist[i])));
00391 for (j = 0; j < npts; j++)
00392 if (test[j] > (skymed + 1.5*skysig))
00393 immask[j] = 1;
00394 cpl_image_delete(outim);
00395 }
00396 freespace(test);
00397
00398
00399
00400 (void)vircam_pfits_get_njsteps(vircam_fits_get_phu(inlist[0]),&njit);
00401
00402
00403
00404 xskys = cpl_malloc(njit*sizeof(xsky_struct));
00405 for (i = 0; i < njit; i++) {
00406 xskys[i].n = 0;
00407 xskys[i].in = cpl_malloc(8*sizeof(vir_fits *));
00408 xskys[i].nalloc = 8;
00409 xskys[i].xsky = NULL;
00410 xskys[i].status = VIR_OK;
00411 }
00412 xsky_fits = cpl_malloc(njit*sizeof(vir_fits *));
00413
00414
00415
00416
00417
00418
00419
00420 for (i = 0; i < nfiles; i++) {
00421 (void)vircam_pfits_get_jitteri(vircam_fits_get_phu(inlist[i]),&ji);
00422 ji--;
00423 if (xskys[ji].n == xskys[ji].nalloc) {
00424 xskys[ji].in = cpl_realloc(xskys[ji].in,
00425 (xskys[ji].nalloc+8)*sizeof(vir_fits *));
00426 xskys[ji].nalloc += 8;
00427 }
00428 xskys[ji].in[xskys[ji].n] = inlist[i];
00429 xskys[ji].n += 1;
00430 }
00431
00432
00433
00434
00435 ns = 0;
00436 for (i = 0; i < njit; i++) {
00437 *status = VIR_OK;
00438 if (xskys[i].n == 0) {
00439 xskys[i].xsky = NULL;
00440 continue;
00441 } else if (xskys[i].n == 1) {
00442 xskys[i].xsky = NULL;
00443 xsky_fits[ns++] = xskys[i].in[0];
00444 continue;
00445 }
00446 outim = NULL;
00447 (void)vircam_imcombine(xskys[i].in,xskys[i].n,1,1,0,1.0,&outim,&rejmask,
00448 &rejplus,&drs,status);
00449 freespace(rejmask);
00450 freespace(rejplus);
00451 freepropertylist(drs);
00452 if (*status == VIR_OK) {
00453 xskys[i].xsky = vircam_fits_wrap(outim,xskys[i].in[0],NULL,NULL);
00454 xsky_fits[ns++] = xskys[i].xsky;
00455 } else {
00456 freeimage(outim);
00457 }
00458 }
00459
00460
00461
00462 if (ns != 0) {
00463 outim = NULL;
00464 (void)vircam_imcombine(xsky_fits,ns,1,1,0,1.0,&outim,&rejmask,&rejplus,
00465 &drs,status);
00466 freespace(rejmask);
00467 freespace(rejplus);
00468 freepropertylist(drs);
00469 if (*status == VIR_OK) {
00470 *skyout = vircam_fits_wrap(outim,inlist[0],NULL,NULL);
00471 } else {
00472 freeimage(outim);
00473 *skyout = NULL;
00474 }
00475 } else {
00476 *skyout = NULL;
00477 }
00478
00479
00480
00481 freespace(xsky_fits);
00482 for (i = 0; i < njit; i++) {
00483 freespace(xskys[i].in);
00484 freefits(xskys[i].xsky);
00485 }
00486 freespace(xskys);
00487 return(*status);
00488 }
00489
00490
00491
00509
00510
00511 static void vircam_sky_mask_grow(cpl_image *dith, float rad) {
00512 cpl_binary *inmap,*outmap;
00513 int nx,ny,ir,i,j,indx,ixmin,ixmax,iymin,iymax,ii,jj,indx2;
00514 float dx,dy,radius;
00515
00516
00517
00518 inmap = cpl_mask_get_data(cpl_image_get_bpm(dith));
00519 nx = cpl_image_get_size_x(dith);
00520 ny = cpl_image_get_size_y(dith);
00521
00522
00523
00524 outmap = cpl_malloc(nx*ny*sizeof(*outmap));
00525 memmove(outmap,inmap,nx*ny*sizeof(*inmap));
00526
00527
00528
00529
00530 ir = vircam_nint(rad);
00531
00532
00533
00534
00535
00536
00537 for (j = 0; j < ny; j++) {
00538 for (i = 0; i < nx; i++) {
00539 indx = j*nx + i;
00540 if (! inmap[indx])
00541 continue;
00542 ixmin = max(0,i-ir);
00543 ixmax = min(nx-1,i+ir);
00544 iymin = max(0,j-ir);
00545 iymax = min(ny-1,j+ir);
00546 for (jj = iymin; jj <= iymax; jj++) {
00547 dy = (float)(jj - j);
00548 for (ii = ixmin; ii <= ixmax; ii++) {
00549 dx = (float)(ii - i);
00550 radius = (float)sqrt(pow(dx,2.0) + pow(dy,2.0));
00551 if (radius <= rad) {
00552 indx2 = jj*nx + ii;
00553 outmap[indx2] = 1;
00554 }
00555 }
00556 }
00557 }
00558 }
00559
00560
00561
00562
00563 memmove(inmap,outmap,nx*ny*sizeof(*inmap));
00564 cpl_free(outmap);
00565 }
00566
00567
00585
00586
00587 static float vircam_sky_med(vir_fits *sky) {
00588 int npts;
00589 float *data,med;
00590 unsigned char *bpm;
00591 cpl_image *skyim;
00592
00593
00594
00595 skyim = vircam_fits_get_image(sky);
00596 npts = cpl_image_get_size_x(skyim)*cpl_image_get_size_y(skyim);
00597
00598
00599
00600 data = cpl_image_get_data_float(skyim);
00601 bpm = (unsigned char *)cpl_mask_get_data(cpl_image_get_bpm(skyim));
00602
00603
00604
00605 med = vircam_med(data,bpm,(long)npts);
00606 return(med);
00607 }
00608
00609
00629
00630
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
00743
00744
00745 static void vircam_sky_joffs(vir_fits **inlist, int nfiles, float **xoffs,
00746 float **yoffs) {
00747 float xoff,yoff;
00748 cpl_wcs *wcsref,*wcs;
00749 int refset,i,status;
00750 const double maxoffset = 2048;
00751 vir_fits *ff;
00752 const char *fctid = "vircam_sky_joffs";
00753
00754
00755
00756 *xoffs = cpl_malloc(nfiles*sizeof(float));
00757 *yoffs = cpl_malloc(nfiles*sizeof(float));
00758
00759
00760
00761 refset = 0;
00762 wcsref = NULL;
00763 for (i = 0; i < nfiles; i++) {
00764 ff = inlist[i];
00765 wcs = cpl_wcs_new_from_propertylist(vircam_fits_get_ehu(ff));
00766
00767
00768
00769
00770 if (wcs == NULL) {
00771 cpl_msg_warning(fctid,"Unable to get WCS for %s",
00772 vircam_fits_get_filename(ff));
00773 (*xoffs)[i] = 0.0;
00774 (*yoffs)[i] = 0.0;
00775 vircam_fits_set_error(ff,VIR_WARN);
00776 continue;
00777 }
00778
00779
00780
00781 if (! refset) {
00782 (*xoffs)[0] = 0.0;
00783 (*yoffs)[0] = 0.0;
00784 refset = 1;
00785 wcsref = wcs;
00786 continue;
00787 }
00788
00789
00790
00791 status = VIR_OK;
00792 (void)vircam_diffxywcs(wcs,wcsref,&xoff,&yoff,&status);
00793
00794
00795
00796 if (status != VIR_OK) {
00797 (*xoffs)[i] = 0.0;
00798 (*yoffs)[i] = 0.0;
00799 cpl_msg_warning(fctid,"Unable to WCS difference for %s",
00800 vircam_fits_get_filename(ff));
00801 } else if (fabs((double)xoff) > maxoffset ||
00802 fabs((double)yoff) > maxoffset) {
00803 vircam_fits_set_error(ff,VIR_FATAL);
00804 cpl_msg_error(fctid,"WCS offsets for %s are >%g: %g %g -- ignoring",
00805 vircam_fits_get_filename(ff),maxoffset,xoff,yoff);
00806 } else {
00807 (*xoffs)[i] = xoff;
00808 (*yoffs)[i] = yoff;
00809 }
00810 cpl_wcs_delete(wcs);
00811 }
00812 if (wcsref != NULL)
00813 cpl_wcs_delete(wcsref);
00814
00815
00816
00817 for (i = 0; i < nfiles; i++) {
00818 ff = inlist[i];
00819 cpl_propertylist_update_double(vircam_fits_get_ehu(ff),
00820 "ESO DRS XOFFDITHER",
00821 (double)(*xoffs)[i]);
00822 cpl_propertylist_update_double(vircam_fits_get_ehu(ff),
00823 "ESO DRS YOFFDITHER",
00824 (double)(*yoffs)[i]);
00825 }
00826 }
00827
00830
00831
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