int AcsSum (char *input, char *output, char *mtype, int printtime, int verbose) { extern int status; IRAFPointer tpin; AcsSumInfo acs; IODescPtr im; /* descriptor for input image */ Hdr phdr; /* primary header for input image */ int nimgs; int i; char acs_input[CHAR_FNAME_LENGTH]; int FileExists (char *); void TimeStamp (char *, char *); void PrBegin (char *); void PrEnd (char *); void PrFileName (char *, char *); void PrHdrInfo (char *, char *, char *, char *); int MkName (char *, char *, char *, char *, char *, int); void WhichError (int); void InitSumTrl (char *input, char *output); void FindAsnRoot (char *, char *); int mkNewSpt (char *, char *, char *); /* Determine input and output trailer files, then initialize output file by combining inputs into output file */ InitSumTrl (input, output); PrBegin ("ACSSUM"); nimgs = 0; if (printtime) TimeStamp ("ACSSUM started", ""); /* open the input file template */ tpin = c_imtopen (input); nimgs = c_imtlen(tpin); /* Initialize structure containing acssum information. */ AcsInit (&acs,nimgs); /* Copy command-line arguments into acs. */ for (i = 0; i < nimgs; i++) { c_imtgetim (tpin, acs.input[i], CHAR_FNAME_LENGTH); PrFileName ("input", acs.input[i]); } /* close file template */ c_imtclose (tpin); strcpy (acs.output, output); acs.printtime = printtime; acs.verbose = verbose; PrFileName ("output", acs.output); FindAsnRoot (output, acs.rootname); initHdr (&phdr); /* Check whether the output file already exists. */ if (FileExists (acs.output)) { FreeAcsInput (acs.input, nimgs); return (status); } strcpy(acs_input,acs.input[0]); /* Open input image in order to read its primary header. */ im = openInputImage (acs_input, "", 0); if (hstio_err()) { FreeAcsInput (acs.input, nimgs); return (status = OPEN_FAILED); } getHeader (im, &phdr); /* get primary header */ if (hstio_err()) { FreeAcsInput (acs.input, nimgs); return (status = OPEN_FAILED); } closeImage (im); /* Get keyword values from primary header. */ if (GetSumKeyInfo (&acs, &phdr)) { FreeAcsInput (acs.input, nimgs); return (status); } freeHdr (&phdr); /* Print information about this image. */ PrHdrInfo (acs.aperture, acs.filter1, acs.filter2, acs.det); if (acs.printtime) TimeStamp ("Begin processing", acs.rootname); /* Sum all imsets. */ if (SumGrps (&acs,mtype)){ FreeAcsInput (acs.input, nimgs); return (status); } /* create new SPT file for output product */ if (mkNewSpt (input, mtype, output)) { return(status); } /* Done... */ trlmessage ("\n"); PrEnd ("ACSSUM"); if (acs.printtime) TimeStamp ("ACSSUM completed", acs.rootname); /* Write out temp trailer file to final file */ WriteTrlFile (); FreeAcsInput (acs.input, nimgs); return (status); }
int GetGrpInfo1 (StisInfo1 *sts, Hdr *hdr) { /* arguments: StisInfo1 *sts io: calibration switches and info Hdr *hdr i: header of current extension */ int status; char *buf; /* scratch for keyword value */ int sdqflags; /* serious data quality flags */ int rsize; /* 1 for CCD, 2 for MAMA */ int corner[2]; /* subarray start points, detector coords */ double cd11, cd12, cd21, cd22; /* CD matrix */ int doppon; /* Doppler correction done on-board? */ int use_def = 1; /* use default if missing keyword */ int no_default = 0; /* missing keyword is fatal error */ int GetDetTemp (Hdr *, int, double *); int GetEPCTab (StisInfo1 *, float); /* Get generic parameters. */ /* Check whether we're processing a science file or wavecal, based on ASN_MTYP. Note that we won't reset the wavecal flag to false (it may have been set in GetKeyInfo1) if ASN_MTYP doesn't indicate that the observation is a wavecal, because this file might not be part of an association. */ if ((buf = calloc (STIS_FNAME+1, sizeof(char))) == NULL) return (OUT_OF_MEMORY); if ((status = Get_KeyS (hdr, "ASN_MTYP", use_def, "unknown", buf, STIS_FNAME))) return (status); /* Possible values for wavecals are "AUTO-WAVECAL" and "GO-WAVECAL" */ if (strstr (buf, "WAVECAL") != NULL) sts->wavecal = 1; free (buf); if ((status = Get_KeyD (hdr, "EXPTIME", no_default, 0., &sts->exptime))) return (status); if (sts->exptime < 0.) { printf ("ERROR Exposure time is invalid: %14.6g.\n", sts->exptime); return (GENERIC_ERROR_CODE); } if ((status = Get_KeyD (hdr, "EXPSTART", no_default, 0., &sts->expstart))) return (status); if ((status = Get_KeyD (hdr, "EXPEND", no_default, 0., &sts->expend))) return (status); /* Find out which data quality bits are considered serious; default value means all bits are serious. */ if ((status = Get_KeyI (hdr, "SDQFLAGS", use_def, 32767, &sdqflags))) return (status); sts->sdqflags = (short) sdqflags; /* Get the pixel size (ignore corner location) from ltm & ltv. */ rsize = (sts->detector == CCD_DETECTOR) ? 1 : 2; if ((status = GetCorner (hdr, rsize, sts->bin, corner))) return (status); /* For spectroscopic data, we want the dispersion axis and the sign of the dispersion. We'll get the latter from one element of the CD matrix. We also want the pixel size, which we compute from the CD matrix. */ sts->dispaxis = 1; /* initial values */ sts->dispsign = 1; if (strcmp (sts->obstype, "IMAGING") == 0) { if ((status = Get_KeyD (hdr, "CD1_1", use_def, 1., &cd11))) return (status); if ((status = Get_KeyD (hdr, "CD1_2", use_def, 0., &cd12))) return (status); if ((status = Get_KeyD (hdr, "CD2_1", use_def, 0., &cd21))) return (status); if ((status = Get_KeyD (hdr, "CD2_2", use_def, 1., &cd22))) return (status); sts->cdelt[0] = sqrt (cd11 * cd11 + cd21 * cd21); sts->cdelt[1] = sqrt (cd12 * cd12 + cd22 * cd22); } else if (strcmp (sts->obstype, "SPECTROSCOPIC") == 0) { if ((status = Get_KeyI (hdr, "DISPAXIS", use_def, 1, &sts->dispaxis))) return (status); if ((status = Get_KeyD (hdr, "CD1_1", use_def, 1., &cd11))) return (status); if ((status = Get_KeyD (hdr, "CD2_2", use_def, 1., &cd22))) return (status); if (sts->dispaxis == 1) { if (cd11 >= 0.) sts->dispsign = 1; else sts->dispsign = -1; sts->cdelt[0] = cd22; /* assume square pixels */ sts->cdelt[1] = cd22; } else if (sts->dispaxis == 2) { if (cd22 >= 0.) sts->dispsign = 1; else sts->dispsign = -1; sts->cdelt[0] = cd11; sts->cdelt[1] = cd11; } } sts->detector_temp = -1.; /* initial value (not defined) */ /* Get MAMA-specific parameters. */ if (sts->detector == NUV_MAMA_DETECTOR || sts->detector == FUV_MAMA_DETECTOR) { if ((status = Get_KeyD (hdr, "GLOBRATE", no_default, 0., &sts->globrate))) return (status); /* Get info if we need to do Doppler convolution of ref files. */ if (sts->doppcorr == PERFORM) { /* Was Doppler correction done on-board? */ if ((status = Get_KeyI (hdr, "DOPPON", use_def, 0, &doppon))) return (status); /* doppon could be False in timetag mode. */ if (!doppon) { if (strcmp (sts->obsmode, "TIME-TAG") == 0) { if ((status = Get_KeyD (hdr, "DOPPMAG", use_def, -1., &sts->doppmag))) return (status); doppon = (sts->doppmag > 0.); } } if (doppon) { if ((status = Get_KeyD (hdr, "DOPPZERO", no_default, 0., &sts->doppzero))) return (status); if ((status = Get_KeyD (hdr, "DOPPMAG", no_default, 0., &sts->doppmag))) return (status); if ((status = Get_KeyD (hdr, "ORBITPER", no_default, 0., &sts->orbitper))) return (status); } else { /* Silently reset the switch. */ sts->doppcorr = OMIT; } } } /* Get CCD-specific parameters. */ if (sts->detector == CCD_DETECTOR) { float occdhtav = -1.; /* if OCCDHTAV is present and > 0, then data is from Side B, * so look for EPC file. Otherwise, data is from Side A and * EPC file and temperature can be ignored. */ if (((status = Get_KeyF(hdr, "OCCDHTAV", use_def, -1., &occdhtav)) == 0) && (occdhtav >= 0.)) { char expname[81], epcname[81]; expname[0] = epcname[0] = '\0'; if ((status = Get_KeyS(hdr, "EXPNAME", no_default, "", expname, 80))) return (status); if (sts->crcorr != COMPLETE) { strncpy(epcname, expname, 8); epcname[8] = '\0'; sprintf(sts->epctab.name, "%sj_epc.fits", epcname); PrFileName("epcfile", sts->epctab.name); status = GetEPCTab(sts, 0.40); if (status && status != OPEN_FAILED) return (status); } if ((status = UpdateCCDTemperature(sts, hdr))) return (status); } } /* Get the detector temperature (or housing temperature, if CCD). Note that for side-2 CCD data this function must be called after calling UpdateCCDTemperature. */ if ((status = GetDetTemp (hdr, sts->detector, &sts->detector_temp))) { return (status); } /* If images have been combined (e.g. by cosmic-ray rejection), then determine the number of images that were combined together; we need this for bias image subtraction. (This isn't really a CCD-specific keyword, but it does only affect CCD data in the context of calstis1.) */ if ((status = Get_KeyI (hdr, "NCOMBINE", use_def, 1, &sts->ncombine))) return (status); if (sts->ncombine < 1) { printf ("Warning NCOMBINE = %d, reset to one.\n", sts->ncombine); sts->ncombine = 1; } return (0); }
int CalAcsRun (char *input, int printtime, int save_tmp, int verbose, int debug, const unsigned nThreads, const unsigned cteAlgorithmGen, const char * pcteTabNameFromCmd) { /* arguments: char *input i: name of the FITS file/table to be processed int printtime i: true --> print time stamps at intermediate steps int *save_tmp i: true --> save temporary files int verbose i: true --> print info during processing int debug i: true --> print debugging info during processing int onecpu i: true --> turn off use of OpenMP during processing */ extern int status; ACSInfo acshdr; /* calibration switches, etc */ AsnInfo asn; /* association table data */ char *acsdth_input; /* Input list for ACSDTH */ int prod; void PrBegin (char *); void PrEnd (char *); void PrFileName (char *, char *); void TimeStamp (char *, char *); /* Association table routines */ void initAsnInfo (AsnInfo *); void freeAsnInfo (AsnInfo *); int LoadAsn (AsnInfo *); int ProcessACSCCD (AsnInfo *, ACSInfo *, int *, int, const unsigned nThreads, const unsigned cteAlgorithmGen, const char * pcteTabNameFromCmd); int ProcessMAMA (AsnInfo *, ACSInfo *, int); int AcsDth (char *, char *, int, int, int); char *BuildDthInput (AsnInfo *, int); void InitDthTrl (char *, char *); /* Post error handler */ push_hstioerr (errchk); PrBegin ("CALACS"); /* *** CALACS -- Version ... *** */ if (printtime) TimeStamp ("CALACS started", ""); /* Determine if input is a single file or an association table, then populate ASN structure with appropriate information to control processing. */ initAsnInfo(&asn); if (debug) { trlmessage ("Initialized Association data ... "); } /* Copy Input filename to ASN structure */ strcpy (asn.input, input); /* Print image name. */ trlmessage ("\n"); PrFileName ("input", asn.input); /* Set verbose flag... */ asn.verbose = verbose; asn.debug = debug; /* LoadAsn will determine whether input is a single file or an Association table. If a single image, it will look in that images association table to see what products are associated with it, and process them accordingly. If it is just a single image as its own output, it will proceed as a 1 element table. Based on routines from n_getAsnTable() and n_setup() in CALNICB */ if(LoadAsn(&asn)) { freeAsnInfo (&asn); return (status); } /* Check to see that detector is known, as it could come through with a value of 0 or UNKNOWN_DETECTOR. WJH 2Mar99 */ if (asn.detector == UNKNOWN_DETECTOR || asn.detector == 0) { trlwarn ("Unknown detector type for observations."); freeAsnInfo(&asn); return (status = NOTHING_TO_DO); } if (asn.verbose) { sprintf (MsgText,"CALACS: Detector %s, type %d ",asn.instr, asn.detector); trlmessage (MsgText); } /* Determine what detector we are working with... */ if (asn.detector != MAMA_DETECTOR ) { /* Process CCD data ... */ if (asn.verbose) { trlmessage ("CALACS: processing a CCD product"); } if (ProcessACSCCD(&asn, &acshdr, &save_tmp, printtime, nThreads, cteAlgorithmGen, pcteTabNameFromCmd)) { if (status == NOTHING_TO_DO) { trlwarn ("No processing desired for CCD data."); } else { trlerror ("Couldn't process CCD data"); } freeAsnInfo(&asn); return (status); } trlmessage("Finished CCD processing..."); } else { /* Process MAMA observations here */ trlmessage("Starting to process MAMA data now..."); if (ProcessMAMA(&asn, &acshdr, printtime)) { if (status == NOTHING_TO_DO){ trlwarn ("No processing desired for MAMA data."); } else{ trlerror ("Couldn't process MAMA data"); } freeAsnInfo(&asn); return (status); } trlmessage("Finished MAMA processing..."); } /* Add DTH processing here... */ /* For each DTH product... */ if (asn.process == FULL){ if (asn.verbose) { trlmessage ("CALACS: Building DTH products"); } acsdth_input = NULL; for (prod = 0; prod < asn.numprod; prod++) { /* Create empty DTH product, header only */ /* This uses only one sub-product for the header template, but later versions should use a function similar to BuildSumInput to create list of subproducts as inputs... */ acsdth_input = BuildDthInput (&asn, prod); /* We always want to create a final concatenated trailer file for the entire association whether there is a product or not. So, we set up the trailer file based on the association file name itself. */ /* If desired, we could optionally use the full _drz.tra filename as the trailer filename, based on the output dither product name. if (strcmp(asn.product[prod].prodname,"") != 0) { InitDthTrl (acsdth_input, asn.product[prod].prodname); } else { */ InitDthTrl(acsdth_input, asn.rootname); /* End brace for optional dither product name assignment... } */ /* Check if we have a PROD-DTH specified...*/ if (strcmp(asn.product[prod].prodname, "") != 0) { if ((asn.dthcorr == PERFORM || asn.dthcorr == DUMMY)) { if (AcsDth (acsdth_input, asn.product[prod].prodname, asn.dthcorr, printtime, asn.verbose) ) return (status); /* Pass posid of 0 to indicate a PRODUCT is to be updated */ updateAsnTable(&asn, prod, NOPOSID); } } else { trlwarn ("No DTH product name specified. No product created."); /*status = ACS_OK; */ } } free (acsdth_input); } if (asn.verbose) { trlmessage ("CALACS: Finished processing product "); } freeAsnInfo(&asn); trlmessage ("\n"); PrEnd ("CALACS"); /* *** CALACS complete *** */ if (printtime) TimeStamp ("CALACS completed", acshdr.rootname); /* Return the final value of status, which should be ACS_OK if all went well or some error condition otherwise. */ return (status); }
int CalStis11 (char *inwav, char *insci, char *output, int printtime, int verbose) { int status; StisInfo11 wavecal, scidata; /* calibration switches, etc. */ IODescPtr imWav; /* descriptor for input wavecal */ IODescPtr imSci; /* descriptor for input science file */ Hdr phdrWav; /* primary header for input wavecal */ Hdr phdrSci; /* primary header for input science file */ int subscicorr; /* PERFORM if CCD and sclamp is HITM1 or 2 */ int GetKeyInfo11 (StisInfo11 *, Hdr *); int SubSci (StisInfo11 *, StisInfo11 *); PrBegin (11); if (printtime) TimeStamp ("CALSTIS-11 started", ""); /* Initialize structure containing calstis information. */ StisInit11 (&wavecal, &scidata); /* Copy command-line arguments into wavecal & scidata. */ strcpy (wavecal.input, inwav); strcpy (scidata.input, insci); strcpy (wavecal.output, output); wavecal.printtime = printtime; scidata.printtime = printtime; wavecal.verbose = verbose; scidata.verbose = verbose; PrFileName ("wavecal", wavecal.input); PrFileName ("science", scidata.input); PrFileName ("output", wavecal.output); initHdr (&phdrWav); initHdr (&phdrSci); /* Check whether the output file already exists. */ if ((status = FileExists (wavecal.output))) return (status); /* Read primary header of input wavecal. */ imWav = openInputImage (wavecal.input, "", 0); if (hstio_err()) return (OPEN_FAILED); getHeader (imWav, &phdrWav); if (hstio_err()) return (OPEN_FAILED); closeImage (imWav); /* Get keyword values from wavecal primary header. */ if ((status = GetKeyInfo11 (&wavecal, &phdrWav))) return (status); freeHdr (&phdrWav); /* Print information about the input wavecal. */ PrHdrInfo (wavecal.obsmode, wavecal.aperture, wavecal.opt_elem, wavecal.det); /* Do we need to subtract the science image from the wavecal? */ subscicorr = PERFORM; /* initial value */ if (wavecal.detector != CCD_DETECTOR) { subscicorr = OMIT; printf ("Warning Detector is %s\n", wavecal.det); } if (strcmp (wavecal.sclamp, "HITM1") != 0 && strcmp (wavecal.sclamp, "HITM2") != 0) { subscicorr = OMIT; printf ("Warning Wavecal SCLAMP is `%s', not HITM1 or HITM2\n", wavecal.sclamp); } if (wavecal.texpstrt >= EXT_SHUTTER_CLOSED) { subscicorr = OMIT; printf ( "Warning TEXPSTRT=%.2f implies external shutter is closed.\n", wavecal.texpstrt); } if (subscicorr != PERFORM) { printf ( "Warning Science data will not be subtracted from wavecal.\n"); return (NOTHING_TO_DO); } /* Read primary header of input science file. */ imSci = openInputImage (scidata.input, "", 0); if (hstio_err()) return (OPEN_FAILED); getHeader (imSci, &phdrSci); if (hstio_err()) return (OPEN_FAILED); closeImage (imSci); if (wavecal.printtime) TimeStamp ("Begin processing", wavecal.rootname); /* Get keyword values from science file primary header. */ if ((status = GetKeyInfo11 (&scidata, &phdrSci))) return (status); freeHdr (&phdrSci); /* Detector, central wavelength, grating, and aperture must be the same in the wavecal and science file. */ if (wavecal.detector != scidata.detector || wavecal.cenwave != scidata.cenwave || strcmp (wavecal.opt_elem, scidata.opt_elem) != 0 || strcmp (wavecal.aperture, scidata.aperture) != 0) { printf ("Warning Wavecal and science file do not match; \\\n"); printf ("Warning the science file will not be subtracted.\n"); return (NOTHING_TO_DO); } /* Subtract the science image from the wavecal. */ if ((status = SubSci (&wavecal, &scidata))) return (status); printf ("\n"); PrEnd (11); if (wavecal.printtime) TimeStamp ("CALSTIS-11 completed", wavecal.rootname); return (0); }
int WF3cte (char *input, char *output, CCD_Switch *cte_sw, RefFileInfo *refnames, int printtime, int verbose, int onecpu) { /* input: filename output: filename cte_sw: the calibration flags refnames: the names of the calibration reference files onecpu: use parallel processing? The following are new primary header keywords which will be added to the data so that they can be updated by the code. They are also specified in the PCTETAB reference file. These are taken from the PCTETAB CTE_NAME - name of cte algorithm CTE_VER - version number of cte algorithm CTEDATE0 - date of wfc3/uvis installation in HST, in MJD CTEDATE1 - reference date of CTE model pinning, in MJD PCTETLEN - max length of CTE trail PCTERNOI - readnoise amplitude for clipping PCTESMIT - number of iterations used in CTE forward modeling PCTESHFT - number of iterations used in the parallel transfer PCTENSMD - readnoise mitigation algorithm PCTETRSH - over-subtraction threshold PCTEFRAC - cte scaling frac calculated from expstart PCTERNOI - the readnoise clipping level to use #These are taken from getreffiles.c DRKCFILE is a new dark reference file used only in the CTE branch *_DRC.fits BIACFILE is a new super-bias reference file used only in the CTE branch *_BIC.fits PCTETAB is a new reference file FITS table which will contain the software parameter switches for the CTE correction *_CTE.fit This is the main workhorse function for removing the CTE from WFC3 UVIS images Unfortunately this happens before anything else in wfc3, so there's a lot of reading files at the beginning in order to populate needed information. The rest of the pipeline works on one chip at a time and the structures are all defined to support that. None of these structures are defined until the code enters the single chip loops. This differs from the CTE correction in ACS which occurs later in the process after basic structures are defined. */ extern int status; WF3Info wf3; /*structure with calibration switches and reference files for passing*/ Hdr phdr; /*primary header for input image, all output information saved here*/ CTEParams cte_pars; /*STRUCTURE HOLDING THE MODEL PARAMETERS*/ SingleGroup cd; /*SCI 1*/ SingleGroup ab; /*SCI 2*/ SingleGroup raz; /* THE LARGE FORMAT COMBINATION OF CDAB*/ SingleGroup rsz; /* LARGE FORMAT READNOISE CORRECTED IMAGE */ SingleGroup rsc; /* CTE CORRECTED*/ SingleGroup rzc; /* FINAL CTE CORRECTED IMAGE */ SingleGroup chg; /* THE CHANGE DUE TO CTE */ SingleGroup raw; /* THE RAW IMAGE IN RAZ FORMAT */ int i,j; /*loop vars*/ int max_threads=1; clock_t begin; double time_spent; float hardset=0.0; begin = (double)clock(); Bool subarray; /* to verify that no subarray is being used, it's not implemented yet*/ /*CONTAIN PARALLEL PROCESSING TO A SINGLE THREAD AS USER OPTION*/ # ifdef _OPENMP trlmessage("Using parallel processing provided by OpenMP inside CTE routine"); if (onecpu){ omp_set_dynamic(0); max_threads=1; sprintf(MsgText,"onecpu == TRUE, Using only %i threads/cpu", max_threads); } else { omp_set_dynamic(0); max_threads = omp_get_num_procs(); /*be nice, use 1 less than avail?*/ sprintf(MsgText,"Setting max threads to %i of %i cpus",max_threads, omp_get_num_procs()); } omp_set_num_threads(max_threads); trlmessage(MsgText); # endif /* COPY COMMAND-LINE ARGUMENTS INTO WF3. */ WF3Init (&wf3); strcpy (wf3.input, input); strcpy (wf3.output, output); PrBegin ("WFC3CTE"); if (wf3.printtime) TimeStamp("WFC3CTE Started: ",wf3.rootname); /* CHECK WHETHER THE OUTPUT FILE ALREADY EXISTS. */ if (FileExists (wf3.output)){ WhichError(status); return (ERROR_RETURN); } wf3.pctecorr = cte_sw->pctecorr; wf3.darkcorr = cte_sw->darkcorr; wf3.biascorr = cte_sw->biascorr; wf3.blevcorr = cte_sw->blevcorr; wf3.printtime = printtime; wf3.verbose = verbose; wf3.refnames = refnames; PrFileName ("input", wf3.input); PrFileName ("output", wf3.output); if (wf3.biascorr == COMPLETE){ trlmessage("BIASCORR complete for input image, CTE can't be performed"); return(ERROR_RETURN); } if (wf3.darkcorr == COMPLETE){ trlmessage("DARKCORR complete for input image, CTE can't be performed"); return(ERROR_RETURN); } if (wf3.blevcorr == COMPLETE){ trlmessage("BLEVCORR complete for input image, CTE can't be performed"); return(ERROR_RETURN); } /* DETERMINE THE NAMES OF THE TRAILER FILES BASED ON THE INPUT AND OUTPUT FILE NAMES, THEN INITIALIZE THE TRAILER FILE BUFFER WITH THOSE NAMES. */ if (initCTETrl (input, output)) return (status); /* OPEN INPUT IMAGE IN ORDER TO READ ITS PRIMARY HEADER. */ if (LoadHdr (wf3.input, &phdr) ){ WhichError(status); return (ERROR_RETURN); } /* GET KEYWORD VALUES FROM PRIMARY HEADER. */ if (GetKeys (&wf3, &phdr)) { freeHdr (&phdr); return (status); } if (GetCTEFlags (&wf3, &phdr)) { freeHdr(&phdr); return (status); } /* OPEN THE INPUT IMAGES AND GET THE SCIENCE EXTENSIONS */ initSingleGroup (&cd); getSingleGroup (wf3.input, 1, &cd); if (hstio_err()) return (status = OPEN_FAILED); /*** MAKE SURE THIS IS NOT A SUBARRAY ***/ if (GetKeyBool (cd.globalhdr, "SUBARRAY", NO_DEFAULT, 0, &subarray)) return (status=KEYWORD_MISSING); if (subarray) { sprintf(MsgText,"**SUBARRAY FOUND!; SUBARRAY images are not yet supported for CTE**"); trlmessage(MsgText); status=ERROR_RETURN; return(status); } initSingleGroup (&ab); getSingleGroup (wf3.input, 2, &ab); if (hstio_err()) return (status = OPEN_FAILED); if (GetKeyBool (ab.globalhdr, "SUBARRAY", NO_DEFAULT, 0, &subarray)) return (status=KEYWORD_MISSING); if (subarray) { sprintf(MsgText,"SUBARRAY FOUND; **SUBARRAY images are not yet supported for CTE**"); trlmessage(MsgText); status=ERROR_RETURN; return(status); } /*READ IN THE CTE PARAMETER TABLE*/ initCTEParams(&cte_pars); if (GetCTEPars (wf3.pctetab.name,&cte_pars)) return (status); if (verbose){ PrRefInfo ("pctetab", wf3.pctetab.name, wf3.pctetab.pedigree, wf3.pctetab.descrip, wf3.pctetab.descrip2); } /*SAVE THE PCTETABLE INFORMATION TO THE HEADER OF THE SCIENCE IMAGE AFTER CHECKING TO SEE IF THE USER HAS SPECIFIED ANY CHANGES TO THE CTE CODE VARIABLES. */ if (CompareCTEParams(&cd, &cte_pars)){ return (status); } /*SET UP THE ARRAYS WHICH WILL BE PASSED AROUND*/ initSingleGroup(&raz); allocSingleGroup(&raz, RAZ_COLS, RAZ_ROWS); initSingleGroup(&rsz); allocSingleGroup(&rsz, RAZ_COLS, RAZ_ROWS); initSingleGroup(&rsc); allocSingleGroup(&rsc, RAZ_COLS, RAZ_ROWS); initSingleGroup(&rzc); allocSingleGroup(&rzc, RAZ_COLS, RAZ_ROWS); initSingleGroup(&raw); allocSingleGroup(&raw, RAZ_COLS, RAZ_ROWS); initSingleGroup(&chg); allocSingleGroup(&chg, RAZ_COLS, RAZ_ROWS); for (i=0;i<RAZ_COLS;i++){ for(j=0;j<RAZ_ROWS;j++){ Pix(raw.sci.data,i,j)=hardset; Pix(rsz.sci.data,i,j)=hardset; Pix(raz.sci.data,i,j)=hardset; Pix(rsc.sci.data,i,j)=hardset; Pix(rzc.sci.data,i,j)=hardset; Pix(chg.sci.data,i,j)=hardset; } } /* SAVE A COPY OF THE RAW IMAGE FOR LATER */ makesciRAZ(&cd,&ab,&raw); /***SUBTRACT THE CTE BIAS FROM BOTH CHIPS IN PLACE***/ if (doCteBias(&wf3,&cd)){ freeSingleGroup(&cd); return(status); } if (doCteBias(&wf3,&ab)){ freeSingleGroup(&ab); return(status); } /*CONVERT TO RAZ FORMAT AND CORRECT FOR GAIN*/ if (raw2raz(&wf3, &cd, &ab, &raz)) return (status); /***CALCULATE THE SMOOTH READNOISE IMAGE***/ trlmessage("CTE: Calculating smooth readnoise image"); /***CREATE THE NOISE MITIGATION MODEL ***/ if (cte_pars.noise_mit == 0) { if (raz2rsz(&wf3, &raz, &rsz, cte_pars.rn_amp, max_threads)) return (status); } else { trlmessage("Only noise model 0 implemented!"); return (status=ERROR_RETURN); } /***CONVERT THE READNOISE SMNOOTHED IMAGE TO RSC IMAGE THIS IS WHERE THE CTE GETS CALCULATED ***/ if (rsz2rsc(&wf3, &rsz, &rsc, &cte_pars)) return (status); /*** SAVE USEFULL HEADER INFORMATION ***/ if (cteHistory (&wf3, cd.globalhdr)) return (status); /*** CREATE THE FINAL CTE CORRECTED IMAGE, PUT IT BACK INTO ORIGNAL RAW FORMAT***/ for (i=0;i<RAZ_COLS;i++){ for(j=0; j<RAZ_ROWS; j++){ Pix(chg.sci.data,i,j) = (Pix(rsc.sci.data,i,j) - Pix(rsz.sci.data,i,j))/wf3.ccdgain; Pix(rzc.sci.data,i,j) = Pix(raw.sci.data,i,j) + Pix(chg.sci.data,i,j); } } /*BACK TO NORMAL FORMATTING*/ undosciRAZ(&cd,&ab,&rzc); /*UPDATE THE OUTPUT HEADER ONE FINAL TIME*/ PutKeyDbl(cd.globalhdr, "PCTEFRAC", cte_pars.scale_frac,"CTE scaling fraction based on expstart"); trlmessage("PCTEFRAC saved to header"); /*SAVE THE NEW RAW FILE WITH UPDATED SCIENCE ARRAYS AND PRIMARY HEADER TO RAC*/ putSingleGroup(output,cd.group_num, &cd,0); putSingleGroup(output,ab.group_num, &ab,0); /** CLEAN UP **/ freeSingleGroup(&rzc); freeSingleGroup(&rsc); freeSingleGroup(&chg); freeSingleGroup(&raz); freeSingleGroup(&rsz); freeSingleGroup(&raw); time_spent = ((double) clock()- begin +0.0) / CLOCKS_PER_SEC; if (verbose){ sprintf(MsgText,"CTE run time: %.2f(s) with %i procs/threads\n",time_spent,max_threads); trlmessage(MsgText); } PrSwitch("pctecorr", COMPLETE); if(wf3.printtime) TimeStamp("PCTECORR Finished",wf3.rootname); return (status); }