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 #include "muse_sky.h"
00027 #include "muse_cplwrappers.h"
00028 #include "muse_data_format_z.h"
00029
00030
00047
00050
00062
00063 cpl_array *
00064 muse_sky_lines_spectrum(const cpl_array *aLambda, cpl_table *aLines,
00065 const cpl_image *aLsfImage,
00066 const muse_wcs *aLsfWCS)
00067 {
00068 cpl_size n_lines = cpl_table_get_nrow(aLines);
00069 cpl_size i_line;
00070 double l_min = aLsfWCS->crval1 + aLsfWCS->cd11 * (1 - aLsfWCS->crpix1),
00071 l_max = aLsfWCS->crval1
00072 + aLsfWCS->cd11 * (cpl_image_get_size_x(aLsfImage) - aLsfWCS->crpix1);
00073 cpl_array *spectrum = cpl_array_new(cpl_array_get_size(aLambda),
00074 CPL_TYPE_DOUBLE);
00075 cpl_array_fill_window(spectrum, 0, cpl_array_get_size(aLambda), 0.0);
00076 for (i_line = 0; i_line < n_lines; i_line++) {
00077 double l_lambda = cpl_table_get(aLines, "lambda", i_line, NULL);
00078 double l_flux = cpl_table_get(aLines, "flux", i_line, NULL);
00079 cpl_size imin = muse_cplarray_find_sorted(aLambda, l_lambda + l_min);
00080 cpl_size imax = muse_cplarray_find_sorted(aLambda, l_lambda + l_max);
00081 if (imax <= imin) {
00082 continue;
00083 }
00084 cpl_array *l0 = cpl_array_extract(aLambda, imin, imax-imin+1);
00085 cpl_array_subtract_scalar(l0, l_lambda);
00086 muse_lsf_apply(aLsfImage, aLsfWCS, l0, l_lambda);
00087 cpl_array_multiply_scalar(l0, l_flux);
00088 muse_cplarray_add_window(spectrum, imin, l0);
00089 cpl_array_delete(l0);
00090 }
00091 return spectrum;
00092 }
00093
00094
00100
00101 static cpl_error_code
00102 muse_sky_subtract_lines_slice(muse_pixtable *aPixtable, cpl_table *aLines,
00103 cpl_image *aLsfImage, muse_wcs *aLsfWCS)
00104 {
00105 cpl_propertylist *order = cpl_propertylist_new();
00106 cpl_propertylist_append_bool(order, MUSE_PIXTABLE_LAMBDA, CPL_FALSE);
00107 cpl_table_sort(aPixtable->table, order);
00108 cpl_propertylist_delete(order);
00109
00110 cpl_array *data = muse_cpltable_extract_column(aPixtable->table,
00111 MUSE_PIXTABLE_DATA);
00112
00113 cpl_array *lambda = NULL;
00114 if (cpl_table_get_column_type(aPixtable->table, MUSE_PIXTABLE_LAMBDA)
00115 == CPL_TYPE_DOUBLE) {
00116 lambda = muse_cpltable_extract_column(aPixtable->table,
00117 MUSE_PIXTABLE_LAMBDA);
00118 } else {
00119 cpl_table_cast_column(aPixtable->table, MUSE_PIXTABLE_LAMBDA,
00120 "lambda_double", CPL_TYPE_DOUBLE);
00121 lambda = muse_cpltable_extract_column(aPixtable->table, "lambda_double");
00122 }
00123
00124 if ((aLines != NULL) && (aLsfImage != NULL) && (aLsfWCS != NULL)) {
00125 cpl_array *spectrum = muse_sky_lines_spectrum(lambda, aLines,
00126 aLsfImage, aLsfWCS);
00127 cpl_array_subtract(data, spectrum);
00128 cpl_array_delete(spectrum);
00129 }
00130
00131 cpl_array_unwrap(data);
00132 cpl_array_unwrap(lambda);
00133 if (cpl_table_has_column(aPixtable->table, "lambda_double")) {
00134 cpl_table_erase_column(aPixtable->table, "lambda_double");
00135 }
00136
00137 return CPL_ERROR_NONE;
00138 }
00139
00140
00148
00149 cpl_error_code
00150 muse_sky_subtract_lines(muse_pixtable *aPixtable,
00151 cpl_table *aLines, muse_lsf_cube **aLsfCube)
00152 {
00153 cpl_ensure_code(aPixtable != NULL, CPL_ERROR_NULL_INPUT);
00154 cpl_ensure_code(aPixtable->table != NULL, CPL_ERROR_NULL_INPUT);
00155 cpl_ensure_code(muse_cpltable_check(aPixtable->table, muse_pixtable_def) == CPL_ERROR_NONE,
00156 CPL_ERROR_DATA_NOT_FOUND);
00157 cpl_ensure_code(aLines != NULL, CPL_ERROR_NULL_INPUT);
00158 cpl_ensure_code(aLsfCube != NULL, CPL_ERROR_NULL_INPUT);
00159
00160 muse_pixtable **slice_pixtable =
00161 muse_pixtable_extracted_get_slices(aPixtable);
00162 cpl_size n_slices = muse_pixtable_extracted_get_size(slice_pixtable);
00163 cpl_size i_slice;
00164 cpl_error_code rc[n_slices];
00165 cpl_msg_info(__func__, "Starting sky subtraction of %"CPL_SIZE_FORMAT
00166 " slices", n_slices);
00167 cpl_boolean debug = getenv("MUSE_DEBUG_SKY")
00168 && atoi(getenv("MUSE_DEBUG_SKY")) > 0;
00169 #pragma omp parallel for default(none) \
00170 shared(aLsfCube, aLines, debug, n_slices, slice_pixtable, rc)
00171 for (i_slice = 0; i_slice < n_slices; i_slice++) {
00172 muse_pixtable *slice_pt = slice_pixtable[i_slice];
00173 uint32_t origin =
00174 (uint32_t) cpl_table_get_int(slice_pt->table,
00175 MUSE_PIXTABLE_ORIGIN, 0, NULL);
00176 int ifu = muse_pixtable_origin_get_ifu(origin);
00177 int slice = muse_pixtable_origin_get_slice(origin);
00178 if ((aLsfCube[ifu-1] == NULL) && (aLines != NULL)) {
00179 cpl_msg_warning(__func__,
00180 "No LSF params for slice #%i.%i."
00181 " Ignoring lines in sky subtraction for this slice.",
00182 ifu, slice);
00183 rc[i_slice] = CPL_ERROR_NONE;
00184 continue;
00185 }
00186
00187 cpl_size nrows = muse_pixtable_get_nrow(slice_pt);
00188 if (debug) {
00189 cpl_msg_debug(__func__, "Sky subtraction of %"CPL_SIZE_FORMAT" pixels for"
00190 " slice #%i.%i (%i)", nrows, ifu, slice, (int)i_slice+1);
00191 }
00192 cpl_image *lsfImage = cpl_imagelist_get(aLsfCube[ifu-1]->img, slice-1);
00193 rc[i_slice] = muse_sky_subtract_lines_slice(slice_pt,
00194 aLines, lsfImage,
00195 aLsfCube[ifu-1]->wcs);
00196 }
00197 muse_pixtable_extracted_delete(slice_pixtable);
00198
00199 for (i_slice = 0; i_slice < n_slices; i_slice++) {
00200 if (rc[i_slice] != CPL_ERROR_NONE) {
00201 return rc[i_slice];
00202 }
00203 }
00204 return CPL_ERROR_NONE;
00205 }
00206
00207
00214
00215 cpl_error_code
00216 muse_sky_subtract_continuum(muse_pixtable *aPixtable, cpl_table *aSpectrum)
00217 {
00218 cpl_ensure_code(aPixtable != NULL, CPL_ERROR_NULL_INPUT);
00219 cpl_ensure_code(aPixtable->table != NULL, CPL_ERROR_NULL_INPUT);
00220 cpl_ensure_code(muse_cpltable_check(aPixtable->table, muse_pixtable_def) == CPL_ERROR_NONE,
00221 CPL_ERROR_DATA_NOT_FOUND);
00222 cpl_ensure_code(aSpectrum != NULL, CPL_ERROR_NULL_INPUT);
00223 cpl_ensure_code(cpl_table_has_column(aSpectrum, "lambda") &&
00224 cpl_table_has_column(aSpectrum, "flux"),
00225 CPL_ERROR_DATA_NOT_FOUND);
00226
00227
00228 double lmin = cpl_table_get_column_min(aSpectrum, "lambda");
00229 double lmax = cpl_table_get_column_max(aSpectrum, "lambda");
00230 cpl_msg_info(__func__, "Cutting data to %.3f...%.3f Angstrom for sky "
00231 "subtraction (range of continuum)", lmin, lmax);
00232 muse_pixtable_restrict_wavelength(aPixtable, lmin, lmax);
00233
00234 muse_pixtable **slice_pixtable =
00235 muse_pixtable_extracted_get_slices(aPixtable);
00236 cpl_size n_slices = muse_pixtable_extracted_get_size(slice_pixtable);
00237 cpl_size i_slice;
00238 cpl_boolean debug = getenv("MUSE_DEBUG_SKY")
00239 && atoi(getenv("MUSE_DEBUG_SKY")) > 0;
00240 #pragma omp parallel for default(none) \
00241 shared(aSpectrum, debug, n_slices, slice_pixtable)
00242 for (i_slice = 0; i_slice < n_slices; i_slice++) {
00243 muse_pixtable *slice_pt = slice_pixtable[i_slice];
00244 cpl_propertylist *order = cpl_propertylist_new();
00245 cpl_propertylist_append_bool(order, MUSE_PIXTABLE_LAMBDA, CPL_FALSE);
00246 cpl_table_sort(slice_pt->table, order);
00247 cpl_propertylist_delete(order);
00248 cpl_array *lambda = NULL;
00249 if (cpl_table_get_column_type(slice_pt->table, MUSE_PIXTABLE_LAMBDA)
00250 == CPL_TYPE_DOUBLE) {
00251 lambda = muse_cpltable_extract_column(slice_pt->table,
00252 MUSE_PIXTABLE_LAMBDA);
00253 } else {
00254 cpl_table_cast_column(slice_pt->table, MUSE_PIXTABLE_LAMBDA,
00255 "lambda_double", CPL_TYPE_DOUBLE);
00256 lambda = muse_cpltable_extract_column(slice_pt->table, "lambda_double");
00257 }
00258
00259 cpl_array *data = muse_cpltable_extract_column(slice_pt->table,
00260 MUSE_PIXTABLE_DATA);
00261 cpl_array *continuum
00262 = muse_cplarray_interpolate_table_linear(lambda, aSpectrum,
00263 "lambda", "flux");
00264
00265 if (debug) {
00266 cpl_msg_debug(__func__, "Subtracting continuum from %"CPL_SIZE_FORMAT
00267 " pixels", cpl_array_get_size(continuum));
00268 }
00269 cpl_array_subtract(data, continuum);
00270 cpl_array_delete(continuum);
00271 cpl_array_unwrap(data);
00272 cpl_array_unwrap(lambda);
00273 if (cpl_table_has_column(slice_pt->table, "lambda_double")) {
00274 cpl_table_erase_column(slice_pt->table, "lambda_double");
00275 }
00276 }
00277 muse_pixtable_extracted_delete(slice_pixtable);
00278 return CPL_ERROR_NONE;
00279 }
00280