/*GetImageLineByProj: PRIVATE routine called by getLineByProj. Has same semantics as getLineByProj. Returns zero-padded float array in out. */ void getImageLineByProj(double px,double py,int ns,image *im,float *out) { #define MIN(a,b) ((a)<(b) ? (a) : (b)) register int x; int reqLine,reqSample; reqSample=(px-im->pStartX)/im->pDistX; reqLine=(py-im->pStartY)/im->pDistY; /*printf("Projection %f,%f corresponds to line %i, sample %i\n", px,py,reqLine,reqSample);*/ if ((reqLine>=0) && (reqLine < im->ddr.nl)) /*Line is in bounds, so we read it in and zero-fill the rest of the line.*/ { int inSample,outSample,copySamples; if (reqSample>0) { inSample=reqSample; outSample=0; } else { inSample=0; outSample=-reqSample; } copySamples=MIN(ns-outSample,im->ddr.ns-inSample); getFloatLine(im->f,&im->ddr,reqLine,im->readBuf); for (x=0;x<outSample;x++) out[x]=0.0; for (x=0;x<copySamples;x++) out[x+outSample]=im->readBuf[x+inSample]; for (x=outSample+copySamples;x<ns;x++) out[x]=0.0; } else /*Fill blank line.*/ for (x=0;x<ns;x++) out[x]=0.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); }
/* acsrej_init -- get the initial average pixel values Description: ------------ Get the initial average according to the specified scheme Date Author Description ---- ------ ----------- 22-Sep-1998 W.J. Hack initial version, uses multiamp noise,gain 20-Mar-2000 W.J. Hack corrected problem with rog2, needed to be array 15-Apr-2002 W.J. Hack correctly zero'd out npts array, added DQ checking for BOTH median and minimum images, also added ERR array for median image. 26-Aug-2002 J. Blakeslee Modified threshhold for minimum to use SCALENSE only with sky-subtracted pixels. 01-Dec-2015 P.L. Lim Calculations now entirely in electrons. 13-Jan-2016 P.L. Lim Removed variance init and cleaned up function. */ int acsrej_init (IODescPtr ipsci[], IODescPtr ipdq[], clpar *par, int nimgs, int dim_x, int dim_y, float efac[], float skyval[], SingleGroup *sg, float *work) { /* Parameters: ipsci i: Array of pointers to SCI extension of the given EXTVER, each pointer is an input image. Unit now in electrons. ipdq i: Array of pointers to DQ extension of the given EXTVER, each pointer is an input image. par i: User specified parameters. nimgs i: Number of input images. dim_x, dim_y i: Image dimension taken from the first input image. All images must have the same dimension. efac i: Array of EXPTIME for each image. If all inputs have EXPTIME=0 (all biases), then the values are all set to 1. skyval i: Array of sky values for each input image. Unit now in electrons. sg o: Its "sci" component is the average image used for comparison during CR rejection. Unit is e/s. This is really the median or minimum depending on "initgues" provided by the user. work o: Intermediate result used to calculate sg but not used outside this function. */ extern int status; float val, raw, dumf; int i, j, n, p, dum; float *buf; short *bufdq; int *npts, *ipts; short dqpat; Hdr dqhdr; void ipiksrt (float [], int, int[]); /* -------------------------------- begin ------------------------------- */ dqpat = par->badinpdq; ipts = calloc (nimgs, sizeof(int)); npts = calloc (dim_x, sizeof(int)); buf = calloc (dim_x, sizeof(float)); bufdq = calloc (dim_x, sizeof(short)); /* 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)); for (n = 0; n < nimgs; n++) { initHdr(&dqhdr); getHeader(ipdq[n], &dqhdr); getFloatLine (ipsci[n], j, buf); /* electrons */ getShortLine (ipdq[n], j, bufdq); freeHdr(&dqhdr); /* Only use GOOD pixels to build initial image. work array is already initialized to zeroes in acsrej_do.c */ if (efac[n] > 0.) { for (i = 0; i < dim_x; i++) { if ((bufdq[i] & dqpat) == OK) { PIX(work, npts[i], i, nimgs) = (buf[i] - skyval[n]) / efac[n]; /* e/s */ npts[i] += 1; } } } } /* End of nimgs loop */ /* ALL AMPS */ for (i = 0; i < dim_x; i++) { dum = npts[i]; /* Number of good data points */ 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); /* Even number of input images for this pixel */ if ((dum / 2) * 2 == dum) { Pix(sg->sci.data, i, j) = (PIX(work, dum / 2 - 1, i, nimgs) + PIX(work, dum / 2, i, nimgs)) / 2.; } else { Pix(sg->sci.data, i, j) = PIX(work, dum / 2, i, nimgs); } } } /* End loop over ALL AMPS used on pixels in the line */ } /* End loop over lines */ /* use the minimum to construct the initial average */ } else { 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++) { getFloatLine (ipsci[n], j, buf); /* electrons */ getShortLine (ipdq[n], j, bufdq); /* ALL AMPS */ for (i = 0; i < dim_x; i++) { raw = buf[i]; /* e */ dumf = raw - skyval[n]; /* e */ if (efac[n] > 0.) { /* Can be negative */ val = dumf / efac[n]; /* e/s */ } else { val = 0.; } if ( (n == 0) || (val < Pix(sg->sci.data, i, j)) ) { /* If this pixel is bad in the first image, then the min is automatically set to 0. As a result, only negative val is going to be stored and valid positive min is ignored. SLIGHTLY BUGGY HERE??? */ if ((bufdq[i] & dqpat) == OK && (efac[n] > 0.)) { Pix(sg->sci.data, i, j) = val; /* e/s */ } else { Pix(sg->sci.data, i, j) = 0.; } } } /* End of loop over ALL AMPS 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 (bufdq); return (status); }
void rej_sky (char *sky, IODescPtr ipsci[], IODescPtr ipdq[], int nimgs, short badinpdq, float efac[], DataUnits bunit[], float skyval[]) { /* Revision history: ** ** H. Bushouse 18-Jun-2002 Made bin width checking more robust. Also ** allocate and free histogram for each image ** (following CALACS changes). ** H. Bushouse 06-Dec-2007 Added calls to getHeader before each call to ** getShortLine to prevent getShortLine from ** crashing on null DQ arrays. ** H. Bushouse 22-May-2008 Avoid arithmetic overflow in binning ** calculations. ** H. Bushouse 08-Oct-2008 Added capabilities for "mean" sky calculation ** mode, using resistmean function. ** H. Bushouse 14-Dec-2011 Upgraded to rescale input data that are in ** units of count rates. (PR 69969; Trac #814) */ extern int status; int *histgrm; /* pointer to the histogram */ int nbins; /* number of bins */ int min, max; float data_min; float hwidth; /* histogram resolution */ float hmin; /* minimum histogram value */ int i, k, h; float *a; short *b; int line, npt; int dimx, dimy; float sum, mean; Hdr dqhdr; Bool mode, rmean; /* sky calculation mode flags */ float *skyarr; /* pointer to sky values array */ float ssig, smin, smax; /* sky resistantmean values */ float cr_mode (int *, int, float, float); int resistmean (float *, int, float, float *, float *, float *, float *); /* -------------------------------- begin ------------------------------- */ nbins=0; min=0; max=0; hwidth=0.0f; hmin=0.0f; npt=0; histgrm=NULL; skyarr=NULL; /* decide what to do according to sky */ if (strcmp (sky, "none") == 0) { for (k = 0; k < nimgs; ++k) { skyval[k] = 0.; } return; } else if (strcmp (sky, "mode") == 0) { mode = True; rmean = False; } else if (strcmp (sky, "mean") == 0) { rmean = True; mode = False; } else { trlerror ("illegal sky value"); status = INVALID_VALUE; return; } dimx = getNaxis1(ipsci[0]); dimy = getNaxis2(ipsci[0]); a = (float *) calloc (dimx, sizeof(float)); b = (short *) calloc (dimx, sizeof(short)); if (a == NULL || b == NULL) { trlerror ("Couldn't allocate memory for sky arrays"); status = OUT_OF_MEMORY; return; } if (mode) { /* compute MIN and MAX values for data */ /* use the minimum and twice of the mean to determine the data range */ data_min = INT_MAX; sum = 0.; npt = 0; initHdr (&dqhdr); getHeader(ipdq[0], &dqhdr); for (line = 0; line < dimy; line++) { /* read the data in */ getFloatLine (ipsci[0], line, a); getShortLine (ipdq[0], line, b); /* Rescale data to counts, if necessary */ if (bunit[0] == COUNTRATE) { for (i = 0; i < dimx; ++i) { a[i] *= efac[0]; } } for (i = 0; i < dimx; ++i) { if ( (b[i] & badinpdq) == WF3_OK) { data_min = (a[i] < data_min) ? a[i] : data_min; sum += a[i]; npt++; } } } /* End of loop over lines */ freeHdr(&dqhdr); /* Compute min and max for histogram. MIN is min of good data or MINVAL, which ever is greater DELTA is difference between mean of data and MIN MAX is mean plus DELTA This insures that the mean falls in the center of the range between min and max. */ if (npt == 0) npt = 1; min = (data_min < MINVAL) ? MINVAL : data_min; mean = (sum > 0.) ? (int) ( (sum / (float)npt) + 1) : 1; max = 2 * mean - min; /* use the mode as sky value, use the bin size of 1 (DN) */ nbins = max - min + 1; /* Insure that there are at least MIN_BINS in the histogram and reset the width accordingly. */ if (nbins < MIN_BINS) { nbins = MIN_BINS; hwidth = (float) nbins / (float)MIN_BINS; } else if (nbins > MAX_BINS) { hwidth = (float) nbins / (float)MAX_BINS; nbins = MAX_BINS; } else { hwidth = 1.; } hmin = (float) min; /* sprintf (MsgText, "sky computed using min %d, max %d, mean %g, bins %d, and width %g", min, max, mean, nbins, hwidth); trlmessage (MsgText); */ } /* Now loop over the input images, computing the sky value for each ** image, using either the mode or the resistant mean */ for (k = 0; k < nimgs; ++k) { if (mode) { /* set up a new histogram array for each image */ histgrm = (int *) calloc (nbins, sizeof(int)); if (histgrm == NULL){ trlerror ("Couldn't allocate memory for sky histogram array"); status = OUT_OF_MEMORY; return; } } else if (rmean) { skyarr = (float *) calloc (dimx*dimy, sizeof(float)); if (skyarr == NULL){ trlerror ("Couldn't allocate memory for sky array"); status = OUT_OF_MEMORY; return; } npt = 0; } initHdr (&dqhdr); getHeader (ipdq[k], &dqhdr); for (line = 0; line < dimy; line++) { /* read the data in */ getFloatLine (ipsci[k], line, a); getShortLine (ipdq[k], line, b); /* Rescale data to counts, if necessary */ if (bunit[k] == COUNTRATE) { for (i = 0; i < dimx; ++i) { a[i] *= efac[k]; } } /* construct the histogram for the mode calculation */ if (mode) { for (i = 0; i < dimx; ++i) { if (b[i] == WF3_OK) { /* Adjust the bin position by the width of each bin */ if (fabs((a[i]-min)/hwidth) < INT_MAX) { h = (int)((a[i] - min) / hwidth); if (h >= 0 && h < nbins) histgrm[h]++; } } } /* load the sky array for calculating the mean */ } else if (rmean) { for (i = 0; i < dimx; ++i) { if (b[i] == WF3_OK) { skyarr[npt] = a[i]; npt++; } } } } /* End of loop over lines */ freeHdr(&dqhdr); /* calculate the mode from the histogram */ if (mode) { skyval[k] = cr_mode (histgrm, nbins, hwidth, hmin); free (histgrm); /* calculate the resistant mean */ } else if (rmean) { resistmean (skyarr, npt, SIGREJ, &skyval[k], &ssig, &smin, &smax); free (skyarr); } } free(a); free(b); }