00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include <string.h>
00037 #include <math.h>
00038
00039 #include <cpl.h>
00040
00041 #include "visir_spc_distortion.h"
00042 #include "visir_utils.h"
00043
00044
00048
00049
00050
00051
00052
00053
00054 static cpl_error_code visir_spc_det_warp_xy(int, double, double, double, double,
00055 double, double, double, double,
00056 double, double, double *, double*);
00057
00058
00059
00060
00063
00089
00090 cpl_error_code visir_spc_det_fix(cpl_image ** images, int nimages,
00091 cpl_boolean is_interm,
00092 double wlen, visir_spc_resol resol,
00093 double phi, double ksi, double eps,
00094 double delta, int doplot)
00095 {
00096
00097 cpl_image * spectrum = NULL;
00098
00099 int nx = 0;
00100 int ny = 0;
00101 int k;
00102
00103
00104 skip_if (0);
00105
00106
00107 if (resol == VISIR_SPC_R_LRP) return CPL_ERROR_NONE;
00108
00109 skip_if (images == NULL);
00110 skip_if (nimages <= 0);
00111
00112 skip_if (!is_interm && nimages != 1);
00113
00114 for (k=0; k < nimages; k++) {
00115 if (images[k] == NULL) break;
00116
00117 if (cpl_image_get_type(images[k]) != CPL_TYPE_FLOAT) {
00118
00119 cpl_image * to_float = cpl_image_cast(images[k], CPL_TYPE_FLOAT);
00120
00121 cpl_image_delete(images[k]);
00122
00123 images[k] = to_float;
00124
00125 }
00126
00127 if (k == 0) {
00128 nx = cpl_image_get_size_x(images[0]);
00129 ny = cpl_image_get_size_y(images[0]);
00130
00131 skip_if (nx < 1);
00132 } else {
00133 skip_if (nx != cpl_image_get_size_x(images[k]));
00134 skip_if (ny != cpl_image_get_size_y(images[k]));
00135 }
00136
00137 }
00138
00139
00140
00141 if (resol == VISIR_SPC_R_HR) {
00142
00143 visir_optmod ins_settings;
00144
00145
00146 if (visir_spc_optmod_init(VISIR_SPC_R_HR, wlen, &ins_settings, 0)) {
00147 visir_error_set(CPL_ERROR_ILLEGAL_INPUT);
00148 skip_if(1);
00149 }
00150
00151 if (visir_spc_optmod_side_is_A(&ins_settings)) {
00152
00153 eps = 0;
00154
00155 delta *= 1.5;
00156 } else {
00157
00158 eps *= 0.115/0.052;
00159
00160 delta *= 0.5;
00161 }
00162 ksi = 0;
00163 } else if (resol == VISIR_SPC_R_MR) {
00164 eps *= 0.25;
00165 }
00166
00167 cpl_msg_info(cpl_func, "Skew and Curvature: %g %g %g %g", phi, ksi, eps,
00168 delta);
00169
00170
00171 ksi *= CPL_MATH_RAD_DEG;
00172 phi *= CPL_MATH_RAD_DEG;
00173
00174 if (!is_interm) {
00175
00176 float * px;
00177 const double fdead = 0.25;
00178 int ndead = 0;
00179 const int mdeadmax = 4;
00180 int i,j;
00181
00182 skip_if (visir_image_reject_hot(images[0], NULL));
00183
00184
00185
00186 spectrum = cpl_image_collapse_create(images[0], 1);
00187 skip_if (0);
00188
00189 px = cpl_image_get_data(spectrum);
00190
00191 if (doplot > 1) visir_image_col_plot("", "t 'The collapsed 1/2-cycle "
00192 "spectrum'", "", spectrum, 1,1,1);
00193
00194 for (j = 1; j < mdeadmax; j++) {
00195 const float g0 = px[ny -j] - px[ny-1-j];
00196 const float g1 = px[ny-1-j] - px[ny-2-j];
00197
00198 cpl_msg_debug(cpl_func, "GRAD(%g): %g <> %g", ny-j-0.5, g0, g1);
00199
00200 if ((g1 < 0 && g0 * fdead < g1) || (g1 >=0 && g0 < g1 * fdead))
00201 ndead = j;
00202 }
00203
00204 if (ndead) {
00205 cpl_msg_info(cpl_func, "Rejecting dead pixels %d -> %d. "
00206 "GRAD: %g << %g", ny-ndead, ny-1,
00207 px[ny -ndead] - px[ny-1-ndead],
00208 px[ny-1-ndead] - px[ny-2-ndead]);
00209
00210 for (i = 0; i < nx; i++) {
00211 for (j = ny-ndead; j < ny; j++) {
00212 skip_if (cpl_image_reject(images[0], i+1, j+1));
00213 }
00214 }
00215 ndead = 0;
00216 }
00217
00218 px = cpl_image_get_data(spectrum);
00219
00220 for (j = 1; j < mdeadmax; j++) {
00221 const float g0 = px[j-1] - px[j];
00222 const float g1 = px[j] - px[j+1];
00223
00224 cpl_msg_debug(cpl_func, "GRAD(%g:%d): %g <> %g", j-0.5, ndead, g0, g1);
00225
00226 if ((g1 < 0 && g0 * fdead < g1) || (g1 >=0 && g0 < g1 * fdead))
00227 ndead = j;
00228 }
00229
00230 if (ndead) {
00231 cpl_msg_info(cpl_func, "Rejecting dead pixels 1 -> %d. GRAD: "
00232 "%g << %g", ndead, px[ndead-1] - px[ndead],
00233 px[ndead] - px[ndead+1]);
00234
00235 for (i = 0; i < nx; i++) {
00236 for (j = 0; j < ndead; j++) {
00237 skip_if (cpl_image_reject(images[0], i+1, j+1));
00238 }
00239 }
00240 }
00241 cpl_image_delete(spectrum);
00242 spectrum = NULL;
00243
00244 }
00245
00246
00247 skip_if (visir_spc_det_warp(images, nimages, 0., 0., phi, ksi, eps, delta));
00248
00249 if (doplot > 1) visir_image_plot("", "t 'The first corrected image'",
00250 "", images[0]);
00251
00252 end_skip;
00253
00254 cpl_image_delete(spectrum);
00255
00256 return cpl_error_get_code();
00257
00258 }
00259
00260
00261
00277
00278 cpl_error_code visir_spc_det_warp(cpl_image ** images, int nimages,
00279 double xshift, double yshift,
00280 double phi, double ksi,
00281 double eps, double delta)
00282 {
00283
00284
00285 const double radius = CPL_KERNEL_DEF_WIDTH;
00286 const int tabsperpix = CPL_KERNEL_TABSPERPIX;
00287 const int nx = cpl_image_get_size_x(images[0]);
00288 const int ny = cpl_image_get_size_y(images[0]);
00289 const cpl_boolean do_warp = phi != 0 || ksi != 0 ||
00290 eps != 0 || delta != 0 || xshift != 0 || yshift != 0;
00291 int iu, iv;
00292 int iimage;
00293 int ipix;
00294
00295 cpl_image * copy = NULL;
00296 cpl_vector * xyprofile = NULL;
00297 cpl_image * coord_x = NULL;
00298 cpl_image * coord_y = NULL;
00299 double * piv = NULL;
00300 double * piu = NULL;
00301 cpl_error_code didfail = CPL_ERROR_NONE;
00302 cpl_errorstate cleanstate = cpl_errorstate_get();
00303
00304
00305 skip_if (0);
00306
00307 if (do_warp) {
00308 double x = 0.0;
00309 double y = 0.0;
00310
00311
00312
00313 xyprofile = cpl_vector_new(1 + radius * tabsperpix);
00314 cpl_vector_fill_kernel_profile(xyprofile, CPL_KERNEL_DEFAULT, radius);
00315 coord_x = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00316 coord_y = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00317
00318 piu = cpl_image_get_data(coord_x);
00319 piv = cpl_image_get_data(coord_y);
00320
00321 skip_if (0);
00322
00323 for (ipix = 0, iv = 1; iv <= ny; iv++) {
00324 for (iu = 1; iu <= nx; iu++, ipix++) {
00325
00326 skip_if (visir_spc_det_warp_xy(1, nx, ny, iu, iv,
00327 xshift, yshift, phi, ksi, eps,
00328 delta, &x, &y));
00329 piu[ipix] = x;
00330 piv[ipix] = y;
00331 }
00332 }
00333
00334 }
00335
00336 #ifdef _OPENMP
00337 #pragma omp parallel for private(iimage, ipix, iv, iu, copy) if (nimages > 1)
00338 #endif
00339 for (iimage = 0 ; iimage < nimages; iimage++) {
00340 cpl_image * image = images[iimage];
00341 cpl_mask * rejected = NULL;
00342 float * px = cpl_image_get_data(image);
00343 double fluxprev, fluxpost;
00344 int nbad = 0;
00345 cpl_binary * preject = NULL;
00346
00347
00348 if (!do_warp || cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00349 nbad = cpl_image_count_rejected(image);
00350
00351 cpl_msg_debug(cpl_func, "Raw image has %d bad pixels", nbad);
00352 }
00353
00354 if (cpl_error_get_code()) {
00355 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00356 irplib_error_recover(cleanstate, "Failure for image %d", iimage+1);
00357 continue;
00358 }
00359
00360 if (!do_warp && nbad == 0) continue;
00361
00362 fluxprev = cpl_image_get_flux(image);
00363
00364 if (cpl_error_get_code()) {
00365 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00366 irplib_error_recover(cleanstate, "Failure for image %d", iimage+1);
00367 continue;
00368 }
00369
00370 if (do_warp) {
00371 copy = cpl_image_duplicate(image);
00372
00373 if (cpl_error_get_code()) {
00374 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00375 irplib_error_recover(cleanstate, "Failure for image %d",
00376 iimage+1);
00377 continue;
00378 }
00379
00380 nbad = 0;
00381 for (ipix = 0, iv = 1; iv <= ny; iv++) {
00382 for (iu = 1; iu <= nx; iu++, ipix++) {
00383 double value;
00384 double confidence;
00385
00386 value = cpl_image_get_interpolated(copy, piu[ipix], piv[ipix],
00387 xyprofile, radius,
00388 xyprofile, radius,
00389 &confidence);
00390 if (confidence < 0) {
00391 cpl_mask_delete(rejected);
00392 didfail = cpl_error_set(cpl_func,
00393 CPL_ERROR_ILLEGAL_INPUT);
00394 irplib_error_recover(cleanstate, "Failure for image %d",
00395 iimage+1);
00396 continue;
00397 }
00398
00399 if (confidence < 0.5) {
00400 nbad++;
00401 if (rejected == NULL) {
00402 rejected = cpl_mask_new(nx, ny);
00403 preject = cpl_mask_get_data(rejected);
00404 }
00405 preject[ipix] = CPL_BINARY_1;
00406 px[ipix] = NAN;
00407 } else {
00408
00409
00410 px[ipix] = value;
00411 }
00412 }
00413 }
00414
00415 cpl_image_delete(copy);
00416 copy = NULL;
00417 }
00418
00419 if (nbad > 0) {
00420 if (do_warp) {
00421 const cpl_error_code error
00422 = cpl_image_reject_from_mask(image, rejected);
00423
00424 cpl_mask_delete(rejected);
00425 rejected = NULL;
00426 preject = NULL;
00427
00428 if (error) {
00429 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00430 irplib_error_recover(cleanstate, "Failure for image %d",
00431 iimage+1);
00432 continue;
00433 }
00434 }
00435 if (iimage == 0)
00436 cpl_msg_info(cpl_func, "Cleaning %d bad pixels in "
00437 "each of the %d images", nbad, nimages);
00438 if (cpl_detector_interpolate_rejected(image)) {
00439 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00440 irplib_error_recover(cleanstate, "Failure for image %d",
00441 iimage+1);
00442 continue;
00443 }
00444
00445 }
00446
00447 fluxpost = cpl_image_get_flux(image);
00448
00449 if (cpl_error_get_code()) {
00450 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00451 irplib_error_recover(cleanstate, "Failure for image %d", iimage+1);
00452 continue;
00453 }
00454
00455 cpl_msg_info(cpl_func, "Corrected distortion in image %d, flux: %g => %g",
00456 1+iimage, fluxprev, fluxpost);
00457
00458 }
00459 skip_if(didfail);
00460
00461 end_skip;
00462
00463 if (cpl_error_get_code())
00464 cpl_msg_error(cpl_func, "Detector unwarp failed (at %s): %s",
00465 cpl_error_get_where(), cpl_error_get_message());
00466
00467 cpl_vector_delete(xyprofile);
00468 cpl_image_delete(copy);
00469 cpl_image_delete(coord_x);
00470 cpl_image_delete(coord_y);
00471
00472 return cpl_error_get_code();
00473 }
00474
00477
00513
00514 static cpl_error_code visir_spc_det_warp_xy(int inv, double nx, double ny,
00515 double x, double y,
00516 double xshift, double yshift,
00517 double phi, double ksi,
00518 double eps, double delta,
00519 double *pu, double *pv)
00520 {
00521
00522
00523 #ifdef VISIR_DET_WARP_ROTATE
00524 double z;
00525 const double skew = phi + ksi;
00526 #endif
00527
00528 cpl_ensure_code(pu, CPL_ERROR_NULL_INPUT);
00529 cpl_ensure_code(pv, CPL_ERROR_NULL_INPUT);
00530
00531 cpl_ensure_code(nx > 0, CPL_ERROR_ILLEGAL_INPUT);
00532 cpl_ensure_code(ny > 0, CPL_ERROR_ILLEGAL_INPUT);
00533
00534
00535
00536 x -= (nx+1)/2;
00537 y -= (ny+1)/2;
00538
00539 if (inv) {
00540
00541 if (delta != 0) {
00542
00543 const double R = ((ny/2)*(ny/2) + delta*delta) / fabs(2 * delta);
00544
00545 cpl_ensure_code(R >= y, CPL_ERROR_ILLEGAL_INPUT);
00546
00547 x -= (R - sqrt(R*R - y * y)) * (delta > 0 ? 1 : -1);
00548 }
00549
00550 if (eps != 0) {
00551
00552 const double R = ((nx/2)*(nx/2) + eps*eps) / fabs(2 * eps);
00553
00554 cpl_ensure_code(R >= x, CPL_ERROR_ILLEGAL_INPUT);
00555
00556 y += (R - sqrt(R*R - x * x)) * (eps > 0 ? 1 : -1);
00557 }
00558
00559
00560 y -= x * tan(phi);
00561
00562
00563 x -= y * tan(ksi);
00564
00565 x -= xshift;
00566 y -= yshift;
00567
00568 } else {
00569
00570 x += xshift;
00571 y += yshift;
00572
00573
00574 x += y * tan(ksi);
00575
00576
00577 y += x * tan(phi);
00578
00579 if (eps != 0) {
00580
00581 const double R = ((ny/2)*(ny/2) + eps*eps) / fabs(2 * eps);
00582
00583 cpl_ensure_code(R >= x, CPL_ERROR_ILLEGAL_INPUT);
00584
00585 y -= (R - sqrt(R*R - x * x)) * (eps > 0 ? 1 : -1);
00586 }
00587 if (delta != 0) {
00588
00589 const double R = ((ny/2)*(ny/2) + delta*delta) / fabs(2 * delta);
00590
00591 cpl_ensure_code(R >= y, CPL_ERROR_ILLEGAL_INPUT);
00592
00593 x += (R - sqrt(R*R - y * y)) * (delta > 0 ? 1 : -1);
00594 }
00595 }
00596
00597
00598 x += (nx+1)/2;
00599 y += (ny+1)/2;
00600
00601 *pu = x;
00602 *pv = y;
00603
00604 return CPL_ERROR_NONE;
00605
00606 }