Пример #1
0
void Interp2D (SingleGroup *in, short sdqflags,
	double ix, double iy, double jacobian,
	int err_algorithm,
	float *oSci, float *oErr, short *oDQ) {

/* arguments:
SingleGroup *in   i: input data
short sdqflags    i: which data quality flags are serious
double ix, iy     i: pixel location in input
double jacobian   i: factor for conserving flux
float *oSci       o: interpolated value in science array
float *oErr       o: interpolated error value
short *oDQ        o: interpolated data quality value
*/

	float p, q, r, s;	/* 1-D weights */
	float w0, w1, w2, w3;	/* weight for each pixel */
	float e0, e1, e2, e3;	/* error * weight for each pixel */
	float sumw;		/* sum of weights */
	float value;		/* interpolated value (sci or err) */
	int inx, iny;		/* size of input image */
	int ii, ij;		/* a pixel location in input */
	int iix, iiy; 		/* nearest integers to ix & iy */
	int ngood;		/* number of neighbors (1-4) flagged as good */

	inx = in->sci.data.nx;
	iny = in->sci.data.ny;

	/* Round off to nearest integer, and check for out of bounds. */
	iix = NINT(ix);
	iiy = NINT(iy);
	if (iix < 0 || iix > inx-1 ||
	    iiy < 0 || iiy > iny-1) {
	    /* The current point is outside the input image. */
	    *oSci = 0.;			/* harmless values */
	    *oErr = 0.;
	    *oDQ = DETECTORPROB;
	    return;
	}

	/* Use bilinear interpolation on the four pixels centered
	   near (ix,iy).  These pixels are:
		[ii, ij+1]  [ii+1, ij+1]
		[ii, ij  ]  [ii+1, ij  ]
	*/

	ii = (int)ix;
	if (ii < 0)
	    ii = 0;
	if (ii > inx-2)
	    ii = inx-2;
	q = ix - ii;		/* weights for X direction */
	p = 1.0F - q;

	ij = (int)iy;
	if (ij < 0)
	    ij = 0;
	if (ij > iny-2)
	    ij = iny-2;
	s = iy - ij;		/* weights for Y direction */
	r = 1.0F - s;

	/* Assign a weight for each of the four pixels. */

	ngood = 0;
	if (DQPix (in->dq.data, ii, ij) & sdqflags) {
	    w0 = 0.0F;
	} else {
	    w0 = p * r;		/* lower left pixel */
	    ngood++;
	}
	if (DQPix (in->dq.data, ii+1, ij) & sdqflags) {
	    w1 = 0.0F;
	} else {
	    w1 = q * r;		/* lower right pixel */
	    ngood++;
	}
	if (DQPix (in->dq.data, ii, ij+1) & sdqflags) {
	    w2 = 0.0F;
	} else {
	    w2 = p * s;		/* upper left pixel */
	    ngood++;
	}
	if (DQPix (in->dq.data, ii+1, ij+1) & sdqflags) {
	    w3 = 0.0F;
	} else {
	    w3 = q * s;		/* upper right pixel */
	    ngood++;
	}

	sumw = w0 + w1 + w2 + w3;

	if (ngood == 0 || sumw <= 0.) {

	    /* All four are bad, or the sum of weights is zero,
		so just copy values from the nearest pixel.
	    */
	    *oSci = Pix (in->sci.data, iix, iiy) * jacobian;
	    *oErr = Pix (in->err.data, iix, iiy) * sqrt (jacobian);

	} else {

	    if (ngood < 4) {
		/* Normalize the weights so their sum is one. */
		w0 /= sumw;
		w1 /= sumw;
		w2 /= sumw;
		w3 /= sumw;
	    }

	    /* Interpolate. */

	    value = w0 * Pix (in->sci.data, ii, ij) +
		    w1 * Pix (in->sci.data, ii+1, ij) +
		    w2 * Pix (in->sci.data, ii, ij+1) +
		    w3 * Pix (in->sci.data, ii+1, ij+1);
	    *oSci = jacobian * value;

	    e0 = Pix (in->err.data, ii, ij);
	    e1 = Pix (in->err.data, ii+1, ij);
	    e2 = Pix (in->err.data, ii, ij+1);
	    e3 = Pix (in->err.data, ii+1, ij+1);
	    if (err_algorithm == WGT_VARIANCE) {
		value = (w0 * e0 * e0) + (w1 * e1 * e1) +
		        (w2 * e2 * e2) + (w3 * e3 * e3);
	    } else if (err_algorithm == WGT_ERROR) {
		value = (w0 * w0 * e0 * e0) + (w1 * w1 * e1 * e1) +
		        (w2 * w2 * e2 * e2) + (w3 * w3 * e3 * e3);
	    } else {
		value = -1.;	/* cannot happen */
	    }
	    if (jacobian * value > 0.)
		*oErr = sqrt (jacobian * value);
	    else
		*oErr = 0.;
	}

	*oDQ = DQPix (in->dq.data, ii, ij) |
	       DQPix (in->dq.data, ii+1, ij) |
	       DQPix (in->dq.data, ii, ij+1) |
	       DQPix (in->dq.data, ii+1, ij+1);
}
Пример #2
0
int SinkDetect(WF3Info *wf3, SingleGroup *x){

    extern int status;
    int i,j, jj;
    short dqval=0;
    float scipix; /*to save the value of the science pixel*/
    float refdate=50000.;
    int keep_going=1;
    
    sprintf(MsgText,"\nPerforming SINK pixel detection for imset %i",x->group_num);
    trlmessage(MsgText);
    

    /*THE SCIENCE IMAGE*/
    SingleGroup raz; /*quad rotated image to work with*/    

    /* INIT THE SCIENCE INPUT  */
    initSingleGroup (&raz);
    allocSingleGroup (&raz,RAZ_COLS/2, RAZ_ROWS);
        
    /*CONVERT DQ DATA TO RAZ FORMAT FOR SCIENCE FILE*/
    makedqRAZ(x, &raz);
    makeSciSingleRAZ(x, &raz);

	/* GET THE SINK FILE REFERENCE IMAGE FROM SINKFILE AND INITIALIZE */
    FloatHdrData sinkref;
    initFloatHdrData(&sinkref);
    getFloatHD(wf3->sink.name,"SCI",x->group_num,&sinkref);
                 
    /*NOW TURN THE SINK REFERENCE IMAGES INTO RAZ FORMAT*/
    FloatTwoDArray sinkraz;    
    initFloatData(&sinkraz); /*float 2d arrays*/
    allocFloatData(&sinkraz,RAZ_COLS/2, RAZ_ROWS);     

    makeFloatRaz(&sinkref.data,&sinkraz,x->group_num);

       
    /*THE MJD OF THE SCIENCE EXPOSURE IS THE COMPARISON DATE
     THE FOLLOWING TRANSLATION TAKEN FROM ISR WFC3-2014-22.PDF */
    
    scipix=0.;
    for (i=0;i<(RAZ_COLS/2);i++){
        for (j=0; j<RAZ_ROWS; j++){
        
            if (  (PPix(&sinkraz,i,j) > refdate)  &&  ( wf3->expstart > PPix(&sinkraz,i,j))  ){
                keep_going=1;
                
                /*FLAG THE PRIMARY SINK PIXEL*/
                dqval = TRAP | DQPix (raz.dq.data, i, j);
                DQSetPix (raz.dq.data, i, j, dqval);
                scipix = Pix(raz.sci.data,i,j);
                
                /*FLAG THE DOWNSTREAM PIXEL*/
                if (PPix(&sinkraz,i,j-1) < 0 ){
                    dqval = TRAP | DQPix (raz.dq.data, i, j-1);
                    DQSetPix (raz.dq.data, i, j-1, dqval);
                }

                /*FLAG THE UPSTREAM PIXELS*/
                for (jj=j+1; jj<RAZ_ROWS; jj++){
                    if ((int) PPix(&sinkraz,i,jj) == 0)
                        keep_going=0;
                    if ( PPix(&sinkraz,i,jj) > refdate)
                        keep_going=0;
                    if ( 0. < PPix(&sinkraz,i,jj) &&  PPix(&sinkraz,i,jj) < 1000. && keep_going){
                        if (scipix <= PPix(&sinkraz,i,jj) ){
                           dqval = TRAP | DQPix (raz.dq.data, i, jj);
                           DQSetPix (raz.dq.data, i, jj, dqval);
                        }                
                    } else {
                        keep_going=0;
                    }
                }                
            } /*end if*/ 
        } /*end j*/
    }/*end i*/   

    
    /*format the dq data back to expected orientation*/
    undodqRAZ(x,&raz);

    freeSingleGroup(&raz);
    freeFloatData(&sinkraz);
    freeFloatHdrData(&sinkref);
    trlmessage("Sink pixel flagging complete");
    return(status);
}
Пример #3
0
int RebinData (SingleGroup *iim, SingleGroup *oim, RowContents **ix1d,
               RowContents **ox1d , int rebinfactor, int nrows) {


/* arguments
SingleGroup *iim;		i: input image
SingleGroup *oim;		o: output image
RowContents **ix1d;		i: input array with table data.
RowContents **ox1d;		o: output array with table data.
int rebinfactor;		i: rebinning factor
int nrows;			i: number of rows
*/
	int i, j, i2, j2, rf;
	double hold;

	/* Alloc memory in output x1d array. */

	rf = (rebinfactor > 0) ? rebinfactor : -rebinfactor;
	for (j = 0; j < nrows; j++) {
	    ox1d[j]->sporder = ix1d[j]->sporder;
	    ox1d[j]->npts    = ix1d[j]->npts / rf;
	    ox1d[j]->wave     = (double *) calloc (ox1d[j]->npts,
                                                  sizeof(double));
	    ox1d[j]->gross    = (float *) calloc (ox1d[j]->npts,
                                                  sizeof(float));
	    ox1d[j]->net      = (float *) calloc (ox1d[j]->npts,
                                                  sizeof(float));
	    ox1d[j]->extrlocy = (float *) calloc (ox1d[j]->npts,
                                                 sizeof(float));
	    if (ox1d[j]->wave == NULL || ox1d[j]->gross    == NULL ||
                ox1d[j]->net  == NULL || ox1d[j]->extrlocy == NULL) {
                printf ("Not enough memory to allocate data arrays.\n");
	        return (OUT_OF_MEMORY);
	    }
	}

	switch (rebinfactor) {

	case 1:

	    /* Just copy. */

	    for (j = 0; j < iim->sci.data.ny; j++) {
	        for (i = 0; i < iim->sci.data.nx; i++) {
	            Pix (oim->sci.data, j, i)   = Pix (iim->sci.data, j, i);
	            Pix (oim->err.data, j, i)   = Pix (iim->err.data, j, i);
	            DQPix (oim->dq.data, j, i)  = DQPix (iim->dq.data, j, i);
	        }
	    }
	    for (j = 0; j < nrows; j++) {
	        for (i = 0; i < iim->sci.data.nx; i++) {
	            ox1d[j]->wave[i] = ix1d[j]->wave[i];
	            ox1d[j]->gross[i] = ix1d[j]->gross[i];
	            ox1d[j]->net[i] = ix1d[j]->net[i];
	            ox1d[j]->extrlocy[i] = ix1d[j]->extrlocy[i];
	        }
	    }
	    return (STIS_OK);

	case 2:

	    /* Squeeze by a factor 2. Only the SCI data is processed since
               the algorithm doesn't propagate ERR and DQ info anyway.
            */
	    for (j = 0; j < oim->sci.data.ny-1; j++) {
	        j2 = 2 * j;
	        for (i = 0; i < oim->sci.data.nx-1; i++) {
	            i2 = 2 * i;
	            Pix (oim->sci.data, j, i) = (Pix (iim->sci.data, j2, i2) +
                        Pix (iim->sci.data, j2, i2+1) +
                        Pix (iim->sci.data, j2+1, i2) +
                        Pix (iim->sci.data, j2+1, i2+1)) / 4.0;
	        }
	    }

	    for (j = 0; j < nrows; j++) {
	        for (i = 0; i < oim->sci.data.nx-1; i++) {
	            i2 = 2 * i;
	            ox1d[j]->wave[i]     = (ix1d[j]->wave[i2] +
                                            ix1d[j]->wave[i2+1]) / 2.0 ;
	            ox1d[j]->gross[i]    = (ix1d[j]->gross[i2] +
                                            ix1d[j]->gross[i2+1]) / 2.0 ;
	            ox1d[j]->net[i]      = (ix1d[j]->net[i2] +
                                            ix1d[j]->net[i2+1]) / 2.0 ;
	            ox1d[j]->extrlocy[i] = (ix1d[j]->extrlocy[i2] +
                                            ix1d[j]->extrlocy[i2+1]) / 2.0 ;
	            ox1d[j]->extrlocy[i] /= (double)rebinfactor;
	        }
	        ox1d[j]->wave[oim->sci.data.nx-1] =
                    ox1d[j]->wave[oim->sci.data.nx-2];
	        ox1d[j]->gross[oim->sci.data.nx-1] =
                    ox1d[j]->gross[oim->sci.data.nx-2];
	        ox1d[j]->net[oim->sci.data.nx-1] =
                    ox1d[j]->net[oim->sci.data.nx-2];
	        ox1d[j]->extrlocy[oim->sci.data.nx-1] =
                    ox1d[j]->extrlocy[oim->sci.data.nx-2];
	    }

	    return (STIS_OK);

	case -2:

	    /* Expand by a factor 2. Only the SCI data is processed since
               the algorithm doesn't propagate ERR and DQ info anyway. It
               is assumed that the output image already stores this info.
            */
	    for (j = 0; j < iim->sci.data.ny; j++) {
	        j2 = 2 * j;
	        for (i = 0; i < iim->sci.data.nx; i++) {
	            i2 = 2 * i;
	            hold = Pix (iim->sci.data,j,i) / 2.0;
	            Pix (oim->sci.data, j2,i2)     = hold;
	            Pix (oim->sci.data, j2+1,i2)   = hold;
	            Pix (oim->sci.data, j2,i2+1)   = hold;
	            Pix (oim->sci.data, j2+1,i2+1) = hold;
	        }
	    }
	    /* No need to expand x1d array. */

	    return (STIS_OK);

	default:
	    return (ERROR_RETURN);
	}
}
Пример #4
0
int doAtoD (WF3Info *wf3, SingleGroup *x) {

/* arguments:
WF3Info *wf3	 i: calibration switches, etc
SingleGroup *x	io: image to be calibrated; written to in-place
*/

	extern int status;

	TblInfo tabinfo;	/* pointer to table descriptor, etc */
	TblRow tabrow;		/* values read from a table row */
	TblArray tabarray;	/* correction array read from table row */

	int foundit;		/* row found in table? */
	int row;		/* loop index for row number */
	int row_min;		/* row with matching keyword */
	double ref_key_value;	/* value gotten from image header */
	double dt, dt_min;	/* for finding desired row in table */
	int ival;		/* input science data value from x */
	int i, j;
	short dqval;

	int GetKeyDbl (Hdr *, char *, int, double, double *);
	int RowPedigree (RefTab *, int, IRAFPointer, IRAFPointer, IRAFPointer);
	int SameFlt (float, float);
	int SameString (char *, char *);

    row_min=0;
    dt_min=0.0f;
    
	if (wf3->atodcorr != PERFORM)
	    return (status);

	if (wf3->ncombine > 1) {
	    trlerror 
		("NCOMBINE is already > 1 before ATODCORR has been performed.");
	    return (status = 1010);
	}

	/* Open the A-to-D table. */
	if (OpenAtoDTab (wf3->atod.name, &tabinfo))
	    return (status);

	/* Find the row with value closest to the temperature. */

	foundit = 0;
	for (row = 1;  row <= tabinfo.nrows;  row++) {
	    if (ReadAtoDTab (&tabinfo, row, &tabrow))
		return (status);
	    if (SameString (tabrow.ccdamp, wf3->ccdamp) &&
		SameFlt (tabrow.ccdgain, wf3->ccdgain)) {
		if (GetKeyDbl (x->globalhdr, tabrow.ref_key, NO_DEFAULT,
			       0., &ref_key_value))
		    return (status);
		if (!foundit) {
		    /* assign initial values */
		    foundit = 1;
		    row_min = row;
		    dt_min = fabs (ref_key_value - tabrow.ref_key_value);
		} else {
		    /* Get value from image, and update dt_min. */
		    dt = fabs (ref_key_value - tabrow.ref_key_value);
		    if (dt < dt_min) {
			dt_min = dt;
			row_min = row;
		    }
		}
	    }
	}

	if (!foundit) {
	    sprintf (MsgText, "CCD amp %s, gain %g, not found in ATODTAB `%s'.",
		wf3->ccdamp, wf3->ccdgain, wf3->atod.name);
	    trlerror (MsgText);
	    CloseAtoDTab (&tabinfo);
	    return (status = TABLE_ERROR);
	}

	/* Get pedigree & descrip from the row. */
	if (RowPedigree (&wf3->atod, row_min,
		tabinfo.tp, tabinfo.cp_pedigree, tabinfo.cp_descrip))
	    return (status);
	if (wf3->atod.goodPedigree == DUMMY_PEDIGREE) {
	    wf3->atodcorr = DUMMY;
	    CloseAtoDTab (&tabinfo);
	    return (status);
	}

	/* Reread the appropriate row to get the correction array. */
	if (ReadAtoDArray (&tabinfo, row_min, &tabarray))
	    return (status);

	/* Apply this correction to each pixel in the image.  At this
	   stage the values should still be integers, so assigning
	   a value to an integer (ival) should not result in truncation.
	*/
	dqval = 0;
	for (j = 0;  j < x->sci.data.ny;  j++) {
	    for (i = 0;  i < x->sci.data.nx;  i++) {
		ival = (int) Pix (x->sci.data, i, j);
		if (ival >= tabarray.nelem) {
		    Pix (x->sci.data, i, j) = tabarray.atod[tabarray.nelem-1];
			dqval = SATPIXEL | DQPix (x->dq.data, i, j);
		    DQSetPix (x->dq.data, i, j, dqval);	/* saturated */
		} else if (ival >= 0) {
		    Pix (x->sci.data, i, j) = tabarray.atod[ival];
		}		/* else if ival < 0, no change */
	    }
	}

	free (tabarray.atod);
	if (CloseAtoDTab (&tabinfo))
	    return (status);

	return (status);
}
Пример #5
0
int doDQI (StisInfo1 *sts, SingleGroup *x) {

/* arguments:
StisInfo1 *sts    i: calibration switches, etc
SingleGroup *x    io: image to be calibrated; DQ array written to in-place
*/

	int status;

	TblInfo tabinfo;	/* pointer to table descriptor, etc */
	TblRow tabrow;		/* values read from a table row */

	ShortTwoDArray ydq;		/* scratch space */

	/* mappings from one coordinate system to another */
	double ri_m[2], ri_v[2];	/* reference to image */
	double rs_m[2], rs_v[2];	/* reference to scratch */
	double si_m[2], si_v[2];	/* scratch to image */

	/* for copying from scratch array (only copy overlap region): */
	int first[2], last[2];	/* corners of overlap region in image coords */
	int sfirst[2];		/* lower left corner of overlap in scratch */
	int rbin[2];		/* bin size of image relative to ref bin size */

	int snpix[2];		/* size of scratch array */
	int npix[2];		/* size of current image */

	float *ds;		/* Doppler smearing array */
	int nds, d0;		/* size of ds and index in ds of zero point */
	int k, kmin, kmax;	/* loop index; range of indexes in ds */
	int doppmin, doppmax;	/* Doppler offsets relative to d0 */

	int in_place;		/* true if same bin size and no Doppler */
	int high_res;		/* true if Doppler or either axis is high-res */
	int i, j, i0, j0;	/* indexes for scratch array ydq */
	int m, n;		/* indexes for data quality array in x */
	short sum_dq;		/* for binning data quality array */

	int row;		/* loop index for row number */

	void FlagFilter (StisInfo1 *, ShortTwoDArray *,
		int, int, double *, double *);
	int MakeDopp (double, double, double, double, double, int,
		float *, int *, int *);

	/* We could still flag saturation even if the bpixtab was dummy. */
	if (sts->dqicorr != PERFORM && sts->dqicorr != DUMMY)
	    return (0);

	/* For the CCD, check for and flag saturation. */
	if (sts->detector == CCD_DETECTOR) {
	    for (j = 0;  j < x->sci.data.ny;  j++) {
		for (i = 0;  i < x->sci.data.nx;  i++) {
		    if ((int) Pix (x->sci.data, i, j) > sts->saturate) {
			sum_dq = DQPix (x->dq.data, i, j) | SATPIXEL;
			DQSetPix (x->dq.data, i, j, sum_dq);	/* saturated */
		    }
		}
	    }
	}

	/* Get the linear transformation between reference and input image. */
	if ((status = GetLT0 (&x->sci.hdr, ri_m, ri_v))) /* zero indexed LTV */
	    return (status);

	/* Flag regions beyond the bounderies of the aperture, for CCD data. */
	if (sts->detector == CCD_DETECTOR) {
	    FlagFilter (sts, &x->dq.data, x->dq.data.nx, x->dq.data.ny,
			ri_m, ri_v);
	}

	/* There might not be any bad pixel table.  If not, quit now. */
	if (sts->bpix.exists == EXISTS_NO || sts->dqicorr != PERFORM)
	    return (0);

	initShortData (&ydq);

	/* In some cases we can set the data quality flags directly in
	   the DQ array, but in other cases we must create a scratch
	   array and copy back to the original.  Either the original or
	   the scratch may be in high-res mode.
	*/
	if (sts->detector == CCD_DETECTOR) {

	    if (sts->bin[0] == 1 && sts->bin[1] == 1)
		in_place = 1;			/* no binning */
	    else
		in_place = 0;
	    high_res = 0;

	} else {				/* MAMA */

	    if (sts->doppcorr == PERFORM) {

		high_res = 1;

		if (sts->bin[0] == 1 && sts->bin[1] == 1)
		    in_place = 1;		/* high-res in both axes */
		else
		    in_place = 0;

	    } else {				/* no Doppler convolution */

		if (sts->bin[0] == 2 && sts->bin[1] == 2) {
		    high_res = 0;		/* both axes low-res */
		    in_place = 1;
		} else if (sts->bin[0] == 1 && sts->bin[1] == 1) {
		    high_res = 1;		/* both axes high-res */
		    in_place = 1;
		} else {
		    high_res = 1;		/* low-res in one axis */
		    in_place = 0;
		}
	    }
	}

	/* Get the other linear transformations (ri_m & ri_v were gotten
	   earlier, just after checking for saturation.)
	*/
	if (!in_place) {
	    if (high_res) {
		/* DQ array is binned finer than reference coords */
		rs_m[0] = 2.;
		rs_m[1] = 2.;
		rs_v[0] = 0.5;
		rs_v[1] = 0.5;
		/* assumes rs_m = 2, rs_v = 0.5 */
		si_m[0] = ri_m[0] * 0.5;
		si_m[1] = ri_m[1] * 0.5;
		si_v[0] = ri_v[0] - ri_m[0] * 0.25;
		si_v[1] = ri_v[1] - ri_m[1] * 0.25;
	    } else {
		/* scratch is in reference coords */
		rs_m[0] = 1.;
		rs_m[1] = 1.;
		rs_v[0] = 0.;
		rs_v[1] = 0.;
		/* assumes rs_m = 1, rs_v = 0 */
		si_m[0] = ri_m[0];
		si_m[1] = ri_m[1];
		si_v[0] = ri_v[0];
		si_v[1] = ri_v[1];
	    }
	}

	if (sts->doppcorr == PERFORM) {
	    /* Compute the Doppler smearing array, if we need it.  We need
		the size (nds) and zero point (d0), not the array itself.
	    */
	    nds = 2 * (sts->doppmag + 1) + 21;	/* reassigned by makeDopp */
	    ds = (float *) calloc (nds, sizeof (float));
	    if ((status = MakeDopp (sts->doppzero, sts->doppmag, sts->orbitper,
                                    sts->expstart, sts->exptime, sts->dispsign,
                                    ds, &nds, &d0)))
		return (status);
	    /* Find the range of non-zero elements in ds. */
	    kmin = nds - 1;		/* initial values */
	    kmax = 0;
	    for (k = 0;  k < nds;  k++) {
		if (ds[k] > 0.) {	/* there will be no negative values */
		    if (k < kmin)
			kmin = k;
		    if (k > kmax)
			kmax = k;
		}
	    }
	    /* It's the indexes relative to d0 that are important. */
	    doppmin = kmin - d0;
	    doppmax = kmax - d0;
	    free (ds);
	} else {
	    doppmin = 0;
	    doppmax = 0;
	}

	/* Open the data quality initialization table, find columns, etc. */
	if ((status = OpenBpixTab (sts->bpix.name, &tabinfo)))
	    return (status);

	/* Size of scratch image */
	if (high_res) {
	    snpix[0] = 2 * tabinfo.axlen1;
	    snpix[1] = 2 * tabinfo.axlen2;
	} else {
	    snpix[0] = tabinfo.axlen1;
	    snpix[1] = tabinfo.axlen2;
	}

	/* size of current image */
	npix[0] = x->dq.data.nx;
	npix[1] = x->dq.data.ny;

	if (!in_place) {
	    /* Allocate space for a scratch array. */
	    allocShortData (&ydq, snpix[0], snpix[1], True);
	    if (hstio_err()) {
		printf (
		"ERROR    (doDQI) couldn't allocate data quality array.\n");
		return (OUT_OF_MEMORY);
	    }
	    for (j = 0;  j < snpix[1];  j++)
		for (i = 0;  i < snpix[0];  i++)
		    DQSetPix (ydq, i, j, 0);		/* initially OK */
	}

	/* Read each row of the table, and fill in data quality values. */

	for (row = 1;  row <= tabinfo.nrows;  row++) {

	    if ((status = ReadBpixTab (&tabinfo, row, &tabrow))) {
		printf ("ERROR    Error reading BPIXTAB.\n");
		return (status);
	    }

	    if (!SameString (tabrow.opt_elem, sts->opt_elem))
		continue;

	    if (tabrow.xstart < 0 || tabrow.xstart >= tabinfo.axlen1 ||
		tabrow.ystart < 0 || tabrow.ystart >= tabinfo.axlen2) {
		printf (
	"Warning  Starting pixel (%d,%d) in BPIXTAB is out of range.\n",
			tabrow.xstart+1, tabrow.ystart+1);
		continue;			/* ignore this row */
	    }

	    /* Assign the flag value to all relevant pixels. */
	    if (in_place) {
		if (high_res)
		    DQIHigh (&x->dq.data, ri_v, &tabrow, doppmin, doppmax);
		else
		    DQINormal (&x->dq.data, ri_v, &tabrow);
	    } else {				/* use scratch array */
		if (high_res)
		    DQIHigh (&ydq, rs_v, &tabrow, doppmin, doppmax);
		else
		    DQINormal (&ydq, rs_v, &tabrow);
	    }
	}

	if ((status = CloseBpixTab (&tabinfo)))	/* done with the table */
	    return (status);

	if (!in_place) {

	    /* Get corners of region of overlap between image and
		scratch array.
	    */
	    FirstLast (si_m, si_v, snpix, npix, rbin, first, last, sfirst);

	    /* We have been writing to a scratch array ydq.  Now copy or
		bin the values down to the actual size of x.
	    */
	    j0 = sfirst[1];
	    for (n = first[1];  n <= last[1];  n++) {
		i0 = sfirst[0];
		for (m = first[0];  m <= last[0];  m++) {
		    sum_dq = DQPix (x->dq.data, m, n);
		    for (j = j0;  j < j0+rbin[1];  j++)
			for (i = i0;  i < i0+rbin[0];  i++)
			    sum_dq |= DQPix (ydq, i, j);
		    DQSetPix (x->dq.data, m, n, sum_dq);
		    i0 += rbin[0];
		}
		j0 += rbin[1];
	    }

	    freeShortData (&ydq);			/* done with ydq */
	}

	return (0);
}
Пример #6
0
int doAtoD (StisInfo1 *sts, SingleGroup *x) {

/* arguments:
StisInfo1 *sts     i: calibration switches, etc
SingleGroup *x    io: image to be calibrated; written to in-place
*/

	int status;

	TblInfo tabinfo;	/* pointer to table descriptor, etc */
	TblRow tabrow;		/* values read from a table row */
	TblArray tabarray;	/* correction array read from table row */

	int foundit;		/* row found in table? */
	int row;		/* loop index for row number */
	int row_min;		/* row with closest temperature (min dt) */
	double ref_key_value;	/* value gotten from image header */
	double dt, dt_min;	/* for finding temperature in table */
	int ival;		/* input science data value from x */
	int i, j;
	short dq;		/* a data quality value */

	int no_default = 0;	/* missing keyword is fatal error */

	if (sts->atodcorr != PERFORM)
	    return (0);

	if (sts->ncombine > 1) {
	    printf (
"ERROR    NCOMBINE is already > 1 before ATODCORR has been performed.\n");
	    return (GENERIC_ERROR_CODE);
	}

	/* Open the A-to-D table. */
	if ((status = OpenAtoDTab (sts->atod.name, &tabinfo)))
	    return (status);

	/* Find the row with value closest to the temperature. */

	foundit = 0;
	for (row = 1;  row <= tabinfo.nrows;  row++) {
	    if ((status = ReadAtoDTab (&tabinfo, row, &tabrow)))
		return (status);
	    if (SameString (tabrow.ccdamp, sts->ccdamp) &&
		SameInt (tabrow.ccdgain, sts->ccdgain)) {
		/* Get value from header. */
		if ((status = Get_KeyD (&x->sci.hdr, tabrow.ref_key, no_default,
                                        0., &ref_key_value)))
		    return (status);
		dt = fabs (ref_key_value - tabrow.ref_key_value);
		if (!foundit) {
		    foundit = 1;	/* assign initial values */
		    dt_min = dt;
		    row_min = row;
		} else if (dt < dt_min) {	/* update dt_min */
		    dt_min = dt;
		    row_min = row;
		}
	    }
	}

	if (!foundit) {
	    printf (
	"ERROR    CCD amp %s, gain %d, not found in ATODTAB `%s'.\n",
		sts->ccdamp, sts->ccdgain, sts->atod.name);
	    CloseAtoDTab (&tabinfo);
	    return (TABLE_ERROR);
	}

	/* Get pedigree & descrip from the row. */
	if ((status = RowPedigree (&sts->atod, row_min,
                tabinfo.tp, tabinfo.cp_pedigree, tabinfo.cp_descrip)))
	    return (status);
	if (sts->atod.goodPedigree == DUMMY_PEDIGREE) {
	    sts->atodcorr = DUMMY;
	    CloseAtoDTab (&tabinfo);
	    return (0);
	}

	/* Reread the appropriate row to get the correction array. */
	if ((status = ReadAtoDArray (&tabinfo, row_min, &tabarray)))
	    return (status);

	/* Apply this correction to each pixel in the image.  At this
	   stage the values should still be integers, so assigning
	   a value to an integer (ival) should not result in truncation.
	*/
	for (j = 0;  j < x->sci.data.ny;  j++) {
	    for (i = 0;  i < x->sci.data.nx;  i++) {
		ival = (int) Pix (x->sci.data, i, j);
		if (ival >= tabarray.nelem) {
		    Pix (x->sci.data, i, j) = tabarray.atod[tabarray.nelem-1];
		    dq = DQPix (x->dq.data, i, j) | SATPIXEL;
		    DQSetPix (x->dq.data, i, j, dq);	/* saturated */
		} else if (ival >= 0) {
		    Pix (x->sci.data, i, j) = tabarray.atod[ival];
		}		/* else if ival < 0, no change */
	    }
	}

	free (tabarray.atod);
	if ((status = CloseAtoDTab (&tabinfo)))
	    return (status);

	return (0);
}
Пример #7
0
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);
}
Пример #8
0
static int nlincorr (WF3Info *wf3, SingleNicmosGroup *input, NlinData *nlin,
		     SingleNicmosGroup *zsig) {

/* Arguments:
**	wf3	 i: WFC3 info structure
**	input	io: input image to be corrected
**	nlin	 i: nonlinearity reference data
**	zsig	 i: MULTIACCUM zero-read signal image
*/

	/* Local variables */
	int i, j, li, lj, k;	/* pixel indexes */
	int ibeg, iend;		/* loop limits */
	int jbeg, jend;		/* loop limits */
	int li_beg, lj_beg;	/* loop limits */
	int rsize = 1;		/* for use by GetCorner */
	int sci_bin[2];		/* bin size of science image */
	int sci_corner[2];	/* science image corner location */
	int ref_bin[2];		/* bin size of reference image */
	int ref_corner[2];	/* ref image corner location */
	int nsatpix;		/* number of saturated pixels */
	float sval, eval;	/* science and err image values */
	float corr;		/* correction value */
	float n1;		/* node value */

	/* Function definitions */
	int GetCorner (Hdr *, int, int *, int*);

	/* Compute subarray offsets, if any, between ref data
	** science data. */
	if ( (status = GetCorner(&input->sci.hdr, rsize, sci_bin, sci_corner)))
	    return (status);
	if ( (status = GetCorner(&nlin->coeff[0].hdr, rsize, ref_bin, ref_corner)))
	    return (status);

	/* Initialize saturated pixel counter */
	nsatpix = 0;

	/* Loop through science image */
	ibeg = wf3->trimx[0]; iend = input->sci.data.nx - wf3->trimx[1];
	jbeg = wf3->trimy[0]; jend = input->sci.data.ny - wf3->trimy[1];
	li_beg = (sci_corner[0] - ref_corner[0]) + ibeg;
	lj_beg = (sci_corner[1] - ref_corner[1]) + jbeg;

	for (j = jbeg, lj = lj_beg; j < jend; j++, lj++) {
	for (i = ibeg, li = li_beg; i < iend; i++, li++) {

	     /* Get the science and error image values */
	     sval = Pix(input->sci.data,i,j);
	     eval = Pix(input->err.data,i,j);

	     /* Temporarily add the MULTIACCUM zero-read signal back into the
	     ** the pixel value, but only if ZSIG step is turned on and only 
	     ** for groups other than the zeroth-read itself */
	     if (wf3->zsigcorr == PERFORM && wf3->group != wf3->ngroups) {
		 sval += Pix(zsig->sci.data,i,j);
		 if (DQPix(zsig->dq.data,i,j) & ZEROSIG) {
		     DQSetPix(input->dq.data,i,j,
			DQPix(input->dq.data,i,j) | ZEROSIG);
		 }
	     }

	     /* Get the node values for this pixel */
	     n1 = Pix(nlin->nodes[0].data,li,lj);

	     /* Propagate the DQ value from the NLIN ref data */
	     DQSetPix(input->dq.data,i,j,
		DQPix(input->dq.data,i,j) | DQPix(nlin->dqual[0].data,li,lj));

	     /* If it's already flagged as saturated,
	     ** skip the correction */
	     if (DQPix(input->dq.data,i,j) & SATPIXEL) {
		 nsatpix++;

	     /* Apply the correction for the non-linear region */
	     /*} else if (sval >= n1 && sval <= n2) {*/
	     } else if (sval <= n1) {

	       /* Compute the new science image pixel value */
	       corr = 1.0;
	       for (k=0; k < nlin->ncoeff; k++)
		    corr += Pix(nlin->coeff[k].data,li,lj) * (pow(sval,k));
	       Pix(input->sci.data,i,j) = sval * corr;

	       /* Remove the MULTIACCUM zero-read signal that was added in
	       ** above, but only if ZSIG step is turned on and only for 
	       ** groups other than the zeroth-read itself */
	       if (wf3->zsigcorr == PERFORM && wf3->group != wf3->ngroups)
		   Pix(input->sci.data,i,j) -= Pix(zsig->sci.data,i,j);

	     /* Above the saturation node, just mark the pixel as saturated */
	     } else if (sval > n1) {
	       nsatpix++;
	       DQSetPix(input->dq.data,i,j,
		  DQPix(input->dq.data,i,j) | SATPIXEL);
	     }
	}}

	/* Report the number of saturated pixels */
	sprintf (MsgText, "NLINCORR detected %d saturated pixels in imset %d",
		 nsatpix, wf3->group);
	trlmessage (MsgText);

	/* Successful return */
	return (status = 0);
}