コード例 #1
0
ファイル: acsmember.c プロジェクト: jhunkeler/hstcal
int GetSingle (AsnInfo *asn, ACSInfo *acs) {

/* arguments:
AsnInfo *asn      	i: calibration flags and other info
ACSInfo *acs		o: exposure specific flags and info
*/
	extern int status;
	char rootname[CHAR_FNAME_LENGTH];
	*rootname = '\0';
	void FindAsnRoot (const char *, char *);
	
	const char * outroot = asn->filename;
	
	/* Make sure we are only passing a rootname, and not a full filename.*/
	FindAsnRoot (outroot, rootname);
	strcpy (acs->outroot, rootname);
	strcpy (acs->rootname, rootname);
	
	if (asn->debug) {
		sprintf (MsgText, "GetSingle: Rootname: %s, Output rootname: %s",rootname, outroot);
		trlmessage (MsgText);
	}

	/* Check to see that this value of rootname is what we really need... */
	strcpy (acs->asn_table, asn->asn_table);	
	strcpy (acs->rawfile, asn->filename);
	
	/* Set sci_* flags for acs */	
	acs->sci_crcorr = asn->crcorr;
	acs->sci_dthcorr = asn->dthcorr;
	acs->sci_rptcorr = asn->rptcorr;
	acs->detector = asn->detector;
	acs->nimages = 1;

    /* Set MemType appropriate for output */
    acs->mtype[0] = '\0';

	return (status);
}
コード例 #2
0
ファイル: acssum.c プロジェクト: jhunkeler/hstcal
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);
}
コード例 #3
0
ファイル: wf3table.c プロジェクト: brechmos-stsci/hstcal
int SetInput (AsnInfo *asn) {

    /* Arguments:
     **  asn			io: Association info structure
     */	
    extern int status;

    /* Local Variables */
    char filename[SZ_FNAME+1];	
    int exist;			/* EXISTS_YES or EXISTS_NO */
    int in_dot;
    char linput[SZ_FNAME+1];	/* Lower case version of input */
    int incase;			/* What kind of input do we have? */

    int  DoesFileExist (char *);
    char *lowcase (char *, char *);
    int  GetAsnName (char *, char *);
    void FindAsnRoot (char *, char *);

    /* Initialize internal variables here... */
    filename[0] = '\0';

    /* convert input to lowercase for use only in looking for extensions */
    lowcase (linput, asn->input);

    /* Determine what kind of input: root only, 
     **				 root + suffix, or 
     **				 root + suffix + extension
     ** We will look for '.fit' or '.fits' extensions.
     */

    /* First, let's complete the input filename with a FITS extension.*/
    if (strstr(linput, ".fit") == NULL) {
        strcpy (filename, asn->input);
        strcat (filename, ".fits");
    } else {
        strcpy (filename, asn->input);
        strcat (filename, "\0");
    } 		

    /* Initialize local variable */
    incase = 0;

    /* Now, we find out what kind of input name was provided... */
    if (strstr(linput, "_asn") != NULL){
        incase = 0;
    } else if (strstr(linput, "_raw") != NULL ) {
        incase = 1;
    } else if (!IsProduct (linput)) {
        /* Not a sub-product/intermediate product... */
        incase = 2;
    } else {
        /* treat as if it was only a rootname (plus '.fits') */
        incase = 3;
    }

    if (asn->debug) {
        sprintf (MsgText, "GetAsnTable: incase = %d",incase);
        trlmessage (MsgText);
    }

    /* Given this full filename for a file which exists, 
     ** copy out just the rootname. */
    FindAsnRoot(filename, asn->rootname);

    /* Can we find the file as it is input? */
    exist = DoesFileExist(filename);

    /* Treat filename according to what was input... */
    switch (incase) {

        case 0:  /* We have an ASN file explicitly specified */

            if (exist == EXISTS_YES) {

                /* Found an ASN file:  Set values in ASN structure */
                asn->process = FULL;
                strcpy(asn->asn_table, filename);
                strcpy(asn->filename, filename);

                if (asn->verbose) {
                    trlmessage ("Processing FULL ASN table...");
                }			

            } else {

                /* Couldn't find specified ASN file... */
                sprintf (MsgText, "File %s not found for processing",
                        filename);
                trlerror (MsgText);
                return (status = OPEN_FAILED);			
            }
            break;

        case 1:  /* We have a RAW file explicitly specified */

            if (exist == EXISTS_YES) {

                /* Found a RAW file: Set values in ASN structure */
                strcpy (asn->filename, filename);
                strcpy (asn->asn_table, filename);
                strcat (asn->asn_table, "\0");

                if (asn->verbose) {
                    sprintf (MsgText, "Processing SINGLE image %s...",
                            asn->filename);
                    trlmessage (MsgText);
                }
                asn->process = SINGLE;

            } else {

                /* Couldn't find specified RAW file... */
                sprintf (MsgText,"File %s not found for processing",
                        filename);
                trlerror (MsgText);
                return (status = OPEN_FAILED);			
            }
            break;

        case 2:  /* We have a sub-product/intermediate file specified
                  ** for re-processing. They should really just run the
                  ** stand-alone tasks separately by hand, but...  */

            if (exist == EXISTS_YES) {
                strcpy (asn->filename, filename);

                /* Look for ASN_TAB in file's header, and copy to
                 ** ASN->asn_table if it is found. */
                if (!GetAsnName (filename, asn->asn_table) ) {

                    /* No ASN table listed, process as a
                     ** SINGLE exposure */
                    asn->process = SINGLE;				
                    if (asn->verbose) {
                        trlmessage 
                            ("Re-Processing a SINGLE image from ASN table...");
                    }
                } else {

                    /* ASN table given in file, PARTIALLY process
                     ** table */ 	
                    asn->process = PARTIAL;	
                    if (asn->verbose) {
                        trlmessage 
                            ("Re-Processing PART of ASN table...");
                    }
                }

            } else {

                /* Couldn't find specified file... */
                sprintf (MsgText,"File %s not found for re-processing",
                        filename);
                trlerror (MsgText);
                return (status = OPEN_FAILED);			
            }
            break;

        case 3:  /* We only have a rootname (with .fits extension)
                  ** specified */
        default:		

            if (exist == EXISTS_YES) {
                strcpy (asn->filename, filename);

                /* Look for ASN_TAB in file's header, and copy to
                 ** ASN->asn_table if it is found. */
                if (!GetAsnName (filename, asn->asn_table)) {

                    /* No ASN table listed, process as a SINGLE
                     ** exposure */
                    asn->process = SINGLE;				
                    if (asn->verbose) {
                        trlmessage 
                            ("Processing a SINGLE image from ASN table...");
                    }
                } else {

                    /* ASN table given in file, PARTIALLY process
                     ** table */ 	
                    asn->process = PARTIAL;	
                    if (asn->verbose) {
                        trlmessage ("Processing PART of ASN table...");
                    }
                }			

            } else {

                /* Let's start fresh, shall we?  At this point we only
                 ** have as rootname and (maybe) a .fits extension... 

                 in_dot = strcspn (filename, ".fit");
                 */	
                in_dot = strlen(filename) -
                    strlen(strstr (filename, ".fit"));

                if (asn->debug){
                    sprintf (MsgText, "For file %s, in_dot = %d",
                            filename, in_dot);
                    trlmessage (MsgText);
                }

                /* Truncate extension off of filename */
                filename[in_dot] = '\0';

                /* Create full ASN table name from input rootname */
                strcat (filename, "_asn.fits");
                exist = DoesFileExist (filename);

                if (exist == EXISTS_YES) {
                    strcat (filename, "\0");
                    /* If a name was specified, the file must exist. */
                    strcpy (asn->asn_table, filename);
                    if (asn->verbose) {
                        trlmessage 
                            ("Found and processing FULL ASN table...");
                    }
                    asn->process = FULL;
                } else {

                    /* Couldn't find ASN file, so
                     ** trim off suffix previously tested. */
                    in_dot = strlen (filename) - 
                        strlen (strstr(filename, "_asn")) ;
                    filename[in_dot] = '\0';

                    /* ... and look for RAW file */
                    strcat (filename, "_raw.fits");
                    exist = DoesFileExist (filename);

                    if (exist == EXISTS_YES) {

                        /* Found a RAW file;
                         ** Set values in ASN structure */
                        strcat (filename, "\0");
                        strcpy (asn->asn_table, filename);
                        if (asn->verbose) {
                            trlmessage 
                                ("Processing a SINGLE image from ASN table...");
                        }
                        asn->process = SINGLE;

                    } else {

                        /* Is INPUT the rootname of a product which
                         ** hasn't been created yet? */
                        /* Extract just the rootname plus last character
                         ** of rootname (which may be the subproduct ID*/
                        in_dot = strlen (filename) - 
                            strlen (strstr (filename, "_raw"));
                        filename[in_dot -1] = '\0';

                        /* Replace last character of filename with
                         ** 0_asn.fits	*/
                        strcat (filename, "0_asn.fits");
                        exist = DoesFileExist (filename);

                        if (exist == EXISTS_YES) {
                            strcpy (asn->asn_table, filename);
                            if (asn->verbose) {
                                trlmessage 
                                    ("PARTIAL processing of ASN table...");
                            }
                            asn->process = PARTIAL;
                        } else {
                            /* We can't find a matching file or ASN
                             ** table to process */
                            sprintf (MsgText,
                                    "File %s not found for processing",
                                    filename);
                            trlerror (MsgText);
                            return (status = OPEN_FAILED);
                        }
                    }
                }			
            } /* End of Exists ELSE statement for this case */

            break; /* End of Case 3 and DEFAULT case */
    } /* End of switch statement */

    if (asn->debug) {
        trlmessage 
            ("SetInput: Determined what ASN table to process and how.");
    }

    return (status);
} 
コード例 #4
0
ファイル: acsmember.c プロジェクト: jhunkeler/hstcal
/* GETASNMEMBER: Copy information from association table structure
**	to a single image structure for use by the remainder of the 
**	processing tasks.
*/
int GetAsnMember (AsnInfo *asn, int prodid, int posid, int expid, ACSInfo *acs) {

/* arguments:
AsnInfo *asn      	i: calibration flags and other info
int prodid			i: product id for exposure
int posid			i: sub-product id for exposure 
int expid			i: id of exposure within sub-product
ACSInfo *acs		o: exposure specific flags and info
*/
	extern int status;
	
	char rootname[CHAR_FNAME_LENGTH+1];
	char mtype[SZ_STRKWVAL+1];
    int mlen;
	void FindAsnRoot (const char *, char *);
    void UpperAll (char *, char *, int);
    
	/* find out if the member we want exists... */	
	if (asn->product[prodid].subprod[posid].exp[expid].name[0] == '\0') {
		sprintf(MsgText,"Couldn't find exposure %d of sub-product %d for product %d. ", expid, posid, prodid);
		trlerror (MsgText);
		return (status = NO_GOOD_DATA);
	}

	/* Initialize local strings... */
	rootname[0] = '\0';
    mtype[0] = '\0';

    const char * outroot = asn->product[prodid].subprod[posid].name;
	
	/* Make sure we are only passing a rootname, and not a full filename.*/
	FindAsnRoot (outroot, rootname);
	strcpy (acs->outroot, rootname);
					
	strcpy (acs->rootname, asn->product[prodid].subprod[posid].exp[expid].name);
	strcpy (acs->crj_root, asn->product[prodid].subprod[posid].spname);

	/* Make sure we are only passing a rootname, and not a full filename.*/
	FindAsnRoot (acs->rootname, rootname);
	strcpy (acs->rootname, rootname);
	
	if (asn->debug){
		sprintf (MsgText, "GetAsnMember: Rootname: %s, Output rootname: %s",rootname, outroot);
		trlmessage (MsgText);
	}
	/* Check to see that this value of rootname is what we really need... */
	strcpy (acs->asn_table, asn->asn_table);	
	strcpy (acs->rawfile, asn->product[prodid].subprod[posid].exp[expid].expname);
	
	/* Set sci_* flags for acs */	
	acs->sci_crcorr = asn->crcorr;
	acs->sci_dthcorr = asn->dthcorr;
	acs->sci_rptcorr = asn->rptcorr;
	acs->detector = asn->detector;
	acs->nimages = asn->spmems[posid];

    /* Set MemType appropriate for output */
    if (!strncmp (rootname, acs->asn_table, 8) ) {
        mlen = strlen(acs->mtype);
        UpperAll (acs->mtype, mtype, mlen);
        strcpy(mtype, asn->product[prodid].subprod[posid].mtype);
    }
    
	return (status);
}
コード例 #5
0
ファイル: acsrej_do.c プロジェクト: pllim/hstcal
/*  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);
}