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