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 <math.h>
00035 #include <cpl.h>
00036 #include "vircam_mods.h"
00037 #include "vircam_utils.h"
00038 #include "vircam_fits.h"
00039 #include "vircam_stats.h"
00040 #include "vircam_pfits.h"
00041 
00042 typedef struct {
00043     vir_fits  *fname;
00044     vir_fits  *conf;
00045     float     xoff;
00046     float     yoff;
00047     int       ixoff;
00048     int       iyoff;
00049     int       nx;
00050     int       ny;
00051     float     sky;
00052     float     skydiff;
00053     float     noise;
00054     float     expscale;
00055     float     weight;
00056     float     *data;
00057     int       *cdata;
00058     int       ndata;
00059 } dstrct;
00060 
00061 typedef struct {
00062     float         *values;
00063     float         *confs;
00064     float         *weights;
00065     short int     *iff;
00066     int           n;
00067     long          outindex;
00068     unsigned char clipped;
00069 } keeptabs;
00070 
00071 #define NROWSBUF 512
00072 
00073 static dstrct *fileptrs = NULL;
00074 static float *odata = NULL;
00075 static float *owdata = NULL;
00076 static keeptabs *clipmon = NULL;
00077 
00078 static float lsig;
00079 static float hsig;
00080 static float sumweight;
00081 static int   nxo;
00082 static int   nyo;
00083 
00084 static void average(keeptabs *, float *, float *, float, float, float);
00085 static keeptabs *clip_open( int);
00086 static void clip_close(keeptabs **);
00087 static void fileptrs_close(void);
00088 static void skyest(float *, long, float, float *, float *);
00089 static void tidy(void);
00090 
00093 
00154 
00155     
00156 extern int vircam_imdither(vir_fits **inf, vir_fits **inconf, int nimages, 
00157                            int nconfs, float lthr, float hthr,
00158                            cpl_propertylist **p, cpl_image **out, 
00159                            cpl_image **outc, int *status) {
00160 
00161     int i,itx,iy,ccur,clast,ix,n,iline,icol,jy,jx,*ocdata;
00162     long npts,ielm,iloc,index_y,index;
00163     dstrct *dd;
00164     keeptabs *c;
00165     float minxoff,minyoff,expref,sky,skynoise,clip1,clip2,outdata;
00166     float outconf,avlev,avvar,renorm,exposure;
00167     double crpix1,crpix2;
00168     cpl_propertylist *ehu,*p2;
00169     const char *fctid = "vircam_imdither";
00170     char timestamp[25];
00171 
00172     
00173 
00174     *out = NULL;
00175     *outc = NULL;
00176     *p = NULL;
00177     if (*status != VIR_OK)
00178         return(*status);
00179 
00180     
00181 
00182     if (nimages == 0) {
00183         cpl_msg_error(fctid,"No input files to combine");
00184         tidy();
00185         FATAL_ERROR
00186     }
00187 
00188     
00189 
00190     lsig = lthr;
00191     hsig = hthr;
00192 
00193     
00194 
00195     fileptrs = cpl_malloc(nimages*sizeof(dstrct));
00196     (void)vircam_pfits_get_exptime(vircam_fits_get_phu(inf[0]),&exposure);
00197     expref = max(0.5,exposure);
00198     minxoff = 1.0e10;
00199     minyoff = 1.0e10;
00200     for (i = 0; i < nimages; i++) {
00201         dd = fileptrs + i;
00202         dd->fname = inf[i];
00203         dd->data = cpl_image_get_data_float(vircam_fits_get_image(inf[i]));
00204         if (nconfs == 0) {
00205             dd->conf = NULL;
00206         } else if (nconfs == 1) {
00207             dd->conf = inconf[0];
00208             dd->cdata = cpl_image_get_data_int(vircam_fits_get_image(inconf[0]));
00209         } else {
00210             dd->conf = inconf[i];
00211             dd->cdata = cpl_image_get_data_int(vircam_fits_get_image(inconf[i]));
00212         }
00213         ehu = vircam_fits_get_ehu(dd->fname);
00214         (void)vircam_pfits_get_jxoff(ehu,&(dd->xoff));
00215         (void)vircam_pfits_get_jyoff(ehu,&(dd->yoff));
00216         minxoff = min(dd->xoff,minxoff);
00217         minyoff = min(dd->yoff,minyoff);
00218         (void)vircam_pfits_get_exptime(ehu,&exposure);
00219         dd->expscale = exposure/expref;
00220 
00221         
00222 
00223         dd->nx = cpl_image_get_size_x(vircam_fits_get_image(dd->fname));
00224         dd->ny = cpl_image_get_size_y(vircam_fits_get_image(dd->fname));
00225         npts = dd->nx*dd->ny;
00226         skyest(dd->data,npts,3.0,&sky,&skynoise);
00227         dd->sky = sky;
00228         dd->noise = skynoise;
00229         
00230         
00231 
00232 
00233         if (cpl_image_get_size_x(vircam_fits_get_image(dd->conf)) != dd->nx || 
00234             cpl_image_get_size_y(vircam_fits_get_image(dd->conf)) != dd->ny) {
00235             cpl_msg_error(fctid,"VIRCAM_IMDITHER: Image %s and Confidence map %s don't match",
00236                           vircam_fits_get_fullname(dd->fname),
00237                           vircam_fits_get_fullname(dd->conf));
00238             tidy();
00239             FATAL_ERROR
00240         }
00241     }
00242 
00243     
00244 
00245     for (i = 0; i < nimages; i++) {
00246         dd = fileptrs + i;
00247         dd->xoff -= minxoff;
00248         dd->yoff -= minyoff;
00249         dd->ixoff = (int)(dd->xoff + 0.5);
00250         dd->iyoff = (int)(dd->yoff + 0.5);
00251     }
00252 
00253     
00254 
00255 
00256 
00257     fileptrs->sky /= fileptrs->expscale;
00258     fileptrs->skydiff = 0.0;
00259     fileptrs->weight = 1.0;
00260     sumweight = 1.0;
00261     for (i = 1; i < nimages; i++) {
00262         dd = fileptrs + i;
00263         dd->sky /= dd->expscale;
00264         dd->skydiff = fileptrs->sky - dd->sky;
00265         dd->noise /= (float)sqrt((double)dd->expscale);
00266         dd->weight = (float)(pow((double)fileptrs->noise,2.0)/pow((double)dd->noise,2.0)); 
00267         sumweight += dd->weight;
00268     }
00269 
00270     
00271 
00272     clip1 = fileptrs->sky - lthr*fileptrs->noise;
00273     clip2 = fileptrs->sky + hthr*fileptrs->noise;
00274 
00275     
00276 
00277 
00278     nxo = 0;
00279     nyo = 0;
00280     for (i = 0; i < nimages; i++) {
00281         dd = fileptrs + i;
00282         itx = dd->nx + dd->ixoff;
00283         nxo = max(nxo,itx);
00284         itx = dd->ny + dd->iyoff;
00285         nyo = max(nyo,itx);
00286     }
00287 
00288     
00289 
00290     *out = cpl_image_new(nxo,nyo,CPL_TYPE_FLOAT);
00291 
00292     
00293 
00294     if (nconfs != 0) 
00295         *outc = cpl_image_new(nxo,nyo,CPL_TYPE_INT);
00296     else 
00297         *outc = NULL;
00298 
00299     
00300 
00301     npts = nxo*nyo;
00302     odata = cpl_image_get_data_float(*out);
00303     if (*outc != NULL) 
00304         owdata = cpl_malloc(npts*sizeof(float));
00305     clipmon = clip_open(nimages);
00306 
00307     
00308 
00309 
00310     for (iy = 0; iy < nyo; iy++) {
00311         ccur = (iy % 2)*nxo;
00312         clast = nxo - ccur;
00313         for (ix = 0; ix < nxo; ix++) {
00314             c = clipmon + ccur + ix;
00315             c->n = 0;
00316             c->clipped = 0;
00317             n = 0;
00318             for (i = 0; i < nimages; i++) {             
00319                 dd = fileptrs + i;
00320                 iline = iy - dd->iyoff;
00321                 if (iline < 0 || iline >= dd->ny)
00322                     continue;
00323                 icol = ix - dd->ixoff;
00324                 if (icol < 0 || icol >= dd->nx)
00325                     continue;
00326 
00327                 
00328 
00329                 
00330                 ielm = dd->nx*iline + icol;
00331                 c->values[n] = dd->data[ielm];
00332                 c->confs[n] = dd->cdata[ielm];
00333                 c->weights[n] = dd->weight;
00334                 c->iff[n] = (short int)i;
00335                 n++;
00336             }
00337             c->outindex = nxo*iy + ix;
00338             c->n = n;
00339             average(c,&outdata,&outconf,clip1,clip2,0.0);
00340             odata[c->outindex] = outdata;
00341             if (owdata != NULL) 
00342                 owdata[c->outindex] = outconf;
00343         }
00344 
00345         
00346 
00347 
00348 
00349         if (iy < 2)
00350             continue;
00351         for (ix = 1; ix < nxo-1; ix++) {
00352             c = clipmon + clast + ix;
00353             if (! c->clipped)
00354                 continue;
00355 
00356             
00357 
00358 
00359             iloc = c->outindex;
00360             avlev = 0.0;
00361             for (jy = -1; jy <= 1; jy++) {
00362                 index_y = iloc + jy*nxo;
00363                 for (jx = -1; jx <= 1; jx++) {
00364                     index = index_y + jx;
00365                     avlev += odata[index];
00366                 }
00367             }
00368             avlev /= 9.0;
00369             avvar = 0.0;
00370             for (jy = -1; jy <= 1; jy++) {
00371                 index_y = iloc + jy*nxo;
00372                 for (jx = -1; jx <= 1; jx++) {
00373                     index = index_y + jx;
00374                     avvar += fabs(odata[index] - avlev);
00375                 }
00376             }
00377             avvar /= 9.0;
00378 
00379             
00380 
00381 
00382 
00383             if (avlev < clip2 || avvar <= 2.0*fileptrs->noise)
00384                 continue;
00385 
00386             
00387 
00388             average(c,&outdata,&outconf,clip1,clip2,3.0*avvar);
00389             odata[c->outindex] = outdata;
00390             if (owdata != NULL) 
00391                 owdata[c->outindex] = outconf;
00392         }
00393     }
00394     
00395     
00396     
00397     if (owdata != NULL) {
00398         skyest(owdata,npts,3.0,&sky,&skynoise);
00399         renorm = 100.0/sky;
00400         ocdata = cpl_image_get_data_int(*outc);
00401         for (i = 0; i < npts; i++) 
00402             ocdata[i] = max(0,min(110,((int)(owdata[i]*renorm + 0.5))));
00403     }
00404 
00405     
00406 
00407     *p = cpl_propertylist_duplicate(vircam_fits_get_ehu(inf[0]));    
00408     vircam_prov(*p,inf,nimages);
00409 
00410     
00411 
00412     vircam_timestamp(timestamp,25);
00413     p2 = vircam_fits_get_phu(inf[0]);
00414     cpl_propertylist_update_string(p2,"VIR_TIME",timestamp);
00415     cpl_propertylist_set_comment(p2,"VIR_TIME",
00416                                  "Timestamp for matching to conf map");
00417 
00418     
00419 
00420     (void)vircam_pfits_get_crpix1(*p,&crpix1);
00421     (void)vircam_pfits_get_crpix2(*p,&crpix2);
00422     crpix1 += fileptrs->xoff;
00423     crpix2 += fileptrs->yoff;
00424     cpl_propertylist_update_double(*p,"CRPIX1",crpix1);
00425     cpl_propertylist_update_double(*p,"CRPIX2",crpix2);
00426 
00427     
00428 
00429     tidy();
00430     GOOD_STATUS
00431 }
00432 
00433 static void average(keeptabs *c, float *outdata, float *outconf, float cliplow,
00434                     float cliphigh, float extra) {
00435     int i,imin,imax;
00436     float valuemax,valuemin,cwmin,cwmax,sum,cnumb,numb,cw,cv,reflev,noise;
00437     float sky,clipval;
00438     
00439     
00440 
00441 
00442     
00443     if (c->n <= 0) {
00444         *outdata = fileptrs->sky;
00445         *outconf = 0.0;
00446         return;
00447     }
00448     
00449     
00450 
00451     
00452     valuemin = 1.0e10;
00453     valuemax = -1.0e10;
00454     cwmin = 1.0e10;
00455     cwmax = -1.0e10;
00456     imin = 0;
00457     imax = 0;
00458     sum = 0.0;
00459     cnumb = 0.0;
00460     numb = 0.0;
00461     
00462     
00463 
00464     
00465     for (i = 0; i < c->n; i++) {
00466         cw = c->weights[i]*c->confs[i];
00467         cv = c->values[i];
00468         sum += cv*cw;
00469         cnumb +=cw;
00470         numb += c->confs[i];
00471         if (cv < valuemin) {
00472             valuemin = cv;
00473             cwmin = cw;
00474             imin = i;
00475         } 
00476         if (cv > valuemax) {
00477             valuemax = cv;
00478             cwmax = cw;
00479             imax = i;
00480         }
00481     }
00482     if (cnumb > 0.0)
00483         *outdata = sum/cnumb;
00484     else
00485         *outdata = fileptrs->sky;
00486 
00487     
00488     
00489     if (valuemax > cliphigh && numb > 150.0 && cnumb > 150.0) {
00490         reflev = (sum - valuemax*cwmax)/(cnumb - cwmax);
00491         noise = (fileptrs+c->iff[imax])->noise;
00492         sky = (fileptrs+c->iff[imax])->sky;
00493         clipval = reflev + hsig*noise*max(1.0,reflev)/max(1.0,sky) + extra;
00494         if (valuemax > clipval) {
00495             sum -= valuemax*cwmax;
00496             cnumb -= cwmax;
00497             *outdata = reflev;
00498             c->clipped = 1;
00499         }
00500     }
00501     
00502     
00503     
00504     if (valuemin < cliplow && numb > 150.0 && cnumb > 150.0) {
00505         reflev = (sum - valuemin*cwmin)/(cnumb - cwmin);
00506         noise = (fileptrs+c->iff[imin])->noise;
00507         clipval = reflev - lsig*noise;
00508         if (valuemin < clipval) {
00509             cnumb -= cwmin;
00510             *outdata = reflev;
00511         }
00512     }
00513     
00514     
00515     
00516     *outconf = cnumb/sumweight;
00517 }
00518         
00519     
00520 static keeptabs *clip_open(int nimages) {
00521     keeptabs *c;
00522     int i;
00523     short int *iff;
00524     float *dptr;
00525 
00526     c = cpl_malloc(2*nxo*sizeof(keeptabs));
00527     for (i = 0; i < 2*nxo; i++) {
00528         dptr = cpl_malloc(3*nimages*sizeof(*dptr));
00529         iff = cpl_malloc(nimages*sizeof(*iff));
00530         (c+i)->values = dptr;
00531         (c+i)->confs = dptr + nimages;
00532         (c+i)->weights = dptr + 2*nimages;
00533         (c+i)->iff = iff;
00534         (c+i)->n = 0;
00535         (c+i)->outindex = -1;
00536         (c+i)->clipped = 0;
00537     }
00538     return(c);
00539 }
00540 
00541 static void clip_close(keeptabs **c) {
00542     int i;
00543 
00544     for (i = 0; i < 2*nxo; i++) {
00545         freespace((*c+i)->values);
00546         freespace((*c+i)->iff);
00547     }
00548     freespace(*c);
00549 }
00550 
00551 static void fileptrs_close(void) {
00552 
00553 
00554     freespace(fileptrs);
00555 }    
00556 
00557 
00558 static void skyest(float *data, long npts, float thresh, float *skymed,
00559                    float *skynoise) {
00560     unsigned char *bpm;
00561 
00562     
00563 
00564     bpm = cpl_calloc(npts,sizeof(*bpm));
00565 
00566     
00567 
00568     vircam_qmedsig(data,bpm,npts,thresh,2,-1000.0,65535.0,skymed,skynoise);
00569 
00570     
00571 
00572     freespace(bpm);
00573 }
00574 
00575 static void tidy(void) {
00576 
00577     freespace(owdata);
00578     clip_close(&clipmon);
00579     fileptrs_close();
00580 }    
00581 
00584 
00585 
00586 
00587 
00588 
00589 
00590 
00591 
00592 
00593 
00594 
00595 
00596 
00597 
00598 
00599 
00600 
00601 
00602 
00603 
00604 
00605 
00606 
00607 
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615 
00616 
00617 
00618 
00619 
00620 
00621 
00622 
00623 
00624 
00625 
00626 
00627 
00628 
00629 
00630