41 #include "visir_spc_distortion.h"
42 #include "visir_utils.h"
54 static cpl_error_code visir_spc_det_warp_xy(
int,
double,
double,
double,
double,
55 double,
double,
double,
double,
56 double,
double,
double *,
double*);
90 cpl_error_code visir_spc_det_fix(cpl_image ** images,
int nimages,
91 cpl_boolean is_interm,
92 double wlen, visir_spc_resol resol,
93 double phi,
double ksi,
double eps,
94 double delta,
int doplot)
97 cpl_image * spectrum = NULL;
107 if (resol == VISIR_SPC_R_LRP)
return CPL_ERROR_NONE;
109 skip_if (images == NULL);
110 skip_if (nimages <= 0);
112 skip_if (!is_interm && nimages != 1);
114 for (k=0; k < nimages; k++) {
115 if (images[k] == NULL)
break;
117 if (cpl_image_get_type(images[k]) != CPL_TYPE_FLOAT) {
119 cpl_image * to_float = cpl_image_cast(images[k], CPL_TYPE_FLOAT);
121 cpl_image_delete(images[k]);
123 images[k] = to_float;
128 nx = cpl_image_get_size_x(images[0]);
129 ny = cpl_image_get_size_y(images[0]);
133 skip_if (nx != cpl_image_get_size_x(images[k]));
134 skip_if (ny != cpl_image_get_size_y(images[k]));
141 if (resol == VISIR_SPC_R_HR) {
146 if (visir_spc_optmod_init(VISIR_SPC_R_HR, wlen, &ins_settings, 0)) {
147 visir_error_set(CPL_ERROR_ILLEGAL_INPUT);
151 if (visir_spc_optmod_side_is_A(&ins_settings)) {
163 }
else if (resol == VISIR_SPC_R_MR) {
167 cpl_msg_info(cpl_func,
"Skew and Curvature: %g %g %g %g", phi, ksi, eps,
171 ksi *= CPL_MATH_RAD_DEG;
172 phi *= CPL_MATH_RAD_DEG;
177 const double fdead = 0.25;
179 const int mdeadmax = 4;
186 spectrum = cpl_image_collapse_create(images[0], 1);
189 px = cpl_image_get_data(spectrum);
191 if (doplot > 1) visir_image_col_plot(
"",
"t 'The collapsed 1/2-cycle "
192 "spectrum'",
"", spectrum, 1,1,1);
194 for (j = 1; j < mdeadmax; j++) {
195 const float g0 = px[ny -j] - px[ny-1-j];
196 const float g1 = px[ny-1-j] - px[ny-2-j];
198 cpl_msg_debug(cpl_func,
"GRAD(%g): %g <> %g", ny-j-0.5, g0, g1);
200 if ((g1 < 0 && g0 * fdead < g1) || (g1 >=0 && g0 < g1 * fdead))
205 cpl_msg_info(cpl_func,
"Rejecting dead pixels %d -> %d. "
206 "GRAD: %g << %g", ny-ndead, ny-1,
207 px[ny -ndead] - px[ny-1-ndead],
208 px[ny-1-ndead] - px[ny-2-ndead]);
210 for (i = 0; i < nx; i++) {
211 for (j = ny-ndead; j < ny; j++) {
212 skip_if (cpl_image_reject(images[0], i+1, j+1));
218 px = cpl_image_get_data(spectrum);
220 for (j = 1; j < mdeadmax; j++) {
221 const float g0 = px[j-1] - px[j];
222 const float g1 = px[j] - px[j+1];
224 cpl_msg_debug(cpl_func,
"GRAD(%g:%d): %g <> %g", j-0.5, ndead, g0, g1);
226 if ((g1 < 0 && g0 * fdead < g1) || (g1 >=0 && g0 < g1 * fdead))
231 cpl_msg_info(cpl_func,
"Rejecting dead pixels 1 -> %d. GRAD: "
232 "%g << %g", ndead, px[ndead-1] - px[ndead],
233 px[ndead] - px[ndead+1]);
235 for (i = 0; i < nx; i++) {
236 for (j = 0; j < ndead; j++) {
237 skip_if (cpl_image_reject(images[0], i+1, j+1));
241 cpl_image_delete(spectrum);
247 skip_if (visir_spc_det_warp(images, nimages, 0., 0., phi, ksi, eps, delta));
249 if (doplot > 1) visir_image_plot(
"",
"t 'The first corrected image'",
254 cpl_image_delete(spectrum);
256 return cpl_error_get_code();
278 cpl_error_code visir_spc_det_warp(cpl_image ** images,
int nimages,
279 double xshift,
double yshift,
280 double phi,
double ksi,
281 double eps,
double delta)
285 const double radius = CPL_KERNEL_DEF_WIDTH;
286 const int tabsperpix = CPL_KERNEL_TABSPERPIX;
287 const int nx = cpl_image_get_size_x(images[0]);
288 const int ny = cpl_image_get_size_y(images[0]);
289 const cpl_boolean do_warp = phi != 0 || ksi != 0 ||
290 eps != 0 || delta != 0 || xshift != 0 || yshift != 0;
295 cpl_image * copy = NULL;
296 cpl_vector * xyprofile = NULL;
297 cpl_image * coord_x = NULL;
298 cpl_image * coord_y = NULL;
301 cpl_error_code didfail = CPL_ERROR_NONE;
302 cpl_errorstate cleanstate = cpl_errorstate_get();
313 xyprofile = cpl_vector_new(1 + radius * tabsperpix);
314 cpl_vector_fill_kernel_profile(xyprofile, CPL_KERNEL_DEFAULT, radius);
315 coord_x = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
316 coord_y = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
318 piu = cpl_image_get_data(coord_x);
319 piv = cpl_image_get_data(coord_y);
323 for (ipix = 0, iv = 1; iv <= ny; iv++) {
324 for (iu = 1; iu <= nx; iu++, ipix++) {
326 skip_if (visir_spc_det_warp_xy(1, nx, ny, iu, iv,
327 xshift, yshift, phi, ksi, eps,
337 #pragma omp parallel for private(iimage, ipix, iv, iu, copy) if (nimages > 1)
339 for (iimage = 0 ; iimage < nimages; iimage++) {
340 cpl_image * image = images[iimage];
341 cpl_mask * rejected = NULL;
342 float * px = cpl_image_get_data(image);
343 double fluxprev, fluxpost;
345 cpl_binary * preject = NULL;
348 if (!do_warp || cpl_msg_get_level() <= CPL_MSG_DEBUG) {
349 nbad = cpl_image_count_rejected(image);
351 cpl_msg_debug(cpl_func,
"Raw image has %d bad pixels", nbad);
354 if (cpl_error_get_code()) {
355 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
356 irplib_error_recover(cleanstate,
"Failure for image %d", iimage+1);
360 if (!do_warp && nbad == 0)
continue;
362 fluxprev = cpl_image_get_flux(image);
364 if (cpl_error_get_code()) {
365 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
366 irplib_error_recover(cleanstate,
"Failure for image %d", iimage+1);
371 copy = cpl_image_duplicate(image);
373 if (cpl_error_get_code()) {
374 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
375 irplib_error_recover(cleanstate,
"Failure for image %d",
381 for (ipix = 0, iv = 1; iv <= ny; iv++) {
382 for (iu = 1; iu <= nx; iu++, ipix++) {
386 value = cpl_image_get_interpolated(copy, piu[ipix], piv[ipix],
390 if (confidence < 0) {
391 cpl_mask_delete(rejected);
392 didfail = cpl_error_set(cpl_func,
393 CPL_ERROR_ILLEGAL_INPUT);
394 irplib_error_recover(cleanstate,
"Failure for image %d",
399 if (confidence < 0.5) {
401 if (rejected == NULL) {
402 rejected = cpl_mask_new(nx, ny);
403 preject = cpl_mask_get_data(rejected);
405 preject[ipix] = CPL_BINARY_1;
415 cpl_image_delete(copy);
421 const cpl_error_code error
422 = cpl_image_reject_from_mask(image, rejected);
424 cpl_mask_delete(rejected);
429 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
430 irplib_error_recover(cleanstate,
"Failure for image %d",
436 cpl_msg_info(cpl_func,
"Cleaning %d bad pixels in "
437 "each of the %d images", nbad, nimages);
438 if (cpl_detector_interpolate_rejected(image)) {
439 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
440 irplib_error_recover(cleanstate,
"Failure for image %d",
447 fluxpost = cpl_image_get_flux(image);
449 if (cpl_error_get_code()) {
450 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
451 irplib_error_recover(cleanstate,
"Failure for image %d", iimage+1);
455 cpl_msg_info(cpl_func,
"Corrected distortion in image %d, flux: %g => %g",
456 1+iimage, fluxprev, fluxpost);
463 if (cpl_error_get_code())
464 cpl_msg_error(cpl_func,
"Detector unwarp failed (at %s): %s",
465 cpl_error_get_where(), cpl_error_get_message());
467 cpl_vector_delete(xyprofile);
468 cpl_image_delete(copy);
469 cpl_image_delete(coord_x);
470 cpl_image_delete(coord_y);
472 return cpl_error_get_code();
514 static cpl_error_code visir_spc_det_warp_xy(
int inv,
double nx,
double ny,
516 double xshift,
double yshift,
517 double phi,
double ksi,
518 double eps,
double delta,
519 double *pu,
double *pv)
523 #ifdef VISIR_DET_WARP_ROTATE
525 const double skew = phi + ksi;
528 cpl_ensure_code(pu, CPL_ERROR_NULL_INPUT);
529 cpl_ensure_code(pv, CPL_ERROR_NULL_INPUT);
531 cpl_ensure_code(nx > 0, CPL_ERROR_ILLEGAL_INPUT);
532 cpl_ensure_code(ny > 0, CPL_ERROR_ILLEGAL_INPUT);
543 const double R = ((ny/2)*(ny/2) + delta*delta) / fabs(2 * delta);
545 cpl_ensure_code(R >= y, CPL_ERROR_ILLEGAL_INPUT);
547 x -= (R - sqrt(R*R - y * y)) * (delta > 0 ? 1 : -1);
552 const double R = ((nx/2)*(nx/2) + eps*eps) / fabs(2 * eps);
554 cpl_ensure_code(R >= x, CPL_ERROR_ILLEGAL_INPUT);
556 y += (R - sqrt(R*R - x * x)) * (eps > 0 ? 1 : -1);
581 const double R = ((ny/2)*(ny/2) + eps*eps) / fabs(2 * eps);
583 cpl_ensure_code(R >= x, CPL_ERROR_ILLEGAL_INPUT);
585 y -= (R - sqrt(R*R - x * x)) * (eps > 0 ? 1 : -1);
589 const double R = ((ny/2)*(ny/2) + delta*delta) / fabs(2 * delta);
591 cpl_ensure_code(R >= y, CPL_ERROR_ILLEGAL_INPUT);
593 x += (R - sqrt(R*R - y * y)) * (delta > 0 ? 1 : -1);
604 return CPL_ERROR_NONE;