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