Changeset 40624
- Timestamp:
- Feb 23, 2019, 10:23:16 AM (7 years ago)
- File:
-
- 1 edited
-
trunk/Ohana/src/opihi/mana/deimos_mkobj.c (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Ohana/src/opihi/mana/deimos_mkobj.c
r40622 r40624 6 6 7 7 // input parameters: 8 // trace : spline fit of slit central x pos vs y-coord9 // profile : slit window profile (vector)10 // object : vector of object flux vs y-coord11 // sky : vector of local sky signal vs y-coord12 // background : vector of extra-slit background flux vs y-coord13 // PSF : point-spread function vector (flux normalized, x-dir)14 // LSF : sline-spread function vector (flux normalized, y-dir)15 // stilt : slit tilt response : 2D kernel?8 // * trace : spline fit of slit central x pos vs y-coord 9 // * profile : slit window profile (vector) 10 // * object : vector of object flux vs y-coord 11 // * sky : vector of local sky signal vs y-coord 12 // * background : vector of extra-slit background flux vs y-coord 13 // * PSF : point-spread function vector (flux normalized, x-dir) 14 // * LSF : sline-spread function vector (flux normalized, y-dir) 15 // * stilt : slit tilt response : 2D kernel? 16 16 17 17 int N; … … 30 30 Buffer *output = NULL; 31 31 32 float stilt = 0.0; // angle of the slit 33 32 34 if ((N = get_argument (argc, argv, "-trace"))) { 33 35 remove_argument (N, &argc, argv); … … 63 65 remove_argument (N, &argc, argv); 64 66 if ((lsf = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE); 67 remove_argument (N, &argc, argv); 68 } 69 if ((N = get_argument (argc, argv, "-stilt"))) { 70 remove_argument (N, &argc, argv); 71 stilt = atof (argv[N]); 65 72 remove_argument (N, &argc, argv); 66 73 } … … 74 81 } 75 82 76 if (argc != 4) {83 if (argc != 3) { 77 84 gprint (GP_ERR, "USAGE: deimos mkobj (buffer) (Ncross) [-Nwave N] [-object vector] [-sky vector] [-backgnd vector] [-trace spline] [-profile vector]\n"); 78 85 return FALSE; … … 110 117 111 118 if ((output = SelectBuffer (argv[1], ANYBUFFER, TRUE)) == NULL) return (FALSE); 112 int Nx = atoi(argv[2]); 119 int NxBase = atoi(argv[2]); 120 if (NxBase % 2 == 0) NxBase ++; // force Nx to be odd 121 int Nx = NxBase; 113 122 123 // if we are appying a trace offset spline, we need to generate an output window which 124 // is Nx + the full swing of the trace, then window back down 125 if (trace) { 126 float dXmin = +1000; 127 float dXmax = -1000; 128 for (int iy = 0; iy < Ny; iy++) { 129 // evaluate the trace spline at this y-coord to find the x-coord offset of the profile center 130 float dx = spline_apply_dbl (trace->xk, trace->yk, trace->y2, trace->Nknots, iy); 131 dXmin = MIN (dx, dXmin); 132 dXmax = MAX (dx, dXmax); 133 } 134 int dXrange = ceil(dXmax - dXmin); 135 if (dXrange % 2) dXrange ++; // force dXrange to be even (so Nx will be odd) 136 Nx += dXrange; 137 } 138 114 139 ResetBuffer (output, Nx, Ny, -32, 0.0, 1.0); 115 140 … … 117 142 opihi_flt *skyV = (opihi_flt *) (sky ? sky->elements.Flt : NULL); 118 143 opihi_flt *psfV = (opihi_flt *) (psf ? psf->elements.Flt : NULL); 119 120 float *out = (float *) output[0].matrix.buffer; 144 opihi_flt *lsfV = (opihi_flt *) (lsf ? lsf->elements.Flt : NULL); 121 145 122 146 // psf vector must have odd number of pixels: 123 147 int Npsf = 0; 124 int Np of = floor(Nx/2);148 int NpsfFull = 0; 125 149 if (psf) { 126 150 if (psf->Nelements % 2 == 0) { … … 128 152 return FALSE; 129 153 } 130 Npsf = psf->Nelements / 2; 131 Npof -= Npsf; 132 } 154 NpsfFull = psf->Nelements; 155 Npsf = NpsfFull / 2; 156 } 157 158 // lsf vector must have odd number of pixels: 159 int Nlsf = 0; 160 int NlsfFull = 0; 161 if (lsf) { 162 if (lsf->Nelements % 2 == 0) { 163 gprint (GP_ERR, "lsf vector must have an odd number of pixels\n"); 164 return FALSE; 165 } 166 NlsfFull = lsf->Nelements; 167 Nlsf = NlsfFull / 2; 168 } 169 170 // *** apply the PSF to the object flux, add in the sky flux 171 172 ALLOCATE_PTR (s1, float, Nx*Ny); 133 173 134 174 // loop over the y positions … … 138 178 opihi_flt skyVy = skyV ? skyV[iy] : 0.0; // if sky is not supplied, flux defaults to 0.0 139 179 180 int Npof = floor(Nx/2); 181 if (psf) Npof -= Npsf; 182 140 183 // flux = obj * PSF + sky 141 184 for (int ix = 0; ix < Nx; ix++) { … … 144 187 145 188 if (psfV) { 146 int n = ix - Npof; // n is the pixel in the PSF corresponding to the ix pixel in the output image 147 if (n < 0) continue; 148 if (n >= Npsf) continue; 149 150 value += objVy * psfV[n]; 189 int n = ix - Npof; 190 // n is the pixel in the PSF corresponding to the ix pixel in the output image 191 // only add in the flux if we are in range of the PSF 192 if ((n >= 0) && (n < NpsfFull)) { 193 value += objVy * psfV[n]; 194 } 151 195 } else { 152 196 if (ix == Nx / 2) value += objVy; 153 197 } 154 out[ix + iy*Nx] = value; 155 } 156 } 198 s1[ix + iy*Nx] = value; 199 } 200 } 201 202 // *** apply the slit tilt & lsf 203 204 // first, generate the interpolation kernels. For a slit tilt of theta, there is a 205 // displacement in the y-direction of dy = dx sin(theta) where dx is the x-coord 206 // relative to the slit window center (Nx / 2). we thus need an image of size Nx, 207 // Nx*sin(theta) 208 209 float sin_stilt = sin(stilt*RAD_DEG); 210 int Nyk = ceil(Nx * fabs(sin_stilt)); 211 if (Nyk < 3) Nyk = 3; // minimum of 3 pixels (or kernel assumption below fails) 212 Nyk += NlsfFull; 213 if (Nyk % 2 == 0) Nyk ++; // force Nyk to be odd 214 int Nyk2 = Nyk/2; // Nyk2 is the center pixel of the interpolations 215 ALLOCATE_PTR (kernel, float, Nx*Nyk); 216 int Nkpix = Nx*Nyk; 217 218 int Nx2 = floor(Nx/2); 219 for (int ix = 0; ix < Nx; ix++) { 220 for (int iy = 0; iy < Nyk; iy++) { kernel[ix + iy*Nx] = 0.0; } 221 222 // displacement in y-dir due to slit tilt: 223 float dy = (ix - Nx2) * sin_stilt; 224 int dyi = floor(dy); 225 float dyf = dy - dyi; 226 227 if (lsf) { 228 int Sy = Nyk2 - Nlsf + dyi; 229 int doInterp = (fabs(dyf) < 1e-5) ? FALSE : TRUE; 230 for (int iy = 0; iy < Nyk; iy++) { 231 int py = iy - Sy; 232 if (py < 0) continue; 233 if (py >= NlsfFull) continue; 234 235 float vout = NAN; 236 if (doInterp) { 237 if ((py > 0) && (py < NlsfFull - 1)) { 238 vout = lsfV[py]*(1 - dyf) + lsfV[py-1]*dyf; 239 } 240 if (py == 0) { 241 vout = lsfV[py]*dyf; 242 } 243 if (py == NlsfFull - 1) { 244 vout = lsfV[py]*(1.0 - dyf); 245 } 246 } else { 247 vout = lsfV[py]; 248 } 249 int Nkpix_i = ix + iy*Nx; 250 myAssert (Nkpix_i < Nkpix, "oops"); 251 kernel[Nkpix_i] = vout; 252 } 253 } else { 254 int Nkpix_i; 255 Nkpix_i = ix + (dyi + Nyk2 + 0)*Nx; 256 myAssert (Nkpix_i < Nkpix, "oops"); 257 kernel[Nkpix_i] = 1.0 - dyf; 258 259 Nkpix_i = ix + (dyi + Nyk2 + 1)*Nx; 260 myAssert (Nkpix_i < Nkpix, "oops"); 261 kernel[Nkpix_i] = dyf; 262 fprintf (stderr, "%d, %d: %f %f\n", ix, (dyi + Nyk2), kernel[ix + (dyi + Nyk2 + 0)*Nx], kernel[ix + (dyi + Nyk2 + 1)*Nx]); 263 } 264 } 265 266 float *out = (float *) output[0].matrix.buffer; 267 268 // next, apply the interpolation kernel to the image 269 270 // loop over the y positions 271 for (int iy = 0; iy < Ny; iy++) { 272 273 // use the tilt kernel to interpolate to this x coordinate 274 for (int ix = 0; ix < Nx; ix++) { 275 276 // if the LSF is defined, we cannot bypass the convolution 277 if (!lsf && (fabs(stilt) < 1e-5)) { 278 out[ix + iy*Nx] = s1[ix + iy*Nx]; 279 } else { 280 opihi_flt g = 0.0, s = 0.0; 281 for (int n = -Nyk2; n <= Nyk2; n++) { 282 if (iy + n < 0) continue; // bottom edge of full image 283 if (iy + n >= Ny) continue; // top edge of full image 284 int Nkpix_i = ix + (n + Nyk2)*Nx; 285 myAssert (Nkpix_i < Nkpix, "oops"); 286 s += kernel[Nkpix_i]*s1[ix + (iy + n)*Nx]; 287 g += kernel[Nkpix_i]; 288 } 289 out[ix + iy*Nx] = s / g; 290 } 291 } 292 } 293 free (kernel); 294 free (s1); 295 296 // next, apply the profile (output = input * profile) 297 opihi_flt *profileV = (opihi_flt *) (profile ? profile->elements.Flt : NULL); 298 if (profile) { 299 int Nprof = profile->Nelements; 300 int Nprof2 = Nprof / 2; 301 302 // loop over the y positions 303 for (int iy = 0; iy < Ny; iy++) { 304 305 int Sx = (int)(Nx2 - Nprof2); 306 307 for (int ix = 0; ix < Nx; ix++) { 308 309 // equivalent coord in the profile: 310 int px = ix - Sx; 311 if ((px >= 0) && (px < Nprof)) { 312 out[ix + iy*Nx] *= profileV[px]; 313 } else { 314 out[ix + iy*Nx] = 0.0; 315 } 316 } 317 } 318 } 319 320 // add in the background 321 opihi_flt *backgndV = (opihi_flt *) (backgnd ? backgnd->elements.Flt : NULL); 322 if (backgnd) { 323 for (int iy = 0; iy < Ny; iy++) { 324 for (int ix = 0; ix < Nx; ix++) { 325 out[ix + iy*Nx] += backgndV[iy]; 326 } 327 } 328 } 329 330 // shift pixels in x based on the trace 331 if (trace) { 332 ALLOCATE_PTR (outTraceBuffer, char, NxBase*Ny*sizeof(float)); 333 float *outTrace = (float *) outTraceBuffer; 334 int NxBase2 = NxBase / 2; 335 336 for (int iy = 0; iy < Ny; iy++) { 337 338 // evaluate the trace spline at this y-coord to find the x-coord offset of the profile center 339 float dx = -spline_apply_dbl (trace->xk, trace->yk, trace->y2, trace->Nknots, iy); 340 341 // extract the integer pixel offset and the fractional offset 342 int dxi = floor(dx); // -1.7 -> -2, -0.5 -> -1, +0.5 -> 0, +1.7 -> 1 343 float dxf = dx - dxi; // -1.7 -> +0.3, -0.5 -> +0.5, +0.5 ->+0.5, +1.7 -> +0.7 344 float dxr = 1 - dxf; 345 346 // if fractional offset is small, do not interpolate 347 int doInterp = fabs(dxf) < 1e-5 ? FALSE : TRUE; 348 349 // How do I handle this? define a temporary window which is a fraction of the full output window? 350 int Sx = Nx2 - NxBase2 + dxi; 351 352 // save the original output row 353 // for (int ix = 0; ix < Nx; ix++) { tmprow[ix] = out[ix + iy*Nx]; } 354 355 for (int ix = 0; ix < NxBase; ix++) { 356 357 // equivalent coord in temporary buffer (Nx * Ny): 358 int px = ix + Sx; 359 if (px < 0) { 360 outTrace[ix + iy*NxBase] = out[iy*Nx]; 361 continue; 362 } 363 if (px >= Nx) { 364 outTrace[ix + iy*NxBase] = out[(Nx - 1) + iy*Nx]; 365 continue; 366 } 367 368 // a default value: 369 float vout = NAN; 370 371 int Npix = px + iy*Nx; 372 373 if (doInterp) { 374 if ((px > 0) && (px < Nx - 1)) { 375 vout = out[Npix]*dxr + out[Npix + 1]*dxf; 376 } 377 if (px == 0) { 378 vout = out[Npix]; 379 } 380 if (px == Nx - 1) { 381 vout = out[Npix]; 382 } 383 } else { 384 vout = out[Npix]; 385 } 386 outTrace[ix + iy*NxBase] = vout; 387 } 388 } 389 390 ResetBuffer (output, NxBase, Ny, -32, 0.0, 1.0); 391 free (output[0].matrix.buffer); 392 output[0].matrix.buffer = outTraceBuffer; 393 } 394 157 395 return TRUE; 158 396 }
Note:
See TracChangeset
for help on using the changeset viewer.
