/* acsrej_do -- Perform the cosmic ray rejection for ACS images Description: ------------ This is mostly a file bookkeeping routine for the cosmic ray rejection task. It takes care of input/output files open/close, check for dimensions, read/ write data from/to files, allocate memory spaces etc. Date Author Description ---- ------ ----------- 06-May-1996 J.-C. Hsu Adapt from the SPP code crrej_do.x 05-Aug-1998 W. Hack Modified to handle ACS data 11-Feb-1999 W. Hack EXPTIME now in Pri. Hdr. 18-Mar-1999 W.J. Hack Revised to read EXPTIMEs from Primary headers for cr_scaling using tpin directly 14-Sep-1999 W.J. Hack Cleaned up SHADCORR usage. Added check for max number of files here. */ int acsrej_do (IRAFPointer tpin, char *outfile, char *mtype, clpar *par, int newpar[]) { extern int status; IODescPtr ipsci[MAX_FILES]; /* science image descriptor */ IODescPtr ipdq[MAX_FILES]; /* data quality image descriptor */ float skyval[MAX_FILES]; /* background DN values */ float efac[MAX_FILES]; /* exposure factors */ multiamp noise; /* readout noise */ multiamp gain; /* A-to-D gain factors */ float exptot; float texpt; int nimgs; SingleGroup sg; int niter = 0; float sigma[MAX_ITER]; Hdr phdr; /* primary header */ int extver; /* Current extension being processed*/ int numext; /* Number of extensions in each image */ int nextend; /* Number of output extensions */ char imgname[MAX_FILES][CHAR_FNAME_LENGTH]; char fimage[CHAR_FNAME_LENGTH]; /* Name of first image in list */ char root[CHAR_FNAME_LENGTH]; /* ROOTNAME for output CRJ file */ char uroot[CHAR_FNAME_LENGTH]; /* Upper case version of rootname */ char *shadrefname; int ext[MAX_FILES]; int dim_x, dim_y; /* image dimensions */ int i, j, n; /* loop indices */ float *efacsum, *work; int nrej; /* total number of rejected pixels */ float skysum; /* total sky level */ int logit; RefImage shadref; int shadswitch; double expend, expstart; int non_zero; /* number of input images with EXPTIME>0.*/ int found; char imgdefault[CHAR_FNAME_LENGTH]; /* name of first input image with EXPTIME > 0. */ int GetSwitch (Hdr *, char *, int *); int UpdateSwitch (char *, int, Hdr *, int *); void InitRefImg (RefImage *); int ImgHistory (const RefImage *, Hdr *); int ImgPedigree (RefImage *); int acsrej_check (IRAFPointer, int, int, clpar *, int [], char [][CHAR_FNAME_LENGTH], int [], IODescPtr [], IODescPtr [], multiamp *, multiamp *, int *, int *, int); int cr_scaling (char *, IRAFPointer, float [], int *, double *, double *); int rejpar_in(clpar *, int [], int, float, int *, float []); void acsrej_sky (char *, IODescPtr [], IODescPtr [], int, short, float []); void cr_history (SingleGroup *, clpar *, int); int acsrej_init (IODescPtr [], IODescPtr [], clpar *, int, int, int, multiamp, multiamp, float [], float [], SingleGroup *, float *); int acsrej_loop (IODescPtr [], IODescPtr [], char [][CHAR_FNAME_LENGTH], int [], int, clpar *, int, int, int, float [], multiamp, multiamp, float [], float [], FloatTwoDArray *, FloatTwoDArray *, float *, ShortTwoDArray *, int *, char *); int PutKeyFlt (Hdr *, char *, float, char *); int PutKeyDbl (Hdr *, char *, double, char *); int PutKeyStr (Hdr *, char *, char *, char *); int GetKeyStr (Hdr *, char *, int, char *, char *, int); int PutKeyInt (Hdr *, char *, int, char *); int GetKeyInt (Hdr *, char *, int, int, int *); void UFilename (char *, Hdr *); void UMemType (char *, Hdr *); void UExpname (char *, Hdr *); int LoadHdr (char *, Hdr *); void UpperAll (char *, char *, int); void TimeStamp (char *, char *); void WhichError (int); void PrSwitch (char *, int); void FindAsnRoot (char *, char *); void initmulti (multiamp *); /* -------------------------------- begin ---------------------------------- */ /* Initialize necessary structures */ InitRefImg (&shadref); root[0] = '\0'; uroot[0] = '\0'; initmulti (&noise); initmulti (&gain); numext = 0; nextend = 0; /* Since CR-SPLIT images are in separate files, we need to combine the same chip's exposure from each file. Therefore we will loop over each extension in the first image, determine what chip that corresponds to, and get the same chip from the rest of the images (which could be in any arbitrary extension in each of the images). */ /* First, let's determine how many extensions/chips in each file */ c_imtgetim (tpin, fimage, CHAR_FNAME_LENGTH); if (LoadHdr (fimage, &phdr) ) return (status = ERROR_RETURN); if (GetKeyInt (&phdr, "NEXTEND", NO_DEFAULT, 0, &nextend) == 0) numext = nextend / EXT_PER_GROUP; else numext = 1; shadswitch = 0; /* Check to see if SHADCORR was set to PERFORM in image header */ if (GetSwitch (&phdr, "SHADCORR", &shadswitch) ) return(status); /* If shadcorr was set either by the user on the command line or in the image header, initialize shadcorr processing. */ if (par->shadcorr == PERFORM || shadswitch == PERFORM) { /* Use par->shadcorr as switch for performing shading correction */ par->shadcorr = PERFORM; shadrefname = calloc(CHAR_FNAME_LENGTH, sizeof(char)); if (GetKeyStr (&phdr, "SHADFILE", NO_DEFAULT, "", shadrefname, CHAR_FNAME_LENGTH) ) return(status); strcpy (shadref.name, shadrefname); /* Read in PEDIGREE and DESCRIPTION for SHADFILE */ if (ImgPedigree (&shadref) ) return (status); /* If a DUMMY shadfile was specified, turn off shadcorr */ if (shadref.goodPedigree == DUMMY) par->shadcorr = OMIT; free (shadrefname); } freeHdr (&phdr); /* Initialize efac */ for (n = 0; n < MAX_FILES; n++) efac[n] = 1.0; /* calculate the scaling factors due to different exposure time */ strcpy (par->expname, "EXPTIME"); if (cr_scaling (par->expname, tpin, efac, &nimgs, &expend, &expstart) ){ WhichError (status); return (status); } /* make sure there is more than one image to process */ if (nimgs < 2) { trlmessage ("Needs more than one input image."); return (status = NOTHING_TO_DO); } /* calculate the total exposure time */ exptot = 0.; non_zero = 0; for (n = 0; n < nimgs; ++n) { exptot += efac[n]; /* Count how many inputs have non-zero(valid) EXPTIME */ if (efac[n] > 0.) non_zero++; } /* for the case of all images have zero exposure time, use equal exposure time of 1. */ if (exptot == 0.) { for (n = 0; n < nimgs; ++n) { efac[n] = 1.; } texpt = (float) nimgs; non_zero = nimgs; } else { texpt = exptot; } /* Now, start the loop. */ for (extver = 1; extver <= numext; extver++) { if (par->printtime) { TimeStamp ("Start cosmic ray rejection",""); } /* open input files and temporary files, check the parameters */ if (acsrej_check (tpin, extver, numext, par, newpar, imgname, ext, ipsci, ipdq, &noise, &gain, &dim_x, &dim_y, nimgs)) { WhichError (status); return(status); } /* Now that we have read in SHADCORR, report if it will be performed */ PrSwitch ("shadcorr", par->shadcorr); /* read in the parameters */ if (rejpar_in (par, newpar, nimgs, exptot, &niter, sigma) ) return(status); /* allocate array space */ efacsum = calloc (dim_x*dim_y, sizeof(float)); work = calloc (nimgs*dim_x, sizeof(float)); /* calculate the sky levels */ acsrej_sky (par->sky, ipsci, ipdq, nimgs, par->badinpdq, skyval); if (status != ACS_OK) { WhichError (status); return (status); } if (par->verbose) { for (n = 0; n < nimgs; n++) { sprintf (MsgText, "sky of '%s[sci,%d]' is %0.3f DN", imgname[n], ext[n], skyval[n]); trlmessage (MsgText); } } /* use the first input image to set up the data structure */ initSingleGroup (&sg); /* Find the first image in the input list which has an EXPTIME > 0. to use for initializing the output SingleGroup. */ found = 0; n = 0; /* By default, simply use the first one, so initialize accordingly.*/ strcpy (imgdefault, imgname[0]); do { if (efac[n] > 0.) { strcpy(imgdefault,imgname[n]); found = 1; } n++; } while (found == 0); getSingleGroup (imgdefault, extver, &sg); if (non_zero > 1){ /* compute the initial pixel values to be used to compare against all images. */ if (non_zero < nimgs){ trlwarn ("Some input exposures had EXPTIME = 0."); } if (acsrej_init (ipsci, ipdq, par, nimgs, dim_x, dim_y, noise, gain, efac, skyval, &sg, work) ) { WhichError(status); closeSciDq(nimgs, ipsci, ipdq, par); return (status); } if (par->printtime) TimeStamp ("Calculated initial guess for extension", ""); /* do the iterative cosmic ray rejection calculations */ if (acsrej_loop (ipsci, ipdq, imgname, ext, nimgs, par, niter, dim_x, dim_y, sigma, noise, gain, efac, skyval, &sg.sci.data, &sg.err.data, efacsum, &sg.dq.data, &nrej, shadref.name) ) { WhichError(status); closeSciDq(nimgs, ipsci, ipdq, par); return (status); } } else { trlwarn ("Cosmic-ray rejection NOT performed!"); if (non_zero > 0) { trlwarn ("Some input exposures had EXPTIME = 0."); trlwarn ("Output product will not be cosmic-ray cleaned!"); } /*else { trlwarn ("ALL input exposures had EXPTIME = 0."); trlwarn ("Output product will be BLANK!"); } */ } /* End if(non_zero) block */ /* must close all images, now that we are done reading them */ closeSciDq(nimgs, ipsci, ipdq, par); /* calculate the total sky ... */ skysum = 0.; for (n = 0; n < nimgs; ++n) { skysum += skyval[n]; } /* ... and force it to be non-negative */ if (skysum < 0.) skysum = 0.; if (par->printtime){ if (non_zero > 1){ TimeStamp ("Finished detecting cosmic rays on extension", ""); } else { TimeStamp ("Done checking this extension",""); } } /* write to the output image */ if (non_zero > 0){ for (j = 0; j < dim_y; ++j) { for (i = 0; i < dim_x; ++i) { PPix(&sg.sci.data,i,j) = PPix(&sg.sci.data,i,j)*texpt + skysum; PPix(&sg.err.data,i,j) *= texpt; } } } else { for (j = 0; j < dim_y; ++j) { for (i = 0; i < dim_x; ++i) { PPix(&sg.sci.data,i,j) = par->fillval; PPix(&sg.err.data,i,j) = 0.; /* Set DQ value to one which will always be considered BAD */ PPix(&sg.dq.data,i,j) = 1; } } /* Set at least one pixel to a different value to insure that an image array actually gets produced. */ PPix(&sg.err.data,0,0) = -1.; PPix(&sg.dq.data,0,0) = 8; } /* update the exposure time of the output images */ PutKeyFlt (sg.globalhdr, "TEXPTIME", exptot, ""); PutKeyFlt (sg.globalhdr, "SKYSUM", skysum, "Total sky level (DN)"); PutKeyDbl (sg.globalhdr, "EXPSTART", expstart, "computed exposure start time (Modified Julian Date)"); PutKeyDbl (sg.globalhdr, "EXPEND", expend, "exposure end time (Modified Julian Date)"); /* Updated REJ_RATE to use 'texpt' as a safe value when EXPTIME=0 for all members. WJH, 24 Feb 2003 */ PutKeyFlt (sg.globalhdr, "REJ_RATE", (float)nrej/texpt, "Cosmic ray impact rate (pixels/sec)"); PutKeyFlt (sg.globalhdr, "EXPTIME", exptot, ""); if (par->shadcorr) { logit = 0; if (UpdateSwitch ("SHADCORR", par->shadcorr, sg.globalhdr, &logit) ) return (status); PrSwitch ("shadcorr", COMPLETE); if (logit) { /*Records SHADFILE information in header comments... */ if (ImgHistory (&shadref, sg.globalhdr)) return (status); } } /* record parameters to the output file */ cr_history (&sg, par, nextend); PutKeyInt (&sg.sci.hdr, "NCOMBINE", nimgs, ""); UFilename (outfile, sg.globalhdr); UMemType (mtype, sg.globalhdr); FindAsnRoot (outfile, root); UpperAll (root, uroot, strlen(root)+1 ); /* EXPNAME values modified for all extensions in a SingleGroup. WJH 7 July 1999 */ UExpname (root, &sg.sci.hdr); UExpname (root, &sg.err.hdr); UExpname (root, &sg.dq.hdr); PutKeyStr (sg.globalhdr, "ROOTNAME", uroot,"Rootname of the observation set"); /* Output CHIP to the same EXTVER as the CHIP ID */ putSingleGroup (outfile, extver, &sg, 0); freeSingleGroup (&sg); if (par->printtime) TimeStamp ("Finished writing out extension", ""); /* deallocate memories */ free (efacsum); free (work); } /* Set status to a value which will be understood by CALACS to turn off subsequent processing. */ if (non_zero == 0) status = NO_GOOD_DATA; return (status); }
static int SumGrps (AcsSumInfo *acs, char *mtype) { extern int status; SingleGroup x; /* first imset */ SingleGroupLine y; /* line from Nth imset */ double exptime; /* exposure time of current image */ double sumexptime = 0.; /* accumulated exposure time */ char *message; /* for printtime info */ int extver; /* imset number */ int i; /* counter for current image */ int chip, ychip; /*Chip being summed */ int extchip; /* Extension of chip being summed */ int line; /* Line of chip being summed */ char uroot[CHAR_FNAME_LENGTH]; /* Upper case version of rootname */ int doStat (SingleGroup *, short); void TimeStamp (char *, char *); void PrGrpBegin (char *, int); void PrGrpEnd (char *, int); void PrSwitch (char *, int); void UCalVer (Hdr *); void UFilename (char *, Hdr *); void UMemType (char *, Hdr *); void UExpname (char *, Hdr *); int DetCCDChip (char *, int, int, int *); void UpperAll (char *, char *, int); int GetKeyInt (Hdr *, char *, int, int, int *); int GetKeyDbl (Hdr *, char *, int, double, double *); int PutKeyStr (Hdr *, char *, char *, char *); initSingleGroup (&x); initSingleGroupLine (&y); if (acs->printtime) { if ((message = calloc (CHAR_LINE_LENGTH+1, sizeof (char))) == NULL) return (status = OUT_OF_MEMORY); } for (extver = 1; extver <= acs->nimsets; extver++) { PrGrpBegin ("imset", extver); getSingleGroup (acs->input[0], extver, &x); if (hstio_err()) return (status = OPEN_FAILED); if (acs->printtime) TimeStamp ("first imset read", acs->input[0]); /* get from x */ if (GetKeyInt (&x.sci.hdr, "CCDCHIP", USE_DEFAULT, 1, &chip)) return (status); if (GetKeyDbl (x.globalhdr, "EXPEND", NO_DEFAULT, 0., &acs->expend)) return (status); sumexptime = acs->exptime; /* Square the errors to convert to variance. */ SquareErr (&x); /* operate on x */ /* For each imset/extver, loop over all images */ for (i = 1; i < acs->nimages; i++) { /* Determine which extension corresponds to desired chip ** for the remainder of the images. */ extchip = 0; if (DetCCDChip(acs->input[i], chip, acs->nimsets, &extchip) ) { return (status); } /* Get the first line of bias image data. */ openSingleGroupLine (acs->input[i], extchip, &y); if (hstio_err()) return (status = OPEN_FAILED); /* Update exposure time info. */ /* get from y */ if (GetKeyInt (&y.sci.hdr, "CCDCHIP", USE_DEFAULT, 1, &ychip)) return (status); if (GetKeyDbl (y.globalhdr, "EXPTIME", NO_DEFAULT, 0., &exptime)) return (status); if (GetKeyDbl (y.globalhdr, "EXPEND", NO_DEFAULT, 0., &acs->expend)) return (status); sumexptime += exptime; /*Loop over lines in each subsequent image */ for (line = 0; line < x.sci.data.ny; line++) { status = getSingleGroupLine (acs->input[i], line, &y); if (status) { sprintf(MsgText,"Could not read line %d from image %d.",line+1,i+1); trlerror(MsgText); return (status = OPEN_FAILED); } SquareErrLine (&y); /* operate on y */ /* Add current imset to sum (i.e. add y to x). This differs from add2d in that RptSum adds variances, rather than adding errors in quadrature. */ if (RptSumLine (&x, line, &y)) return (status); } /*End loop over lines */ if (acs->printtime) { if (i == 1) strcpy (message, "1st imset added"); else if (i == 2) strcpy (message, "2nd imset added"); else if (i == 3) strcpy (message, "3rd imset added"); else sprintf (message, "%dth imset added", i); TimeStamp (message, acs->input[i]); } closeSingleGroupLine (&y); } /* End loop over images */ freeSingleGroupLine (&y); /* Take the square root of variance to convert back to errors. */ SqrtErr (&x); /* Compute statistics and update keywords in output headers. */ trlmessage ("\n"); if (doStat (&x, acs->sdqflags)) return (status); if (acs->printtime) TimeStamp ("Image statistics computed", acs->rootname); /* Update header info in output. */ if (PutSumHdrInfo (&x, sumexptime, acs->expend, acs->nimages, acs->nimsets)) return (status); /* Update CAL_VER and FILENAME, then write output file. EXPNAME values modified for all extensions in a SingleGroup. WJH 7 July 1999 */ UCalVer (x.globalhdr); UFilename (acs->output, x.globalhdr); UMemType (mtype, x.globalhdr); UExpname (acs->rootname, &x.sci.hdr); UExpname (acs->rootname, &x.err.hdr); UExpname (acs->rootname, &x.dq.hdr); UpperAll (acs->rootname, uroot, strlen(acs->rootname)+1 ); PutKeyStr (x.globalhdr, "ROOTNAME", uroot,"Rootname of the observation set"); putSingleGroup (acs->output, extver, &x, 0); if (hstio_err()) return (status = 1001); freeSingleGroup (&x); PrGrpEnd ("imset", extver); if (acs->printtime) TimeStamp ("Output written to disk", acs->rootname); } /* End loop over imsets */ if (acs->printtime) free (message); return (status); }
/* This routine copies a FITS file. */ static int CopyFFile (char *infile, char *outfile) { /* arguments: infile i: name of input file outfile i: name of output file */ extern int status; FILE *ifp, *ofp; /* for input and output files */ void *buf; /* buffer for copying blocks */ int nin, nout; /* number read and written */ int done; IODescPtr im; Hdr phdr; /* function from lib */ void UFilename (char *, Hdr *); if ((buf = calloc (FITS_BUFSIZE, sizeof(char))) == NULL) return (status = OUT_OF_MEMORY); if ((ofp = fopen (outfile, "wb")) == NULL) { sprintf (MsgText,"Can't create temporary file %s.", outfile); trlerror(MsgText); free (buf); return (status = INVALID_TEMP_FILE); } if ((ifp = fopen (infile, "rb")) == NULL) { sprintf (MsgText, "Can't open %s.", infile); trlerror (MsgText); (void)fcloseWithStatus(&ofp); remove (outfile); free (buf); return (status = OPEN_FAILED); } done = 0; while (!done) { nin = fread (buf, sizeof(char), FITS_BUFSIZE, ifp); if (ferror (ifp)) { sprintf (MsgText, "Can't read from %s (copying to %s).", infile, outfile); trlerror (MsgText); (void)fcloseWithStatus(&ofp); (void)fcloseWithStatus(&ifp); free (buf); return (status = FILE_NOT_READABLE); } if (feof (ifp)) done = 1; nout = fwrite (buf, sizeof(char), nin, ofp); if (nout < nin) { sprintf (MsgText, "Can't copy %s to %s.", infile, outfile); trlerror (MsgText); (void)fcloseWithStatus(&ofp); (void)fcloseWithStatus(&ifp); free (buf); return (status = COPY_NOT_POSSIBLE); } } (void)fcloseWithStatus(&ofp); (void)fcloseWithStatus(&ifp); free (buf); /* Update the FILENAME keyword in the primary header of the output file. */ initHdr (&phdr); im = openUpdateImage (outfile, "", 0, &phdr); UFilename (outfile, &phdr); putHeader (im); closeImage (im); freeHdr (&phdr); return (status); }