/* 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); }
int photcalc (WF3Info *wf3, MultiNicmosGroup *input) { /* Arguments: ** wf3 i: WFC3 info structure ** input io: input image */ /* Local variables */ PhotPar obs; float photfnu; char photmode[CHAR_LINE_LENGTH+1], obsmode[CHAR_LINE_LENGTH+1]; int status; /* Function definitions */ int GetKeyStr (Hdr *, char *, int, char *, char *, int); int PutKeyFlt (Hdr *, char *, float, char *); void PrSwitch (char *, int); if (wf3->photcorr == PERFORM) { /* Extract photmode from sci extension header */ if ( (status=GetKeyStr (input->group[0].globalhdr, "PHOTMODE", USE_DEFAULT, "", photmode, CHAR_LINE_LENGTH))) return (status); /* Convert PHOTMODE string into synphot OBSMODE syntax */ Phot2Obs (photmode, obsmode); if (wf3->verbose) { sprintf (MsgText, "Created obsmode of: %s", obsmode); trlmessage (MsgText); } /* Initialize PhotPar structure */ InitPhotPar (&obs, wf3->phot.name, wf3->phot.pedigree); /* Get the photometry values from the IMPHTTAB table */ if (GetPhotTab (&obs, obsmode)) { trlerror ("Error return GetPhotTab."); } if (wf3->verbose) { sprintf (MsgText, "Computed PHOTFLAM value of %g", obs.photflam); } /* Update the photometry keyword values in the header */ if (PutKeyFlt (input->group[0].globalhdr, "PHOTFLAM", obs.photflam, "")) return (status); if (PutKeyFlt (input->group[0].globalhdr, "PHOTZPT", obs.photzpt, "")) return (status); if (PutKeyFlt (input->group[0].globalhdr, "PHOTPLAM", obs.photplam, "")) return (status); if (PutKeyFlt (input->group[0].globalhdr, "PHOTBW", obs.photbw, "")) return (status); photfnu = 3.33564e+4 * obs.photflam * obs.photplam*obs.photplam; if (PutKeyFlt (input->group[0].globalhdr, "PHOTFNU", photfnu, "")) return (status); FreePhotPar (&obs); PrSwitch ("photcorr", COMPLETE); } /* Successful return */ return (status = 0); }
/* remove stripes from post-SM4 full frame WFC data using information in * the prescan regions. chip2 is amps C & D, chip1 is amps A & B. */ int doDestripe(ACSInfo *acs, SingleGroup *chip2, SingleGroup *chip1) { extern int status; /* iteration variables */ int i, j, k; /* amp array size variables */ int arr_rows, arr_cols; /* array of arrays for each amp's data in order of AMPSORDER */ double * ampdata[NAMPS]; /* arrays of bias column means and standard deviation */ double bias_col_means[NBIAS_COLS]; double bias_col_stds[NBIAS_COLS]; /* array of arrays designating whether a row is usable or not. 0: bad, 1:good */ char * good_rows[NAMPS]; /* array of number of good rows for each amp */ int num_good_rows[NAMPS]; /* number of rows ultimately worked on and fixed */ int rows_fixed; int rows_skipped; /* character array for holding history messages */ char history[ACS_LINE]; /* bias pixel mean, standard deviation, and number of good pixels */ double bias_mean, bias_std; int good_bias_pix; /* holder of bias means from each amp, saved here so I can put the * MEANBLEV keyword in the science extension headers */ double bias_mean_arr[NAMPS]; int PutKeyFlt(Hdr *, char *, float, char *); int blevHistory(ACSInfo *, Hdr *, int, int); int MkName (char *, char *, char *, char *, char *, int); /* figure out the size of individual amp arrays * should be 2068 rows by 2072 columns */ arr_rows = chip2->sci.data.ny; arr_cols = chip2->sci.data.nx/2; /* allocate space for the amp arrays */ for (i = 0; i < NAMPS; i++) { ampdata[i] = malloc(arr_rows * arr_cols * sizeof(double)); good_rows[i] = malloc(arr_rows * sizeof(char)); } /* copy data from SingleGroup structs to amp arrays */ for (i = 0; i < NAMPS; i++) { if (i < 2) { make_amp_array(arr_rows, arr_cols, chip1, i, ampdata[i]); } else { make_amp_array(arr_rows, arr_cols, chip2, i, ampdata[i]); } } /* subtract each column's mean as computed after removing the mean of each * bias row, ignoring bias rows near saturated pixels, and doing * sigma rejection of outlying bias pixels. */ for (i = 0; i < NAMPS; i++) { if (bias_col_mean_std(arr_rows, arr_cols, ampdata[i], bias_col_means, bias_col_stds)) { return status; } if (sub_bias_col_means(arr_rows, arr_cols, NBIAS_COLS, bias_col_means, ampdata[i])) { return status; } } /* for each amp figure out which rows to use and how many good rows there are */ for (i = 0; i < NAMPS; i++) { find_good_rows(arr_rows, arr_cols, ampdata[i], good_rows[i], &num_good_rows[i]); } /* for each amp, figure out the mean of the good bias pixels with "sigma" * clipping, then subtract that mean from all that amp's data. */ for (i = 0; i < NAMPS; i++) { if (calc_bias_mean_std(arr_rows, arr_cols, ampdata[i], good_rows[i], &bias_mean, &bias_std, &good_bias_pix)) { return status; } /* subtract the mean from all the pixels in the image. */ for (j = 0; j < arr_rows; j++) { for (k = 0; k < arr_cols; k++) { ampdata[i][arr_cols*j + k] -= bias_mean; } } /* report bias level subtracted to user */ sprintf(MsgText, " bias level of %.6g electrons was subtracted for AMP %c.", bias_mean, AMPSORDER[i]); trlmessage(MsgText); acs->blev[i] += bias_mean; bias_mean_arr[i] = bias_mean; } /* add MEANBLEV keyword to science extension headers */ if (PutKeyFlt (&chip1->sci.hdr, "MEANBLEV", (bias_mean_arr[0] + bias_mean_arr[1])/2., "mean of bias levels subtracted in electrons")) { return (status); } if (PutKeyFlt (&chip2->sci.hdr, "MEANBLEV", (bias_mean_arr[2] + bias_mean_arr[3])/2., "mean of bias levels subtracted in electrons")) { return (status); } /* remove stripes */ if (remove_stripes(arr_rows, arr_cols, good_rows, ampdata, &rows_fixed, &rows_skipped)) { return status; } /* add history keywords about rows fixed and rows skipped */ sprintf(history, "DESTRIPE: number of rows fixed per amp: %i", rows_fixed); addHistoryKw(chip2->globalhdr, history); if (hstio_err()) { return (status = HEADER_PROBLEM); } sprintf(history, "DESTRIPE: number of rows skipped per amp: %i", rows_skipped); addHistoryKw(chip2->globalhdr, history); if (hstio_err()) { return (status = HEADER_PROBLEM); } /* copy modified data back to SingleGroup structs */ for (i = 0; i < NAMPS; i++) { if (i < 2) { unmake_amp_array(arr_rows, arr_cols, chip1, i, ampdata[i]); } else { unmake_amp_array(arr_rows, arr_cols, chip2, i, ampdata[i]); } } /* free allocated arrays */ for (i = 0; i < NAMPS; i++) { free(ampdata[i]); free(good_rows[i]); } return status; }
int doStat (SingleGroup *out, short sdqflags) { /* arguments: SingleGroup *out io: image to be calibrated; the headers are modified short sdqflags i: "serious" data quality flags */ extern int status; double value; /* current data value */ double valsum, valmin, valmax; double stddev; /* current error estimate */ double errsum, errmin, errmax; double snr; /* current signal-to-noise ratio */ double snrsum, snrmin, snrmax; int numgood; /* number of good pixels */ int num_bad_stddev; /* number of pixels with err = 0 */ int area; /* total number of pixels */ int i, j; int dimx, dimy; short flagval; /* data quality flag value */ int PutKeyFlt (Hdr *, char *, float, char *); int PutKeyInt (Hdr *, char *, int, char *); /* Statistics for the science data. */ numgood = 0; valmin=0.0f; valmax=0.0f; errmin=0.0f; errmax=0.0f; snrmin=0.0f; snrmax=0.0f; num_bad_stddev = 0; valsum = 0.; errsum = 0.; snrsum = 0.; dimx = out->sci.data.nx; dimy = out->sci.data.ny; for (j = 0; j < dimy; j++) { for (i = 0; i < dimx; i++) { flagval = DQPix (out->dq.data, i, j); if (!(sdqflags & flagval)) { /* no serious flag bit set */ value = Pix (out->sci.data, i, j); stddev = Pix (out->err.data, i, j); if (stddev <= 0.) { num_bad_stddev++; continue; /* bad error value */ } else { snr = value / stddev; } if (numgood < 1) { valsum = value; valmin = value; valmax = value; errsum = stddev; errmin = stddev; errmax = stddev; snrsum = snr; snrmin = snr; snrmax = snr; numgood = 1; } else { valsum += value; errsum += stddev; snrsum += snr; if (value < valmin) valmin = value; if (value > valmax) valmax = value; if (stddev < errmin) errmin = stddev; if (stddev > errmax) errmax = stddev; if (snr < snrmin) snrmin = snr; if (snr > snrmax) snrmax = snr; numgood++; } } } } if (numgood > 0) { valsum /= (double) numgood; errsum /= (double) numgood; snrsum /= (double) numgood; } else { area = dimy * dimx; if (area == 0) { trlwarn ("Output image size is zero."); } else if (num_bad_stddev > 0) { if (num_bad_stddev == area) { trlwarn ("No ERR values > 0."); } else { trlwarn ("All output pixels either flagged as bad or ERR <= 0."); } } else { trlwarn ("All output pixels flagged as bad."); } PutKeyInt (&out->sci.hdr, "NGOODPIX", numgood, ""); PutKeyInt (&out->err.hdr, "NGOODPIX", numgood, ""); return (status); } /* Update header values for the science array. */ if (PutKeyInt (&out->sci.hdr, "NGOODPIX", numgood, "number of good pixels")) return (status); if (PutKeyFlt (&out->sci.hdr, "GOODMIN", (float) valmin, "minimum good data value")) return (status); if (PutKeyFlt (&out->sci.hdr, "GOODMAX", (float) valmax, "maximum good data value")) return (status); if (PutKeyFlt (&out->sci.hdr, "GOODMEAN", (float) valsum, "average of good data values")) return (status); if (PutKeyFlt (&out->sci.hdr, "SNRMIN", (float) snrmin, "minimum S/N of good data values")) return (status); if (PutKeyFlt (&out->sci.hdr, "SNRMAX", (float) snrmax, "maximum S/N of good data values")) return (status); if (PutKeyFlt (&out->sci.hdr, "SNRMEAN", (float) snrsum, "mean S/N of good data values")) return (status); /* Update header values for the error array. */ if (PutKeyInt (&out->err.hdr, "NGOODPIX", numgood, "number of good pixels")) return (status); if (PutKeyFlt (&out->err.hdr, "GOODMIN", (float) errmin, "minimum sigma for good data")) return (status); if (PutKeyFlt (&out->err.hdr, "GOODMAX", (float) errmax, "maximum sigma for good data")) return (status); if (PutKeyFlt (&out->err.hdr, "GOODMEAN", (float) errsum, "average of sigma for good data")) return (status); return (status); }
int doPhot (ACSInfo *acs2d, SingleGroup *x) { /* arguments: ACSInfo *acs2d i: calibration switches, etc SingleGroup *x io: image to be calibrated; primary header is modified */ extern int status; PhotPar obs; char photmode[CHAR_LINE_LENGTH],obsmode[CHAR_LINE_LENGTH]; /* function prototypes from lib */ int GetKeyStr (Hdr *, char *, int, char *, char *, int); int PutKeyFlt (Hdr *, char *, float, char *); if (acs2d->photcorr == DUMMY) return (status); /* Extract photmode from sci extension header*/ if (GetKeyStr(&x->sci.hdr,"PHOTMODE",USE_DEFAULT,"",photmode, CHAR_LINE_LENGTH)) return (status); /* Add commas to PHOTMODE string and change all strings to lower case for use in synphot. */ Phot2Obs(photmode,obsmode); if (acs2d->verbose){ sprintf(MsgText,"Created SYNPHOT obsmode of: %s",obsmode); trlmessage(MsgText); } /* Initialize PhotPar struct */ InitPhotPar(&obs, acs2d->phot.name, acs2d->phot.pedigree); /* get phot values */ if (GetPhotTab(&obs,obsmode)) { trlerror("Error return from GetPhotTab."); return status; } if (acs2d->verbose){ sprintf(MsgText,"Computed PHOTFLAM value of %g",obs.photflam); trlmessage(MsgText); } /* Update the photometry keyword values in the SCI header. Revised 10 March 1999 WJH */ if (PutKeyFlt (&x->sci.hdr, "PHOTFLAM", obs.photflam, "inverse sensitivity")) return (status); if (PutKeyFlt (&x->sci.hdr, "PHOTZPT", obs.photzpt, "zero point")) return (status); if (PutKeyFlt (&x->sci.hdr, "PHOTPLAM", obs.photplam, "pivot wavelength")) return (status); if (PutKeyFlt (&x->sci.hdr, "PHOTBW", obs.photbw, "RMS bandwidth")) return (status); FreePhotPar(&obs); /* check whether GetPhotTab returned -9999, which means it was asked to do extrapolation */ if (obs.photflam == -9999) { trlwarn("IMPHTTAB extrapolation not supported, PHOTCORR skipped."); return (status = CAL_STEP_NOT_DONE); } return (status); }