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 #ifdef HAVE_CONFIG_H
00066 # include <config.h>
00067 #endif
00068
00069
00073
00076
00077
00078
00079
00080 #include <uves_reduce_utils.h>
00081
00082 #include <uves_pfits.h>
00083 #include <uves_utils.h>
00084 #include <uves_utils_wrappers.h>
00085 #include <uves_error.h>
00086 #include <uves_msg.h>
00087
00088 #include <cpl.h>
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00120
00121 cpl_image *
00122 uves_normalize_spectrum(const cpl_image *spectrum, const cpl_image *spectrum_error,
00123 const uves_propertylist *spectrum_header,
00124 const uves_propertylist *raw_header,
00125 int n_traces,
00126 enum uves_chip chip,
00127 const cpl_table *atm_extinction,
00128 bool correct_binning,
00129 cpl_image **scaled_error)
00130 {
00131 cpl_image *scaled = NULL;
00132 double exptime, gain;
00133 int binx;
00134 int norders, ny, nx;
00135
00136 assure_nomsg( spectrum != NULL, CPL_ERROR_NULL_INPUT);
00137 assure_nomsg( scaled_error == NULL || spectrum_error != NULL, CPL_ERROR_NULL_INPUT);
00138 assure_nomsg( spectrum_header != NULL, CPL_ERROR_NULL_INPUT);
00139
00140 nx = cpl_image_get_size_x(spectrum);
00141 ny = cpl_image_get_size_y(spectrum);
00142
00143 if (spectrum_error != NULL)
00144 {
00145 assure( nx == cpl_image_get_size_x(spectrum_error) &&
00146 ny == cpl_image_get_size_y(spectrum_error), CPL_ERROR_INCOMPATIBLE_INPUT,
00147 "Error spectrum geometry differs from spectrum: %dx%d vs. %dx%d",
00148 cpl_image_get_size_x(spectrum_error),
00149 cpl_image_get_size_y(spectrum_error),
00150 nx, ny);
00151 }
00152
00153 assure( ny % n_traces == 0, CPL_ERROR_INCOMPATIBLE_INPUT,
00154 "Spectrum image height (%d) is not a multiple of "
00155 "the number of traces (%d). Confused, bailing out",
00156 ny, n_traces);
00157
00158 norders = ny / n_traces;
00159
00160
00161
00162
00163 check( exptime = uves_pfits_get_exptime(raw_header),
00164 "Could not read exposure time");
00165
00166 check( gain = uves_pfits_get_gain(raw_header, chip),
00167 "Could not read gain factor");
00168
00169 if (correct_binning)
00170 {
00171
00172 check( binx = uves_pfits_get_biny(raw_header),
00173 "Could not read binning");
00174 }
00175 else
00176 {
00177 uves_msg("Spectrum will not be normalized to unit binning");
00178 binx = 1;
00179 }
00180
00181 assure( exptime > 0, CPL_ERROR_ILLEGAL_INPUT, "Non-positive exposure time: %f s", exptime);
00182 assure( gain > 0, CPL_ERROR_ILLEGAL_INPUT, "Non-positive gain: %f", gain);
00183 assure( binx > 0, CPL_ERROR_ILLEGAL_INPUT, "Illegal binning: %d", binx);
00184
00185 uves_msg("Correcting for exposure time = %f s, gain = %f, binx = %d", exptime, gain, binx);
00186
00187 check( scaled = cpl_image_divide_scalar_create(spectrum, exptime * gain * binx),
00188 "Error correcting spectrum for gain, exposure time, binning");
00189
00190 if (scaled_error != NULL)
00191 {
00192 check( *scaled_error = cpl_image_divide_scalar_create(spectrum_error,
00193 exptime * gain * binx),
00194 "Error correcting rebinned spectrum for gain, exposure time, binning");
00195 }
00196
00197
00198
00199
00200 {
00201 double airmass;
00202 double dlambda, lambda_start;
00203 int order;
00204
00205 {
00206 double airmass_start, airmass_end;
00207
00208 check( airmass_start = uves_pfits_get_airmass_start(raw_header),
00209 "Error reading airmass start");
00210
00211 check( airmass_end = uves_pfits_get_airmass_end(raw_header),
00212 "Error reading airmass end");
00213
00214
00215 airmass = (airmass_start + airmass_end) / 2;
00216
00217 }
00218
00219 uves_msg("Correcting for extinction through airmass %f", airmass);
00220
00221 check( dlambda = uves_pfits_get_cdelt1(spectrum_header),
00222 "Error reading bin width from header");
00223
00224 for (order = 1; order <= norders; order++)
00225 {
00226 int trace;
00227
00228
00229
00230
00231
00232 if (norders == 1)
00233 {
00234 check( lambda_start = uves_pfits_get_crval1(spectrum_header),
00235 "Error reading start wavelength from header");
00236 }
00237 else
00238 {
00239 check( lambda_start = uves_pfits_get_wstart(spectrum_header, order),
00240 "Error reading start wavelength from header");
00241 }
00242
00243 for (trace = 1; trace <= n_traces; trace++)
00244 {
00245 int spectrum_row = (order - 1)*n_traces + trace;
00246 int x;
00247
00248 for (x = 1; x <= nx; x++)
00249 {
00250 int pis_rejected1;
00251 int pis_rejected2;
00252 double flux;
00253 double dflux = 0;
00254 double extinction;
00255 double lambda;
00256
00257 lambda = lambda_start + (x-1) * dlambda;
00258
00259 flux = cpl_image_get(scaled, x, spectrum_row, &pis_rejected1);
00260 if (scaled_error != NULL)
00261 {
00262 dflux = cpl_image_get(*scaled_error, x,
00263 spectrum_row, &pis_rejected2);
00264 }
00265
00266 if (!pis_rejected1 && (scaled_error == NULL || !pis_rejected2))
00267 {
00268 int istart = 0;
00269
00270
00271 check( extinction =
00272 uves_spline_hermite_table(
00273 lambda, atm_extinction,
00274 "LAMBDA", "LA_SILLA", &istart),
00275 "Error interpolating extinction coefficient");
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 cpl_image_set(
00288 scaled, x, spectrum_row,
00289 flux * pow(10, 0.4 * extinction * airmass));
00290 if (scaled_error != NULL)
00291 {
00292 cpl_image_set(
00293 *scaled_error, x, spectrum_row,
00294 dflux * pow(10, 0.4 * extinction * airmass));
00295 }
00296 }
00297 else
00298 {
00299 cpl_image_reject(scaled, x, spectrum_row);
00300 if (scaled_error != NULL)
00301 {
00302 cpl_image_reject(*scaled_error, x, spectrum_row);
00303 }
00304 }
00305 }
00306
00307 }
00308
00309 }
00310 }
00311
00312 cleanup:
00313 if (cpl_error_get_code() != CPL_ERROR_NONE)
00314 {
00315 uves_free_image(&scaled);
00316 if (scaled_error != NULL)
00317 {
00318 uves_free_image(scaled_error);
00319 }
00320 }
00321
00322 return scaled;
00323 }
00324