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 *, int *, 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,j;
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(vircam_fits_get_phu(dd->fname),&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,dd->cdata,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 for (i = 1; i < nimages; i++) {
00273 dd = fileptrs + i;
00274 npts = dd->nx*dd->ny;
00275 for (j = 0; j < npts; j++)
00276 dd->data[j] = dd->data[j]/dd->expscale + dd->skydiff;
00277 }
00278
00279
00280
00281 clip1 = fileptrs->sky - lthr*fileptrs->noise;
00282 clip2 = fileptrs->sky + hthr*fileptrs->noise;
00283
00284
00285
00286
00287 nxo = 0;
00288 nyo = 0;
00289 for (i = 0; i < nimages; i++) {
00290 dd = fileptrs + i;
00291 itx = dd->nx + dd->ixoff;
00292 nxo = max(nxo,itx);
00293 itx = dd->ny + dd->iyoff;
00294 nyo = max(nyo,itx);
00295 }
00296
00297
00298
00299 *out = cpl_image_new(nxo,nyo,CPL_TYPE_FLOAT);
00300
00301
00302
00303 if (nconfs != 0)
00304 *outc = cpl_image_new(nxo,nyo,CPL_TYPE_INT);
00305 else
00306 *outc = NULL;
00307
00308
00309
00310 npts = nxo*nyo;
00311 odata = cpl_image_get_data_float(*out);
00312 if (*outc != NULL)
00313 owdata = cpl_malloc(npts*sizeof(float));
00314 clipmon = clip_open(nimages);
00315
00316
00317
00318
00319 for (iy = 0; iy < nyo; iy++) {
00320 ccur = (iy % 2)*nxo;
00321 clast = nxo - ccur;
00322 for (ix = 0; ix < nxo; ix++) {
00323 c = clipmon + ccur + ix;
00324 c->n = 0;
00325 c->clipped = 0;
00326 n = 0;
00327 for (i = 0; i < nimages; i++) {
00328 dd = fileptrs + i;
00329 iline = iy - dd->iyoff;
00330 if (iline < 0 || iline >= dd->ny)
00331 continue;
00332 icol = ix - dd->ixoff;
00333 if (icol < 0 || icol >= dd->nx)
00334 continue;
00335
00336
00337
00338
00339 ielm = dd->nx*iline + icol;
00340 c->values[n] = dd->data[ielm];
00341 c->confs[n] = dd->cdata[ielm];
00342 c->weights[n] = dd->weight;
00343 c->iff[n] = (short int)i;
00344 n++;
00345 }
00346 c->outindex = nxo*iy + ix;
00347 c->n = n;
00348 average(c,&outdata,&outconf,clip1,clip2,0.0);
00349 odata[c->outindex] = outdata;
00350 if (owdata != NULL)
00351 owdata[c->outindex] = outconf;
00352 }
00353
00354
00355
00356
00357
00358 if (iy < 2)
00359 continue;
00360 for (ix = 1; ix < nxo-1; ix++) {
00361 c = clipmon + clast + ix;
00362 if (! c->clipped)
00363 continue;
00364
00365
00366
00367
00368 iloc = c->outindex;
00369 avlev = 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 avlev += odata[index];
00375 }
00376 }
00377 avlev /= 9.0;
00378 avvar = 0.0;
00379 for (jy = -1; jy <= 1; jy++) {
00380 index_y = iloc + jy*nxo;
00381 for (jx = -1; jx <= 1; jx++) {
00382 index = index_y + jx;
00383 avvar += fabs(odata[index] - avlev);
00384 }
00385 }
00386 avvar /= 9.0;
00387
00388
00389
00390
00391
00392 if (avlev < clip2 || avvar <= 2.0*fileptrs->noise)
00393 continue;
00394
00395
00396
00397 average(c,&outdata,&outconf,clip1,clip2,3.0*avvar);
00398 odata[c->outindex] = outdata;
00399 if (owdata != NULL)
00400 owdata[c->outindex] = outconf;
00401 }
00402 }
00403
00404
00405
00406 if (owdata != NULL) {
00407 skyest(owdata,NULL,npts,3.0,&sky,&skynoise);
00408 renorm = 100.0/sky;
00409 ocdata = cpl_image_get_data_int(*outc);
00410 for (i = 0; i < npts; i++)
00411 ocdata[i] = max(0,min(1000,((int)(owdata[i]*renorm + 0.5))));
00412 }
00413
00414
00415
00416 *p = cpl_propertylist_duplicate(vircam_fits_get_ehu(inf[0]));
00417 vircam_prov(*p,inf,nimages);
00418
00419
00420
00421 vircam_timestamp(timestamp,25);
00422 p2 = vircam_fits_get_phu(inf[0]);
00423 cpl_propertylist_update_string(p2,"VIR_TIME",timestamp);
00424 cpl_propertylist_set_comment(p2,"VIR_TIME",
00425 "Timestamp for matching to conf map");
00426
00427
00428
00429 (void)vircam_pfits_get_crpix1(*p,&crpix1);
00430 (void)vircam_pfits_get_crpix2(*p,&crpix2);
00431 crpix1 += fileptrs->xoff;
00432 crpix2 += fileptrs->yoff;
00433 cpl_propertylist_update_double(*p,"CRPIX1",crpix1);
00434 cpl_propertylist_update_double(*p,"CRPIX2",crpix2);
00435
00436
00437
00438 tidy();
00439 GOOD_STATUS
00440 }
00441
00442 static void average(keeptabs *c, float *outdata, float *outconf, float cliplow,
00443 float cliphigh, float extra) {
00444 int i,imin,imax;
00445 float valuemax,valuemin,cwmin,cwmax,sum,cnumb,numb,cw,cv,reflev,noise;
00446 float sky,clipval;
00447
00448
00449
00450
00451
00452 if (c->n <= 0) {
00453 *outdata = fileptrs->sky;
00454 *outconf = 0.0;
00455 return;
00456 }
00457
00458
00459
00460
00461 valuemin = 1.0e10;
00462 valuemax = -1.0e10;
00463 cwmin = 1.0e10;
00464 cwmax = -1.0e10;
00465 imin = 0;
00466 imax = 0;
00467 sum = 0.0;
00468 cnumb = 0.0;
00469 numb = 0.0;
00470
00471
00472
00473
00474 for (i = 0; i < c->n; i++) {
00475 cw = c->weights[i]*c->confs[i];
00476 cv = c->values[i];
00477 sum += cv*cw;
00478 cnumb +=cw;
00479 numb += c->confs[i];
00480 if (cv < valuemin) {
00481 valuemin = cv;
00482 cwmin = cw;
00483 imin = i;
00484 }
00485 if (cv > valuemax) {
00486 valuemax = cv;
00487 cwmax = cw;
00488 imax = i;
00489 }
00490 }
00491 if (cnumb > 0.0)
00492 *outdata = sum/cnumb;
00493 else
00494 *outdata = fileptrs->sky;
00495
00496
00497
00498 if (valuemax > cliphigh && numb > 150.0 && cnumb > 150.0) {
00499 reflev = (sum - valuemax*cwmax)/(cnumb - cwmax);
00500 noise = (fileptrs+c->iff[imax])->noise;
00501 sky = (fileptrs+c->iff[imax])->sky;
00502 clipval = reflev + hsig*noise*max(1.0,reflev)/max(1.0,sky) + extra;
00503 if (valuemax > clipval) {
00504 sum -= valuemax*cwmax;
00505 cnumb -= cwmax;
00506 *outdata = reflev;
00507 c->clipped = 1;
00508 }
00509 }
00510
00511
00512
00513 if (valuemin < cliplow && numb > 150.0 && cnumb > 150.0) {
00514 reflev = (sum - valuemin*cwmin)/(cnumb - cwmin);
00515 noise = (fileptrs+c->iff[imin])->noise;
00516 clipval = reflev - lsig*noise;
00517 if (valuemin < clipval) {
00518 cnumb -= cwmin;
00519 *outdata = reflev;
00520 }
00521 }
00522
00523
00524
00525 *outconf = cnumb/sumweight;
00526 }
00527
00528
00529 static keeptabs *clip_open(int nimages) {
00530 keeptabs *c;
00531 int i;
00532 short int *iff;
00533 float *dptr;
00534
00535 c = cpl_malloc(2*nxo*sizeof(keeptabs));
00536 for (i = 0; i < 2*nxo; i++) {
00537 dptr = cpl_malloc(3*nimages*sizeof(*dptr));
00538 iff = cpl_malloc(nimages*sizeof(*iff));
00539 (c+i)->values = dptr;
00540 (c+i)->confs = dptr + nimages;
00541 (c+i)->weights = dptr + 2*nimages;
00542 (c+i)->iff = iff;
00543 (c+i)->n = 0;
00544 (c+i)->outindex = -1;
00545 (c+i)->clipped = 0;
00546 }
00547 return(c);
00548 }
00549
00550 static void clip_close(keeptabs **c) {
00551 int i;
00552
00553 for (i = 0; i < 2*nxo; i++) {
00554 freespace((*c+i)->values);
00555 freespace((*c+i)->iff);
00556 }
00557 freespace(*c);
00558 }
00559
00560 static void fileptrs_close(void) {
00561
00562
00563 freespace(fileptrs);
00564 }
00565
00566
00567 static void skyest(float *data, int *cdata, long npts, float thresh,
00568 float *skymed, float *skynoise) {
00569 unsigned char *bpm;
00570 int i;
00571
00572
00573
00574 bpm = cpl_calloc(npts,sizeof(*bpm));
00575 if (cdata != NULL) {
00576 for (i = 0; i < npts; i++)
00577 bpm[i] = (cdata[i] == 0);
00578 }
00579
00580
00581
00582 vircam_qmedsig(data,bpm,npts,thresh,2,-1000.0,65535.0,skymed,skynoise);
00583
00584
00585
00586 freespace(bpm);
00587 }
00588
00589 static void tidy(void) {
00590
00591 freespace(owdata);
00592 clip_close(&clipmon);
00593 fileptrs_close();
00594 }
00595
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
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653