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