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