00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include <config.h>
00024 #endif
00025
00026
00027
00028
00029 #include <string.h>
00030
00031 #include <muse.h>
00032 #include "muse_geometry_z.h"
00033
00034
00035
00036
00037
00038
00048
00049 static void
00050 muse_geometry_qc_spots(cpl_table *aSpots, cpl_propertylist *aHeader)
00051 {
00052 if (!aSpots || !aHeader) {
00053 return;
00054 }
00055
00056 unsigned int nexp,
00057 nexp1 = cpl_table_get_column_min(aSpots, "image"),
00058 nexp2 = cpl_table_get_column_max(aSpots, "image");
00059 cpl_msg_debug(__func__, "Adding QC keywords for %u exposures to %s",
00060 nexp2 - nexp1 + 1, MUSE_TAG_SPOTS_TABLE);
00061
00062 cpl_array *amean = cpl_array_new(nexp2 - nexp1 + 1, CPL_TYPE_DOUBLE);
00063 for (nexp = nexp1; nexp <= nexp2; nexp++) {
00064 cpl_table_unselect_all(aSpots);
00065 cpl_table_or_selected_int(aSpots, "image", CPL_EQUAL_TO, nexp);
00066 cpl_table_and_selected_double(aSpots, "xfwhm", CPL_GREATER_THAN, 0.);
00067 cpl_table_and_selected_double(aSpots, "yfwhm", CPL_GREATER_THAN, 0.);
00068 cpl_table_and_selected_double(aSpots, "flux", CPL_GREATER_THAN, 1000.);
00069 cpl_table *table = cpl_table_extract_selected(aSpots);
00070
00071 cpl_table_duplicate_column(table, "fwhm", table, "xfwhm");
00072 cpl_table_add_columns(table, "fwhm", "yfwhm");
00073 cpl_table_multiply_scalar(table, "fwhm", 0.5);
00074 double mean = cpl_table_get_column_mean(table, "fwhm"),
00075 median = cpl_table_get_column_median(table, "fwhm"),
00076 stdev = cpl_table_get_column_stdev(table, "fwhm");
00077 cpl_table_delete(table);
00078
00079 char keyword[KEYWORD_LENGTH];
00080 snprintf(keyword, KEYWORD_LENGTH, QC_GEO_EXPk_MEAN, nexp);
00081 cpl_propertylist_update_float(aHeader, keyword, mean);
00082 snprintf(keyword, KEYWORD_LENGTH, QC_GEO_EXPk_MEDIAN, nexp);
00083 cpl_propertylist_update_float(aHeader, keyword, median);
00084 snprintf(keyword, KEYWORD_LENGTH, QC_GEO_EXPk_STDEV, nexp);
00085 cpl_propertylist_update_float(aHeader, keyword, stdev);
00086
00087 cpl_array_set_double(amean, nexp - nexp1, mean);
00088 }
00089 cpl_propertylist_update_float(aHeader, QC_GEO_FWHM_MEAN,
00090 cpl_array_get_mean(amean));
00091 cpl_propertylist_update_float(aHeader, QC_GEO_FWHM_STDEV,
00092 cpl_array_get_stdev(amean));
00093 cpl_array_delete(amean);
00094 }
00095
00096
00107
00108 static void
00109 muse_geometry_qc_ifu(muse_geo_table *aGeoInit, cpl_propertylist *aHeader,
00110 const cpl_vector *aLambdas)
00111 {
00112 if (!aGeoInit || !aHeader || !aLambdas) {
00113 return;
00114 }
00115 cpl_table *gtinit = aGeoInit->table;
00116 const unsigned char ifu = cpl_table_get_int(gtinit, MUSE_GEOTABLE_FIELD, 0, NULL);
00117
00118 double angle = -cpl_table_get_column_mean(gtinit, MUSE_GEOTABLE_ANGLE),
00119 astdev = cpl_table_get_column_stdev(gtinit, MUSE_GEOTABLE_ANGLE),
00120 amedian = -cpl_table_get_column_median(gtinit, MUSE_GEOTABLE_ANGLE);
00121
00122 if (getenv("MUSE_GEOMETRY_NO_INVERSION")
00123 && atoi(getenv("MUSE_GEOMETRY_NO_INVERSION")) > 0) {
00124 angle *= -1.;
00125 amedian *= -1.;
00126 }
00127 cpl_msg_debug(__func__, "Adding QC keywords for IFU %hhu: angle = %.3f +/- %.3f "
00128 "(%.3f) deg", ifu, angle, astdev, amedian);
00129 char *keyword = cpl_sprintf(QC_GEO_IFUi_ANGLE, ifu);
00130 cpl_propertylist_update_float(aHeader, keyword, amedian);
00131 cpl_free(keyword);
00132
00133 int i, n = cpl_vector_get_size(aLambdas);
00134 for (i = 1; i <= n; i++) {
00135 double lambda = cpl_vector_get(aLambdas, i - 1);
00136 char *kw = cpl_sprintf(QC_GEO_IFUi_WLENj, ifu, i),
00137 *kwmean = cpl_sprintf(QC_GEO_IFUi_MEANj, ifu, i),
00138 *kwmedi = cpl_sprintf(QC_GEO_IFUi_MEDIANj, ifu, i),
00139 *kwstdv = cpl_sprintf(QC_GEO_IFUi_STDEVj, ifu, i);
00140 cpl_propertylist_update_float(aHeader, kw, lambda);
00141
00142 cpl_table_unselect_all(gtinit);
00143 cpl_table_or_selected_double(gtinit, "lambda", CPL_EQUAL_TO, lambda);
00144 if (cpl_table_count_selected(gtinit) < 1) {
00145 cpl_propertylist_update_float(aHeader, kwmean, i);
00146 cpl_propertylist_update_float(aHeader, kwmedi, i);
00147 cpl_propertylist_update_float(aHeader, kwstdv, i);
00148 } else {
00149 cpl_table *t = cpl_table_extract_selected(gtinit);
00150 cpl_propertylist_update_float(aHeader, kwmean,
00151 cpl_table_get_column_mean(t, "flux"));
00152 cpl_propertylist_update_float(aHeader, kwmedi,
00153 cpl_table_get_column_median(t, "flux"));
00154 cpl_propertylist_update_float(aHeader, kwstdv,
00155 cpl_table_get_column_stdev(t, "flux"));
00156 cpl_table_delete(t);
00157 }
00158 cpl_free(kw);
00159 cpl_free(kwmean);
00160 cpl_free(kwmedi);
00161 cpl_free(kwstdv);
00162 }
00163 }
00164
00165
00172
00173 static muse_imagelist *
00174 muse_geometry_load_images(muse_processing *aProcessing, unsigned short aIFU)
00175 {
00176 unsigned int skip = 0;
00177 if (getenv("MUSE_GEOMETRY_SKIP") && atoi(getenv("MUSE_GEOMETRY_SKIP")) > 0) {
00178 skip = atoi(getenv("MUSE_GEOMETRY_SKIP"));
00179 }
00180
00181 muse_imagelist *images;
00182 if (!skip) {
00183
00184
00185 cpl_frame *fbias = muse_frameset_find_master(aProcessing->inframes,
00186 MUSE_TAG_MASTER_BIAS, aIFU);
00187
00188 cpl_propertylist *hbias = cpl_propertylist_load(cpl_frame_get_filename(fbias), 0);
00189 cpl_frame_delete(fbias);
00190 muse_basicproc_params *bpars = muse_basicproc_params_new_from_propertylist(hbias);
00191 cpl_propertylist_delete(hbias);
00192 images = muse_basicproc_load(aProcessing, aIFU, bpars);
00193 muse_basicproc_params_delete(bpars);
00194 } else {
00195 images = muse_imagelist_new();
00196
00197 unsigned int ifile, nfiles = 99;
00198 if (skip >= 2) {
00199 cpl_msg_warning(__func__, "Skipping spot measurements, only loading first"
00200 " (reduced) file for IFU %02hu", aIFU);
00201 nfiles = 1;
00202 } else {
00203 cpl_msg_warning(__func__, "Skipping raw image processing, loading all "
00204 "reduced images directly");
00205 }
00206 for (ifile = 0; ifile < nfiles; ifile++) {
00207 char *fn = cpl_sprintf("MASK_REDUCED_00%02u-%02hu.fits", ifile + 1, aIFU);
00208 cpl_errorstate es = cpl_errorstate_get();
00209 muse_image *image = muse_image_load(fn);
00210 if (!image) {
00211 cpl_errorstate_set(es);
00212 cpl_free(fn);
00213 break;
00214 }
00215 cpl_frame *frame = cpl_frame_new();
00216 cpl_frame_set_filename(frame, fn);
00217 cpl_frame_set_tag(frame, "MASK");
00218 muse_processing_append_used(aProcessing, frame, CPL_FRAME_GROUP_RAW, 0);
00219 cpl_msg_debug(__func__, "file = %s", fn);
00220 muse_imagelist_set(images, image, ifile);
00221 cpl_free(fn);
00222 }
00223 cpl_msg_debug(__func__, "Read %u file%s", ifile, ifile == 1 ? "" : "s");
00224 }
00225 return images;
00226 }
00227
00228
00251
00252 static cpl_error_code
00253 muse_geometry_reconstruct_combined(muse_processing *aProcessing,
00254 muse_geometry_params_t *aParams,
00255 muse_geo_table *aGeo,
00256 double aLMin, double aLMax)
00257 {
00258 cpl_ensure_code(aProcessing && aParams && aGeo && aGeo->table,
00259 CPL_ERROR_NULL_INPUT);
00260 if (aLMin >= aLMax) {
00261 cpl_msg_warning(__func__, "Invalid wavelength range for reconstruction "
00262 "(%.2f..%.2f), skipping combined reconstruction!", aLMin, aLMax);
00263 return CPL_ERROR_ILLEGAL_INPUT;
00264 }
00265 cpl_msg_info(__func__, "Reconstructing combined input as cube in the "
00266 "wavelength range %.2f..%.2f.", aLMin, aLMax);
00267 unsigned int skip = 0;
00268 if (getenv("MUSE_GEOMETRY_SKIP") && atoi(getenv("MUSE_GEOMETRY_SKIP")) > 0) {
00269 skip = atoi(getenv("MUSE_GEOMETRY_SKIP"));
00270 }
00271 cpl_table *gt = aGeo->table;
00272
00273 muse_pixtable **pts = cpl_calloc(kMuseNumIFUs, sizeof(muse_pixtable));
00274 unsigned char nifu;
00275 #pragma omp parallel for default(none) \
00276 shared(gt, aParams, aProcessing, pts, skip)
00277 for (nifu = (unsigned)aParams->ifu1; nifu <= (unsigned)aParams->ifu2; nifu++) {
00278 cpl_table *trace = muse_table_load(aProcessing, MUSE_TAG_TRACE_TABLE, nifu),
00279 *wavecal = muse_table_load(aProcessing, MUSE_TAG_WAVECAL_TABLE, nifu);
00280 if (!trace || !wavecal) {
00281 cpl_table_delete(trace);
00282 cpl_table_delete(wavecal);
00283 continue;
00284 }
00285
00286 cpl_frame *cframe = NULL;
00287 if (skip == 2) {
00288
00289 cframe = cpl_frame_new();
00290 char *fn = cpl_sprintf("MASK_COMBINED-%02hhu.fits", nifu);
00291 cpl_frame_set_filename(cframe, fn);
00292 cpl_free(fn);
00293 } else {
00294 cframe = muse_frameset_find_master(aProcessing->outframes,
00295 MUSE_TAG_MASK_COMBINED, nifu);
00296 }
00297 if (!cframe) {
00298 cpl_table_delete(trace);
00299 cpl_table_delete(wavecal);
00300 continue;
00301 }
00302 cpl_msg_debug(__func__, "reconstructing IFU %2hhu using \"%s\"", nifu,
00303 cpl_frame_get_filename(cframe));
00304 muse_image *combined = muse_image_load(cpl_frame_get_filename(cframe));
00305 cpl_frame_delete(cframe);
00306 pts[nifu - 1] = muse_pixtable_create(combined, trace, wavecal, gt);
00307 cpl_table_delete(trace);
00308 cpl_table_delete(wavecal);
00309 muse_image_delete(combined);
00310 if (!pts[nifu - 1]) {
00311 cpl_msg_warning(__func__, "Could not create a pixel table for reconstruction"
00312 " for IFU %2hhu!", nifu++);
00313 }
00314 }
00315
00316
00317
00318 nifu = aParams->ifu1;
00319 muse_pixtable *pt = pts[nifu - 1];
00320 pts[nifu - 1] = NULL;
00321 while (!pt && nifu <= aParams->ifu2) {
00322 nifu++;
00323 pt = pts[nifu - 1];
00324 pts[nifu - 1] = NULL;
00325 }
00326 if (pt) {
00327 for ( ; nifu <= (unsigned)aParams->ifu2; nifu++) {
00328 if (pts[nifu - 1]) {
00329 cpl_table_insert(pt->table, pts[nifu - 1]->table, muse_pixtable_get_nrow(pt));
00330 muse_pixtable_delete(pts[nifu - 1]);
00331 }
00332 }
00333 }
00334 cpl_free(pts);
00335
00336
00337 muse_pixtable_restrict_wavelength(pt, aLMin, aLMax);
00338 if (muse_pixtable_get_nrow(pt) < 1) {
00339 muse_pixtable_delete(pt);
00340 return cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_OUTPUT,
00341 "After cutting to %.2f..%.2f in wavelength no "
00342 "pixels for image reconstruction are left!",
00343 aLMin, aLMax);
00344 }
00345
00346
00347 muse_resampling_params *rp = muse_resampling_params_new(MUSE_RESAMPLE_WEIGHTED_DRIZZLE);
00348 rp->crsigma = -1.;
00349 muse_datacube *cube = muse_resampling_cube(pt, rp, NULL);
00350 muse_resampling_params_delete(rp);
00351 muse_pixtable_delete(pt);
00352
00353 muse_image *white = muse_datacube_collapse(cube, NULL);
00354 cube->recimages = muse_imagelist_new();
00355 cube->recnames = cpl_array_new(1, CPL_TYPE_STRING);
00356 muse_imagelist_set(cube->recimages, white, 0);
00357 cpl_array_set_string(cube->recnames, 0, "white");
00358 muse_processing_save_cube(aProcessing, -1, cube, "GEOMETRY_CUBE",
00359 MUSE_CUBE_TYPE_FITS);
00360 muse_datacube_delete(cube);
00361
00362 return CPL_ERROR_NONE;
00363 }
00364
00365
00391
00392 static cpl_error_code
00393 muse_geometry_reconstruct(muse_processing *aProcessing,
00394 muse_geometry_params_t *aParams,
00395 muse_geo_table *aGeo, double aLMin, double aLMax)
00396 {
00397 cpl_ensure_code(aProcessing && aParams && aGeo && aGeo->table,
00398 CPL_ERROR_NULL_INPUT);
00399 if (aLMin >= aLMax) {
00400 cpl_msg_warning(__func__, "Invalid wavelength range for reconstruction "
00401 "(%.2f..%.2f), skipping reconstruction!", aLMin, aLMax);
00402 return CPL_ERROR_ILLEGAL_INPUT;
00403 }
00404
00405
00406
00407
00408 cpl_frameset *usedoriginal = cpl_frameset_duplicate(aProcessing->usedframes);
00409 int iframe, nframes = cpl_frameset_get_size(aProcessing->usedframes);
00410 for (iframe = 0; iframe < nframes; iframe++) {
00411 cpl_frame *frame = cpl_frameset_get_position(aProcessing->usedframes, iframe);
00412 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_RAW) {
00413 cpl_frame_set_group(frame, CPL_FRAME_GROUP_CALIB);
00414 }
00415 }
00416
00417 cpl_table *gt = aGeo->table;
00418 cpl_frameset *frames = muse_frameset_find(aProcessing->inframes,
00419 "MASK_CHECK", 0, CPL_FALSE);
00420 nframes = cpl_frameset_get_size(frames);
00421 cpl_msg_info(__func__, "Found %d datasets to reconstruct", nframes);
00422 for (iframe = 0; iframe < nframes; iframe++) {
00423 cpl_frame *frame = cpl_frameset_get_position(frames, iframe);
00424 const char *fn = cpl_frame_get_filename(frame);
00425 cpl_msg_info(__func__, "Reconstructing image %d (from \"%s\"), using "
00426 "wavelength range %.2f..%.2f", iframe + 1, fn, aLMin, aLMax);
00427 muse_pixtable **pts = cpl_calloc(kMuseNumIFUs, sizeof(muse_pixtable));
00428 unsigned char nifu;
00429 #pragma omp parallel for default(none) \
00430 shared(aParams, aProcessing, fn, frames, gt, pts)
00431 for (nifu = (unsigned)aParams->ifu1; nifu <= (unsigned)aParams->ifu2; nifu++) {
00432 cpl_table *trace = muse_table_load(aProcessing, MUSE_TAG_TRACE_TABLE, nifu),
00433 *wavecal = muse_table_load(aProcessing, MUSE_TAG_WAVECAL_TABLE, nifu);
00434 if (!trace || !wavecal) {
00435 cpl_table_delete(trace);
00436 cpl_table_delete(wavecal);
00437 continue;
00438 }
00439 cpl_frame *bframe = muse_frameset_find_master(aProcessing->inframes,
00440 MUSE_TAG_MASTER_BIAS, nifu);
00441 if (!bframe) {
00442 cpl_table_delete(trace);
00443 cpl_table_delete(wavecal);
00444 continue;
00445 }
00446 const char *bname = cpl_frame_get_filename(bframe);
00447 cpl_errorstate es = cpl_errorstate_get();
00448 muse_image *bias = muse_image_load(bname);
00449 if (!bias) {
00450 cpl_errorstate_set(es);
00451 bias = muse_image_load_from_extensions(bname, nifu);
00452 }
00453 cpl_frame_delete(bframe);
00454
00455
00456 int ext = muse_utils_get_extension_for_ifu(fn, nifu);
00457 muse_image *raw = muse_image_load_from_raw(fn, ext);
00458 if (!raw) {
00459 cpl_table_delete(trace);
00460 cpl_table_delete(wavecal);
00461 muse_image_delete(bias);
00462 continue;
00463 }
00464 muse_basicproc_params *bpars = muse_basicproc_params_new_from_propertylist(bias->header);
00465 muse_quadrants_overscan_stats(raw, bpars ? bpars->rejection : "dcr", 0);
00466 if (bpars && !strncmp(bpars->overscan, "vpoly", 5)) {
00467
00468 unsigned char ovscvorder = 3;
00469 double frms = 1.01,
00470 fchisq = 1.04;
00471 char *rest = strchr(bpars->overscan, ':');
00472 if (strlen(bpars->overscan) > 6 && rest++) {
00473 ovscvorder = strtol(rest, &rest, 10);
00474 if (strlen(rest++) > 0) {
00475 frms = strtod(rest, &rest);
00476 if (strlen(rest++) > 0) {
00477 fchisq = strtod(rest, &rest);
00478 }
00479 }
00480 }
00481 muse_quadrants_overscan_polyfit_vertical(raw, bpars->ovscignore,
00482 ovscvorder, bpars->ovscsigma,
00483 frms, fchisq);
00484 }
00485 muse_image *image = muse_quadrants_trim_image(raw);
00486 muse_image_delete(raw);
00487 muse_image_variance_create(image, bias);
00488 if (bpars && !strncmp(bpars->overscan, "offset", 6)) {
00489 muse_quadrants_overscan_correct(image, bias);
00490 }
00491 muse_basicproc_params_delete(bpars);
00492 muse_image_subtract(image, bias);
00493 muse_image_delete(bias);
00494 muse_image_adu_to_count(image);
00495 pts[nifu - 1] = muse_pixtable_create(image, trace, wavecal, gt);
00496 cpl_table_delete(trace);
00497 cpl_table_delete(wavecal);
00498 muse_image_delete(image);
00499 if (!pts[nifu - 1]) {
00500 cpl_msg_warning(__func__, "Could not create a pixel table for "
00501 "reconstruction for IFU %2hhu!", nifu++);
00502 }
00503 }
00504
00505
00506
00507 nifu = aParams->ifu1;
00508 muse_pixtable *pt = pts[nifu - 1];
00509 pts[nifu - 1] = NULL;
00510 while (!pt && nifu <= aParams->ifu2) {
00511 nifu++;
00512 pt = pts[nifu - 1];
00513 pts[nifu - 1] = NULL;
00514 }
00515 if (pt) {
00516 for ( ; nifu <= (unsigned)aParams->ifu2; nifu++) {
00517 if (pts[nifu - 1]) {
00518 cpl_table_insert(pt->table, pts[nifu - 1]->table, muse_pixtable_get_nrow(pt));
00519 muse_pixtable_delete(pts[nifu - 1]);
00520 }
00521 }
00522 }
00523 cpl_free(pts);
00524
00525
00526 muse_pixtable_restrict_wavelength(pt, aLMin, aLMax);
00527 if (muse_pixtable_get_nrow(pt) < 1) {
00528 cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_OUTPUT,
00529 "After cutting to %.2f..%.2f in wavelength no "
00530 "pixels for image reconstruction of \"%s\" are "
00531 "left!", aLMin, aLMax, fn);
00532 muse_pixtable_delete(pt);
00533 continue;
00534 }
00535
00536
00537 muse_resampling_params *rp = muse_resampling_params_new(MUSE_RESAMPLE_WEIGHTED_DRIZZLE);
00538 rp->crsigma = -1.;
00539
00540
00541 rp->dlambda = 10000.;
00542 muse_datacube *cube = muse_resampling_cube(pt, rp, NULL);
00543 muse_resampling_params_delete(rp);
00544 muse_pixtable_delete(pt);
00545
00546
00547
00548
00549 muse_processing_append_used(aProcessing, frame, CPL_FRAME_GROUP_RAW, 1);
00550 #pragma omp critical(muse_processing_used_frames)
00551 cpl_frameset_insert(usedoriginal, cpl_frame_duplicate(frame));
00552 cpl_propertylist *header = cpl_propertylist_load(fn, 0);
00553 muse_processing_save_cimage(aProcessing, -1, cpl_imagelist_get(cube->data, 0),
00554 header, "GEOMETRY_CHECK");
00555 cpl_propertylist_delete(header);
00556 muse_datacube_delete(cube);
00557 }
00558 cpl_frameset_delete(frames);
00559 cpl_frameset_delete(aProcessing->usedframes);
00560 aProcessing->usedframes = usedoriginal;
00561
00562 return CPL_ERROR_NONE;
00563 }
00564
00565
00572
00573 int
00574 muse_geometry_compute(muse_processing *aProcessing,
00575 muse_geometry_params_t *aParams)
00576 {
00577
00578 muse_geo_centroid_type centroid = MUSE_GEO_CENTROID_BARYCENTER;
00579 if (aParams->centroid == MUSE_GEOMETRY_PARAM_CENTROID_GAUSSIAN) {
00580 centroid = MUSE_GEO_CENTROID_GAUSSIAN;
00581 } else if (aParams->centroid != MUSE_GEOMETRY_PARAM_CENTROID_BARYCENTER) {
00582 cpl_msg_error(__func__, "unknown centroiding method \"%s\"", aParams->centroid_s);
00583 return -1;
00584 }
00585
00586
00587 cpl_table *linelist = muse_table_load(aProcessing, MUSE_TAG_LINE_CATALOG, 0);
00588 cpl_propertylist *linehead = muse_propertylist_load(aProcessing,
00589 MUSE_TAG_LINE_CATALOG);
00590 cpl_boolean listvalid = muse_wave_lines_check(linelist, linehead);
00591 cpl_propertylist_delete(linehead);
00592 cpl_vector *vlines = muse_geo_lines_get(linelist);
00593 cpl_table_delete(linelist);
00594 if (!listvalid || !vlines) {
00595 cpl_msg_error(__func__, "%s could not be loaded/verified or enough suitable"
00596 "lines are missing", MUSE_TAG_LINE_CATALOG);
00597 cpl_vector_delete(vlines);
00598 return -1;
00599 }
00600
00601 cpl_msg_info(__func__, "Analyzing IFUs %d to %d", aParams->ifu1, aParams->ifu2);
00602 cpl_error_code rc[kMuseNumIFUs];
00603 cpl_table *mspots[kMuseNumIFUs],
00604 *trace[kMuseNumIFUs],
00605 *wavecal[kMuseNumIFUs];
00606 cpl_propertylist *headfinal = NULL;
00607 cpl_array *dy = cpl_array_new(0, CPL_TYPE_DOUBLE);
00608 unsigned int nifu;
00609 #pragma omp parallel for default(none) \
00610 shared(aParams, aProcessing, centroid, dy, headfinal, mspots, rc, \
00611 trace, vlines, wavecal)
00612 for (nifu = (unsigned)aParams->ifu1; nifu <= (unsigned)aParams->ifu2; nifu++) {
00613 rc[nifu - 1] = CPL_ERROR_NONE;
00614 mspots[nifu - 1] = NULL;
00615
00616
00617
00618 trace[nifu - 1] = muse_table_load(aProcessing, MUSE_TAG_TRACE_TABLE, nifu);
00619 wavecal[nifu - 1] = muse_table_load(aProcessing, MUSE_TAG_WAVECAL_TABLE, nifu);
00620 if (!trace[nifu - 1] || !wavecal[nifu - 1]) {
00621 cpl_msg_error(__func__, "Calibration could not be loaded for IFU %u: %s%s",
00622 nifu, !trace[nifu - 1] ? " "MUSE_TAG_TRACE_TABLE : "",
00623 !wavecal[nifu - 1] ? " "MUSE_TAG_WAVECAL_TABLE : "");
00624 cpl_table_delete(trace[nifu - 1]);
00625 cpl_table_delete(wavecal[nifu - 1]);
00626 trace[nifu - 1] = NULL;
00627 wavecal[nifu - 1] = NULL;
00628 rc[nifu - 1] = CPL_ERROR_NULL_INPUT;
00629 continue;
00630 }
00631
00632
00633
00634 muse_imagelist *images = muse_geometry_load_images(aProcessing, nifu);
00635 if (!images) {
00636 cpl_msg_error(__func__, "Loading and basic processing of the raw input "
00637 "images failed for IFU %u!", nifu);
00638 cpl_table_delete(trace[nifu - 1]);
00639 cpl_table_delete(wavecal[nifu - 1]);
00640 trace[nifu - 1] = NULL;
00641 wavecal[nifu - 1] = NULL;
00642 rc[nifu - 1] = cpl_error_get_code();
00643 continue;
00644 }
00645
00646 unsigned int skip = 0;
00647 if (getenv("MUSE_GEOMETRY_SKIP") && atoi(getenv("MUSE_GEOMETRY_SKIP")) > 0) {
00648 skip = atoi(getenv("MUSE_GEOMETRY_SKIP"));
00649 }
00650 cpl_propertylist *header;
00651 if (skip >= 2) {
00652 char *fn = cpl_sprintf("SPOTS_TABLE-%02u.fits", nifu);
00653 cpl_msg_warning(__func__, "Reading spot measurements from \"%s\"", fn);
00654 mspots[nifu - 1] = cpl_table_load(fn, 1, 1);
00655 cpl_free(fn);
00656 } else {
00657 muse_image *av = muse_combine_average_create(images);
00658 cpl_propertylist_append(av->header, muse_imagelist_get(images, 0)->header);
00659 muse_processing_save_image(aProcessing, nifu, av, MUSE_TAG_MASK_COMBINED);
00660 muse_image_reject_from_dq(av);
00661 mspots[nifu - 1] = muse_geo_measure_spots(av, images, trace[nifu - 1],
00662 wavecal[nifu - 1], vlines,
00663 aParams->sigma, centroid);
00664 muse_image_delete(av);
00665
00666 header = cpl_propertylist_duplicate(muse_imagelist_get(images, 0)->header);
00667
00668
00669 muse_geometry_qc_spots(mspots[nifu - 1], header);
00670 muse_processing_save_table(aProcessing, nifu, mspots[nifu - 1], header,
00671 MUSE_TAG_SPOTS_TABLE, MUSE_TABLE_TYPE_CPL);
00672 cpl_propertylist_delete(header);
00673 }
00674 cpl_msg_info(__func__, "measured %"CPL_SIZE_FORMAT" spots in %u images",
00675 cpl_table_get_nrow(mspots[nifu - 1]), muse_imagelist_get_size(images));
00676 cpl_table_delete(wavecal[nifu - 1]);
00677
00678 if (!skip) {
00679
00680
00681 unsigned int k;
00682 for (k = 0; k < muse_imagelist_get_size(images); k++) {
00683 muse_image *image = muse_imagelist_get(images, k);
00684 muse_processing_save_image(aProcessing, nifu, image,
00685 MUSE_TAG_MASK_REDUCED);
00686 }
00687 }
00688 #pragma omp critical (muse_geo_header_construct)
00689 {
00690 if (!headfinal) {
00691 headfinal = cpl_propertylist_duplicate(muse_imagelist_get(images, 0)->header);
00692
00693
00694
00695
00696
00697 cpl_propertylist_erase_regexp(headfinal,
00698 "EXTNAME|ESO DET (CHIP|OUT)|ESO DET2", 0);
00699 }
00700 }
00701 muse_imagelist_delete(images);
00702
00703 muse_geo_compute_pinhole_local_distance(dy, mspots[nifu - 1]);
00704 }
00705
00706 double pinholedy = muse_geo_compute_pinhole_global_distance(dy, 0.001, 0.5, 0.8);
00707
00708
00709 UNUSED_ARGUMENT(pinholedy);
00710 cpl_array_delete(dy);
00711
00712
00713 cpl_table *spots = NULL;
00714 muse_geo_table *geotable = NULL;
00715 #pragma omp parallel for default(none) \
00716 shared(aParams, geotable, headfinal, mspots, spots, trace, vlines)
00717 for (nifu = (unsigned)aParams->ifu1; nifu <= (unsigned)aParams->ifu2; nifu++) {
00718
00719 muse_geo_table *geoinit = muse_geo_determine_initial(mspots[nifu - 1], trace[nifu - 1]);
00720 muse_geo_table *geohori = muse_geo_determine_horizontal(geoinit);
00721 cpl_table_delete(trace[nifu - 1]);
00722
00723 #pragma omp critical (muse_geo_header_construct)
00724 muse_geometry_qc_ifu(geoinit, headfinal, vlines);
00725 muse_geo_table_delete(geoinit);
00726
00727
00728 #pragma omp critical (muse_geo_table_insert)
00729 {
00730 if (!geotable) {
00731 geotable = geohori;
00732 } else {
00733 if (fabs(geotable->scale - geohori->scale) > 1e-10) {
00734
00735
00736
00737 cpl_msg_warning(__func__, "Combined and single geometry tables have "
00738 "different scales (%.15f / %.15f)!", geotable->scale,
00739 geohori->scale);
00740 }
00741 cpl_table_insert(geotable->table, geohori->table,
00742 cpl_table_get_nrow(geotable->table));
00743 muse_geo_table_delete(geohori);
00744 }
00745 }
00746 #pragma omp critical (muse_spots_table_insert)
00747 {
00748 if (!spots) {
00749 spots = mspots[nifu - 1];
00750 } else {
00751 cpl_table_insert(spots, mspots[nifu - 1], cpl_table_get_nrow(spots));
00752 cpl_table_delete(mspots[nifu - 1]);
00753 }
00754 }
00755 }
00756 cpl_vector_delete(vlines);
00757 cpl_error_code result = CPL_ERROR_NONE;
00758
00759 for (nifu = (unsigned)aParams->ifu1; nifu <= (unsigned)aParams->ifu2; nifu++) {
00760 if (result < rc[nifu - 1]) {
00761 result = rc[nifu - 1];
00762 }
00763 }
00764 #if 0
00765 cpl_table_save(geotable, NULL, NULL, "geocombined.fits", CPL_IO_CREATE);
00766 cpl_table_save(spots, NULL, NULL, "spotscombined.fits", CPL_IO_CREATE);
00767 #endif
00768 muse_geo_refine_horizontal(geotable, spots);
00769 cpl_table_delete(spots);
00770
00771 muse_geo_table *geofinal = muse_geo_determine_vertical(geotable);
00772 muse_geo_table_delete(geotable);
00773 cpl_error_code rcfinal = muse_geo_finalize(geofinal);
00774 if (result < rcfinal) {
00775 result = rcfinal;
00776 }
00777
00778 if (aParams->smooth > 0.) {
00779
00780 if (geofinal) {
00781 muse_geo_qc_global(geofinal, headfinal);
00782 muse_processing_save_table(aProcessing, -1, geofinal->table, headfinal,
00783 MUSE_TAG_GEOMETRY_OLD, MUSE_TABLE_TYPE_CPL);
00784 }
00785 rcfinal = muse_geo_correct_slices(geofinal, headfinal, aParams->smooth);
00786 if (result < rcfinal) {
00787 result = rcfinal;
00788 }
00789 } else {
00790
00791 cpl_propertylist_update_int(headfinal, QC_GEO_SMOOTH_NX, -1);
00792 cpl_propertylist_update_int(headfinal, QC_GEO_SMOOTH_NY, -1);
00793 cpl_propertylist_update_int(headfinal, QC_GEO_SMOOTH_NA, -1);
00794 cpl_propertylist_update_int(headfinal, QC_GEO_SMOOTH_NW, -1);
00795 }
00796
00797 if (geofinal) {
00798
00799 muse_geo_qc_global(geofinal, headfinal);
00800 muse_processing_save_table(aProcessing, -1, geofinal->table, headfinal,
00801 MUSE_TAG_GEOMETRY_TABLE, MUSE_TABLE_TYPE_CPL);
00802 }
00803
00804 muse_geometry_reconstruct_combined(aProcessing, aParams, geofinal,
00805 aParams->lambdamin, aParams->lambdamax);
00806
00807
00808 muse_geometry_reconstruct(aProcessing, aParams, geofinal,
00809 aParams->lambdamin, aParams->lambdamax);
00810 muse_geo_table_delete(geofinal);
00811 cpl_propertylist_delete(headfinal);
00812
00813 return result != CPL_ERROR_NONE ? -1 : 0;
00814 }