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) {
49 if (!cpl_fits_find_extension(aFile,
"OH_TRANSITIONS")) {
66 muse_sky_ohtransitions_save(
const cpl_table *aTable,
const char *aFile) {
84 muse_sky_lines_reindex_groups(cpl_table *aLines) {
85 cpl_ensure_code(aLines, CPL_ERROR_NULL_INPUT);
86 cpl_size n_rows = cpl_table_get_nrow(aLines);
89 int i_max = cpl_table_get_column_max(aLines,
"group");
90 int new_ids[i_max + 1];
91 for (i = 0; i <= i_max; i++) {
96 for (i_row = 0; i_row < n_rows; i_row++) {
97 int old_id = cpl_table_get_int(aLines,
"group", i_row, NULL);
98 if (new_ids[old_id] < 0) {
99 new_ids[old_id] = i_max++;
101 cpl_table_set_int(aLines,
"group", i_row, new_ids[old_id]);
104 return CPL_ERROR_NONE;
123 cpl_ensure_code(aLines, CPL_ERROR_NULL_INPUT);
124 #pragma omp critical(cpl_table_select)
125 cpl_table_unselect_all(aLines);
126 cpl_table_or_selected_double(aLines,
"lambda", CPL_LESS_THAN, aLow);
127 cpl_table_or_selected_double(aLines,
"lambda", CPL_GREATER_THAN, aHigh);
128 cpl_table_erase_selected(aLines);
129 muse_sky_lines_reindex_groups(aLines);
131 return CPL_ERROR_NONE;
147 cpl_ensure(aProcessing, CPL_ERROR_NULL_INPUT, NULL);
149 MUSE_TAG_SKY_LINES, 0, CPL_FALSE);
150 cpl_errorstate es = cpl_errorstate_get();
151 cpl_frame *frame = cpl_frameset_get_position(frames, 0);
153 cpl_frameset_delete(frames);
154 cpl_errorstate_set(es);
157 const char *fn = cpl_frame_get_filename(frame);
158 cpl_msg_info(__func__,
"using sky line table %s", fn);
160 cpl_table *oh_transitions = muse_sky_ohtransitions_load(fn);
162 if (lines == NULL && oh_transitions == NULL) {
163 cpl_frameset_delete(frames);
169 if (strcmp(cpl_table_get_column_unit(lines,
"flux"),
170 "erg/(s cm^2 arcsec^2)") == 0) {
171 cpl_msg_info(__func__,
"Scaling flux by 1e20");
172 cpl_table_multiply_scalar(lines,
"flux", 1e20);
173 cpl_table_set_column_unit(lines,
"flux",
174 "10**(-20)*erg/(s cm^2 arcsec^2)");
176 if (strcmp(cpl_table_get_column_unit(lines,
"flux"),
177 "10**(-20)*erg/(s cm^2 arcsec^2)") != 0) {
178 cpl_msg_warning(__func__,
"Unsupported flux unit %s",
179 cpl_table_get_column_unit(lines,
"flux"));
184 cpl_frameset_delete(frames);
188 cpl_table_delete(oh_transitions);
189 cpl_table_delete(lines);
208 cpl_ensure_code(aLines != NULL, CPL_ERROR_NULL_INPUT);
209 cpl_ensure_code(aStrength != NULL, CPL_ERROR_NULL_INPUT);
211 int *group = cpl_table_get_data_int(aLines,
"group");
212 double *flux = cpl_table_get_data_double(aLines,
"flux");
213 cpl_size nRows = cpl_table_get_nrow(aLines);
215 for (i = 0; i < nRows; i++, group++, flux++) {
216 *flux *= cpl_array_get(aStrength, *group, NULL);
218 return CPL_ERROR_NONE;
235 cpl_ensure_code(aLines != NULL, CPL_ERROR_NULL_INPUT);
236 cpl_table_select_all(aLines);
237 cpl_table_and_selected_double(aLines,
"flux", CPL_LESS_THAN, aMinflux);
238 cpl_table_erase_selected(aLines);
239 return CPL_ERROR_NONE;
264 if ((aTransitions == NULL) || (cpl_table_get_nrow(aTransitions) == 0)) {
268 const int max_level = cpl_table_get_column_max(aTransitions,
"v_u");
269 const int min_level = cpl_table_get_column_min(aTransitions,
"v_u");
270 cpl_ensure(max_level-min_level < 100, CPL_ERROR_UNSUPPORTED_MODE, NULL);
271 const int n_transitions = cpl_table_get_nrow(aTransitions);
275 cpl_table_copy_data_string(lines,
"name",
276 cpl_table_get_data_string_const(aTransitions,
278 cpl_table_copy_data_double(lines,
"lambda",
279 cpl_table_get_data_double_const(aTransitions,
281 cpl_table_copy_data_int(lines,
"group",
282 cpl_table_get_data_int_const(aTransitions,
"v_u"));
283 cpl_table_subtract_scalar(lines,
"group", min_level);
285 cpl_table_fill_column_window_double(lines,
"flux", 0, n_transitions, 0.0);
287 const double k_B = 1.3806504e-23;
288 const double hc = 1.98623e-8;
289 cpl_table_copy_data_double(lines,
"flux",
290 cpl_table_get_data_double_const(aTransitions,
292 cpl_table_divide_scalar(lines,
"flux", -k_B * aTemperature);
293 cpl_table_exponential_column(lines,
"flux", CPL_MATH_E);
295 cpl_table_duplicate_column(lines,
"J_u", aTransitions,
"J_u");
296 cpl_table_multiply_scalar(lines,
"J_u", 2.0);
297 cpl_table_add_scalar(lines,
"J_u", 1.0);
298 cpl_table_multiply_columns(lines,
"flux",
"J_u");
299 cpl_table_erase_column(lines,
"J_u");
301 cpl_table_fill_column_window_int(lines,
"dq", 0, n_transitions, 0);
303 double *flux = cpl_table_get_data_double(lines,
"flux");
304 const int *group = cpl_table_get_data_int_const(lines,
"group");
306 double q[max_level - min_level + 1];
307 memset(q, 0, (max_level - min_level + 1)*
sizeof(
double));
309 for (i_transition = 0; i_transition < n_transitions; i_transition++,
314 cpl_table_duplicate_column(lines,
"A", aTransitions,
"A");
315 cpl_table_multiply_columns(lines,
"flux",
"A");
316 cpl_table_erase_column(lines,
"A");
317 cpl_table_multiply_scalar(lines,
"flux", 2.0 * hc);
318 cpl_table_divide_columns(lines,
"flux",
"lambda");
320 flux = cpl_table_get_data_double(lines,
"flux");
321 group = cpl_table_get_data_int_const(lines,
"group");
323 for (i_transition = 0; i_transition < n_transitions; i_transition++,
328 cpl_table_multiply_scalar(lines,
"flux", 1e20);
330 cpl_table_divide_scalar(lines,
"flux", 50);
332 muse_sky_lines_reindex_groups(lines);
352 const cpl_table *aOh_transitions,
double aT_vibr)
354 int group_start = (aLines && cpl_table_get_nrow(aLines) > 0)?
355 cpl_table_get_column_max(aLines,
"group") + 1: 0;
357 cpl_errorstate prestate = cpl_errorstate_get();
359 cpl_table_add_scalar(res,
"group", group_start);
360 cpl_table_insert(res, aLines, 0);
362 if (!cpl_errorstate_is_equal(prestate)) {
363 cpl_msg_error(__func__,
"while cpl_table_insert(): %s, %s",
364 cpl_table_get_column_unit(res,
"flux"),
365 cpl_table_get_column_unit(aLines,
"flux"));
366 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
367 cpl_errorstate_set(prestate);
cpl_error_code muse_sky_lines_apply_strength(cpl_table *, const cpl_array *)
Apply the line strengths to the lines.
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_error_code muse_sky_lines_set_range(cpl_table *, double, double)
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 *, double)
Remove all lines below a certain flux limit.
static cpl_table * muse_sky_lines_create_oh(const cpl_table *aTransitions, double aTemperature)
Get a list of lines from an OH transition table.
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_frameset * inputFrames
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)