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(cpl_image **, int, double, double,
00055 double, double);
00056
00057 static cpl_error_code visir_spc_det_warp_xy(int, double, double, double, double,
00058 double, double, double, double,
00059 double *, double*);
00060
00061
00062
00063
00066
00092
00093 cpl_error_code visir_spc_det_fix(cpl_image ** images, int nimages,
00094 cpl_boolean is_interm,
00095 double wlen, visir_spc_resol resol,
00096 double phi, double ksi, double eps,
00097 double delta, int doplot)
00098 {
00099
00100 cpl_image * spectrum = NULL;
00101
00102 int nx = 0;
00103 int ny = 0;
00104 int k;
00105
00106
00107 skip_if (0);
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 if (visir_spc_optmod_init(VISIR_SPC_R_HR, wlen, &ins_settings)) {
00146 visir_error_set(CPL_ERROR_ILLEGAL_INPUT);
00147 skip_if(1);
00148 }
00149
00150 if (visir_spc_optmod_side_is_A(&ins_settings)) {
00151
00152 eps = 0;
00153
00154 delta *= 1.5;
00155 } else {
00156
00157 eps *= 0.115/0.052;
00158
00159 delta *= 0.5;
00160 }
00161 ksi = 0;
00162 } else if (resol == VISIR_SPC_R_MR) {
00163 eps *= 0.25;
00164 }
00165
00166 cpl_msg_info(cpl_func, "Skew and Curvature: %g %g %g %g", phi, ksi, eps,
00167 delta);
00168
00169
00170 ksi *= CPL_MATH_RAD_DEG;
00171 phi *= CPL_MATH_RAD_DEG;
00172
00173 if (!is_interm) {
00174
00175 float * px;
00176 const double fdead = 0.25;
00177 int ndead = 0;
00178 const int mdeadmax = 4;
00179 int i,j;
00180
00181 skip_if (visir_image_reject_hot(images[0], NULL));
00182
00183
00184
00185 spectrum = cpl_image_collapse_create(images[0], 1);
00186 skip_if (0);
00187
00188 px = cpl_image_get_data(spectrum);
00189
00190 if (doplot > 1) visir_image_col_plot("", "t 'The collapsed 1/2-cycle "
00191 "spectrum'", "", spectrum, 1,1,1);
00192
00193 for (j = 1; j < mdeadmax; j++) {
00194 const float g0 = px[ny -j] - px[ny-1-j];
00195 const float g1 = px[ny-1-j] - px[ny-2-j];
00196
00197 cpl_msg_debug(cpl_func, "GRAD(%g): %g <> %g", ny-j-0.5, g0, g1);
00198
00199 if ((g1 < 0 && g0 * fdead < g1) || (g1 >=0 && g0 < g1 * fdead))
00200 ndead = j;
00201 }
00202
00203 if (ndead) {
00204 cpl_msg_info(cpl_func, "Rejecting dead pixels %d -> %d. "
00205 "GRAD: %g << %g", ny-ndead, ny-1,
00206 px[ny -ndead] - px[ny-1-ndead],
00207 px[ny-1-ndead] - px[ny-2-ndead]);
00208
00209 for (i = 0; i < nx; i++) {
00210 for (j = ny-ndead; j < ny; j++) {
00211 skip_if (cpl_image_reject(images[0], i+1, j+1));
00212 }
00213 }
00214 ndead = 0;
00215 }
00216
00217 px = cpl_image_get_data(spectrum);
00218
00219 for (j = 1; j < mdeadmax; j++) {
00220 const float g0 = px[j-1] - px[j];
00221 const float g1 = px[j] - px[j+1];
00222
00223 cpl_msg_debug(cpl_func, "GRAD(%g:%d): %g <> %g", j-0.5, ndead, g0, g1);
00224
00225 if ((g1 < 0 && g0 * fdead < g1) || (g1 >=0 && g0 < g1 * fdead))
00226 ndead = j;
00227 }
00228
00229 if (ndead) {
00230 cpl_msg_info(cpl_func, "Rejecting dead pixels 1 -> %d. GRAD: "
00231 "%g << %g", ndead, px[ndead-1] - px[ndead],
00232 px[ndead] - px[ndead+1]);
00233
00234 for (i = 0; i < nx; i++) {
00235 for (j = 0; j < ndead; j++) {
00236 skip_if (cpl_image_reject(images[0], i+1, j+1));
00237 }
00238 }
00239 }
00240 cpl_image_delete(spectrum);
00241 spectrum = NULL;
00242
00243 }
00244
00245
00246 skip_if (visir_spc_det_warp(images, nimages, phi, ksi, eps, delta));
00247
00248 if (doplot > 1) visir_image_plot("", "t 'The first corrected image'",
00249 "", images[0]);
00250
00251 end_skip;
00252
00253 cpl_image_delete(spectrum);
00254
00255 return cpl_error_get_code();
00256
00257 }
00258
00259
00262
00278
00279 static cpl_error_code visir_spc_det_warp(cpl_image ** images, int nimages,
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 || eps != 0 || delta != 0;
00290 int iu, iv;
00291 int iimage;
00292 int ipix;
00293
00294 cpl_image * copy = NULL;
00295 cpl_vector * xyprofile = NULL;
00296 cpl_image * coord_x = NULL;
00297 cpl_image * coord_y = NULL;
00298 double * piv = NULL;
00299 double * piu = NULL;
00300 cpl_error_code didfail = CPL_ERROR_NONE;
00301 cpl_errorstate cleanstate = cpl_errorstate_get();
00302
00303
00304 skip_if (0);
00305
00306 if (do_warp) {
00307 double x = 0.0;
00308 double y = 0.0;
00309
00310
00311
00312 xyprofile = cpl_vector_new(1 + radius * tabsperpix);
00313 cpl_vector_fill_kernel_profile(xyprofile, CPL_KERNEL_DEFAULT, radius);
00314 coord_x = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00315 coord_y = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00316
00317 piu = cpl_image_get_data(coord_x);
00318 piv = cpl_image_get_data(coord_y);
00319
00320 skip_if (0);
00321
00322 for (ipix = 0, iv = 1; iv <= ny; iv++) {
00323 for (iu = 1; iu <= nx; iu++, ipix++) {
00324
00325 skip_if (visir_spc_det_warp_xy(1, nx, ny, iu, iv, phi, ksi, eps,
00326 delta, &x, &y));
00327 piu[ipix] = x;
00328 piv[ipix] = y;
00329 }
00330 }
00331
00332 }
00333
00334 #ifdef _OPENMP
00335 #pragma omp parallel for private(iimage, ipix, iv, iu, copy)
00336 #endif
00337 for (iimage = 0 ; iimage < nimages; iimage++) {
00338 cpl_image * image = images[iimage];
00339 cpl_mask * rejected = NULL;
00340 float * px = cpl_image_get_data(image);
00341 double fluxprev, fluxpost;
00342 int nbad = 0;
00343 cpl_binary * preject = NULL;
00344
00345
00346 if (!do_warp || cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00347 nbad = cpl_image_count_rejected(image);
00348
00349 cpl_msg_debug(cpl_func, "Raw image has %d bad pixels", nbad);
00350 }
00351
00352 if (cpl_error_get_code()) {
00353 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00354 irplib_error_recover(cleanstate, "Failure for image %d", iimage+1);
00355 continue;
00356 }
00357
00358 if (!do_warp && nbad == 0) continue;
00359
00360 fluxprev = cpl_image_get_flux(image);
00361
00362 if (cpl_error_get_code()) {
00363 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00364 irplib_error_recover(cleanstate, "Failure for image %d", iimage+1);
00365 continue;
00366 }
00367
00368 if (do_warp) {
00369 copy = cpl_image_duplicate(image);
00370
00371 if (cpl_error_get_code()) {
00372 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00373 irplib_error_recover(cleanstate, "Failure for image %d",
00374 iimage+1);
00375 continue;
00376 }
00377
00378 nbad = 0;
00379 for (ipix = 0, iv = 1; iv <= ny; iv++) {
00380 for (iu = 1; iu <= nx; iu++, ipix++) {
00381 double value;
00382 double confidence;
00383
00384 value = cpl_image_get_interpolated(copy, piu[ipix], piv[ipix],
00385 xyprofile, radius,
00386 xyprofile, radius,
00387 &confidence);
00388 if (confidence < 0) {
00389 cpl_mask_delete(rejected);
00390 didfail = cpl_error_set(cpl_func,
00391 CPL_ERROR_ILLEGAL_INPUT);
00392 irplib_error_recover(cleanstate, "Failure for image %d",
00393 iimage+1);
00394 continue;
00395 }
00396
00397 if (confidence < 0.5) {
00398 nbad++;
00399 if (rejected == NULL) {
00400 rejected = cpl_mask_new(nx, ny);
00401 preject = cpl_mask_get_data(rejected);
00402 }
00403 preject[ipix] = CPL_BINARY_1;
00404 } else {
00405
00406
00407 px[ipix] = value;
00408 }
00409 }
00410 }
00411
00412 cpl_image_delete(copy);
00413 copy = NULL;
00414 }
00415
00416 if (nbad > 0) {
00417 if (do_warp) {
00418 const cpl_error_code error
00419 = cpl_image_reject_from_mask(image, rejected);
00420
00421 cpl_mask_delete(rejected);
00422 rejected = NULL;
00423 preject = NULL;
00424
00425 if (error) {
00426 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00427 irplib_error_recover(cleanstate, "Failure for image %d",
00428 iimage+1);
00429 continue;
00430 }
00431 }
00432 if (iimage == 0)
00433 cpl_msg_info(cpl_func, "Cleaning %d bad pixels in "
00434 "each of the %d images", nbad, nimages);
00435 if (cpl_detector_interpolate_rejected(image)) {
00436 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00437 irplib_error_recover(cleanstate, "Failure for image %d",
00438 iimage+1);
00439 continue;
00440 }
00441
00442 }
00443
00444 fluxpost = cpl_image_get_flux(image);
00445
00446 if (cpl_error_get_code()) {
00447 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00448 irplib_error_recover(cleanstate, "Failure for image %d", iimage+1);
00449 continue;
00450 }
00451
00452 cpl_msg_info(cpl_func, "Corrected distortion in image %d, flux: %g => %g",
00453 1+iimage, fluxprev, fluxpost);
00454
00455 }
00456 skip_if(didfail);
00457
00458 end_skip;
00459
00460 if (cpl_error_get_code())
00461 cpl_msg_error(cpl_func, "Detector unwarp failed (at %s): %s",
00462 cpl_error_get_where(), cpl_error_get_message());
00463
00464 cpl_vector_delete(xyprofile);
00465 cpl_image_delete(copy);
00466 cpl_image_delete(coord_x);
00467 cpl_image_delete(coord_y);
00468
00469 return cpl_error_get_code();
00470 }
00471
00472
00504
00505 static cpl_error_code visir_spc_det_warp_xy(int inv, double nx, double ny,
00506 double x, double y,
00507 double phi, double ksi,
00508 double eps, double delta,
00509 double *pu, double *pv)
00510 {
00511
00512
00513 #ifdef VISIR_DET_WARP_ROTATE
00514 double z;
00515 const double skew = phi + ksi;
00516 #endif
00517
00518 cpl_ensure_code(pu, CPL_ERROR_NULL_INPUT);
00519 cpl_ensure_code(pv, CPL_ERROR_NULL_INPUT);
00520
00521 cpl_ensure_code(nx > 0, CPL_ERROR_ILLEGAL_INPUT);
00522 cpl_ensure_code(ny > 0, CPL_ERROR_ILLEGAL_INPUT);
00523
00524
00525
00526 x -= (nx+1)/2;
00527 y -= (ny+1)/2;
00528
00529 if (inv) {
00530
00531 if (delta != 0) {
00532
00533 const double R = ((ny/2)*(ny/2) + delta*delta) / fabs(2 * delta);
00534
00535 cpl_ensure_code(R >= y, CPL_ERROR_ILLEGAL_INPUT);
00536
00537 x -= (R - sqrt(R*R - y * y)) * (delta > 0 ? 1 : -1);
00538 }
00539
00540 if (eps != 0) {
00541
00542 const double R = ((ny/2)*(ny/2) + eps*eps) / fabs(2 * eps);
00543
00544 cpl_ensure_code(R >= x, CPL_ERROR_ILLEGAL_INPUT);
00545
00546 y += (R - sqrt(R*R - x * x)) * (eps > 0 ? 1 : -1);
00547 }
00548
00549
00550 y -= x * tan(phi);
00551
00552
00553 x -= y * tan(ksi);
00554
00555 } else {
00556
00557
00558 x += y * tan(ksi);
00559
00560
00561 y += x * tan(phi);
00562
00563 if (eps != 0) {
00564
00565 const double R = ((ny/2)*(ny/2) + eps*eps) / fabs(2 * eps);
00566
00567 cpl_ensure_code(R >= x, CPL_ERROR_ILLEGAL_INPUT);
00568
00569 y -= (R - sqrt(R*R - x * x)) * (eps > 0 ? 1 : -1);
00570 }
00571 if (delta != 0) {
00572
00573 const double R = ((ny/2)*(ny/2) + delta*delta) / fabs(2 * delta);
00574
00575 cpl_ensure_code(R >= y, CPL_ERROR_ILLEGAL_INPUT);
00576
00577 x += (R - sqrt(R*R - y * y)) * (delta > 0 ? 1 : -1);
00578 }
00579 }
00580
00581
00582 x += (nx+1)/2;
00583 y += (ny+1)/2;
00584
00585 *pu = x;
00586 *pv = y;
00587
00588 return cpl_error_get_code();
00589
00590 }