37 #include "vircam_utils.h"
38 #include "vircam_pfits.h"
39 #include "vircam_stats.h"
40 #include "vircam_fits.h"
41 #include "vircam_mods.h"
45 #define FATAL_ERR(_f,_a) {cpl_msg_error(_f,"%s",_a); tidy(); *status = VIR_FATAL; return(*status);}
46 #define WARN_ERR(_f,_a) {cpl_msg_error(_f,"%s",_a); tidy(); *status = VIR_WARN; return(VIR_WARN);}
47 #define INFO_ERR(_f,_a) {cpl_msg_info(_f,"%s",_a);}
67 static litestruct *fileptrs = NULL;
68 static float **datas = NULL;
69 static cpl_binary **masks = NULL;
71 static cpl_binary *omask;
74 static float oskylevel;
77 static unsigned char *rmask = NULL;
78 static unsigned char *rplus = NULL;
82 static void skyest(
float *data, cpl_binary *bpm,
float thresh,
float *skymed,
84 static void medcalc(
float,
float,
int);
85 static void meancalc(
float,
float,
int);
86 static void xclip_med(
float thresh,
int scaletype);
87 static void xclip_mean(
float thresh,
int scaletype);
89 static void tidy(
void);
156 int scaletype,
int xrej,
float thresh,
157 cpl_image **outimage,
unsigned char **rejmask,
158 unsigned char **rejplus, cpl_propertylist **drs,
161 const char *ic_fctid =
"vircam_imcombine";
163 float sumsky,sumsig,texp1,texp2,expfudge,skylevel,skynoise,oskynoise;
167 cpl_propertylist *plist_p;
175 if (*status != VIR_OK)
182 WARN_ERR(ic_fctid,
"No files to combine")
186 fileptrs = cpl_calloc(nf,
sizeof(litestruct));
190 datas = cpl_malloc(nf*
sizeof(
float *));
192 for (k = 0; k < nf; k++)
193 datas[k] = cpl_malloc(npts*
sizeof(
float));
194 masks = cpl_malloc(nf*
sizeof(cpl_binary *));
198 for (k = 0; k < nf; k++) {
200 dat = cpl_image_get_data_float(im);
202 snprintf(msg,SZBUF,
"Failed to load data from extension %d in %s",
205 FATAL_ERR(ic_fctid,msg)
207 for (i = 0; i < npts; i++)
208 datas[k][i] = dat[i];
209 masks[k] = cpl_mask_get_data(cpl_image_get_bpm(im));
215 for (i = 0; i < nf; i++) {
231 if (plist_p == NULL) {
232 snprintf(msg,SZBUF,
"Failed to load primary property list %s",
234 INFO_ERR(ic_fctid,msg)
239 snprintf(msg,SZBUF,
"Failed to get exposure time from %s",
241 INFO_ERR(ic_fctid,msg)
248 texp1 = fileptrs->exptime;
249 expfudge = texp1/texp2;
250 ff->expfudge = expfudge;
256 if (scaletype == 3 && i > 0) {
257 for (j = 0; j < npts; j++)
258 datas[i][j] *= ff->expfudge;
263 skyest(datas[i],masks[i],thresh,&skylevel,&skynoise);
264 ff->skylevel = skylevel;
265 ff->skynoise = skynoise;
271 work = cpl_malloc(nf*
sizeof(
float));
272 for (i = 0; i < nf; i++)
273 work[i] = (fileptrs+i)->skylevel;
275 for (i = 0; i < nf; i++)
276 work[i] = (fileptrs+i)->skynoise;
281 for (i = 0; i < nf; i++)
282 (fileptrs+i)->skyfudge = sumsky - (fileptrs+i)->skylevel;
285 for (i = 0; i < nf; i++)
286 (fileptrs+i)->skyfudge = sumsky/(fileptrs+i)->skylevel;
289 for (i = 0; i < nf; i++)
290 (fileptrs+i)->skyfudge = sumsky - (fileptrs+i)->skylevel;
293 for (i = 0; i < nf; i++)
294 (fileptrs+i)->skyfudge = 0.0;
300 *outimage = cpl_image_new((cpl_size)nx,(cpl_size)ny,CPL_TYPE_FLOAT);
301 odata = cpl_image_get_data_float(*outimage);
302 omask = cpl_mask_get_data(cpl_image_get_bpm(*outimage));
303 if (*outimage == NULL || odata == NULL)
304 FATAL_ERR(ic_fctid,
"Couldn't create output image")
305 *rejmask = cpl_calloc(npts,
sizeof(*rejmask));
307 *rejplus = cpl_calloc(npts,
sizeof(*rejplus));
314 medcalc(thresh,sumsig,scaletype);
317 meancalc(thresh,sumsig,scaletype);
327 skyest(odata,omask,thresh,&oskylevel,&oskynoise);
333 for (i = 0; i < nf; i++) {
335 ff->skyrenorm = ff->skylevel/oskylevel;
338 for (k = 0; k < npts; k++)
339 datas[i][k] -= (odata[k] - oskylevel);
342 for (k = 0; k < npts; k++)
343 datas[i][k] -= (odata[k] - oskylevel)*ff->skyrenorm;
346 for (k = 0; k < npts; k++)
347 datas[i][k] -= (odata[k] - oskylevel);
350 for (k = 0; k < npts; k++)
351 datas[i][k] -= (odata[k] - oskylevel);
357 skyest(datas[i],masks[i],thresh,&skylevel,&skynoise);
358 ff->skynoise = skynoise;
365 xclip_med(thresh,scaletype);
368 xclip_mean(thresh,scaletype);
375 *drs = cpl_propertylist_new();
408 static void xclip_med(
float thresh,
int scaletype) {
409 int nf1,nf2,nfm,nrejmax,is_even,k,is_even2,nrej,nremain,nm,nmm,nplus;
411 float **work,*dork,value,cliplev;
417 work = cpl_malloc(3*
sizeof(
float *));
418 for (i = 0; i < 3; i++)
419 work[i] = cpl_malloc(nf*
sizeof(
float));
420 dork = cpl_malloc(nf*
sizeof(
float));
424 for (i = 0; i < npts; i++) {
433 for (k = 0; k < nf; k++) {
437 work[0][nn] = datas[k][i];
438 work[1][nn] = ff->skynoise;
439 work[2][nn++] = datas[k][i] + odata[i] - oskylevel;
443 for (k = 0; k < nf; k++) {
447 work[0][nn] = datas[k][i] + ff->skyfudge;
448 work[1][nn] = ff->skynoise;
449 work[2][nn++] = datas[k][i] + odata[i] - oskylevel +
454 for (k = 0; k < nf; k++) {
458 work[0][nn] = datas[k][i]*ff->skyfudge;
459 work[1][nn] = ff->skynoise*ff->skyfudge;
460 work[2][nn++] = (datas[k][i] + odata[i]*ff->skyrenorm -
461 ff->skylevel)*ff->skyfudge;
465 for (k = 0; k < nf; k++) {
469 work[0][nn] = datas[k][i] + ff->skyfudge;
470 work[1][nn] = ff->skynoise;
471 work[2][nn++] = datas[k][i] + odata[i] - oskylevel +
481 nfm = (nn + 1)/2 - 1;
489 value = 0.5*(work[0][nf1] + work[0][nf2]);
492 value = work[0][nfm];
494 value = 0.25*(work[0][nfm-1] + work[0][nfm+1]) + 0.5*work[0][nfm];
499 cliplev = value + thresh*work[1][nn-1];
500 while (nplus < nrejmax && work[0][nn-nplus-1] > cliplev)
503 cliplev = value - thresh*work[1][nn-1];
504 while ((nplus+nminus) < nrejmax && work[0][nminus] < cliplev)
506 nrej = nplus + nminus;
514 for (j = 0; j < nremain; j++)
515 dork[j] = work[2][j+nminus];
516 nmm = (nremain + 1)/2 - 1;
517 is_even2 = !(nremain & 1);
520 value = 0.5*(dork[nm] + dork[nm+1]);
525 value = 0.5*dork[nmm] + 0.25*(dork[nmm-1] + dork[nmm+1]);
531 rmask[i] = min(255,nrej);
532 rplus[i] = min(255,nplus);
541 for (i = 0; i < 3; i++)
571 static void xclip_mean(
float thresh,
int scaletype) {
572 int k,nf2,nrej,nplus,kk,krem;
573 float *work[3],value,value2,nrejmax,resid,maxresid;
576 unsigned char *iflag;
580 for (i = 0; i < 3; i++)
581 work[i] = cpl_malloc(nf*
sizeof(
float));
582 iflag = cpl_malloc(nf*
sizeof(
unsigned char));
587 for (i = 0; i < npts; i++) {
596 for (k = 0; k < nf; k++) {
600 work[0][nn] = datas[k][i];
601 work[1][nn] = ff->skynoise;
602 work[2][nn] = datas[k][i] + odata[i] - oskylevel;
607 for (k = 0; k < nf; k++) {
611 work[0][nn] = datas[k][i] + ff->skyfudge;
612 work[1][nn] = ff->skynoise;
613 work[2][nn] = datas[k][i] + odata[i] - oskylevel + ff->skyfudge;
618 for (k = 0; k < nf; k++) {
622 work[0][nn] = datas[k][i]*ff->skyfudge;
623 work[1][nn] = ff->skynoise*ff->skyfudge;
624 work[2][nn] = (datas[k][i] + odata[i]*ff->skyrenorm -
625 ff->skylevel)*ff->skyfudge;
630 for (k = 0; k < nf; k++) {
634 work[0][nn] = datas[k][i] + ff->skyfudge;
635 work[1][nn] = ff->skynoise;
636 work[2][nn] = datas[k][i] + odata[i] - oskylevel + ff->skyfudge;
645 for (k = 0; k < nn; k++)
653 for (kk = 0; kk < nrejmax; kk++) {
656 for (k = 0; k < nn; k++) {
659 resid = fabs(work[0][k] - value);
660 if (resid > thresh*work[1][k]) {
662 resid = work[0][k] - value;
663 if (resid > maxresid) {
678 if ((work[0][krem] - value) > 0.0)
686 for (k = 0; k < nn; k++) {
688 value2 += work[0][k];
693 value = value2/(float)nf2;
702 rmask[i] = min(255,nrej);
703 rplus[i] = min(255,nplus);
708 for (k = 0; k < 3; k++)
739 static void medcalc(
float thresh,
float avskynoise,
int scaletype) {
740 int nf1,nf2,nfm,nrejmax,is_even,nrej,nremain,nm,nmm,is_even2,k,nminus;
743 float value,cliplev,*work;
747 work = cpl_malloc(nf*
sizeof(*work));
751 for (i = 0; i < npts; i++) {
758 for (k = 0; k < nf; k++) {
761 work[nn++] = datas[k][i];
765 for (k = 0; k < nf; k++) {
768 work[nn++] = datas[k][i] + (fileptrs+k)->skyfudge;
772 for (k = 0; k < nf; k++) {
775 work[nn++] = datas[k][i]*(fileptrs+k)->skyfudge;
779 for (k = 0; k < nf; k++) {
782 work[nn++] = datas[k][i] + (fileptrs+k)->skyfudge;
801 nfm = (nn + 1)/2 - 1;
809 value = 0.5*(work[nf1] + work[nf2]);
814 value = 0.25*(work[nfm-1] + work[nfm+1]) + 0.5*work[nfm];
819 cliplev = value + thresh*avskynoise;
820 while (nplus < nrejmax && work[nn-nplus-1] > cliplev)
823 cliplev = value - thresh*avskynoise;
824 while ((nplus+nminus) < nrejmax && work[nminus] < cliplev)
826 nrej = nplus + nminus;
832 nm = nremain/2 - 1 + nminus;
833 nmm = (nremain + 1)/2 - 1 + nminus;
834 is_even2 = !(nremain & 1);
836 value = 0.5*(work[nm] + work[nm+1]);
841 value = 0.5*work[nmm] + 0.25*(work[nmm-1] + work[nmm+1]);
848 rmask[i] = min(255,nrej);
849 rplus[i] = min(255,nplus);
882 static void meancalc(
float thresh,
float avskynoise,
int scaletype) {
883 int nf2,k,nrej,nplus,nrejmax,kk,krem;
885 float *work,value,value2,maxresid,resid,fresid,cliplev;
886 unsigned char *iflag;
890 work = cpl_malloc(nf*
sizeof(*work));
891 iflag = cpl_malloc(nf*
sizeof(
unsigned char));
895 cliplev = thresh*avskynoise;
896 for (i = 0; i < npts; i++) {
903 for (k = 0; k < nf; k++) {
906 work[nn++] = datas[k][i];
910 for (k = 0; k < nf; k++) {
913 work[nn++] = datas[k][i] + (fileptrs+k)->skyfudge;
917 for (k = 0; k < nf; k++) {
920 work[nn++] = datas[k][i]*(fileptrs+k)->skyfudge;
924 for (k = 0; k < nf; k++) {
927 work[nn++] = datas[k][i] + (fileptrs+k)->skyfudge;
945 for (k = 0; k < nn; k++) {
956 for (kk = 0; kk < nrejmax; kk++) {
959 for (k = 0; k < nn; k++) {
962 resid = work[k] - value;
963 fresid = (float)fabs((
double)resid);
964 if (fresid > cliplev) {
966 fresid = work[k] - value;
967 if (fresid > maxresid) {
975 if ((work[krem] - value) > 0.0)
980 for (k = 0; k < nn; k++) {
986 value = value2/(float)nf2;
997 rmask[i] = min(255,nrej);
998 rplus[i] = min(255,nplus);
1034 static void skyest(
float *data, cpl_binary *mask,
float thresh,
float *skymed,
1040 bpm = (
unsigned char *)mask;
1055 static void tidy(
void) {
1060 freespace(fileptrs);
1061 for (i = 0; i < nf; i++)
1062 freespace(datas[i]);
char * vircam_fits_get_filename(vir_fits *p)
void vircam_qmedsig(float *data, unsigned char *bpm, long npts, float thresh, int niter, float lowv, float highv, float *median, float *sigma)
int vircam_pfits_get_exptime(const cpl_propertylist *plist, float *exptime)
Get the value of exposure time.
void vircam_sort(float **a, int n, int m)
int vircam_fits_get_nexten(vir_fits *p)
cpl_image * vircam_fits_get_image(vir_fits *p)
float vircam_med(float *data, unsigned char *bpm, long npts)
cpl_propertylist * vircam_fits_get_phu(vir_fits *p)
int vircam_imcombine(vir_fits **fset, int nfits, int combtype, int scaletype, int xrej, float thresh, cpl_image **outimage, unsigned char **rejmask, unsigned char **rejplus, cpl_propertylist **drs, int *status)
Stack images into a mean or median image with rejection.
long vircam_getnpts(cpl_image *in)
void vircam_prov(cpl_propertylist *p, vir_fits **inlist, int n)