29 #include "muse_utils.h"
30 #include "muse_cplwrappers.h"
31 #include "muse_data_format_z.h"
34 #define MUSE_SKY_T_VIBR 200.0
48 muse_sky_ohtransitions_load(
const char *aFile)
50 if (!cpl_fits_find_extension(aFile,
"OH_TRANSITIONS")) {
70 muse_sky_lines_reindex_groups(cpl_table *aLines)
72 cpl_ensure_code(aLines, CPL_ERROR_NULL_INPUT);
73 cpl_size n_rows = cpl_table_get_nrow(aLines);
76 int i_max = cpl_table_get_column_max(aLines,
"group");
77 int new_ids[i_max + 1];
78 for (i = 0; i <= i_max; i++) {
83 for (i_row = 0; i_row < n_rows; i_row++) {
84 int old_id = cpl_table_get_int(aLines,
"group", i_row, NULL);
85 if (new_ids[old_id] < 0) {
86 new_ids[old_id] = i_max++;
88 cpl_table_set_int(aLines,
"group", i_row, new_ids[old_id]);
91 return CPL_ERROR_NONE;
110 cpl_ensure_code(aLines, CPL_ERROR_NULL_INPUT);
111 #pragma omp critical(cpl_table_select)
112 cpl_table_unselect_all(aLines);
113 cpl_table_or_selected_double(aLines,
"lambda", CPL_LESS_THAN, aLow);
114 cpl_table_or_selected_double(aLines,
"lambda", CPL_GREATER_THAN, aHigh);
115 cpl_table_erase_selected(aLines);
116 muse_sky_lines_reindex_groups(aLines);
118 return CPL_ERROR_NONE;
137 cpl_propertylist *aHeader)
139 cpl_ensure_code(aProcessing && aLines && aHeader, CPL_ERROR_NULL_INPUT);
142 CPL_FRAME_TYPE_TABLE);
143 cpl_ensure_code(frame, CPL_ERROR_ILLEGAL_INPUT);
144 const char *filename = cpl_frame_get_filename(frame);
145 cpl_error_code rc = cpl_propertylist_save(aHeader, filename, CPL_IO_CREATE);
148 if (rc == CPL_ERROR_NONE) {
149 cpl_frameset_insert(aProcessing->
outframes, frame);
151 cpl_frame_delete(frame);
170 cpl_ensure(aProcessing, CPL_ERROR_NULL_INPUT, NULL);
172 MUSE_TAG_SKY_LINES, 0, CPL_FALSE);
173 cpl_errorstate es = cpl_errorstate_get();
174 cpl_frame *frame = cpl_frameset_get_position(frames, 0);
176 cpl_frameset_delete(frames);
177 cpl_errorstate_set(es);
180 const char *fn = cpl_frame_get_filename(frame);
181 cpl_msg_info(__func__,
"using sky line table %s", fn);
183 cpl_table *oh_transitions = muse_sky_ohtransitions_load(fn);
185 if (lines == NULL && oh_transitions == NULL) {
186 cpl_frameset_delete(frames);
192 if (strcmp(cpl_table_get_column_unit(lines,
"flux"),
193 "erg/(s cm^2 arcsec^2)") == 0) {
194 cpl_msg_info(__func__,
"Scaling flux by 1e20");
195 cpl_table_multiply_scalar(lines,
"flux", 1e20);
196 cpl_table_set_column_unit(lines,
"flux",
197 "10**(-20)*erg/(s cm^2 arcsec^2)");
199 if (strcmp(cpl_table_get_column_unit(lines,
"flux"),
200 "10**(-20)*erg/(s cm^2 arcsec^2)") != 0) {
201 cpl_msg_warning(__func__,
"Unsupported flux unit %s",
202 cpl_table_get_column_unit(lines,
"flux"));
207 cpl_frameset_delete(frames);
211 cpl_table_delete(oh_transitions);
212 cpl_table_delete(lines);
231 cpl_ensure_code(aLines != NULL, CPL_ERROR_NULL_INPUT);
232 cpl_ensure_code(aStrength != NULL, CPL_ERROR_NULL_INPUT);
234 int *group = cpl_table_get_data_int(aLines,
"group");
235 double *flux = cpl_table_get_data_double(aLines,
"flux");
236 cpl_size nRows = cpl_table_get_nrow(aLines);
238 for (i = 0; i < nRows; i++, group++, flux++) {
239 *flux *= cpl_array_get(aStrength, *group, NULL);
241 return CPL_ERROR_NONE;
258 cpl_ensure_code(aLines != NULL, CPL_ERROR_NULL_INPUT);
259 cpl_table_select_all(aLines);
260 cpl_table_and_selected_double(aLines,
"flux", CPL_LESS_THAN, aMinflux);
261 cpl_table_erase_selected(aLines);
262 return CPL_ERROR_NONE;
288 muse_sky_lines_create_oh(
const cpl_table *aTransitions,
double aTemperature)
290 if ((aTransitions == NULL) || (cpl_table_get_nrow(aTransitions) == 0)) {
294 const int max_level = cpl_table_get_column_max(aTransitions,
"v_u");
295 const int min_level = cpl_table_get_column_min(aTransitions,
"v_u");
296 cpl_ensure(max_level-min_level < 100, CPL_ERROR_UNSUPPORTED_MODE, NULL);
297 const int n_transitions = cpl_table_get_nrow(aTransitions);
301 cpl_table_copy_data_string(lines,
"name",
302 cpl_table_get_data_string_const(aTransitions,
304 cpl_table_copy_data_double(lines,
"lambda",
305 cpl_table_get_data_double_const(aTransitions,
307 cpl_table_copy_data_int(lines,
"group",
308 cpl_table_get_data_int_const(aTransitions,
"v_u"));
309 cpl_table_subtract_scalar(lines,
"group", min_level);
311 cpl_table_fill_column_window_double(lines,
"flux", 0, n_transitions, 0.0);
313 const double k_B = 1.3806504e-23;
314 const double hc = 1.98623e-8;
315 cpl_table_copy_data_double(lines,
"flux",
316 cpl_table_get_data_double_const(aTransitions,
"E_u"));
317 cpl_table_divide_scalar(lines,
"flux", -k_B * aTemperature);
318 cpl_table_exponential_column(lines,
"flux", CPL_MATH_E);
320 cpl_table_duplicate_column(lines,
"J_u", aTransitions,
"J_u");
321 cpl_table_multiply_scalar(lines,
"J_u", 2.0);
322 cpl_table_add_scalar(lines,
"J_u", 1.0);
323 cpl_table_multiply_columns(lines,
"flux",
"J_u");
324 cpl_table_erase_column(lines,
"J_u");
326 cpl_table_fill_column_window_int(lines,
"dq", 0, n_transitions, 0);
328 double *flux = cpl_table_get_data_double(lines,
"flux");
329 const int *group = cpl_table_get_data_int_const(lines,
"group");
331 double q[max_level - min_level + 1];
332 memset(q, 0, (max_level - min_level + 1)*
sizeof(
double));
334 for (i_transition = 0; i_transition < n_transitions; i_transition++,
339 cpl_table_duplicate_column(lines,
"A", aTransitions,
"A");
340 cpl_table_multiply_columns(lines,
"flux",
"A");
341 cpl_table_erase_column(lines,
"A");
342 cpl_table_multiply_scalar(lines,
"flux", 2.0 * hc);
343 cpl_table_divide_columns(lines,
"flux",
"lambda");
345 flux = cpl_table_get_data_double(lines,
"flux");
346 group = cpl_table_get_data_int_const(lines,
"group");
348 for (i_transition = 0; i_transition < n_transitions; i_transition++,
353 cpl_table_multiply_scalar(lines,
"flux", 1e20);
355 cpl_table_divide_scalar(lines,
"flux", 50);
357 muse_sky_lines_reindex_groups(lines);
378 const cpl_table *aOh_transitions,
double aT_vibr)
380 int group_start = (aLines && cpl_table_get_nrow(aLines) > 0)?
381 cpl_table_get_column_max(aLines,
"group") + 1: 0;
382 cpl_table *res = muse_sky_lines_create_oh(aOh_transitions, aT_vibr);
383 cpl_errorstate prestate = cpl_errorstate_get();
385 cpl_table_add_scalar(res,
"group", group_start);
386 cpl_table_insert(res, aLines, 0);
388 if (!cpl_errorstate_is_equal(prestate)) {
389 cpl_msg_error(__func__,
"while cpl_table_insert(): %s, %s",
390 cpl_table_get_column_unit(res,
"flux"),
391 cpl_table_get_column_unit(aLines,
"flux"));
392 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
393 cpl_errorstate_set(prestate);
cpl_error_code muse_sky_lines_apply_strength(cpl_table *aLines, const cpl_array *aStrength)
Apply the line strengths to the lines.
cpl_error_code muse_sky_lines_save(muse_processing *aProcessing, const cpl_table *aLines, cpl_propertylist *aHeader)
Save sky lines table to file.
cpl_table * muse_sky_lines_create(const cpl_table *aLines, const cpl_table *aOh_transitions, double aT_vibr)
Create the emission lines from the OH transitions and other lines.
cpl_table * muse_sky_lines_load(muse_processing *aProcessing)
Load the sky data files.
cpl_table * muse_cpltable_load(const char *aFile, const char *aExtension, const muse_cpltable_def aDefinition[])
Load a table from disk (and check against definition).
cpl_table * muse_cpltable_new(const muse_cpltable_def *aDef, cpl_size aLength)
Create an empty table according to the specified definition.
cpl_frame * muse_processing_new_frame(muse_processing *aProcessing, int aIFU, cpl_propertylist *aHeader, const char *aTag, cpl_frame_type aType)
Create a new frame for a result file.
cpl_error_code muse_sky_lines_set_range(cpl_table *aLines, double aLow, double aHigh)
Limit the lines in the table to a wavelength range.
void muse_processing_append_used(muse_processing *aProcessing, cpl_frame *aFrame, cpl_frame_group aGroup, int aDuplicate)
Add a frame to the set of used frames.
cpl_error_code muse_sky_lines_cut(cpl_table *aLines, double aMinflux)
Remove all lines below a certain flux limit.
cpl_frameset * muse_frameset_find(const cpl_frameset *aFrames, const char *aTag, unsigned char aIFU, cpl_boolean aInvert)
return frameset containing data from an IFU/channel with a certain tag
cpl_error_code muse_cpltable_append_file(const cpl_table *aTable, const char *aFile, const char *aExtension, const muse_cpltable_def aDefinition[])
Save a table to disk (into a FITS extension)