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 <math.h>
00037 #include <float.h>
00038 #include <cpl.h>
00039
00040 #include "irplib_plugin.h"
00041 #include "irplib_utils.h"
00042 #include "irplib_spectrum.h"
00043
00044 #include "isaac_utils.h"
00045 #include "isaac_pfits.h"
00046 #include "isaac_dfs.h"
00047
00048
00049
00050
00051
00052 #define RECIPE_STRING "isaac_spc_startrace"
00053
00054 #define Z_LR_LEFT_REJ 300
00055 #define Z_LR_RIGHT_REJ 325
00056 #define SZ_LR_LEFT_REJ 300
00057 #define SZ_LR_RIGHT_REJ 325
00058 #define J_LR_LEFT_REJ 200
00059 #define J_LR_RIGHT_REJ 200
00060 #define SH_LR_LEFT_REJ 150
00061 #define SH_LR_RIGHT_REJ 175
00062 #define SK_LR_LEFT_REJ 150
00063 #define SK_LR_RIGHT_REJ 175
00064 #define MR_LEFT_REJ 30
00065 #define MR_RIGHT_REJ 30
00066
00067
00068
00069
00070
00071 static cpl_error_code isaac_spc_startrace_reduce(cpl_frameset *,
00072 const cpl_frameset *,
00073 const cpl_matrix *, char,
00074 const cpl_parameterlist *);
00075
00076 static cpl_size * isaac_spc_startrace_resol(cpl_frameset *);
00077 static cpl_imagelist * isaac_spc_startrace_load(const cpl_frameset *);
00078 static cpl_matrix * isaac_spc_startrace_starpos(const cpl_frameset *);
00079 static cpl_polynomial * isaac_spc_startrace_shape(cpl_image *, double, char,
00080 double *);
00081 static cpl_polynomial * isaac_spc_startrace_distor(cpl_polynomial **,
00082 cpl_vector *, int, int);
00083 static cpl_error_code isaac_spc_startrace_save(cpl_frameset *,
00084 const cpl_table *,
00085 const cpl_matrix *,
00086 const cpl_vector *,
00087 cpl_polynomial **,
00088 const cpl_frameset *,
00089 char,
00090 const cpl_parameterlist *);
00091
00092
00093 cpl_recipe_define(isaac_spc_startrace, ISAAC_BINARY_VERSION,
00094 "Lars Lundin", PACKAGE_BUGREPORT, "2002, 2003, 2008",
00095 "ISAAC Spectro startrace recipe",
00096 RECIPE_STRING " -- ISAAC Spectro startrace recipe\n"
00097 "The files listed in the Set Of Frames (sof-file) "
00098 "must be tagged:\n"
00099 "raw-file.fits "ISAAC_SPC_STARTRACE_IM_RAW" or\n"
00100 "raw-file.fits "ISAAC_SPC_STARTRACE_SP_RAW"\n"
00101 "Given N imaging frames, the spectro frames must consist of "
00102 "N (or zero) low resolution frames and "
00103 "N (or zero) medium resolution frames.");
00104
00105
00106
00107
00108
00109 static struct {
00110
00111 cpl_size degree;
00112 int spec_width;
00113 int reject_left;
00114 int reject_right;
00115 int display;
00116
00117 int arm;
00118 isaac_band band;
00119 double corr_is1;
00120 double corr_is2;
00121 double corr_is3;
00122 double shapes_fit_q;
00123 double dist1;
00124 double distx;
00125 double disty;
00126 double distxy;
00127 double distxx;
00128 double distyy;
00129 } isaac_spc_startrace_config;
00130
00131
00132
00133
00134
00135
00143
00144 static
00145 cpl_error_code isaac_spc_startrace_fill_parameterlist(cpl_parameterlist * self)
00146 {
00147 const char * context = PACKAGE "." RECIPE_STRING;
00148 cpl_error_code err;
00149
00150 cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
00151
00152
00153
00154
00155 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00156 "degree", 3, "deg",
00157 context, "polynomial degree");
00158 cpl_ensure_code(!err, err);
00159
00160
00161 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00162 "spectrum_width", 40, "spec_width",
00163 context, "spectrum width");
00164 cpl_ensure_code(!err, err);
00165
00166
00167 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00168 "reject_left", -1, NULL,
00169 context, "left part rejection");
00170 cpl_ensure_code(!err, err);
00171
00172
00173 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00174 "reject_right", -1, NULL,
00175 context, "right part rejection");
00176 cpl_ensure_code(!err, err);
00177
00178
00179 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
00180 "display", CPL_FALSE, NULL, context,
00181 "Flag to make plots");
00182 cpl_ensure_code(!err, err);
00183
00184 return CPL_ERROR_NONE;
00185 }
00186
00187
00188
00196
00197 static int isaac_spc_startrace(cpl_frameset * framelist,
00198 const cpl_parameterlist * parlist)
00199 {
00200 const char * sval;
00201 cpl_size * labels = NULL;
00202 const cpl_frame * cur_frame;
00203 cpl_propertylist * plist = NULL;
00204 cpl_frameset * imframes = NULL;
00205 cpl_frameset * spframes = NULL;
00206 cpl_frameset * spframes_lr = NULL;
00207 cpl_frameset * spframes_mr = NULL;
00208 cpl_matrix * star_pos = NULL;
00209 int ndone = 0;
00210
00211
00212 bug_if(0);
00213
00214
00215
00216
00217 isaac_spc_startrace_config.degree
00218 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00219 "degree");
00220
00221 isaac_spc_startrace_config.spec_width
00222 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00223 "spectrum_width");
00224
00225 isaac_spc_startrace_config.reject_left
00226 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00227 "reject_left");
00228 isaac_spc_startrace_config.reject_right
00229 = irplib_parameterlist_get_int(parlist, PACKAGE, RECIPE_STRING,
00230 "reject_right");
00231
00232 isaac_spc_startrace_config.display
00233 = irplib_parameterlist_get_bool(parlist, PACKAGE, RECIPE_STRING,
00234 "display");
00235
00236
00237 skip_if (isaac_dfs_set_groups(framelist));
00238
00239
00240 cur_frame = cpl_frameset_get_first_const(framelist);
00241 error_if(cur_frame == NULL, CPL_ERROR_DATA_NOT_FOUND,
00242 "Could not get 1st frame from frameset");
00243 plist = cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
00244 any_if("Could not load propertylist from 1st frame");
00245
00246 sval = isaac_pfits_get_arm(plist);
00247 any_if("Could not get the arm");
00248
00249 if (sval[0] == 'S') {
00250 isaac_spc_startrace_config.arm = 1;
00251 } else if (sval[0] == 'L') {
00252 isaac_spc_startrace_config.arm = 2;
00253 } else {
00254 error_if(1, CPL_ERROR_UNSUPPORTED_MODE, "Unsupported arm: %s", sval);
00255 }
00256
00257
00258 sval = isaac_pfits_get_filter(plist);
00259 any_if("Could not get the filter");
00260
00261 isaac_spc_startrace_config.band = isaac_get_bbfilter(sval);
00262 any_if("Could not get the band");
00263
00264 cpl_propertylist_empty(plist);
00265
00266
00267 imframes = isaac_extract_frameset(framelist, ISAAC_SPC_STARTRACE_IM_RAW);
00268 error_if(imframes == NULL, CPL_ERROR_DATA_NOT_FOUND, "Could not find the "
00269 "imframes in the input list");
00270
00271 spframes = isaac_extract_frameset(framelist, ISAAC_SPC_STARTRACE_SP_RAW);
00272 error_if(spframes == NULL, CPL_ERROR_DATA_NOT_FOUND, "Could not find the "
00273 "spframes in the input list");
00274
00275
00276 labels = isaac_spc_startrace_resol(spframes);
00277 error_if(labels == NULL, cpl_error_get_code(), "Could not differentiate "
00278 "LR and MR");
00279
00280 spframes_lr = cpl_frameset_extract(spframes, labels, 1);
00281 spframes_mr = cpl_frameset_extract(spframes, labels, 2);
00282 cpl_free(labels);
00283 labels = NULL;
00284
00285
00286 cpl_msg_info(cpl_func, "Get the star positions");
00287 star_pos = isaac_spc_startrace_starpos(imframes);
00288 error_if(star_pos == NULL, cpl_error_get_code(), "Could not find star the "
00289 "positions");
00290
00291 cpl_frameset_delete(imframes);
00292 imframes = NULL;
00293
00294 error_if (spframes_lr == NULL && spframes_mr == NULL,
00295 CPL_ERROR_UNSUPPORTED_MODE, "The %d spectro frames are not LR "
00296 "nor MR", (int)cpl_frameset_get_size(spframes));
00297 cpl_frameset_delete(spframes);
00298 spframes = NULL;
00299
00300 if (spframes_lr != NULL) {
00301 cpl_errorstate prestate = cpl_errorstate_get();
00302
00303 cpl_msg_info(cpl_func, "Reducing the LR spectra");
00304 if (isaac_spc_startrace_reduce(framelist, spframes_lr, star_pos,
00305 'L', parlist)) {
00306 irplib_error_recover(prestate, "Could not reduce the LR spectra");
00307 } else {
00308 ndone++;
00309 }
00310 cpl_frameset_delete(spframes_lr);
00311 spframes_lr = NULL;
00312 }
00313 if (spframes_mr != NULL) {
00314 cpl_errorstate prestate = cpl_errorstate_get();
00315
00316 cpl_msg_info(cpl_func, "Reducing the MR spectra");
00317 if (isaac_spc_startrace_reduce(framelist, spframes_mr, star_pos,
00318 'M', parlist)) {
00319 irplib_error_recover(prestate, "Could not reduce the MR spectra");
00320 } else {
00321 ndone++;
00322 }
00323 cpl_frameset_delete(spframes_mr);
00324 spframes_mr = NULL;
00325 }
00326
00327 error_if(!ndone, CPL_ERROR_ILLEGAL_INPUT, "Could not reduce the spectra");
00328
00329 end_skip;
00330
00331 cpl_free(labels);
00332 cpl_propertylist_delete(plist);
00333 cpl_frameset_delete(imframes);
00334 cpl_frameset_delete(spframes);
00335 cpl_frameset_delete(spframes_lr);
00336 cpl_frameset_delete(spframes_mr);
00337 cpl_matrix_delete(star_pos);
00338
00339 return cpl_error_get_code();
00340 }
00341
00342
00353
00354 static
00355 cpl_error_code isaac_spc_startrace_reduce(cpl_frameset * framelist,
00356 const cpl_frameset * spframes,
00357 const cpl_matrix * star_pos,
00358 char resol,
00359 const cpl_parameterlist * parlist)
00360 {
00361
00362 cpl_imagelist * ilist = isaac_spc_startrace_load(spframes);
00363 const int nframes = cpl_frameset_get_size(spframes);
00364 cpl_vector * spec_pos = cpl_vector_new(nframes);
00365 double * pspec_pos = cpl_vector_get_data(spec_pos);
00366 cpl_polynomial * corresp = cpl_polynomial_new(1);
00367 cpl_polynomial ** shapes = cpl_calloc(nframes, sizeof(cpl_polynomial*));
00368 cpl_vector * fit_q = cpl_vector_new(nframes);
00369 double * pfit_q = cpl_vector_get_data(fit_q);
00370 const int nx = cpl_image_get_size_x(cpl_imagelist_get(ilist, 0));
00371 cpl_polynomial * distor = NULL;
00372 cpl_table * out_tab = NULL;
00373 cpl_size power[2];
00374 const cpl_size maxdeg = 2;
00375 cpl_size i;
00376
00377 bug_if(0);
00378 bug_if(framelist == NULL);
00379 bug_if(star_pos == NULL);
00380 bug_if(parlist == NULL);
00381
00382 error_if(cpl_matrix_get_ncol(star_pos) != nframes,
00383 CPL_ERROR_INCOMPATIBLE_INPUT, "Number of spectro frames (%d) "
00384 "differ from number of star positions (%d)", nframes,
00385 (int)cpl_matrix_get_ncol(star_pos));
00386
00387
00388 for (i=0; i<nframes; i++) {
00389 const cpl_image * image = cpl_imagelist_get_const(ilist, i);
00390 const double mean = cpl_image_get_mean(image);
00391 const double min_bright = 20.0 * mean;
00392
00393 error_if (irplib_spectrum_find_brightest(image, 0, NO_SHADOW,
00394 min_bright, 0, &(pspec_pos[i])),
00395 cpl_error_get_code(), "Could not detect spectrum in frame %d "
00396 "of %d with mean flux=%g", (int)i+1, nframes, mean);
00397 }
00398
00399
00400 error_if (cpl_polynomial_fit(corresp, star_pos, NULL, spec_pos, NULL,
00401 CPL_FALSE, NULL, &maxdeg), cpl_error_get_code(),
00402 "Could not fit a %d degree polynomial to the %d positions",
00403 (int)maxdeg, nframes);
00404
00405
00406 i = 0;
00407 isaac_spc_startrace_config.corr_is1 = cpl_polynomial_get_coeff(corresp, &i);
00408 i = 1;
00409 isaac_spc_startrace_config.corr_is2 = cpl_polynomial_get_coeff(corresp, &i);
00410 i = 2;
00411 isaac_spc_startrace_config.corr_is3 = cpl_polynomial_get_coeff(corresp, &i);
00412 cpl_polynomial_delete(corresp);
00413 corresp = NULL;
00414
00415
00416 for (i=0; i<nframes; i++) {
00417 shapes[i] = isaac_spc_startrace_shape(cpl_imagelist_get(ilist, i),
00418 cpl_vector_get(spec_pos, i),
00419 resol,
00420 &(pfit_q[i]));
00421
00422 error_if (shapes[i] == NULL, cpl_error_get_code(), "Could not get the "
00423 "shape of frame %d of %d", (int)i+1, nframes);
00424
00425 cpl_msg_info(cpl_func, "Spectrum %d : Y = %g; Fit mse = %g", (int)i+1,
00426 cpl_vector_get(spec_pos, i), pfit_q[i]);
00427 }
00428 isaac_spc_startrace_config.shapes_fit_q = cpl_vector_get_median_const(fit_q);
00429 cpl_vector_delete(fit_q);
00430 fit_q = NULL;
00431 cpl_imagelist_delete(ilist);
00432 ilist = NULL;
00433
00434
00435 distor = isaac_spc_startrace_distor(shapes, spec_pos, nframes, nx);
00436 error_if (distor == NULL, cpl_error_get_code(), "Could not compute the "
00437 "distortion");
00438
00439
00440 out_tab = cpl_table_new(6);
00441 cpl_table_new_column(out_tab, "Degree_of_x", CPL_TYPE_INT);
00442 cpl_table_new_column(out_tab, "Degree_of_y", CPL_TYPE_INT);
00443 cpl_table_new_column(out_tab, "poly2d_coef", CPL_TYPE_DOUBLE);
00444 power[0] = 0; power[1] = 0;
00445 cpl_table_set_int(out_tab, "Degree_of_x", 0, power[0]);
00446 cpl_table_set_int(out_tab, "Degree_of_y", 0, power[1]);
00447 isaac_spc_startrace_config.dist1 = cpl_polynomial_get_coeff(distor, power);
00448 cpl_table_set_double(out_tab, "poly2d_coef", 0,
00449 isaac_spc_startrace_config.dist1);
00450 power[0] = 1; power[1] = 0;
00451 cpl_table_set_int(out_tab, "Degree_of_x", 1, power[0]);
00452 cpl_table_set_int(out_tab, "Degree_of_y", 1, power[1]);
00453 isaac_spc_startrace_config.distx = cpl_polynomial_get_coeff(distor, power);
00454 cpl_table_set_double(out_tab, "poly2d_coef", 1,
00455 isaac_spc_startrace_config.distx);
00456 power[0] = 0; power[1] = 1;
00457 cpl_table_set_int(out_tab, "Degree_of_x", 2, power[0]);
00458 cpl_table_set_int(out_tab, "Degree_of_y", 2, power[1]);
00459 isaac_spc_startrace_config.disty = cpl_polynomial_get_coeff(distor, power);
00460 cpl_table_set_double(out_tab, "poly2d_coef", 2,
00461 isaac_spc_startrace_config.disty);
00462 power[0] = 1; power[1] = 1;
00463 cpl_table_set_int(out_tab, "Degree_of_x", 3, power[0]);
00464 cpl_table_set_int(out_tab, "Degree_of_y", 3, power[1]);
00465 isaac_spc_startrace_config.distxy = cpl_polynomial_get_coeff(distor, power);
00466 cpl_table_set_double(out_tab, "poly2d_coef", 3,
00467 isaac_spc_startrace_config.distxy);
00468 power[0] = 2; power[1] = 0;
00469 cpl_table_set_int(out_tab, "Degree_of_x", 4, power[0]);
00470 cpl_table_set_int(out_tab, "Degree_of_y", 4, power[1]);
00471 isaac_spc_startrace_config.distxx = cpl_polynomial_get_coeff(distor, power);
00472 cpl_table_set_double(out_tab, "poly2d_coef", 4,
00473 isaac_spc_startrace_config.distxx);
00474 power[0] = 0; power[1] = 2;
00475 cpl_table_set_int(out_tab, "Degree_of_x", 5, power[0]);
00476 cpl_table_set_int(out_tab, "Degree_of_y", 5, power[1]);
00477 isaac_spc_startrace_config.distyy = cpl_polynomial_get_coeff(distor, power);
00478 cpl_table_set_double(out_tab, "poly2d_coef", 5,
00479 isaac_spc_startrace_config.distyy);
00480
00481 cpl_polynomial_delete(distor);
00482 distor = NULL;
00483
00484
00485 cpl_msg_info(cpl_func,
00486 "Distortion : Y(x,y) = a + bx + cy + dxy + exx + fyy");
00487 cpl_msg_info(cpl_func, "a = %g", isaac_spc_startrace_config.dist1);
00488 cpl_msg_info(cpl_func, "b = %g", isaac_spc_startrace_config.distx);
00489 cpl_msg_info(cpl_func, "c = %g", isaac_spc_startrace_config.disty);
00490 cpl_msg_info(cpl_func, "d = %g", isaac_spc_startrace_config.distxy);
00491 cpl_msg_info(cpl_func, "e = %g", isaac_spc_startrace_config.distxx);
00492 cpl_msg_info(cpl_func, "f = %g", isaac_spc_startrace_config.distyy);
00493
00494
00495 skip_if (isaac_spc_startrace_save(framelist, out_tab, star_pos, spec_pos,
00496 shapes, spframes, resol, parlist));
00497
00498 end_skip;
00499
00500 cpl_polynomial_delete(distor);
00501 cpl_vector_delete(fit_q);
00502 cpl_polynomial_delete(corresp);
00503 if (shapes != NULL) {
00504 for (i = 0; i < nframes; i++) cpl_polynomial_delete(shapes[i]);
00505 cpl_free(shapes);
00506 }
00507 cpl_vector_delete(spec_pos);
00508 cpl_imagelist_delete(ilist);
00509 cpl_table_delete(out_tab);
00510
00511 return cpl_error_get_code();
00512 }
00513
00514
00522
00523 static cpl_size * isaac_spc_startrace_resol(cpl_frameset * spframes)
00524 {
00525 int nframes;
00526 cpl_size * labels;
00527 cpl_frame * cur_frame;
00528 cpl_propertylist * plist;
00529 const char * sval;
00530 int i;
00531
00532
00533 if (spframes == NULL) return NULL;
00534
00535
00536 nframes = cpl_frameset_get_size(spframes);
00537
00538
00539 labels = (cpl_size*)cpl_malloc(nframes * sizeof(*labels));
00540
00541
00542 for (i=0; i<nframes; i++) {
00543 cur_frame = cpl_frameset_get_frame(spframes, i);
00544 plist=cpl_propertylist_load(cpl_frame_get_filename(cur_frame), 0);
00545
00546 if ((sval = isaac_pfits_get_resolution(plist)) == NULL) {
00547 cpl_free(labels);
00548 cpl_msg_error(cpl_func,"cannot get the resolution");
00549 return NULL;
00550 }
00551 if (sval[0]=='L') labels[i] = 1;
00552 else if (sval[0]=='M') labels[i] = 2;
00553 else labels[i] = 0;
00554 cpl_propertylist_delete(plist);
00555 }
00556 return labels;
00557 }
00558
00559
00566
00567 static cpl_matrix * isaac_spc_startrace_starpos(const cpl_frameset * imframes)
00568 {
00569 int nframes;
00570 cpl_matrix * ypositions;
00571 cpl_apertures * objects;
00572 double * ypos;
00573 cpl_imagelist * ilist;
00574 int i;
00575
00576
00577 if (imframes == NULL) return NULL;
00578
00579
00580 if ((ilist = isaac_spc_startrace_load(imframes)) == NULL) return NULL;
00581
00582
00583 nframes = cpl_frameset_get_size(imframes);
00584
00585
00586 ypositions = cpl_matrix_new(1, nframes);
00587 ypos = cpl_matrix_get_data(ypositions);
00588
00589
00590 for (i=0; i<nframes; i++) {
00591 double xpos;
00592 if ((objects = cpl_apertures_extract_sigma(cpl_imagelist_get(ilist, i),
00593 2.0)) == NULL) {
00594 cpl_msg_error(cpl_func, "cannot detect any object");
00595 cpl_matrix_delete(ypositions);
00596 cpl_imagelist_delete(ilist);
00597 return NULL;
00598 }
00599 cpl_apertures_sort_by_flux(objects);
00600 xpos = cpl_apertures_get_centroid_x(objects, 1);
00601 ypos[i] = cpl_apertures_get_centroid_y(objects, 1);
00602 cpl_apertures_delete(objects);
00603 cpl_msg_info(cpl_func, "Image %d: Position (%g, %g)", i+1,xpos, ypos[i]);
00604 }
00605 cpl_imagelist_delete(ilist);
00606 return ypositions;
00607 }
00608
00609
00616
00617 static cpl_imagelist * isaac_spc_startrace_load(const cpl_frameset * inframes)
00618 {
00619 cpl_imagelist * ilist;
00620 int nframes;
00621 cpl_image * tmp_im;
00622 int i;
00623
00624
00625 if (inframes == NULL) return NULL;
00626
00627
00628 nframes = cpl_frameset_get_size(inframes);
00629
00630
00631 if ((ilist = cpl_imagelist_load_frameset(inframes, CPL_TYPE_FLOAT, 1,
00632 0)) == NULL) return NULL;
00633
00634
00635 if (isaac_spc_startrace_config.arm == 2) return ilist;
00636
00637
00638 tmp_im = cpl_image_duplicate(cpl_imagelist_get(ilist, 0));
00639 for (i=0; i<nframes-1; i++) {
00640 if (cpl_image_subtract(cpl_imagelist_get(ilist, i),
00641 cpl_imagelist_get(ilist, i+1)) != CPL_ERROR_NONE) {
00642 cpl_msg_error(cpl_func, "cannot subtract images");
00643 cpl_imagelist_delete(ilist);
00644 cpl_image_delete(tmp_im);
00645 return NULL;
00646 }
00647 }
00648
00649 if (cpl_image_subtract(cpl_imagelist_get(ilist, nframes-1),
00650 tmp_im) != CPL_ERROR_NONE) {
00651 cpl_msg_error(cpl_func, "cannot subtract images");
00652 cpl_imagelist_delete(ilist);
00653 cpl_image_delete(tmp_im);
00654 return NULL;
00655 }
00656 cpl_image_delete(tmp_im);
00657
00658
00659 cpl_imagelist_threshold(ilist, 0.0, DBL_MAX, 0.0, 0.0);
00660
00661 return ilist;
00662 }
00663
00664
00674
00675 static cpl_polynomial * isaac_spc_startrace_shape(
00676 cpl_image * in,
00677 double ypos,
00678 char resol,
00679 double * fit_quality)
00680 {
00681 int reject_left, reject_right;
00682 cpl_image * filtered;
00683 int low_side, up_side;
00684 cpl_mask * kernel;
00685 cpl_matrix * fit_x;
00686 cpl_vector * fit_y;
00687 double * pfit_x;
00688 double * pfit_y;
00689 cpl_polynomial * fitted;
00690 cpl_bivector * toplot;
00691 int i;
00692 int nsamples;
00693 const cpl_boolean sampsym = CPL_TRUE;
00694
00695
00696 if ((in == NULL) || (ypos < 0) || (fit_quality == NULL)) return NULL;
00697
00698
00699 reject_left = isaac_spc_startrace_config.reject_left;
00700 reject_right = isaac_spc_startrace_config.reject_right;
00701 low_side = (int)(ypos - (isaac_spc_startrace_config.spec_width)/2);
00702 up_side = low_side + isaac_spc_startrace_config.spec_width;
00703
00704
00705 if ((low_side < 1) || (up_side > cpl_image_get_size_y(in))) {
00706 cpl_msg_error(cpl_func, "spectrum too close to the image border");
00707 return NULL;
00708 }
00709
00710
00711 if (isaac_spc_startrace_config.arm == 1) {
00712
00713 if (reject_left < 0) {
00714 if (resol == 'M') reject_left = MR_LEFT_REJ;
00715 else if (resol == 'L') {
00716 switch (isaac_spc_startrace_config.band) {
00717 case ISAAC_BAND_Z: reject_left = Z_LR_LEFT_REJ; break;
00718 case ISAAC_BAND_SZ: reject_left = SZ_LR_LEFT_REJ; break;
00719 case ISAAC_BAND_JBLOCK:
00720 case ISAAC_BAND_J: reject_left = J_LR_LEFT_REJ; break;
00721 case ISAAC_BAND_SH: reject_left = SH_LR_LEFT_REJ; break;
00722 case ISAAC_BAND_SK: reject_left = SK_LR_LEFT_REJ; break;
00723 default:
00724 cpl_msg_warning(cpl_func, "unsupported filter");
00725 reject_left = 0;
00726 break;
00727 }
00728 }
00729 }
00730 if (reject_right < 0) {
00731 if (resol == 'M') reject_right = MR_RIGHT_REJ;
00732 else if (resol == 'L') {
00733 switch (isaac_spc_startrace_config.band) {
00734 case ISAAC_BAND_Z: reject_right = Z_LR_RIGHT_REJ; break;
00735 case ISAAC_BAND_SZ: reject_right = SZ_LR_RIGHT_REJ;break;
00736 case ISAAC_BAND_JBLOCK:
00737 case ISAAC_BAND_J: reject_right = J_LR_RIGHT_REJ; break;
00738 case ISAAC_BAND_SH: reject_right = SH_LR_RIGHT_REJ;break;
00739 case ISAAC_BAND_SK: reject_right = SK_LR_RIGHT_REJ;break;
00740 default:
00741 cpl_msg_warning(cpl_func, "unsupported filter");
00742 reject_right = 0;
00743 break;
00744 }
00745 }
00746 }
00747 } else if (isaac_spc_startrace_config.arm == 2) {
00748
00749 if (reject_left < 0) reject_left = 150;
00750 if (reject_right < 0) reject_right = 150;
00751
00752 } else {
00753 cpl_msg_error(cpl_func, "Unrecognized mode - abort");
00754 return NULL;
00755 }
00756
00757
00758 kernel = cpl_mask_new(3, 3);
00759 cpl_mask_not(kernel);
00760 filtered = cpl_image_new(cpl_image_get_size_x(in), cpl_image_get_size_y(in),
00761 cpl_image_get_type(in));
00762 if (cpl_image_filter_mask(filtered, in, kernel, CPL_FILTER_MEDIAN,
00763 CPL_BORDER_FILTER)) {
00764 cpl_msg_error(cpl_func, "cannot filter the image");
00765 cpl_mask_delete(kernel);
00766 return NULL;
00767 }
00768 cpl_mask_delete(kernel);
00769
00770
00771 nsamples = cpl_image_get_size_x(in) - reject_right - reject_left;
00772 fit_x = cpl_matrix_new(1, nsamples);
00773 pfit_x = cpl_matrix_get_data(fit_x);
00774 fit_y = cpl_vector_new(nsamples);
00775 pfit_y = cpl_vector_get_data(fit_y);
00776 for (i=0; i < nsamples; i++) {
00777 pfit_x[i] = (double)(i+1+reject_left);
00778 pfit_y[i] = cpl_image_get_centroid_y_window(filtered, i+1+reject_left,
00779 low_side, i+1+reject_left, up_side);
00780 }
00781 cpl_image_delete(filtered);
00782
00783
00784 fitted = cpl_polynomial_new(1);
00785 if (cpl_polynomial_fit(fitted, fit_x, &sampsym, fit_y, NULL, CPL_FALSE,
00786 NULL, &(isaac_spc_startrace_config.degree))) {
00787 cpl_msg_error(cpl_func, "cannot fit the shape");
00788 cpl_polynomial_delete(fitted);
00789 cpl_matrix_delete(fit_x);
00790 cpl_vector_delete(fit_y);
00791 return NULL;
00792 }
00793
00794
00795 if (isaac_spc_startrace_config.display) {
00796 cpl_vector * vfit_x
00797 = cpl_vector_wrap(nsamples, pfit_x);
00798 toplot = cpl_bivector_wrap_vectors(vfit_x, fit_y);
00799 cpl_plot_bivector(NULL, NULL, NULL, toplot);
00800 cpl_bivector_unwrap_vectors(toplot);
00801 (void)cpl_vector_unwrap(vfit_x);
00802 }
00803
00804 cpl_vector_fill_polynomial_fit_residual(fit_y, fit_y, NULL, fitted,
00805 fit_x, NULL);
00806 *fit_quality = cpl_vector_product(fit_y, fit_y) / nsamples;
00807
00808
00809 if (isaac_spc_startrace_config.display) {
00810 cpl_vector * vfit_x
00811 = cpl_vector_wrap(nsamples, pfit_x);
00812 toplot = cpl_bivector_wrap_vectors(vfit_x, fit_y);
00813 for (i=0; i<nsamples; i++) {
00814 pfit_y[i] = cpl_polynomial_eval_1d(fitted, pfit_x[i], NULL);
00815 }
00816 cpl_plot_bivector(NULL, NULL, NULL, toplot);
00817 cpl_bivector_unwrap_vectors(toplot);
00818 (void)cpl_vector_unwrap(vfit_x);
00819 }
00820
00821
00822 cpl_matrix_delete(fit_x);
00823 cpl_vector_delete(fit_y);
00824 return fitted;
00825 }
00826
00827
00837
00838 static cpl_polynomial * isaac_spc_startrace_distor(
00839 cpl_polynomial ** shapes,
00840 cpl_vector * spec_pos,
00841 int nshapes,
00842 int nx)
00843 {
00844 cpl_polynomial * distor;
00845 cpl_matrix * xy_vec;
00846 double * x_data;
00847 double * y_data;
00848 cpl_vector * z_vec;
00849 double * z_data;
00850 int nb_xpoints, npoints;
00851 int pos;
00852 int i, j;
00853 const cpl_size maxdeg = 2;
00854
00855
00856 nb_xpoints = 20;
00857 npoints = nb_xpoints * nshapes;
00858
00859
00860 xy_vec = cpl_matrix_new(2, npoints);
00861 x_data = cpl_matrix_get_data(xy_vec);
00862 y_data = x_data + npoints;
00863 z_vec = cpl_vector_new(npoints);
00864 z_data = cpl_vector_get_data(z_vec);
00865 for (j=0; j<nshapes; j++) {
00866 for (i=0; i<nb_xpoints; i++) {
00867 pos = i + j*nb_xpoints;
00868 x_data[pos] = nx * (i+1) / nb_xpoints;
00869 y_data[pos] = cpl_vector_get(spec_pos, j);
00870 z_data[pos] = cpl_polynomial_eval_1d(shapes[j], x_data[pos], NULL);
00871 }
00872 }
00873
00874
00875 distor = cpl_polynomial_new(2);
00876 if (cpl_polynomial_fit(distor, xy_vec, NULL, z_vec, NULL, CPL_FALSE, NULL,
00877 &maxdeg)) {
00878 cpl_msg_error(cpl_func, "cannot fit the distortion");
00879 cpl_matrix_delete(xy_vec);
00880 cpl_vector_delete(z_vec);
00881 cpl_polynomial_delete(distor);
00882 return NULL;
00883 }
00884 cpl_matrix_delete(xy_vec);
00885 cpl_vector_delete(z_vec);
00886
00887 return distor;
00888 }
00889
00890
00904
00905 static
00906 cpl_error_code isaac_spc_startrace_save(cpl_frameset * set_tot,
00907 const cpl_table * tab,
00908 const cpl_matrix * star_pos,
00909 const cpl_vector * spec_pos,
00910 cpl_polynomial ** shapes,
00911 const cpl_frameset * set,
00912 char resol,
00913 const cpl_parameterlist * parlist)
00914 {
00915 cpl_propertylist * plist;
00916 cpl_propertylist * qclist;
00917 cpl_propertylist * paflist;
00918 const cpl_frame * ref_frame;
00919 char colname[128];
00920 cpl_table * shapes_table;
00921 cpl_table * pos_table;
00922 const char * procatt;
00923 const char * procat;
00924 char * filename;
00925 int i;
00926
00927
00928 qclist = cpl_propertylist_new();
00929
00930
00931 cpl_propertylist_append_double(qclist, "ESO QC CORR_IS1",
00932 isaac_spc_startrace_config.corr_is1);
00933 cpl_propertylist_append_double(qclist, "ESO QC CORR_IS2",
00934 isaac_spc_startrace_config.corr_is2);
00935 cpl_propertylist_append_double(qclist, "ESO QC CORR_IS3",
00936 isaac_spc_startrace_config.corr_is3);
00937 cpl_propertylist_append_double(qclist, "ESO QC FITMSE",
00938 isaac_spc_startrace_config.shapes_fit_q);
00939 cpl_propertylist_append_double(qclist, "ESO QC DIST1",
00940 isaac_spc_startrace_config.dist1);
00941 cpl_propertylist_append_double(qclist, "ESO QC DISTX",
00942 isaac_spc_startrace_config.distx);
00943 cpl_propertylist_append_double(qclist, "ESO QC DISTY",
00944 isaac_spc_startrace_config.disty);
00945 cpl_propertylist_append_double(qclist, "ESO QC DISTXY",
00946 isaac_spc_startrace_config.distxy);
00947 cpl_propertylist_append_double(qclist, "ESO QC DISTXX",
00948 isaac_spc_startrace_config.distxx);
00949 cpl_propertylist_append_double(qclist, "ESO QC DISTYY",
00950 isaac_spc_startrace_config.distyy);
00951
00952
00953 procatt = isaac_spc_startrace_config.arm == 1
00954 ? ISAAC_SPC_STARTRACE_SW_RES : ISAAC_SPC_STARTRACE_LW_RES;
00955 filename = cpl_sprintf("isaac_spc_startrace_2dpoly_%cR.fits", resol);
00956 irplib_dfs_save_table(set_tot,
00957 parlist,
00958 set,
00959 tab,
00960 NULL,
00961 "isaac_spc_startrace",
00962 procatt,
00963 qclist,
00964 NULL,
00965 PACKAGE "/" PACKAGE_VERSION,
00966 filename);
00967 cpl_free(filename);
00968
00969
00970 pos_table = cpl_table_new(cpl_matrix_get_ncol(star_pos));
00971
00972
00973 cpl_table_wrap_double(pos_table, cpl_matrix_get_data((cpl_matrix*)star_pos),
00974 "Star_positions");
00975
00976 cpl_table_wrap_double(pos_table, cpl_vector_get_data((cpl_vector*)spec_pos),
00977 "Spec_positions");
00978
00979 procat = isaac_spc_startrace_config.arm == 1
00980 ? ISAAC_SPC_STARTRACE_SW_POS : ISAAC_SPC_STARTRACE_LW_POS;
00981 filename = cpl_sprintf("isaac_spc_startrace_positions_%cR.fits", resol);
00982 irplib_dfs_save_table(set_tot,
00983 parlist,
00984 set,
00985 tab,
00986 NULL,
00987 "isaac_spc_startrace",
00988 procat,
00989 qclist,
00990 NULL,
00991 PACKAGE "/" PACKAGE_VERSION,
00992 filename);
00993 cpl_free(filename);
00994
00995 (void)cpl_table_unwrap(pos_table, "Star_positions");
00996 (void)cpl_table_unwrap(pos_table, "Spec_positions");
00997 cpl_table_delete(pos_table);
00998
00999
01000 shapes_table = cpl_table_new(isaac_spc_startrace_config.degree + 1);
01001 for (i=0; i<cpl_vector_get_size(spec_pos); i++) {
01002 sprintf(colname, "Spec_%d", i+1);
01003 cpl_table_new_column(shapes_table, colname, CPL_TYPE_DOUBLE);
01004 }
01005 for (i=0; i<cpl_vector_get_size(spec_pos); i++) {
01006 cpl_size j;
01007 sprintf(colname, "Spec_%d", i+1);
01008 for (j=0; j<isaac_spc_startrace_config.degree + 1; j++) {
01009 cpl_table_set_double(shapes_table, colname, j,
01010 cpl_polynomial_get_coeff(shapes[i], &j));
01011 }
01012 }
01013 procat = isaac_spc_startrace_config.arm == 1 ?
01014 ISAAC_SPC_STARTRACE_SW_SHAPE : ISAAC_SPC_STARTRACE_LW_SHAPE;
01015 filename = cpl_sprintf("isaac_spc_startrace_shapes_%cR.fits", resol);
01016 irplib_dfs_save_table(set_tot,
01017 parlist,
01018 set,
01019 tab,
01020 NULL,
01021 "isaac_spc_startrace",
01022 procat,
01023 qclist,
01024 NULL,
01025 PACKAGE "/" PACKAGE_VERSION,
01026 filename);
01027 cpl_free(filename);
01028 cpl_table_delete(shapes_table);
01029
01030
01031 ref_frame = irplib_frameset_get_first_from_group(set, CPL_FRAME_GROUP_RAW);
01032
01033
01034 if ((plist=cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
01035 0)) == NULL) {
01036 cpl_msg_error(cpl_func, "getting header from reference frame");
01037 cpl_propertylist_delete(qclist);
01038 return -1;
01039 }
01040
01041
01042 paflist = cpl_propertylist_new();
01043 cpl_propertylist_copy_property_regexp(paflist, plist,
01044 "^(ARCFILE|MJD-OBS|INSTRUME|ESO TPL ID|ESO TPL NEXP|ESO DPR CATG|"
01045 "ESO DPR TECH|ESO DPR TYPE|DATE-OBS|ESO INS GRAT NAME|"
01046 "ESO OCS SELECT-ARM)$", 0);
01047 cpl_propertylist_delete(plist);
01048
01049
01050 cpl_propertylist_copy_property_regexp(paflist, qclist, "", 0);
01051 cpl_propertylist_delete(qclist);
01052
01053
01054 cpl_propertylist_update_string(paflist, CPL_DFS_PRO_CATG, procatt);
01055
01056
01057 filename = cpl_sprintf("isaac_spc_startrace_%cR.paf", resol);
01058 cpl_dfs_save_paf("ISAAC",
01059 "isaac_spc_startrace",
01060 paflist,
01061 filename);
01062 cpl_free(filename);
01063 cpl_propertylist_delete(paflist);
01064 return 0;
01065 }
01066