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
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #ifdef HAVE_CONFIG_H
00078 # include <config.h>
00079 #endif
00080
00081
00085
00088
00089
00090
00091
00092 #include <uves_response_utils.h>
00093
00094 #include <uves_utils.h>
00095 #include <uves_utils_wrappers.h>
00096 #include <uves_pfits.h>
00097 #include <uves_error.h>
00098 #include <uves_msg.h>
00099
00100 #include <cpl.h>
00101
00102 #include <stdbool.h>
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00132
00133 cpl_image *
00134 uves_calculate_response(const cpl_image *spectrum, const uves_propertylist *spectrum_header,
00135 const cpl_table *flux_table,
00136 const uves_propertylist *raw_header,
00137 double PACCURACY,
00138 bool inverse,
00139 char **ref_obj_id)
00140 {
00141 cpl_image *response = NULL;
00142 cpl_table *catalogue_flux = NULL;
00143 int nx, norders;
00144
00145 nx = cpl_image_get_size_x(spectrum);
00146 norders = cpl_image_get_size_y(spectrum);
00147
00148 response = cpl_image_new(nx, norders, CPL_TYPE_DOUBLE);
00149
00150 check( catalogue_flux = uves_align(raw_header, flux_table, PACCURACY, ref_obj_id),
00151 "Cannot read catalogue flux");
00152
00153
00154 {
00155 double dlambda;
00156 int order;
00157
00158 check( dlambda = uves_pfits_get_cdelt1(spectrum_header),
00159 "Error reading bin width from header");
00160
00161 for (order = 1; order <= norders; order++)
00162 {
00163 double lambda_start;
00164 int x;
00165
00166
00167
00168
00169 if (norders == 1)
00170 {
00171 check( lambda_start = uves_pfits_get_crval1(spectrum_header),
00172 "Error reading start wavelength from header");
00173 }
00174 else
00175 {
00176 check( lambda_start = uves_pfits_get_wstart(spectrum_header, order),
00177 "Error reading start wavelength from header");
00178 }
00179
00180 for (x = 1; x <= nx; x++)
00181 {
00182 int pis_rejected;
00183 double lambda;
00184 double flux, std_flux, resp;
00185 int istart = 0;
00186
00187 lambda = lambda_start + (x-1) * dlambda;
00188
00189 check( flux = cpl_image_get(spectrum, x, order, &pis_rejected),
00190 "Error reading flux");
00191
00192 if (!pis_rejected)
00193 {
00194
00195 check( std_flux = uves_spline_hermite_table(
00196 lambda, catalogue_flux,
00197 "LAMBDA", "F_LAMBDA", &istart),
00198 "Error interpolating catalogue flux");
00199
00200 if (inverse)
00201 {
00202 resp = (flux == 0) ? 0 : std_flux / flux;
00203 }
00204 else
00205 {
00206 resp = (std_flux == 0) ? 0 : flux / std_flux;
00207 }
00208
00209 check( cpl_image_set(response, x, order, resp),
00210 "Error writing response image");
00211 }
00212 else
00213 {
00214 cpl_image_reject(response, x, order);
00215 }
00216 }
00217 }
00218 }
00219
00220 cleanup:
00221 uves_free_table(&catalogue_flux);
00222 if (cpl_error_get_code() != CPL_ERROR_NONE)
00223 {
00224 uves_free_image(&response);
00225 }
00226 return response;
00227 }
00228
00229
00230
00249
00250 cpl_table *
00251 uves_align(const uves_propertylist *object_header, const cpl_table *flux_table,
00252 double accuracy,
00253 char **ref_name_dynamic)
00254 {
00255 double obj_ra, obj_dec;
00256 int nident = 0;
00257 int match_row = 0;
00258 double min_dist = 0;
00259 double std_ra = 0, std_dec = 0;
00260 const char *ref_type = NULL;
00261
00262 cpl_table *result = NULL;
00263
00264 int i;
00265
00266 assure_nomsg( ref_name_dynamic != NULL, CPL_ERROR_NULL_INPUT );
00267 *ref_name_dynamic = NULL;
00268
00269 check( obj_ra = uves_pfits_get_ra (object_header), "Could not read right ascension");
00270 check( obj_dec = uves_pfits_get_dec(object_header), "Could not read declination");
00271
00272 uves_msg("Object RA, DEC = (%e, %e)", obj_ra, obj_dec);
00273
00274 nident = 0;
00275 for (i = 0; i < cpl_table_get_nrow(flux_table); i++)
00276 {
00277 double ref_ra, ref_dec;
00278 double dist;
00279
00280 check( ref_ra = cpl_table_get_double(flux_table, "RA_DEG", i, NULL),
00281 "Could not read catalogue star right ascension");
00282 check( ref_dec = cpl_table_get_double(flux_table, "DEC_DEG", i, NULL),
00283 "Could not read catalogue star declination");
00284
00285
00286
00287
00288
00289
00290
00291 dist =
00292 SIN_DEG(obj_dec)*SIN_DEG(ref_dec) +
00293 COS_DEG(obj_dec)*COS_DEG(ref_dec)*COS_DEG(obj_ra - ref_ra);
00294
00295 dist = uves_max_double(dist, -1);
00296 dist = uves_min_double(dist, 1);
00297
00298 dist = ACOS_DEG(dist) * 3600;
00299
00300 uves_msg_debug("Angular separation = %f arcseconds", dist);
00301
00302
00303
00304 if (i == 0 || dist < min_dist)
00305 {
00306 min_dist = dist;
00307 std_ra = ref_ra;
00308 std_dec = ref_dec;
00309 }
00310
00311
00312
00313 if (dist < accuracy)
00314 {
00315 nident += 1;
00316 match_row = i;
00317 min_dist = dist;
00318 std_ra = ref_ra;
00319 std_dec = ref_dec;
00320 }
00321 }
00322
00323 assure( nident >= 1, CPL_ERROR_INCOMPATIBLE_INPUT,
00324 "No catalogue object within %f arcsecs. "
00325 "Nearest object is %f arcsecs away at (RA, DEC) = (%f, %f)",
00326 accuracy, min_dist, std_ra, std_dec);
00327
00328 assure( nident <= 1, CPL_ERROR_INCOMPATIBLE_INPUT,
00329 "%d matching catalogue objects found. Confused. "
00330 "Decrease pointing accuracy (currently %f arcsecs) to get fewer matches",
00331 nident, accuracy);
00332
00333 check( *ref_name_dynamic = cpl_strdup(
00334 cpl_table_get_string(flux_table, "OBJECT", match_row)),
00335 "Could not read reference object name");
00336
00337 check( ref_type = cpl_table_get_string(flux_table, "TYPE", match_row),
00338 "Could not read reference object type");
00339
00340 uves_msg("Object ID is '%s', type = '%s'. Residual between header/catalogue = %f arcsecs",
00341 *ref_name_dynamic, ref_type, min_dist);
00342
00343
00344
00345 {
00346 const char *columns[3] = {"LAMBDA", "BIN_WIDTH", "F_LAMBDA"};
00347 int ndata;
00348
00349 check( ndata = cpl_table_get_int(flux_table, "NDATA", match_row, NULL),
00350 "Error reading length of flux array");
00351
00352 result = cpl_table_new(ndata);
00353
00354 for(i = 0; i < 3; i++)
00355 {
00356 const cpl_array *data;
00357 int indx;
00358
00359 cpl_table_new_column(result, columns[i], CPL_TYPE_DOUBLE);
00360
00361 data = cpl_table_get_array(flux_table, columns[i], match_row);
00362
00363
00364
00365 uves_msg_debug("3d table array size = %d, ndata = %d",
00366 cpl_array_get_size(data), ndata);
00367
00368 assure( cpl_array_get_size(data) >= ndata,
00369 CPL_ERROR_ILLEGAL_INPUT,
00370 "Flux table row %d: column '%s' depth (%d) "
00371 "is less than NDATA (%d)",
00372 match_row, columns[i], cpl_array_get_size(data), ndata);
00373
00374 for (indx = 0; indx < ndata; indx++)
00375 {
00376
00377 cpl_table_set_double(result, columns[i], indx,
00378 cpl_array_get_float(data, indx, NULL));
00379 }
00380 }
00381 }
00382
00383 cleanup:
00384 if (cpl_error_get_code() != CPL_ERROR_NONE)
00385 {
00386 uves_free_table(&result);
00387 if (ref_name_dynamic != NULL)
00388 {
00389 cpl_free(*ref_name_dynamic);
00390 *ref_name_dynamic = NULL;
00391 }
00392 }
00393
00394 return result;
00395 }
00396