Changeset 6851 for trunk/psphot/src/psphotImageMedian.c
- Timestamp:
- Apr 12, 2006, 8:59:15 PM (20 years ago)
- File:
-
- 1 edited
-
trunk/psphot/src/psphotImageMedian.c (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psphot/src/psphotImageMedian.c
r6753 r6851 1 1 # include "psphot.h" 2 double psImageClippedStats (psImage *image, psImage *mask, psU8 maskValue, double fmin, double fmax);3 void fsort (float *value, int N);4 5 // random number seed to select a fraction of the image pixels6 static psRandom *rnd;7 8 // use no more than MAX_SAMPLE_PIXELS pixels for each median box9 static int MAX_SAMPLE_PIXELS;10 2 11 3 // generate the median in NxN boxes, clipping heavily … … 15 7 bool status; 16 8 psRegion region; 17 psImage *model = NULL;9 int MAX_SAMPLE_PIXELS; 18 10 19 11 psTimerStart ("psphot"); 20 12 13 // select the appropriate recipe information 14 psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, "PSPHOT"); 15 16 MAX_SAMPLE_PIXELS = psMetadataLookupF32 (&status, recipe, "IMSTATS_NPIX"); 17 if (!status) MAX_SAMPLE_PIXELS = 1000; 18 psImageClippedStatsInit(MAX_SAMPLE_PIXELS); 19 20 // subtract this amount extra from the sky 21 float SKY_BIAS = psMetadataLookupF32 (&status, recipe, "SKY_BIAS"); 22 if (!status) SKY_BIAS = 0; 23 21 24 // find the currently selected readout 22 psMetadata *recipe = psMetadataLookupPtr (&status, config->recipes, "PSPHOT"); 23 pmFPAfile *input = psMetadataLookupPtr (&status, config->files, "PSPHOT.INPUT"); 24 pmReadout *readout = pmFPAviewThisReadout (view, input->fpa); 25 pmReadout *readout = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT"); 25 26 26 27 psImage *image = readout->image; 27 28 psImage *mask = readout->mask; 28 29 rnd = psRandomAlloc (PS_RANDOM_TAUS, 0);30 MAX_SAMPLE_PIXELS = psMetadataLookupF32 (&status, recipe, "IMSTATS_NPIX");31 if (!status) MAX_SAMPLE_PIXELS = 1000;32 29 33 30 // dimensions of input & output image … … 49 46 int ny = (Ny % DY) ? (int)(Ny / DY) + 1 : Ny / DY; 50 47 51 // select model pixels, from output background model file, or create 52 model = pmFPAfileReadoutImage (config->files, view, "PSPHOT.BACKMDL", nx, ny, PS_TYPE_F32); 48 // select model pixels (from output background model file, or create internal file) 49 pmReadout *model = pmFPAfileThisReadout (config->files, view, "PSPHOT.BACKMDL"); 50 if (model == NULL) { 51 // select model pixels, from output background model file, or create 52 model = pmFPAfileCreateInternal (config->files, "PSPHOT.BACKMDL", nx, ny, PS_TYPE_F32); 53 } else { 54 // replace the supplied image data with an image of the desired size 55 psImageRecycle (model->image, nx, ny, PS_TYPE_F32); 56 } 57 psF32 **modelData = model->image->data.F32; 53 58 54 59 // measure clipped median for subimages … … 63 68 psImage *submask = psImageSubset (mask, region); 64 69 65 model->data.F32[iy][ix] = psImageClippedStats (subset, submask, 0xff, 0.25, 0.50); 70 // XXX the value of the upper and lower cuts probably should be studied... 71 modelData[iy][ix] = psImageClippedStats (subset, submask, 0xff, 0.25, 0.75) + SKY_BIAS; 66 72 67 73 psFree (subset); … … 76 82 psLogMsg ("psphot", 3, "build median image: %f sec\n", psTimerMark ("psphot")); 77 83 78 // linear interpolation to full-scale 84 // XXX temporarily until we get the pmFPAfile output finished 85 psphotSaveImage (NULL, model->image, "model.fits"); 79 86 80 87 // select background pixels, from output background file, or create 81 psImage *background = pmFPAfileReadoutImage (config->files, view, "PSPHOT.BACKGND", Nx, Ny, PS_TYPE_F32); 82 83 // XXX this code skips the initial pixels 84 for (int Iy = 0; Iy < ny-1; Iy ++) { 85 for (int Ix = 0; Ix < nx-1; Ix ++) { 86 87 float V00 = model->data.F32[Iy+0][Ix+0]; 88 float V01 = model->data.F32[Iy+0][Ix+1]; 89 float V10 = model->data.F32[Iy+1][Ix+0]; 90 float V11 = model->data.F32[Iy+1][Ix+1]; 91 92 // a single binned pixel quad 93 // (Xs,Ys) : (Xe,Ye) : binned pixel centers in unbinned coords 94 // corresponding to (Ix,Iy), (Ix+1,Iy+1) 95 int Xs = (Ix + 1)*DX - dx; 96 int Ys = (Iy + 1)*DY - dy; 97 int Xe = Xs + DX; 98 int Ye = Ys + DY; 99 100 for (int iy = Ys; (iy < Ye) && (iy < Ny); iy++) { 101 float Vxs = (V10 - V00)*(iy - Ys) / DY + V00; 102 float Vxe = (V11 - V01)*(iy - Ys) / DY + V01; 103 float dV = (Vxe - Vxs) / DX; 104 float V = Vxs; 105 for (int ix = Xs; (ix < Xe) && (ix < Nx); ix++) { 106 background->data.F32[iy][ix] = V; 107 V += dV; 108 } 109 } 110 } 88 pmReadout *background = pmFPAfileThisReadout (config->files, view, "PSPHOT.BACKGND"); 89 if (background == NULL) { 90 background = pmFPAfileCreateInternal (config->files, "PSPHOT.BACKGND", Nx, Ny, PS_TYPE_F32); 91 } else { 92 // replace the supplied image data with an image of the desired size 93 // XXX should not have to do this: it should be allocated correctly 94 // psImageRecycle (background->image, Nx, Ny, PS_TYPE_F32); 111 95 } 112 96 113 // side pixels 114 int Xs = DX - dx; 115 int Xe = nx*DX - dx; 116 for (int Iy = 0; Iy < ny - 1; Iy++) { 97 psF32 **backData = background->image->data.F32; 117 98 118 int Ys = (Iy + 1)*DY - dy; 119 int Ye = Ys + DY; 120 121 // leading edge 122 float V0 = model->data.F32[Iy+0][0]; 123 float V1 = model->data.F32[Iy+1][0]; 124 float dV = (V1 - V0) / DY; 125 float V = V0; 126 for (int iy = Ys; (iy < Ye) && (iy < Ny); iy++) { 127 for (int ix = 0; ix < Xs; ix++) { 128 background->data.F32[iy][ix] = V; 129 } 130 V += dV; 131 } 132 133 // trailing edge 134 V0 = model->data.F32[Iy+0][nx-1]; 135 V1 = model->data.F32[Iy+1][nx-1]; 136 dV = (V1 - V0) / DY; 137 V = V0; 138 for (int iy = Ys; (iy < Ye) && (iy < Ny); iy++) { 139 for (int ix = Xe; ix < Nx; ix++) { 140 background->data.F32[iy][ix] = V; 141 } 142 V += dV; 143 } 144 } 145 146 // top and bottom pixels 147 int Ys = DY - dy; 148 int Ye = ny*DY - dy; 149 for (int Ix = 0; Ix < nx - 1; Ix++) { 150 151 int Xs = (Ix + 1)*DX - dx; 152 int Xe = Xs + DX; 153 154 // top edge 155 float V0 = model->data.F32[0][Ix+0]; 156 float V1 = model->data.F32[0][Ix+1]; 157 float dV = (V1 - V0) / DX; 158 for (int iy = 0; iy < Ys; iy++) { 159 float V = V0; 160 for (int ix = Xs; (ix < Xe) && (ix < Nx); ix++) { 161 background->data.F32[iy][ix] = V; 162 V += dV; 163 } 164 } 165 166 // bottom edge 167 V0 = model->data.F32[ny-1][Ix+0]; 168 V1 = model->data.F32[ny-1][Ix+1]; 169 dV = (V1 - V0) / DX; 170 for (int iy = Ye; iy < Ny; iy++) { 171 float V = V0; 172 for (int ix = Xs; (ix < Xe) && (ix < Nx); ix++) { 173 background->data.F32[iy][ix] = V; 174 V += dV; 175 } 176 } 177 } 178 179 // the four corners 180 { 181 float V; 182 // 0,0 183 V = model->data.F32[0][0]; 184 for (int iy = 0; iy < DY - dy; iy++) { 185 for (int ix = 0; ix < DX - dx; ix++) { 186 background->data.F32[iy][ix] = V; 187 } 188 } 189 // Nx,0 190 V = model->data.F32[0][nx-1]; 191 for (int iy = 0; iy < DY - dy; iy++) { 192 for (int ix = nx*DX - dx; ix < Nx; ix++) { 193 background->data.F32[iy][ix] = V; 194 } 195 } 196 // 0,Ny 197 V = model->data.F32[ny-1][0]; 198 for (int iy = ny*DY - dy; iy < Ny; iy++) { 199 for (int ix = 0; ix < DX - dx; ix++) { 200 background->data.F32[iy][ix] = V; 201 } 202 } 203 // Nx,Ny 204 V = model->data.F32[nx-1][ny-1]; 205 for (int iy = ny*DY - dy; iy < Ny; iy++) { 206 for (int ix = nx*DX - dx; ix < Nx; ix++) { 207 background->data.F32[iy][ix] = V; 208 } 209 } 210 } 99 // linear interpolation to full-scale 100 psImageUnbin (background->image, model->image, DX, DY, dx, dy); 211 101 psLogMsg ("psphot", 3, "build resampled image: %f sec\n", psTimerMark ("psphot")); 212 102 213 psphotSaveImage (NULL, background, "back.fits"); 103 // XXX temporarily until we get the pmFPAfile output finished... 104 psphotSaveImage (NULL, background->image, "back.fits"); 214 105 215 106 // back-sub image pixels, from output background file (don't create if not requested) 216 p sImage *backSub = pmFPAfileReadoutImage (config->files, view, "PSPHOT.BACKSUB", 0, 0, PS_TYPE_F32);107 pmReadout *backSub = pmFPAfileThisReadout (config->files, view, "PSPHOT.BACKSUB"); 217 108 218 // subtract the background model 109 // subtract the background model (save in backSub, if requested) 219 110 for (int j = 0; j < image->numRows; j++) { 220 111 for (int i = 0; i < image->numCols; i++) { 221 112 if (!mask->data.U8[j][i]) { 222 image->data.F32[j][i] -= back ground->data.F32[j][i];113 image->data.F32[j][i] -= backData[j][i]; 223 114 if (backSub) { 224 backSub-> data.F32[j][i] = image->data.F32[j][i];115 backSub->image->data.F32[j][i] = image->data.F32[j][i]; 225 116 } 226 117 } … … 229 120 230 121 psLogMsg ("psphot", 3, "subtracted background model: %f sec\n", psTimerMark ("psphot")); 231 ps Free (rnd);122 psImageClippedStatsCleanup(); 232 123 233 // it is safe to free all of these: either they are saved on config->files or are local 234 psFree (model); 235 psFree (background); 236 psFree (backSub); 124 // the pmReadout selected in this function are all view on entries in config->files 237 125 return true; 238 126 } 239 240 double psImageClippedStats (psImage *image, psImage *mask, psU8 maskValue, double fmin, double fmax) {241 242 double value;243 int nx = image->numCols;244 int ny = image->numRows;245 246 if (nx*ny <= 0) return 0.0;247 248 int Nsubset = PS_MIN (MAX_SAMPLE_PIXELS, nx*ny);249 int Npixels = nx*ny;250 251 psVector *values = psVectorAlloc (Nsubset, PS_TYPE_F32);252 253 float min = values->data.F32[0];254 float max = values->data.F32[0];255 256 int n = 0;257 for (int i = 0; i < Nsubset; i++) {258 double frnd = psRandomUniform (rnd);259 int pixel = Npixels * frnd;260 int ix = pixel % nx;261 int iy = pixel / nx;262 263 if (mask->data.U8[iy][ix] & maskValue) continue;264 265 value = image->data.F32[iy][ix];266 min = PS_MIN (value, min);267 max = PS_MIN (value, max);268 values->data.F32[n] = value;269 n++;270 }271 values->n = n;272 273 int imin = fmin * n;274 int imax = fmax * n;275 int npts = imax - imin + 1;276 277 fsort (values->data.F32, n);278 279 value = 0;280 for (int i = imin; (i <= imax) && (i < n); i++) {281 value += values->data.F32[i];282 }283 value = value / npts;284 285 // XXX correct for selection bias??286 287 psFree (values);288 return value;289 }290 291 void fsort (float *value, int N) {292 293 int l,j,ir,i;294 float temp;295 296 if (N < 2) return;297 l = N >> 1;298 ir = N - 1;299 for (;;) {300 if (l > 0) {301 temp = value[--l];302 }303 else {304 temp = value[ir];305 value[ir] = value[0];306 if (--ir == 0) {307 value[0] = temp;308 return;309 }310 }311 i = l;312 j = (l << 1) + 1;313 while (j <= ir) {314 if (j < ir && value[j] < value[j+1]) ++j;315 if (temp < value[j]) {316 value[i]=value[j];317 j += (i=j) + 1;318 }319 else j = ir + 1;320 }321 value[i] = temp;322 }323 }324
Note:
See TracChangeset
for help on using the changeset viewer.
