static int RptSumLine (SingleGroup *a, int line, SingleGroupLine *b) { /* arguments: SingleGroup *a io: input data; output sum int line i: line from input/output to be summed SingleGroupLine *b i: second input data line */ extern int status; int i; short dqa, dqb, dqab; /* data quality for a, b, combined */ if (a->sci.data.nx != b->sci.tot_nx) return (status = SIZE_MISMATCH); /* science data */ for (i = 0; i < a->sci.data.nx; i++) { Pix (a->sci.data, i, line) = Pix(a->sci.data, i, line) + b->sci.line[i]; } /* error array (actually contains variance) */ for (i = 0; i < a->err.data.nx; i++) { Pix (a->err.data, i, line) = Pix (a->err.data, i, line) + b->err.line[i]; } /* data quality */ for (i = 0; i < a->dq.data.nx; i++) { dqa = DQPix (a->dq.data, i, line); dqb = b->dq.line[i]; dqab = dqa | dqb; DQSetPix (a->dq.data, i, line, dqab); } return (status); }
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); }
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); }
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); }
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); }
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); }