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 double fluxprev, fluxpost;
00288 const int nx = cpl_image_get_size_x(images[0]);
00289 const int ny = cpl_image_get_size_y(images[0]);
00290 const cpl_boolean do_warp = phi != 0 || ksi != 0 || eps != 0 || delta != 0;
00291 int iu, iv;
00292 int iimage;
00293 int nbad = 0;
00294 int ipix;
00295
00296 cpl_image * copy = NULL;
00297 cpl_vector * xyprofile = NULL;
00298 cpl_mask * rejected = NULL;
00299 cpl_binary * preject = NULL;
00300 cpl_image * coord_x = NULL;
00301 cpl_image * coord_y = NULL;
00302 double * piv = NULL;
00303 double * piu = NULL;
00304
00305
00306 skip_if (0);
00307
00308 if (do_warp) {
00309 double x = 0.0;
00310 double y = 0.0;
00311
00312 rejected = cpl_mask_new(nx, ny);
00313 preject = cpl_mask_get_data(rejected);
00314
00315 skip_if (0);
00316
00317
00318
00319 xyprofile = cpl_vector_new(1 + radius * tabsperpix);
00320 cpl_vector_fill_kernel_profile(xyprofile, CPL_KERNEL_DEFAULT, radius);
00321 coord_x = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00322 coord_y = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00323
00324 piu = cpl_image_get_data(coord_x);
00325 piv = cpl_image_get_data(coord_y);
00326
00327 skip_if (0);
00328
00329 for (ipix = 0, iv = 1; iv <= ny; iv++) {
00330 for (iu = 1; iu <= nx; iu++, ipix++) {
00331
00332 skip_if (visir_spc_det_warp_xy(1, nx, ny, iu, iv, phi, ksi, eps,
00333 delta, &x, &y));
00334 piu[ipix] = x;
00335 piv[ipix] = y;
00336 }
00337 }
00338
00339 }
00340
00341
00342 for (iimage = 0 ; iimage < nimages; iimage++) {
00343 cpl_image * image = images[iimage];
00344 float * px = cpl_image_get_data(image);
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 skip_if (0);
00353
00354 if (!do_warp && nbad == 0) continue;
00355
00356 fluxprev = cpl_image_get_flux(image);
00357
00358 skip_if(0);
00359
00360 if (do_warp) {
00361 copy = cpl_image_duplicate(image);
00362
00363 skip_if (0);
00364
00365 nbad = 0;
00366 for (ipix = 0, iv = 1; iv <= ny; iv++) {
00367 for (iu = 1; iu <= nx; iu++, ipix++) {
00368 double value;
00369 double confidence;
00370
00371 value = cpl_image_get_interpolated(copy, piu[ipix], piv[ipix],
00372 xyprofile, radius,
00373 xyprofile, radius,
00374 &confidence);
00375 skip_if (confidence < 0);
00376
00377 if (confidence < 0.5) {
00378 nbad++;
00379 preject[ipix] = CPL_BINARY_1;
00380 } else {
00381
00382
00383 px[ipix] = value;
00384 }
00385 }
00386 }
00387
00388 cpl_image_delete(copy);
00389 copy = NULL;
00390 }
00391
00392 if (nbad > 0) {
00393 if (do_warp) {
00394 skip_if(cpl_image_reject_from_mask(image, rejected));
00395
00396 cpl_mask_delete(rejected);
00397 rejected = cpl_mask_new(nx, ny);
00398 preject = cpl_mask_get_data(rejected);
00399
00400
00401 }
00402 if (iimage == 0) cpl_msg_info(cpl_func, "Cleaning %d bad pixels in eac"
00403 "h of the %d images", nbad, nimages);
00404 skip_if (cpl_detector_interpolate_rejected(image));
00405
00406 }
00407
00408 fluxpost = cpl_image_get_flux(image);
00409
00410 skip_if(0);
00411
00412 cpl_msg_info(cpl_func, "Corrected distortion in image %d, flux: %g => %g",
00413 1+iimage, fluxprev, fluxpost);
00414
00415 }
00416
00417 end_skip;
00418
00419 if (cpl_error_get_code())
00420 cpl_msg_error(cpl_func, "Detector unwarp failed (at %s): %s",
00421 cpl_error_get_where(), cpl_error_get_message());
00422
00423 cpl_mask_delete(rejected);
00424 cpl_vector_delete(xyprofile);
00425 cpl_image_delete(copy);
00426 cpl_image_delete(coord_x);
00427 cpl_image_delete(coord_y);
00428
00429 return cpl_error_get_code();
00430 }
00431
00432
00464
00465 static cpl_error_code visir_spc_det_warp_xy(int inv, double nx, double ny,
00466 double x, double y,
00467 double phi, double ksi,
00468 double eps, double delta,
00469 double *pu, double *pv)
00470 {
00471
00472
00473 #ifdef VISIR_DET_WARP_ROTATE
00474 double z;
00475 const double skew = phi + ksi;
00476 #endif
00477
00478 cpl_ensure_code(pu, CPL_ERROR_NULL_INPUT);
00479 cpl_ensure_code(pv, CPL_ERROR_NULL_INPUT);
00480
00481 cpl_ensure_code(nx > 0, CPL_ERROR_ILLEGAL_INPUT);
00482 cpl_ensure_code(ny > 0, CPL_ERROR_ILLEGAL_INPUT);
00483
00484
00485
00486 x -= (nx+1)/2;
00487 y -= (ny+1)/2;
00488
00489 if (inv) {
00490
00491 if (delta != 0) {
00492
00493 const double R = ((ny/2)*(ny/2) + delta*delta) / fabs(2 * delta);
00494
00495 cpl_ensure_code(R >= y, CPL_ERROR_ILLEGAL_INPUT);
00496
00497 x -= (R - sqrt(R*R - y * y)) * (delta > 0 ? 1 : -1);
00498 }
00499
00500 if (eps != 0) {
00501
00502 const double R = ((ny/2)*(ny/2) + eps*eps) / fabs(2 * eps);
00503
00504 cpl_ensure_code(R >= x, CPL_ERROR_ILLEGAL_INPUT);
00505
00506 y += (R - sqrt(R*R - x * x)) * (eps > 0 ? 1 : -1);
00507 }
00508
00509
00510 y -= x * tan(phi);
00511
00512
00513 x -= y * tan(ksi);
00514
00515 } else {
00516
00517
00518 x += y * tan(ksi);
00519
00520
00521 y += x * tan(phi);
00522
00523 if (eps != 0) {
00524
00525 const double R = ((ny/2)*(ny/2) + eps*eps) / fabs(2 * eps);
00526
00527 cpl_ensure_code(R >= x, CPL_ERROR_ILLEGAL_INPUT);
00528
00529 y -= (R - sqrt(R*R - x * x)) * (eps > 0 ? 1 : -1);
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
00541
00542 x += (nx+1)/2;
00543 y += (ny+1)/2;
00544
00545 *pu = x;
00546 *pv = y;
00547
00548 return cpl_error_get_code();
00549
00550 }