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