Пример #1
0
int rej_init (IODescPtr ipsci[], IODescPtr ipdq[], clpar *par, int nimgs,
	      int dim_x, int dim_y, multiamp noise, multiamp gain, float efac[],
	      float skyval[], DataUnits bunit[], SingleGroup *sg, float *work) {

    extern int status;

    float  scale, val, raw, raw0, signal0;
    float  *buf;
    short  *bufdq;
    float  *exp2;
    int    i, j, n;
    int    dum;
    int    *npts, *ipts;
    float  noise2[NAMPS], rog2[NAMPS];
    float  gain2[NAMPS];
    float  nse[2], gn[2];
    int    ampx, ampy, detector, chip;
    int    k, p;
    short  dqpat;
    float  exp2n, expn;
    int    non_zero;
    Hdr    dqhdr;

    void ipiksrt (float [], int, int[]);
    void get_nsegn (int, int, int, int, float *, float*, float *, float *);

    /* -------------------------------- begin ------------------------------ */
    expn=0.0f;
    scale = par->scalense / 100.;
    ampx = gain.colx;
    ampy = gain.coly;
    detector = gain.detector;
    chip = gain.chip;
    dqpat = par->badinpdq;

    ipts = calloc (nimgs, sizeof(int));
    npts = calloc (dim_x, sizeof(int));
    buf = calloc (dim_x, sizeof(float));
    exp2 = (float *) calloc (nimgs, sizeof(float));
    bufdq = calloc (dim_x, sizeof(short));

    for (k = 0; k < NAMPS; k++) {
        gain2[k] = 0.;
        noise2[k] = 0.;
        /* Assumption: ALL images have the same noise/gain values */
        rog2[k] = SQ(noise.val[k]);
    }

    non_zero = 0;
    for (n = 0; n < nimgs; n++) {
        exp2[n] = SQ(efac[n]);
	if (efac[n] > 0.) non_zero++;
    }
    get_nsegn (detector, chip, ampx, ampy, gain.val, rog2, gain2, noise2); 

    /* Use the stack median to construct the initial average */
    if (strncmp(par->initgues, "median", 3) == 0) {
        for (j = 0; j < dim_y; j++) {
            memset (npts, 0, dim_x*sizeof(int));

            /* Set up the gain and noise values used for this line
	    ** in ALL images */
            if (j < ampy ) {
                gn[0] = gain2[AMP_C];
                gn[1] = gain2[AMP_D];
                nse[0] = noise2[AMP_C];
                nse[1] = noise2[AMP_D];
            } else {
                gn[0] = gain2[AMP_A];
                gn[1] = gain2[AMP_B];
                nse[0] = noise2[AMP_A];
                nse[1] = noise2[AMP_B];            
            }

            for (n = 0; n < nimgs; n++) {
                initHdr(&dqhdr);
                getHeader(ipdq[n],&dqhdr);
                getFloatLine (ipsci[n], j, buf);
                getShortLine (ipdq[n], j, bufdq);
                freeHdr(&dqhdr);

		/* Rescale SCI data, if necessary */
		if (bunit[n] == COUNTRATE) {
		    for (i = 0; i < dim_x; i++) {
			 buf[i] *= efac[n];
		    }
		}

                for (i = 0; i < dim_x; i++) {
		     if (efac[n] > 0.) {
                         /* Only use GOOD pixels to build initial image */
                         if ((bufdq[i] & dqpat) == OK) {
                             PIX(work,npts[i],i,nimgs) =
						(buf[i] - skyval[n]) / efac[n];
                             npts[i] += 1;
                         }
		     } else {
			 PIX(work,npts[i],i,nimgs) = 0.;
		     }
                }
            }
 
            for (i = 0; i < ampx; i++) {
                dum = npts[i];

                if (dum == 0)
                    Pix(sg->sci.data,i,j) = 0.0F;

                else {

		    /* Setup index array for sorting... */
		    for (p=0; p < nimgs; p++) ipts[p] = p;
		    /* Sort pixel stack and corresponding index array. */
                    ipiksrt (&PIX(work,0,i,nimgs), dum, ipts);

		    /* Use sorted index array to match proper exptimes to
		       selected pixels for use in ERR array calculation. */
                    if ((dum/2)*2 == dum) {
                        /* Even number of input images for this pixel */
                        Pix(sg->sci.data,i,j) = (PIX(work,dum/2-1,i,nimgs) +
						 PIX(work,dum/2,i,nimgs)) / 2.;
			expn = (exp2[ipts[dum/2-1]] + exp2[ipts[dum/2]]) / 2.;
                    } else {
			/* Odd number of input images for this pixel */
                        Pix(sg->sci.data,i,j) = PIX(work,dum/2,i,nimgs);
			expn = exp2[ipts[dum/2]];
		    }
                }
                
                raw0 = Pix(sg->sci.data,i,j);
		exp2n = (expn > 0.) ? expn : 1.;
                Pix(sg->err.data,i,j) = (nse[0]+ raw0/gn[0] + SQ(scale*raw0)) /
					exp2n;
            } /* End loop over FIRST AMP used on pixels in the line */
             
            for (i = ampx; i < dim_x; i++) {
                dum = npts[i];
                if (dum == 0)
                    Pix(sg->sci.data,i,j) = 0.0F;
                else {
		    for (p=0; p < nimgs; p++) ipts[p] = p;
                    ipiksrt (&PIX(work,0,i,nimgs), dum, ipts);
                    if ((dum/2)*2 == dum) {
                        /* Even number of input images for this pixel */
                        Pix(sg->sci.data,i,j) = (PIX(work,dum/2-1,i,nimgs) +
						 PIX(work,dum/2,i,nimgs)) / 2.;
			expn = (exp2[ipts[dum/2-1]] + exp2[ipts[dum/2]]) / 2.;
                    } else {
                        Pix(sg->sci.data,i,j) = PIX(work,dum/2,i,nimgs);
			expn = exp2[ipts[dum/2]];
		    }
                }
                
                raw0 = Pix(sg->sci.data,i,j);
		exp2n = (expn > 0.) ? expn : 1.;
                Pix(sg->err.data,i,j) = (nse[1]+ raw0/gn[1] + SQ(scale*raw0)) /
					exp2n;
            } /* End loop over SECOND AMP used on pixels in the line */
        } /* End loop over lines */

    } else {

        /* use the minimum to construct the initial average */
        if (strncmp(par->initgues, "minimum", 3) != 0) {
            sprintf (MsgText,"Invalid INITGUES value %s, reset it to 'minimum'",
		     par->initgues);
            trlwarn (MsgText);
            strcpy (par->initgues, "minimum");
        }

        for (n = 0; n < nimgs; n++) {
            initHdr(&dqhdr);
            getHeader(ipdq[n],&dqhdr);
            for (j = 0; j < dim_y; j++) { 
                /* Set up the gain and noise values used for this line
		** in ALL images */
                if (j < ampy ) {
                    gn[0] = gain2[AMP_C];
                    gn[1] = gain2[AMP_D];
                    nse[0] = noise2[AMP_C];
                    nse[1] = noise2[AMP_D];
                } else {
                    gn[0] = gain2[AMP_A];
                    gn[1] = gain2[AMP_B];
                    nse[0] = noise2[AMP_A];
                    nse[1] = noise2[AMP_B];            
                }

                getFloatLine (ipsci[n], j, buf);
		getShortLine (ipdq[n],  j, bufdq);

		/* Rescale SCI data, if necessary */
		if (bunit[n] == COUNTRATE) {
		    for (i = 0; i < dim_x; i++) {
			 buf[i] *= efac[n];
		    }
		}

                /* AMPS C and D */
                for (i = 0; i < ampx; i++) {
                    raw = buf[i];
                    raw0 = (raw > 0.)? raw : 0.;
		    signal0 = ((raw - skyval[n]) > 0.) ? (raw - skyval[n]) : 0.;

		    if (efac[n] > 0.) {
                        val = (raw - skyval[n]) / efac[n];
		    } else {
			val = 0.;
		    }
                    if ((n == 0) || (val < Pix(sg->sci.data,i,j)) ) {
			if ((bufdq[i] & dqpat) == OK && (efac[n] > 0.)) {
                             Pix(sg->sci.data,i,j) = val;
                             /*Pix(sg->err.data,i,j) =
			      (nse[0]+ raw0/gn[0] + SQ(scale*raw0)) / exp2[n];*/
			     Pix(sg->err.data,i,j) =
			    (nse[0] + raw0/gn[0] + SQ(scale*signal0)) / exp2[n];
			} else {
			     Pix(sg->sci.data,i,j) = 0.;
			     Pix(sg->err.data,i,j) = 0.;
			}
                    } 
                } /* End of loop over FIRST AMP for this line in each image */

                for (i = ampx; i < dim_x; i++) {
                    raw = buf[i];
                    raw0 = (raw > 0.)? raw : 0.;
		    signal0 = ((raw - skyval[n]) > 0.) ? (raw - skyval[n]) : 0.;

		    if (efac[n] > 0.) {
                        val = (raw - skyval[n]) / efac[n];
		    } else {
			val = 0.;
		    }
                    if ((n == 0) ||
		       (val<Pix(sg->sci.data,i,j) && ((bufdq[i]&dqpat)==OK))) {
                        Pix(sg->sci.data,i,j) = val;
			if (efac[n] > 0.) {
                            Pix(sg->err.data,i,j) = 
			     (nse[1]+ raw0/gn[1] + SQ(scale*signal0)) / exp2[n];
			} else {
			    Pix(sg->err.data,i,j) = 0.;
			}
                    } 
                } /* End of loop over SECOND AMP for this line in each image */

            } /* End of loop over lines in image (y) */
            freeHdr(&dqhdr);
        } /* End of loop over images in set */
    }

    /* free the memory */
    free (ipts);
    free (npts);
    free (buf);
    free (exp2);
    free (bufdq);

    return (status);
}
Пример #2
0
int doDark (WF3Info *wf32d, SingleGroup *x, float *meandark) {

/* arguments:
WF3Info *wf3       i: calibration switches, etc
SingleGroup *x    io: image to be calibrated; written to in-place
float *meandark	   o: mean of dark image values subtracted
*/

    extern int status;

    SingleGroupLine y, z;	/* y and z are scratch space */
    int extver = 1;		/* get this imset from dark image */
    int rx, ry;			/* for binning dark down to size of x */
    int x0, y0;			/* offsets of sci image */
    int same_size;		/* true if no binning of ref image required */
    int avg = 0;		/* bin2d should sum values within each bin */
    int scilines; 		/* number of lines in science image */
    int i, j;
    float mean, dark;
    float weight, wdark;    	/* weights for line averages */
    int update;
    float gain[NAMPS];
    float rn2[NAMPS];       	/* only need this to call get_nsegn */

    int FindLine (SingleGroup *, SingleGroupLine *, int *, int *, int *,
		  int *, int *);
    int sub1d (SingleGroup *, int, SingleGroupLine *);
    int trim1d (SingleGroupLine *, int, int, int, int, int, SingleGroupLine *);
    int DetCCDChip (char *, int, int, int *);
    void get_nsegn (int, int, int, int, float *, float*, float *, float *);
    void AvgSciValLine (SingleGroupLine *, short, float *, float *);
    void multgn1d (SingleGroupLine *, int, int, int, float *, float);


	initSingleGroupLine (&y);
	
	scilines = x->sci.data.ny;

	/* Compute correct extension version number to extract from
	   reference image to correspond to CHIP in science data.  */
	if (DetCCDChip(wf32d->dark.name, wf32d->chip, wf32d->nimsets, &extver))
	    return (status);	
	
	if (wf32d->verbose) {
	    sprintf (MsgText,
		     "Performing dark subtraction on chip %d in imset %d",
		     wf32d->chip, extver);
	    trlmessage(MsgText);
	}

	/* Get the dark image data. */
	openSingleGroupLine (wf32d->dark.name, extver, &y);
	if (hstio_err())
	    return (status = OPEN_FAILED);

	/* Compare binning of science image and reference image;
	   get same_size flag, and get info about binning and offset
	   for use by bin2d.
	*/
	if (FindLine (x, &y, &same_size, &rx, &ry, &x0, &y0))
	    return (status);
    
	/* Return with error if reference data not binned same as input */
	if (rx != 1 || ry != 1) {
	    closeSingleGroupLine (&y);
	    freeSingleGroupLine (&y);
	    sprintf (MsgText,
	    "DARK image and input are not binned to the same pixel size!");
	    trlerror(MsgText);
	    return (status = SIZE_MISMATCH);
	}
	if (wf32d->verbose){
	    sprintf(MsgText,"Image has an offset of %d,%d",x0,y0);
	    trlmessage(MsgText);
	}

	mean = 0.0;
	weight = 0.0;
    
	/* Multiply the dark image by the exposure time and divide by the
	   atodgain (or just by exposure time for the MAMAs), and
	   subtract it from x.
	*/
    
	for (i = 0; i < NAMPS; i++) {
	     gain[i] = 0.;
	     rn2[i] = 0.;
	}
	get_nsegn (wf32d->detector, wf32d->chip, wf32d->ampx, wf32d->ampy,
		   wf32d->atodgain, wf32d->readnoise, gain, rn2);

	initSingleGroupLine (&z);
	allocSingleGroupLine (&z, x->sci.data.nx);
	for (i=0, j=y0; i < scilines; i++,j++) { 

	     /* We are working with a sub-array and need to apply the
		proper section from the reference image to the science image.
	     */
	     getSingleGroupLine (wf32d->dark.name, j, &y);

             update = NO;

	     if (trim1d (&y, x0, y0, rx, avg, update, &z)) {
		 trlerror ("(darkcorr) size mismatch.");
		 return (status);
	     }

	     multgn1d(&z, j, wf32d->ampx, wf32d->ampy, gain, wf32d->exptime[0]);

	     AvgSciValLine (&z, wf32d->sdqflags, &dark, &wdark);

	     /* Sum the contribution from each line */			
	     mean += dark * wdark;
	     weight += wdark;

	     status = sub1d (x, i, &z);
	     if (status)
		 return (status);
	}
	freeSingleGroupLine (&z);			/* done with z */

	closeSingleGroupLine (&y);
	freeSingleGroupLine (&y);

	/* Compute the mean for the entire image */	
	if (scilines > 0) 
	    *meandark = mean / weight; 
	else 
	    *meandark = 0.;
	
	return (status);
}
Пример #3
0
int to_electrons(ACSInfo *acs, SingleGroup *x) {

  /* arguments:
   ACSInfo *acs    i: calibration switches and info
   SingleGroup *x   io: image to be calibrated; written to in-place
   int *done         o: true if we actually did assign error array values
   */

	extern int status;

	float rn[NAMPS];
  float gain[NAMPS];		    /* gain values for observation */
	int i, j;
	int ampx;		/* border column for 2amp readout regions */
	int ampy;		/* Boundary values corrected for trim regions */
  int dimx, dimy;
  int offsetx, offsety;

  void get_nsegn (int, int, int, int, float *, float*, float *, float *);


  offsetx = (int)(acs->offsetx > 0) ? acs->offsetx : 0;
  offsety = (int)(acs->offsety > 0) ? acs->offsety : 0;
  
  dimx = x->sci.data.nx;
  dimy = x->sci.data.ny;

  /* Correct the AMP readout boundaries for this offset */
  ampx = ((acs->ampx == 0) ? 0 : (int)(acs->ampx + offsetx) );
  ampy = ((acs->ampy == 0) ? 0 : (int)(acs->ampy + offsety) );

  /* Bounds checking to make sure we don't try to apply gain
   and noise outside the bounds of the image.
   This would apply if using only 1 AMP on each WFC chip when
   ampx is given in CCDTAB as something greater image size.
   WJH 8 Sept 2000

   We need to make sure that if the ampx value extends into the
   overscan at the end of the line, ampx gets automatically
   moved to cover the whole line. This allows all AMPX and AMPY
   values to be specified in CCDTAB in trimmed coordinates.
   WJH 27 Oct 2000
   */
  if (ampx >= (dimx - acs->offsetx) || ampx > dimx ) ampx = dimx;
  if (ampy >= (dimy - acs->offsety) || ampy > dimy ) ampy = dimy;

  /* Set up gain and readnoise arrays for use with chip's data */
  for (i=0; i < NAMPS; i++) {
    gain[i] = 0.;
    rn[i] = 0.;
  }
  
  get_nsegn(acs->detector, acs->chip, acs->ampx, acs->ampy, acs->atodgain, 
            acs->readnoise, gain, rn);
  
  /* Now apply the initilalization for each AMP used */
  for (j = 0; j < ampy; j++) {

    /*
     This region corresponds to AMP_C,
     if it is even used for this observation.
     */

    /* Let's make sure we actually found a value for the gain
     */
    if (ampx > 0 && gain[AMP_C] == 0.){
      trlerror ("No valid GAIN value to convert data.");
      return (status = ERROR_RETURN);
    }

    for (i = 0;  i < ampx;  i++) {
      /* convert to electrons */
      Pix(x->sci.data, i, j) = Pix(x->sci.data, i, j) * gain[AMP_C];
      Pix(x->err.data, i, j) = Pix(x->err.data, i, j) * gain[AMP_C];
    }

    /*
     This region corresponds to AMP_D,
     if it is even used for this observation.
     */

    /* Let's make sure we actually found a value for the gain
     **	and readnoise...
     */
    if (ampx == 0 && gain[AMP_D] == 0.){
      trlerror ("No valid GAIN value to convert data.");
      return (status = ERROR_RETURN);
    }

    for (i = ampx;  i < dimx;  i++) {
      /* convert to electrons */
      Pix(x->sci.data, i, j) = Pix(x->sci.data, i, j) * gain[AMP_D];
      Pix(x->err.data, i, j) = Pix(x->err.data, i, j) * gain[AMP_D];
    }
  }

  for (j = ampy; j < dimy; j++) {
    /*
     This region corresponds to AMP_A,
     if it is even used for this observation.
     */
    /* Let's make sure we actually found a value for the gain
     **	and readnoise...
     */
    if (ampx > 0 && gain[AMP_A] == 0.) {
      trlerror ("No valid GAIN value to convert data.");
      return (status = ERROR_RETURN);
    }

    /* Only execute this loop for AMP > 0 (multi-amp for line) */
    for (i = 0;  i < ampx;  i++) {
      /* convert to electrons */
      Pix(x->sci.data, i, j) = Pix(x->sci.data, i, j) * gain[AMP_A];
      Pix(x->err.data, i, j) = Pix(x->err.data, i, j) * gain[AMP_A];
    }

    /*
     This region corresponds to AMP_B,
     if it is even used for this observation.

     Default 1-AMP loop. AMPX and AMPY are zero.
     */
    /* Let's make sure we actually found a value for the gain
     **	and readnoise...
     */
    if (ampx == 0 && gain[AMP_B] == 0.){
      trlerror ("No valid GAIN value to convert data.");
      return (status = ERROR_RETURN);
    }

    for (i = ampx;  i < dimx;  i++) {
      /* convert to electrons */
      Pix(x->sci.data, i, j) = Pix(x->sci.data, i, j) * gain[AMP_B];
      Pix(x->err.data, i, j) = Pix(x->err.data, i, j) * gain[AMP_B];
    }
  }
  
	return (status);
}
Пример #4
0
int doNoise (WF3Info *wf3, SingleGroup *x, int *done) {

/* arguments:
WF3Info *wf3	 i: calibration switches and info
SingleGroup *x	io: image to be calibrated; written to in-place
int *done        o: true if we actually did assign error array values
*/

	extern int status;

	float bias;		/* bias level to subtract (dn) */
	float rn2[NAMPS];       /* square of noise values for observation */
	float gain[NAMPS];	/* gain values for observation */
	float value;		/* dn - bias * gain (i.e. signal in el) */
	int i, j;
	int ampx;		/* border column for 2amp readout regions */
	int ampy;		/* Boundary values corrected for trim regions */
	int dimx, dimy;
	int offsetx, offsety;
	float ccdbias[NAMPS];	/* default ccdbias values for chip */

	void get_nsegn (int, int, int, int, float *, float*, float *, float *);

	*done = 0;				/* initial value */
	
	/* First check for a dummy error array.  If it's not dummy,
	** we just return without doing anything.  */
	dimx = x->err.data.nx;
	dimy = x->err.data.ny;
	for (j = 0;  j < dimy;  j++) {
	    for (i = 0;  i < dimx;  i++) {
		    if (Pix (x->err.data, i, j) != 0.) {
		        return (status);	/* not a dummy error array */
		    }
	    }
	}

    if (wf3->detector != IR_DETECTOR) { 

        /* CCD initialization */
        offsetx = (int)(wf3->offsetx > 0) ? wf3->offsetx : 0;
        offsety = (int)(wf3->offsety > 0) ? wf3->offsety : 0;

	/* Correct the AMP readout boundaries for this offset */
	ampx = ((wf3->ampx == 0) ? 0 : (int)(wf3->ampx + offsetx) );
	ampy = ((wf3->ampy == 0) ? 0 : (int)(wf3->ampy + offsety) );
	ampx += wf3->trimx[2];

	/* Bounds checking to make sure we don't try to apply gain
	** and noise outside the bounds of the image.
	** This would apply if using only 1 AMP on each WFC chip when
	** ampx is given in CCDTAB as something greater than the
	** image size.
	** WJH 8 Sept 2000 (HAB 8 May 2001)
	**
	** We need to make sure that if the ampx value extends into the
	** overscan at the end of the line, ampx gets automatically 
	** moved to cover the whole line. This allows all AMPX and AMPY
	** values to be specified in CCDTAB in trimmed coordinates.
	** WJH 27 Oct 2000 (HAB 8 May 2001)
	*/

	/*if (ampx >= (dimx - wf3->offsetx) || ampx > dimx ) ampx = dimx;*/
	if (ampx >= (dimx - wf3->trimx[1]) || ampx > dimx ) ampx = dimx;
	if (ampy >= (dimy - wf3->offsety) || ampy > dimy ) ampy = dimy;

        /* Set up gain and readnoise arrays for use with chip's data */
        for (i=0; i < NAMPS; i++) {
            gain[i] = 0.;
            rn2[i] = 0.;
        }
        get_nsegn (wf3->detector, wf3->chip, wf3->ampx, wf3->ampy,
		   wf3->atodgain, wf3->readnoise, gain, rn2);

	/* For WFC3 UVIS data, AMPY will always be zero, yet we still need
	** to select the correct ccdbias value to apply. Determine
	** that here. */
	if (wf3->detector == CCD_DETECTOR && wf3->chip == 2) {
	    ccdbias[0] = wf3->ccdbias[2];
	    ccdbias[1] = wf3->ccdbias[3];
	    ccdbias[2] = wf3->ccdbias[2];
	    ccdbias[3] = wf3->ccdbias[3];
	} else {
	    for (i=0; i < NAMPS; i++) ccdbias[i] = wf3->ccdbias[i];
	}

        /* Now square the readnoise */
        for (i = 0; i < NAMPS; i++)
	     rn2[i] = rn2[i] * rn2[i];
        
	if (wf3->ncombine > 1) {
	    trlwarn("NCOMBINE > 1 before the error array was initialized.");
	}

        /* Now apply the initilalization for each AMP used */
        for (j = 0; j < ampy; j++) {
        
            /* This region corresponds to AMP_C, 
                if it is even used for this observation. */
	    /* Let's make sure we actually found a value for the gain
	    **	and readnoise... */

	    if (ampx > 0 && (gain[AMP_C] == 0. || rn2[AMP_C] == 0.)) { 
                trlerror 
		  ("No valid GAIN or READNOISE values to initialize ERR data."); 
		return (status = ERROR_RETURN);
            }
	    bias = ccdbias[2];
	    for (i = 0;  i < ampx;  i++) {
	        /* subtract bias and convert to electrons */
	        value = (Pix (x->sci.data, i, j) - bias) * gain[AMP_C];
	        if (value < 0.)
		    value = 0.;			/* sigma = 0 if signal = 0 */
		/* include readout noise and convert back to dn */
		Pix (x->err.data,i,j) = sqrt(value + rn2[AMP_C]) / gain[AMP_C];

            }

            /* This region corresponds to AMP_D, 
            **  if it is even used for this observation.  */

	    /* Let's make sure we actually found a value for the gain
	    **	and readnoise...  */
	    if (ampx == 0 && (gain[AMP_D] == 0. || rn2[AMP_D] == 0.) ) {
                trlerror 
		  ("No valid GAIN or READNOISE values to initialize ERR data.");
		return (status = ERROR_RETURN);
            }
	    bias = ccdbias[3];
	    for (i = ampx;  i < dimx;  i++) {
		 /* subtract bias and convert to electrons */
		 value = (Pix (x->sci.data, i, j) - bias) * gain[AMP_D];
		 if (value < 0.)
		     value = 0.;		/* sigma = 0 if signal = 0 */
		 /* include readout noise and convert back to dn */
		 Pix (x->err.data,i,j) = sqrt(value + rn2[AMP_D]) / gain[AMP_D];
	    }
        }
        
        
        for (j = ampy; j < dimy; j++) {

            /* This region corresponds to AMP_A, 
            **  if it is even used for this observation.  */

	    /* Let's make sure we actually found a value for the gain
	    **	and readnoise...  */
	    if (ampx > 0 && (gain[AMP_A] == 0. || rn2[AMP_A] == 0.)) {
                trlerror 
		  ("No valid GAIN or READNOISE values to initialize ERR data.");
		return (status = ERROR_RETURN);
            }
	    bias = ccdbias[0];
            /* Only execute this loop for AMP > 0 (multi-amp for line) */
	    for (i = 0;  i < ampx;  i++) {
		 /* subtract bias and convert to electrons */
		 value = (Pix (x->sci.data, i, j) - bias) * gain[AMP_A];
		 if (value < 0.)
		     value = 0.;		/* sigma = 0 if signal = 0 */
		 /* include readout noise and convert back to dn */
		 Pix (x->err.data,i,j) = sqrt(value + rn2[AMP_A]) / gain[AMP_A];
            }

            /* This region corresponds to AMP_B, 
            ** if it is even used for this observation.
            **  
            **  Default 1-AMP loop. AMPX and AMPY are zero.  */

            /* Let's make sure we actually found a value for the gain
            **	and readnoise...  */
            if (ampx == 0 && (gain[AMP_B] == 0. || rn2[AMP_B] == 0.)) {
                trlerror 
		  ("No valid GAIN or READNOISE values to initialize ERR data.");
	        return (status = ERROR_RETURN);
            }
	    bias = ccdbias[1];
	    for (i = ampx;  i < dimx;  i++) {
 
		 /* subtract bias and convert to electrons */
		 value = (Pix (x->sci.data, i, j) - bias) * gain[AMP_B];
		 if (value < 0.)
		     value = 0.;		/* sigma = 0 if signal = 0 */
		 /* include readout noise and convert back to dn */
		 Pix (x->err.data,i,j) = sqrt(value + rn2[AMP_B]) / gain[AMP_B];
	    }
        }

       /* End of CCD initialization */

    } else {

        /* ACS MAMA initialization */
        /* Set error to max of 1 or sqrt(counts) */
        for (j = 0; j < dimy; j++) {
            for (i = 0; i < dimx; i++) {
                value = sqrt(Pix(x->sci.data, i, j));
                Pix (x->err.data, i, j) = (value > 1) ? value : 1;
            }
        }
    }

    *done = 1;
    return (status);

}