38 #include "catalogue/casu_utils.h"
39 #include "casu_stats.h"
40 #include "catalogue/casu_fits.h"
41 #include "casu_mods.h"
45 #define FATAL_ERR(_f,_a) {cpl_msg_error(_f,"%s",_a); tidy(&uinfo); *status = CASU_FATAL; return(*status);}
46 #define WARN_ERR(_f,_a) {cpl_msg_error(_f,"%s",_a); tidy(&uinfo); *status = CASU_WARN; return(CASU_WARN);}
47 #define INFO_ERR(_f,_a) {cpl_msg_info(_f,"%s",_a);}
51 #define DATAMIN -65535.0
52 #define DATAMAX 65535.0
86 static void skyest(
long npts,
float *data, cpl_binary *bpm,
float thresh,
87 float *skymed,
float *skynoise);
88 static void medcalc(usefulinfo *uinfo,
float,
float,
int);
89 static void meancalc(usefulinfo *uinfo,
float,
float,
int);
90 static void xclip_med(usefulinfo *uinfo,
float thresh,
int scaletype);
91 static void xclip_mean(usefulinfo *uinfo,
float thresh,
int scaletype);
93 static void tidy(usefulinfo *uinfo);
166 int combtype,
int scaletype,
int xrej,
float thresh,
167 const char *expkey, cpl_image **outimage,
168 cpl_image **outvimage,
unsigned char **rejmask,
169 unsigned char **rejplus, cpl_propertylist **drs,
172 long npts = 0, nx = -1, ny = -1;
174 float sumsky,sumsig,texp1,texp2,expfudge,skylevel,skynoise,oskynoise;
175 float *dat,*work,**datas,**vars,*odata,*ovdata,oskylevel;
176 litestruct *ff,*fileptrs = NULL;
178 cpl_propertylist *plist_p;
179 cpl_binary **masks,*omask;
181 const char *ic_fctid =
"casu_imcombine";
189 if (outvimage != NULL)
191 if (*status != CASU_OK)
197 WARN_ERR(ic_fctid,
"No files to combine")
201 uinfo.fileptrs = NULL;
211 fileptrs = cpl_calloc(nfits,
sizeof(litestruct));
212 uinfo.fileptrs = fileptrs;
216 datas = cpl_malloc(nfits*
sizeof(
float *));
219 vars = cpl_malloc(nfits*
sizeof(
float *));
225 for (k = 0; k < nfits; k++) {
226 datas[k] = cpl_malloc(npts*
sizeof(
float));
228 vars[k] = cpl_malloc(npts*
sizeof(
float));
230 masks = cpl_malloc(nfits*
sizeof(cpl_binary *));
235 for (k = 0; k < nfits; k++) {
237 dat = cpl_image_get_data_float(im);
239 snprintf(msg,SZBUF,
"Failed to load data from extension %d in %s",
242 FATAL_ERR(ic_fctid,msg)
244 for (i = 0; i < npts; i++)
245 datas[k][i] = dat[i];
246 masks[k] = cpl_mask_get_data(cpl_image_get_bpm(im));
249 dat = cpl_image_get_data_float(im);
251 snprintf(msg,SZBUF,
"Failed to load data from extension %d in %s",
254 FATAL_ERR(ic_fctid,msg)
256 for (i = 0; i < npts; i++)
264 for (i = 0; i < nfits; i++) {
279 if (strlen(expkey)) {
281 for (k = 0; k < 2; k++) {
286 if (plist_p != NULL && cpl_propertylist_has(plist_p,expkey)) {
292 texp2 = (float)cpl_propertylist_get_double(plist_p,expkey);
295 "Couldn't get exposure time for %s - expkey = %s",
297 INFO_ERR(ic_fctid,msg);
307 texp1 = fileptrs->exptime;
308 expfudge = texp1/texp2;
309 ff->expfudge = expfudge;
315 if (scaletype == 3 && i > 0) {
316 for (j = 0; j < npts; j++) {
317 datas[i][j] *= ff->expfudge;
319 vars[i][j] *= powf(ff->expfudge,2.0);
325 skyest(npts,datas[i],masks[i],thresh,&skylevel,&skynoise);
326 ff->skylevel = skylevel;
327 ff->skynoise = skynoise;
333 work = cpl_malloc((
unsigned int)nfits*
sizeof(
float));
334 for (i = 0; i < nfits; i++)
335 work[i] = (fileptrs+i)->skylevel;
336 sumsky =
casu_med(work,NULL,(
long)nfits);
337 for (i = 0; i < nfits; i++)
338 work[i] = (fileptrs+i)->skynoise;
339 sumsig =
casu_med(work,NULL,(
long)nfits);
343 for (i = 0; i < nfits; i++)
344 (fileptrs+i)->skyfudge = sumsky - (fileptrs+i)->skylevel;
347 for (i = 0; i < nfits; i++)
348 (fileptrs+i)->skyfudge = sumsky/(fileptrs+i)->skylevel;
351 for (i = 0; i < nfits; i++)
352 (fileptrs+i)->skyfudge = sumsky - (fileptrs+i)->skylevel;
355 for (i = 0; i < nfits; i++)
356 (fileptrs+i)->skyfudge = 0.0;
362 *outimage = cpl_image_new((cpl_size)nx,(cpl_size)ny,CPL_TYPE_FLOAT);
363 odata = cpl_image_get_data_float(*outimage);
366 *outvimage = cpl_image_new((cpl_size)nx,(cpl_size)ny,CPL_TYPE_FLOAT);
367 ovdata = cpl_image_get_data_float(*outvimage);
371 uinfo.ovdata = ovdata;
372 omask = cpl_mask_get_data(cpl_image_get_bpm(*outimage));
374 if (*outimage == NULL || odata == NULL)
375 FATAL_ERR(ic_fctid,
"Couldn't create output image")
376 *rejmask = cpl_calloc(npts,
sizeof(*rejmask));
377 uinfo.rmask = *rejmask;
378 *rejplus = cpl_calloc(npts,
sizeof(*rejplus));
379 uinfo.rplus = *rejplus;
385 medcalc(&uinfo,thresh,sumsig,scaletype);
388 meancalc(&uinfo,thresh,sumsig,scaletype);
398 skyest(npts,odata,omask,thresh,&oskylevel,&oskynoise);
399 uinfo.oskylevel = oskylevel;
405 for (i = 0; i < nfits; i++) {
407 ff->skyrenorm = ff->skylevel/oskylevel;
410 for (k = 0; k < npts; k++)
411 datas[i][k] -= (odata[k] - oskylevel);
414 for (k = 0; k < npts; k++)
415 datas[i][k] -= (odata[k] - oskylevel)*ff->skyrenorm;
418 for (k = 0; k < npts; k++)
419 datas[i][k] -= (odata[k] - oskylevel);
422 for (k = 0; k < npts; k++)
423 datas[i][k] -= (odata[k] - oskylevel);
429 skyest(npts,datas[i],masks[i],thresh,&skylevel,&skynoise);
430 ff->skynoise = skynoise;
437 xclip_med(&uinfo,thresh,scaletype);
440 xclip_mean(&uinfo,thresh,scaletype);
447 *drs = cpl_propertylist_new();
482 static void xclip_med(usefulinfo *uinfo,
float thresh,
int scaletype) {
483 int nf1,nf2,nfm,nrejmax,is_even,k,is_even2,nrej,nremain,nm,nmm,nplus;
485 cpl_binary **masks,*omask;
486 unsigned char *rmask,*rplus;
488 float **work,**dork,value,cliplev,**datas,*odata,oskylevel,**vars;
489 float valv = 0.0 ,*ovdata;
490 litestruct *ff,*fileptrs;
494 fileptrs = uinfo->fileptrs;
495 datas = uinfo->datas;
497 masks = uinfo->masks;
498 odata = uinfo->odata;
499 ovdata = uinfo->ovdata;
500 omask = uinfo->omask;
503 oskylevel = uinfo->oskylevel;
504 rmask = uinfo->rmask;
505 rplus = uinfo->rplus;
509 work = cpl_malloc(4*
sizeof(
float *));
510 for (i = 0; i < 4; i++)
511 work[i] = cpl_malloc(nf*
sizeof(
float));
512 dork = cpl_malloc(2*
sizeof(
float *));
513 for (i = 0; i < 2; i++)
514 dork[i] = cpl_malloc(nf*
sizeof(
float));
518 for (i = 0; i < npts; i++) {
527 for (k = 0; k < nf; k++) {
531 work[0][nn] = datas[k][i];
532 work[1][nn] = ff->skynoise;
533 work[2][nn] = datas[k][i] + odata[i] - oskylevel;
535 work[3][nn] = vars[k][i];
540 for (k = 0; k < nf; k++) {
544 work[0][nn] = datas[k][i] + ff->skyfudge;
545 work[1][nn] = ff->skynoise;
546 work[2][nn] = datas[k][i] + odata[i] - oskylevel +
549 work[3][nn] = vars[k][i];
554 for (k = 0; k < nf; k++) {
558 work[0][nn] = datas[k][i]*ff->skyfudge;
559 work[1][nn] = ff->skynoise*ff->skyfudge;
560 work[2][nn] = (datas[k][i] + odata[i]*ff->skyrenorm -
561 ff->skylevel)*ff->skyfudge;
563 work[3][nn] = vars[k][i]*powf(ff->skyfudge,2.0);
568 for (k = 0; k < nf; k++) {
572 work[0][nn] = datas[k][i] + ff->skyfudge;
573 work[1][nn] = ff->skynoise;
574 work[2][nn] = datas[k][i] + odata[i] - oskylevel +
577 work[3][nn] = vars[k][i];
587 nfm = (nn + 1)/2 - 1;
595 value = 0.5*(work[0][nf1] + work[0][nf2]);
598 value = work[0][nfm];
600 value = 0.25*(work[0][nfm-1] + work[0][nfm+1]) + 0.5*work[0][nfm];
603 for (j = 0; j < nn; j++)
605 valv *= CPL_MATH_PI_2/powf((
float)nn,2.0);
611 cliplev = value + thresh*work[1][nn-1];
612 while (nplus < nrejmax && work[0][nn-nplus-1] > cliplev)
615 cliplev = value - thresh*work[1][nn-1];
616 while ((nplus+nminus) < nrejmax && work[0][nminus] < cliplev)
618 nrej = nplus + nminus;
626 for (j = 0; j < nremain; j++) {
627 dork[0][j] = work[2][j+nminus];
628 dork[1][j] = work[3][j+nminus];
630 nmm = (nremain + 1)/2 - 1;
631 is_even2 = !(nremain & 1);
634 value = 0.5*(dork[0][nm] + dork[0][nm+1]);
637 value = dork[0][nmm];
639 value = 0.5*dork[0][nmm] + 0.25*(dork[0][nmm-1] +
643 for (j = 0; j < nremain; j++)
645 valv *= CPL_MATH_PI_2/powf((
float)nremain,2.0);
654 rmask[i] = min(255,nrej);
655 rplus[i] = min(255,nplus);
664 for (i = 0; i < 4; i++)
667 for (i = 0; i < 2; i++)
698 static void xclip_mean(usefulinfo *uinfo,
float thresh,
int scaletype) {
699 int k,nf2,nrej,nplus,kk,krem,nf;
700 float *work[4],value,value2,nrejmax,resid,maxresid,**datas,*odata;
701 float oskylevel,**vars,valv = 0.0 ,valv2,*ovdata;
702 cpl_binary **masks,*omask;
704 litestruct *ff,*fileptrs;
705 unsigned char *iflag,*rmask,*rplus;
709 fileptrs = uinfo->fileptrs;
710 datas = uinfo->datas;
712 masks = uinfo->masks;
713 odata = uinfo->odata;
714 ovdata = uinfo->ovdata;
715 omask = uinfo->omask;
718 oskylevel = uinfo->oskylevel;
719 rmask = uinfo->rmask;
720 rplus = uinfo->rplus;
724 for (i = 0; i < 4; i++)
725 work[i] = cpl_malloc(nf*
sizeof(
float));
726 iflag = cpl_malloc(nf*
sizeof(
unsigned char));
731 for (i = 0; i < npts; i++) {
740 for (k = 0; k < nf; k++) {
744 work[0][nn] = datas[k][i];
745 work[1][nn] = ff->skynoise;
746 work[2][nn] = datas[k][i] + odata[i] - oskylevel;
748 work[3][nn] = vars[k][i];
753 for (k = 0; k < nf; k++) {
757 work[0][nn] = datas[k][i] + ff->skyfudge;
758 work[1][nn] = ff->skynoise;
759 work[2][nn] = datas[k][i] + odata[i] - oskylevel + ff->skyfudge;
761 work[3][nn] = vars[k][i];
766 for (k = 0; k < nf; k++) {
770 work[0][nn] = datas[k][i]*ff->skyfudge;
771 work[1][nn] = ff->skynoise*ff->skyfudge;
772 work[2][nn] = (datas[k][i] + odata[i]*ff->skyrenorm -
773 ff->skylevel)*ff->skyfudge;
775 work[3][nn] = vars[k][i]*powf(ff->skyfudge,2.0);
780 for (k = 0; k < nf; k++) {
784 work[0][nn] = datas[k][i] + ff->skyfudge;
785 work[1][nn] = ff->skynoise;
786 work[2][nn] = datas[k][i] + odata[i] - oskylevel + ff->skyfudge;
788 work[3][nn] = vars[k][i];
797 for (k = 0; k < nn; k++)
802 for (k = 0; k < nn; k++)
804 valv /= powf((
float)nn,2.0);
811 for (kk = 0; kk < nrejmax; kk++) {
814 for (k = 0; k < nn; k++) {
817 resid = fabs(work[0][k] - value);
818 if (resid > thresh*work[1][k]) {
820 resid = work[0][k] - value;
821 if (resid > maxresid) {
836 if ((work[0][krem] - value) > 0.0)
845 for (k = 0; k < nn; k++) {
847 value2 += work[0][k];
854 value = value2/(float)nf2;
856 valv = valv2/powf((
float)nf2,2.0);
868 rmask[i] = min(255,nrej);
869 rplus[i] = min(255,nplus);
874 for (k = 0; k < 4; k++)
906 static void medcalc(usefulinfo *uinfo,
float thresh,
float avskynoise,
908 int nf1,nf2,nfm,nrejmax,is_even,nrej,nremain,nm,nmm,is_even2,k,nminus;
911 float value,cliplev,*work[2],**datas,*odata,**vars, valv = 0.0,*ovdata;
912 litestruct *fileptrs;
913 cpl_binary **masks,*omask;
914 unsigned char *rmask,*rplus;
918 fileptrs = uinfo->fileptrs;
919 datas = uinfo->datas;
921 masks = uinfo->masks;
922 odata = uinfo->odata;
923 ovdata = uinfo->ovdata;
924 omask = uinfo->omask;
927 rmask = uinfo->rmask;
928 rplus = uinfo->rplus;
932 work[0] = cpl_malloc(nf*
sizeof(
float));
933 work[1] = cpl_malloc(nf*
sizeof(
float));
937 for (i = 0; i < npts; i++) {
944 for (k = 0; k < nf; k++) {
947 work[0][nn] = datas[k][i];
949 work[1][nn] = vars[k][i];
954 for (k = 0; k < nf; k++) {
957 work[0][nn] = datas[k][i] + (fileptrs+k)->skyfudge;
959 work[1][nn] = vars[k][i];
964 for (k = 0; k < nf; k++) {
967 work[0][nn] = datas[k][i]*(fileptrs+k)->skyfudge;
969 work[1][nn] = vars[k][i]*pow((fileptrs+k)->skyfudge,2.0);
974 for (k = 0; k < nf; k++) {
977 work[0][nn] = datas[k][i] + (fileptrs+k)->skyfudge;
979 work[1][nn] = vars[k][i];
1001 nfm = (nn + 1)/2 - 1;
1003 is_even = !(nn & 1);
1009 value = 0.5*(work[0][nf1] + work[0][nf2]);
1012 value = work[0][nfm];
1014 value = 0.25*(work[0][nfm-1] + work[0][nfm+1]) +
1018 for (j = 0; j < nn; j++)
1020 valv = CPL_MATH_PI_2*valv/powf((
float)nn,2);
1026 cliplev = value + thresh*avskynoise;
1027 while (nplus < nrejmax && work[0][nn-nplus-1] > cliplev)
1030 cliplev = value - thresh*avskynoise;
1031 while ((nplus+nminus) < nrejmax && work[0][nminus] < cliplev)
1033 nrej = nplus + nminus;
1038 nremain = nn - nrej;
1039 nm = nremain/2 - 1 + nminus;
1040 nmm = (nremain + 1)/2 - 1 + nminus;
1041 is_even2 = !(nremain & 1);
1043 value = 0.5*(work[0][nm] + work[0][nm+1]);
1046 value = work[0][nmm];
1048 value = 0.5*work[0][nmm] + 0.25*(work[0][nmm-1] +
1052 for (j = 0; j < nremain; j++)
1054 valv = CPL_MATH_PI_2*valv/powf((
float)nn,2);
1064 rmask[i] = min(255,nrej);
1065 rplus[i] = min(255,nplus);
1101 static void meancalc(usefulinfo *uinfo,
float thresh,
float avskynoise,
1103 int nf2,k,nrej,nplus,nrejmax,kk,krem,nf;
1105 float *work[2],value,value2,maxresid,resid,fresid,cliplev,**datas,*odata;
1106 float **vars,valv,valv2,*ovdata;
1107 cpl_binary **masks,*omask;
1108 unsigned char *iflag,*rmask,*rplus;
1109 litestruct *fileptrs;
1113 fileptrs = uinfo->fileptrs;
1114 datas = uinfo->datas;
1116 masks = uinfo->masks;
1117 odata = uinfo->odata;
1118 ovdata = uinfo->ovdata;
1119 omask = uinfo->omask;
1122 rmask = uinfo->rmask;
1123 rplus = uinfo->rplus;
1127 work[0] = cpl_malloc(nf*
sizeof(
float));
1128 work[1] = cpl_malloc(nf*
sizeof(
float));
1129 iflag = cpl_malloc(nf*
sizeof(
unsigned char));
1133 cliplev = thresh*avskynoise;
1134 for (i = 0; i < npts; i++) {
1139 switch (scaletype) {
1141 for (k = 0; k < nf; k++) {
1144 work[0][nn] = datas[k][i];
1146 work[1][nn] = vars[k][i];
1151 for (k = 0; k < nf; k++) {
1154 work[0][nn] = datas[k][i] + (fileptrs+k)->skyfudge;
1156 work[1][nn] = vars[k][i];
1161 for (k = 0; k < nf; k++) {
1164 work[0][nn] = datas[k][i]*(fileptrs+k)->skyfudge;
1166 work[1][nn] = vars[k][i]*powf((fileptrs+k)->skyfudge,2.0);
1171 for (k = 0; k < nf; k++) {
1174 work[0][nn] = datas[k][i] + (fileptrs+k)->skyfudge;
1176 work[1][nn] = vars[k][i]*powf((fileptrs+k)->skyfudge,2.0);
1198 for (k = 0; k < nn; k++) {
1199 value += work[0][k];
1204 valv /= powf((
float)nn,2.0);
1211 for (kk = 0; kk < nrejmax; kk++) {
1214 for (k = 0; k < nn; k++) {
1217 resid = work[0][k] - value;
1218 fresid = (float)fabs((
double)resid);
1219 if (fresid > cliplev) {
1221 fresid = work[0][k] - value;
1222 if (fresid > maxresid) {
1230 if ((work[0][krem] - value) > 0.0)
1236 for (k = 0; k < nn; k++) {
1237 if (iflag[k] == 0) {
1238 value2 += work[0][k];
1239 valv2 += work[1][k];
1243 value = value2/(float)nf2;
1244 valv = valv2/powf((
float)nf2,2.0);
1257 rmask[i] = min(255,nrej);
1258 rplus[i] = min(255,nplus);
1297 static void skyest(
long npts,
float *data, cpl_binary *mask,
float thresh,
1298 float *skymed,
float *skynoise) {
1303 bpm = (
unsigned char *)mask;
1307 casu_qmedsig(data,bpm,npts,thresh,3,DATAMIN,DATAMAX,skymed,
1318 static void tidy(usefulinfo *uinfo) {
1323 freespace(uinfo->fileptrs);
1324 for (i = 0; i < uinfo->nf; i++)
1325 freespace(uinfo->datas[i]);
1326 if (uinfo->vars != NULL) {
1327 for (i = 0; i < uinfo->nf; i++)
1328 freespace(uinfo->vars[i]);
1330 freespace(uinfo->datas);
1331 freespace(uinfo->vars);
1332 freespace(uinfo->masks);
cpl_image * casu_fits_get_image(casu_fits *p)
char * casu_fits_get_filename(casu_fits *p)
cpl_propertylist * casu_fits_get_phu(casu_fits *p)
int casu_fits_get_nexten(casu_fits *p)
cpl_propertylist * casu_fits_get_ehu(casu_fits *p)
int casu_imcombine(casu_fits **fset, casu_fits **fsetv, int nfits, int combtype, int scaletype, int xrej, float thresh, const char *expkey, cpl_image **outimage, cpl_image **outvimage, unsigned char **rejmask, unsigned char **rejplus, cpl_propertylist **drs, int *status)
Stack images into a mean or median image with rejection.
float casu_med(float *data, unsigned char *bpm, long npts)
void casu_qmedsig(float *data, unsigned char *bpm, long npts, float thresh, int niter, float lowv, float highv, float *median, float *sigma)
void casu_prov(cpl_propertylist *p, casu_fits **inlist, int n, int isextn)
Write provenance keywords.
long casu_getnpts(cpl_image *in)
Get the number of pixels in a 2d image.
void casu_sort(float **a, int n, int m)
Sort a 2d array by the first column and co-sort the rest.