ERIS Pipeline Reference Manual 1.8.15
sc_lines.c
Go to the documentation of this file.
1/*
2 * This file is part of the SKYCORR software package.
3 * Copyright (C) 2009-2013 European Southern Observatory
4 *
5 * This programme is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This programme is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this programme. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19
37/*****************************************************************************
38 * INCLUDES *
39 ****************************************************************************/
40
41#include <sc_lines.h>
42
43
44/*****************************************************************************
45 * CODE *
46 ****************************************************************************/
47
48cpl_error_code sc_lines(cpl_table *groups, cpl_parameterlist *parlist)
49{
70 cpl_error_code status = CPL_ERROR_NONE;
71 cpl_array *varpar;
72
73 /* Read line groups from ASCII file */
74 if ((status = sc_lines_readlist(groups, parlist)) != CPL_ERROR_NONE) {
75 return status;
76 }
77
78 /* Get season and time bins for airglow model from time of observation */
79 if ((status = sc_lines_getmodelbins(parlist)) != CPL_ERROR_NONE) {
80 return status;
81 }
82
83 /* Read scaling factors of line variability classes from ASCII file */
84 varpar = cpl_array_new(0, CPL_TYPE_DOUBLE);
85 if ((status = sc_lines_readvarpar(varpar, parlist)) != CPL_ERROR_NONE) {
86 cpl_array_delete(varpar);
87 return status;
88 }
89
90 /* Modify line fluxes by multiplying factors depending on the variability
91 class and the airmass */
92 sc_lines_scalelines(groups, varpar, parlist);
93
94 /* Convert vacuum to air wavelengths in line group list if required */
95 if ((status = sc_lines_vactoair(groups, parlist)) != CPL_ERROR_NONE) {
96 cpl_array_delete(varpar);
97 return status;
98 }
99
100 /* Free allocated memory */
101 cpl_array_delete(varpar);
102
103 return CPL_ERROR_NONE;
104}
105
106
107cpl_error_code sc_lines_readlist(cpl_table *groups,
108 const cpl_parameterlist *parlist)
109{
129 FILE *stream;
130 const cpl_parameter *p;
131 char* basedir = NULL;
132 char datadir[SC_MAXLEN];
133 char* linetabname = NULL;
134 char linetabfile[2*SC_MAXLEN];
135 char errtxt[3*SC_MAXLEN+50];
136 char str[SC_LENLINE+2];
137 cpl_boolean isoutrange = CPL_FALSE;
138 int nhead = 0, nrec = 0, feat = 0, syst = 0, agroup = 0, bgroup = 0;
139 int ncol0 = 0, ncolmin = 7, i = 0, ncol = 0;
140 double lam = 0., flux = 0., trans = 0.;
141
142 /* Create CPL table columns */
143 cpl_table_new_column(groups, "lambda", CPL_TYPE_DOUBLE);
144 cpl_table_new_column(groups, "flux", CPL_TYPE_DOUBLE);
145 cpl_table_new_column(groups, "trans", CPL_TYPE_DOUBLE);
146 cpl_table_new_column(groups, "feat", CPL_TYPE_INT);
147 cpl_table_new_column(groups, "system", CPL_TYPE_INT);
148 cpl_table_new_column(groups, "groupA", CPL_TYPE_INT);
149 cpl_table_new_column(groups, "groupB", CPL_TYPE_INT);
150
151 /* Open file with sky line data */
152 p = cpl_parameterlist_find_const(parlist, "inst_dir");
153 basedir = cpl_sprintf("%s",cpl_parameter_get_string(p));
154 p = cpl_parameterlist_find_const(parlist, "data_dir");
155 sc_basic_abspath(datadir, cpl_parameter_get_string(p), basedir);
156 p = cpl_parameterlist_find_const(parlist, "linetabname");
157 linetabname = cpl_sprintf("%s",cpl_parameter_get_string(p));
158 sprintf(linetabfile, "%s%s", datadir, linetabname);
159 if ((stream = fopen(linetabfile, "r")) == NULL) {
160 sprintf(errtxt, "%s: %s", SC_ERROR_FOF_TXT, linetabfile);
161 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_FOF, "%s", errtxt);
162 }
163
164 /* Write info message */
165// cpl_msg_debug(cpl_func, "Read line list %s", linetabfile);
166
167 /* Find number of header and data lines */
168 while (fgets(str, SC_LENLINE+2, stream) != NULL) {
169 if (str[0] == '#') {
170 nhead++;
171 if (nrec != 0) {
172 fclose(stream);
173 sprintf(errtxt, "%s: %s (comment line in data part)",
174 SC_ERROR_UFS_TXT, linetabfile);
175 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s",
176 errtxt);
177 }
178 } else if (isdigit(str[0]) || isspace(str[0]) || str[0] == '-') {
179 if (nrec == 0) {
180 /* Number of values per line */
181 ncol0 = sscanf(str, "%le %le %le %d %d %d %d", &lam, &flux,
182 &trans, &feat, &syst, &agroup, &bgroup);
183 if (ncol0 == 0) {
184 fclose(stream);
185 sprintf(errtxt, "%s: %s (empty line)",
186 SC_ERROR_UFS_TXT, linetabfile);
187 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s",
188 errtxt);
189 } else if (ncol0 < ncolmin) {
190 fclose(stream);
191 sprintf(errtxt, "%s: %s (too low number of columns)",
192 SC_ERROR_UFS_TXT, linetabfile);
193 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s",
194 errtxt);
195 }
196 }
197 nrec++;
198 } else {
199 fclose(stream);
200 sprintf(errtxt, "%s: %s (unexpected first character at line)",
201 SC_ERROR_UFS_TXT, linetabfile);
202 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s",
203 errtxt);
204 }
205 }
206 rewind(stream);
207
208 /* No data points */
209 if (nrec == 0) {
210 fclose(stream);
211 sprintf(errtxt, "%s: %s (no data)",
212 SC_ERROR_UFS_TXT, linetabfile);
213 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s", errtxt);
214 }
215
216 /* Resize output table */
217 cpl_table_set_size(groups, nrec);
218
219 /* Skip header */
220 for (i = 0; i < nhead; i++) {
221 if (fgets(str, SC_LENLINE+2, stream)) {};
222 }
223
224 /* Read line data from file and write it to CPL table */
225
226 for (i = 0; i < nrec; i++) {
227
228 ncol = fscanf(stream, "%le %le %le %d %d %d %d",
229 &lam, &flux, &trans, &feat, &syst, &agroup, &bgroup);
230
231 if (ncol != ncol0) {
232 cpl_table_set_size(groups, 0);
233 fclose(stream);
234 sprintf(errtxt, "%s: %s (unexpected number of values at line)",
235 SC_ERROR_UFS_TXT, linetabfile);
236 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s",
237 errtxt);
238 }
239
240 cpl_table_set(groups, "lambda", i, lam);
241 cpl_table_set(groups, "flux", i, flux);
242 cpl_table_set(groups, "trans", i, trans);
243 cpl_table_set(groups, "feat", i, feat);
244 cpl_table_set(groups, "system", i, syst);
245 cpl_table_set(groups, "groupA", i, agroup);
246 if (syst > 0 && bgroup == 0) {
247 /* Negative numbers for molecular lines without B group number */
248 cpl_table_set(groups, "groupB", i, -syst);
249 } else {
250 cpl_table_set(groups, "groupB", i, bgroup);
251 }
252
253 if (flux < 0.) {
254 flux = 0.;
255 isoutrange = CPL_TRUE;
256 }
257
258 if (trans < 0.) {
259 trans = 0.;
260 isoutrange = CPL_TRUE;
261 }
262
263 if (trans > 1.) {
264 trans = 1.;
265 isoutrange = CPL_TRUE;
266 }
267
268 if (feat < 1) {
269 feat = 1;
270 isoutrange = CPL_TRUE;
271 }
272
273 if (agroup < 0) {
274 agroup = 0;
275 isoutrange = CPL_TRUE;
276 }
277
278 if (bgroup < 0) {
279 bgroup = 0;
280 isoutrange = CPL_TRUE;
281 }
282
283 }
284
285 fclose(stream);
286
287 if (isoutrange == CPL_TRUE) {
288 cpl_msg_warning(cpl_func, "%s: Input value(s) out of range -> "
289 "Take lowest/highest allowed value(s)",
290 linetabname);
291 }
292 cpl_free(linetabname);
293 cpl_free(basedir);
294 return CPL_ERROR_NONE;
295}
296
297
298cpl_error_code sc_lines_getmodelbins(cpl_parameterlist *parlist)
299{
325 cpl_error_code status = CPL_ERROR_NONE;
326 cpl_parameter *p, *q;
327 char errtxt[SC_MAXLEN];
328 int year = 0, month = 0, day = 0, hh = 0, mm = 0;
329 int season = 0, timebin = 0;
330 double ss = 0., fracyear = 0., ut = 0., nlen = 0.;
331 double tlim1 = 0., tlim2 = 0.;
332 double nstart[6] = {0.98, 0.48, -0.44, -0.57, -0.23, 0.29};
333 double nend[6] = {8.50, 9.29, 9.77, 10.07, 9.61, 8.60};
334
335 /* Get date in years and UT time in s from parameter list */
336 p = cpl_parameterlist_find(parlist, "date_val");
337 fracyear = cpl_parameter_get_double(p);
338 p = cpl_parameterlist_find(parlist, "time_val");
339 ut = cpl_parameter_get_double(p) / 3600.;
340
341 /* Check for existence of date and time information */
342 if (fracyear < 0 || ut < 0) {
343 sprintf(errtxt, "%s: cpl_parameterlist *parlist (invalid date_val "
344 "and/or time_val)", SC_ERROR_IOV_TXT);
345 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_IOV, "%s", errtxt);
346 }
347
348 /* Derive season bin */
349 sc_basic_fracyear2date(&year, &month, &day, &hh, &mm, &ss, &fracyear);
350 if (month == 12) {
351 season = 1;
352 } else {
353 season = floor(month / 2) + 1;
354 }
355
356 /* Derive time bin */
357 if (ut > 16.) {
358 ut -= 24.;
359 }
360 nlen = nend[season-1] - nstart[season-1];
361 tlim1 = nstart[season-1] + nlen / 3;
362 tlim2 = nend[season-1] - nlen / 3;
363 if (ut < tlim1) {
364 timebin = 1;
365 } else if (ut >= tlim2) {
366 timebin = 3;
367 } else {
368 timebin = 2;
369 }
370
371 /* Write season and time bins into parameter list */
372 p = cpl_parameter_new_value("season", CPL_TYPE_INT, "", "", season);
373 cpl_parameterlist_append(parlist, p);
374 p = cpl_parameter_new_value("timebin", CPL_TYPE_INT, "", "", timebin);
375 cpl_parameterlist_append(parlist, p);
376
377 /* Write year and month into parameter list */
378 p = cpl_parameter_new_value("year", CPL_TYPE_INT, "", "", year);
379 cpl_parameterlist_append(parlist, p);
380 p = cpl_parameter_new_value("month", CPL_TYPE_INT, "", "", month);
381 cpl_parameterlist_append(parlist, p);
382
383 /* Take solar radio flux from parameter list if given */
384 q = cpl_parameterlist_find(parlist, "solflux");
385 if (cpl_parameter_get_double(q) >= 0) {
386 cpl_msg_debug(cpl_func, "SOLFLUX = %g sfu",
387 cpl_parameter_get_double(q));
388 return CPL_ERROR_NONE;
389 }
390
391 /* Get solar radio flux for year and month from file in sysdata/ */
392 p = cpl_parameterlist_find(parlist, "soldatsource");
393 cpl_parameter_set_string(p, "LOCAL");
394 status = sc_lines_readsolflux(parlist);
395
396 /* If reading fails, take flux from file on web server */
397 q = cpl_parameterlist_find(parlist, "solflux");
398 if (cpl_parameter_get_double(q) < 0) {
399 cpl_parameter_set_string(p, "WEB");
400 status = sc_lines_readsolflux(parlist);
401 }
402
403 /* If the procedure fails, take average value of 130 sfu */
404 if (cpl_parameter_get_double(q) < 0) {
405 cpl_parameter_set_string(p, "NONE");
406 sc_lines_readsolflux(parlist);
407 }
408
409 /* Write info message */
410 q = cpl_parameterlist_find(parlist, "solflux");
411// cpl_msg_debug(cpl_func, "SOLFLUX = %g sfu", cpl_parameter_get_double(q));
412
413 return status;
414}
415
416
417cpl_error_code sc_lines_readsolflux(cpl_parameterlist *parlist)
418{
439 FILE *stream;
440 cpl_parameter *p;
441 char* soldatsource = NULL;
442 char* soldaturl = NULL;
443 char* soldatname = NULL;
444 char soldatwebfile[2*SC_MAXLEN+25];
445 char* basedir = NULL;
446 char datadir[SC_MAXLEN];
447 char soldatfile[2*SC_MAXLEN], sys[4*SC_MAXLEN];
448 char errtxt[3*SC_MAXLEN], str[SC_LENLINE+2];
449 int year = 0, month = 0, i = 0, y = 0, m = 0, ncol = 0, ncolmin = 5;
450 double obsflux = 0., adjflux = 0., absflux = 0., solflux = -1.;
451
452 /* Get year and month from parameter list */
453 p = cpl_parameterlist_find(parlist, "year");
454 year = cpl_parameter_get_int(p);
455 p = cpl_parameterlist_find(parlist, "month");
456 month = cpl_parameter_get_int(p);
457
458 /* Set solar radio flux to -1 to indicate if month is not found */
459 p = cpl_parameterlist_find(parlist, "solflux");
460 cpl_parameter_set_double(p, -1.);
461
462 /* Get source of the solar radio flux data from parameter list */
463 p = cpl_parameterlist_find(parlist, "soldatsource");
464
465 soldatsource = cpl_sprintf("%s",cpl_parameter_get_string(p));
466 /* Take average solar radio flux if no data source */
467 if ((strcmp(soldatsource, "LOCAL") != 0 &&
468 strcmp(soldatsource, "WEB") != 0) ||
469 (strcmp(soldatsource, "WEB") == 0 &&
470 ((year == 1947 && month == 1) || year < 1947))) {
471 p = cpl_parameterlist_find(parlist, "solflux");
472 cpl_parameter_set_double(p, 130.);
473 cpl_msg_warning(cpl_func, "No source for solar radio flux available"
474 " -> Take average of 130 sfu");
475 return CPL_ERROR_NONE;
476 }
477
478 /* Merge web address and name of solar radio data file */
479 p = cpl_parameterlist_find(parlist, "soldaturl");
480 soldaturl = cpl_sprintf("%s", cpl_parameter_get_string(p));
481 p = cpl_parameterlist_find(parlist, "soldatname");
482 soldatname = cpl_sprintf("%s",cpl_parameter_get_string(p));
483 sprintf(soldatwebfile, "ftp://%s/%s", soldaturl, soldatname);
484
485 /* Get local data folder */
486 p = cpl_parameterlist_find(parlist, "inst_dir");
487 basedir = cpl_sprintf("%s", cpl_parameter_get_string(p));
488 p = cpl_parameterlist_find(parlist, "data_dir");
489 sc_basic_abspath(datadir, cpl_parameter_get_string(p), basedir);
490
491 /* Merge local path and name of solar radio data file */
492 sprintf(soldatfile, "%s%s", datadir, soldatname);
493
494 /* Download file from Canadian web server if "WEB" is desired as source */
495 if (strcmp(soldatsource, "WEB") == 0) {
496 cpl_msg_debug(cpl_func,
497 "Download solar radio flux data from web server");
498 sprintf(sys, "wget -q --directory-prefix=%s %s", datadir,
499 soldatwebfile);
500 if (system(sys)) {};
501// sprintf(sys, "mv %s.1 %s", soldatfile, soldatfile);
502// if (system(sys)) {};
503 }
504
505 /* Write info message */
506// cpl_msg_debug(cpl_func, "Get solar radio flux for %d/%d from %s", month,
507// year, soldatfile);
508
509 /* Open file with sky line data */
510 if ((stream = fopen(soldatfile, "r")) == NULL) {
511 sprintf(errtxt, "%s: %s", SC_ERROR_FOF_TXT, soldatfile);
512 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_FOF, "%s", errtxt);
513 }
514
515 /* Skip header */
516 for (i = 0; i < 2; i++) {
517 if (fgets(str, SC_LENLINE+2, stream)) {};
518 }
519
520 /* Read file and find solar radio flux for given year and month */
521
522 while (fgets(str, SC_LENLINE+2, stream) != NULL) {
523
524 if (isdigit(str[0]) || isspace(str[0])) {
525
526 /* Read values */
527 ncol = sscanf(str, "%d %d %le %le %le",
528 &y, &m, &obsflux, &adjflux, &absflux);
529
530 /* Check number of values per line */
531 if (ncol == 0) {
532 fclose(stream);
533 sprintf(errtxt, "%s: %s (empty line)",
534 SC_ERROR_UFS_TXT, soldatfile);
535 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s",
536 errtxt);
537 } else if (ncol < ncolmin) {
538 fclose(stream);
539 sprintf(errtxt, "%s: %s (too low number of columns)",
540 SC_ERROR_UFS_TXT, soldatfile);
541 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s",
542 errtxt);
543 }
544
545 /* Check validity of values */
546 if ((y < 1947) || (m < 1) || (m > 12) || (obsflux < 0.)) {
547 fclose(stream);
548 sprintf(errtxt, "%s: %s (invalid value(s))",
549 SC_ERROR_UFS_TXT, soldatfile);
550 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s",
551 errtxt);
552 }
553
554 /* Find solar radio flux for given year and month */
555 if (y == year && m == month) {
556 solflux = obsflux;
557 break;
558 }
559
560 } else {
561
562 /* No digit or space at the beginning of the line */
563 fclose(stream);
564 sprintf(errtxt, "%s: %s (unexpected first character at line)",
565 SC_ERROR_UFS_TXT, soldatfile);
566 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s",
567 errtxt);
568
569 }
570
571 }
572
573 fclose(stream);
574
575 /* If the required month is not in the file on the web server, take the
576 last entry */
577 if(strcmp(soldatsource, "WEB") == 0) {
578 if ((month != 1 && m < month-1 && y == year) ||
579 (month != 1 && y < year) ||
580 (month == 1 && m < 12 && y == year-1) ||
581 (month == 1 && y < year-1)) {
582 /* Warning message if last file entry is outdated */
583 cpl_msg_warning(cpl_func, "Solar radio fluxes until %d/%d only",
584 m, y);
585 }
586 if (obsflux != solflux) {
587 solflux = obsflux;
588 }
589 }
590
591 /* Write solar radio flux into parameter list */
592 p = cpl_parameterlist_find(parlist, "solflux");
593 cpl_parameter_set_double(p, floor(solflux + 0.5));
594 cpl_free(soldatsource);
595 cpl_free(basedir);
596 cpl_free(soldatname);
597 cpl_free(soldaturl);
598 return CPL_ERROR_NONE;
599}
600
601
602cpl_error_code sc_lines_readvarpar(cpl_array *varpar,
603 cpl_parameterlist *parlist)
604{
626 FILE *stream;
627 cpl_parameter *p;
629 char* basedir = NULL;
630 char datadir[SC_MAXLEN];
631 char* vardatname = NULL;
632 char vardatfile[2*SC_MAXLEN];
633 char errtxt[3*SC_MAXLEN];
634 int n = SC_MAXPAR, nfeat = 0, nseason = 0, ntime = 0, season = 0;
635 int timebin = 0, i = 0, j = 0;
636 double alt = 0., solflux = 0., height = 0., scale = 0., cons = 0.;
637 double slope = 0., mean = 0., z = 0., cvr = 0., csol = 0.;
638
639 /* Check existence of airglow scaling parameter file */
640 p = cpl_parameterlist_find(parlist, "inst_dir");
641 basedir = cpl_sprintf("%s", cpl_parameter_get_string(p));
642 p = cpl_parameterlist_find(parlist, "data_dir");
643 sc_basic_abspath(datadir, cpl_parameter_get_string(p), basedir);
644 p = cpl_parameterlist_find(parlist, "vardatname");
645 vardatname = cpl_sprintf("%s", cpl_parameter_get_string(p));
646 sprintf(vardatfile, "%s%s", datadir, vardatname);
647 if ((stream = fopen(vardatfile, "r")) == NULL) {
648 sprintf(errtxt, "%s: %s", SC_ERROR_FOF_TXT, vardatfile);
649 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_FOF, "%s", errtxt);
650 }
651
652 /* Write info message */
653// cpl_msg_debug(cpl_func, "Read line variability model file %s", vardatfile);
654
655 /* Read airglow scaling parameter file */
656
657 /* Read numbers for data set size */
658 sc_basic_readline(stream, x, &n);
659 nfeat = x[0].i;
660 sc_basic_readline(stream, x, &n);
661 nseason = x[0].i;
662 ntime = x[1].i;
663 //nbin = (nseason + 1) * (ntime + 1);
664
665 /* Return NULL vectors in the case of one or more zero for the data set
666 size */
667 if (nfeat == 0 || nseason == 0 || ntime == 0) {
668 fclose(stream);
669 sprintf(errtxt, "%s: %s (nfeat == 0 || nseason == 0 || ntime == 0)",
670 SC_ERROR_UFS_TXT, vardatfile);
671 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_UFS, "%s", errtxt);
672 }
673
674 /* Get and check airglow model parameters */
675 p = cpl_parameterlist_find(parlist, "telalt_val");
676 alt = cpl_parameter_get_double(p);
677 p = cpl_parameterlist_find(parlist, "solflux");
678 solflux = cpl_parameter_get_double(p);
679 p = cpl_parameterlist_find(parlist, "season");
680 season = cpl_parameter_get_int(p);
681 p = cpl_parameterlist_find(parlist, "timebin");
682 timebin = cpl_parameter_get_int(p);
683 if ((alt < 0.) || (alt > 90.) || (solflux < 0.) ||
684 (season < 0) || (season > nseason) || (timebin < 0) || (timebin > ntime)) {
685 fclose(stream);
686 sprintf(errtxt, "%s: cpl_parameterlist *parlist (telalt, solflux, "
687 "season, and/or timebin out of range) ", SC_ERROR_IOV_TXT);
688 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_IOV, "%s", errtxt);
689 }
690
691 /* Set size of varpar array */
692 cpl_array_set_size(varpar, nfeat);
693
694 /* Read data for each feature, extract bin data for selected time, and
695 fill CPL array with feature-specific flux correction factors */
696
697 for (i = 0; i < nfeat; i++) {
698
699 /* Time-independent parameters */
700 sc_basic_readline(stream, x, &n); // skip molmass
701 sc_basic_readline(stream, x, &n); // skip temp
702 sc_basic_readline(stream, x, &n);
703 height = x[0].d;
704 sc_basic_readline(stream, x, &n);
705 scale = x[0].d;
706 sc_basic_readline(stream, x, &n);
707 cons = x[0].d;
708 slope = x[1].d;
709
710 /* Mean value for selected time */
711 for (j = 0; j < ntime + 1; j++) {
712 sc_basic_readline(stream, m, &n);
713 if (j == timebin) {
714 mean = m[season].d;
715 }
716 }
717
718 /* Standard deviation for selected time (skipped) */
719 for (j = 0; j < ntime + 1; j++) {
720 sc_basic_readline(stream, m, &n);
721 }
722
723 /* Emission line brightness depending on airmass and layer height
724 (van Rhijn 1921) */
725 z = (90. - alt) * CPL_MATH_RAD_DEG;
726 cvr = 1 / sqrt(1 - pow((SC_ERAD / (SC_ERAD + height)) * sin(z), 2));
727
728 /* Influence of solar radio flux [sfu] */
729 csol = slope * solflux + cons;
730
731 /* Set feature-specific correction factors */
732 cpl_array_set(varpar, i, scale * cvr * csol * mean);
733
734 }
735
736 /* Close file */
737 fclose(stream);
738
739 cpl_free(vardatname);
740 cpl_free(basedir);
741 return CPL_ERROR_NONE;
742}
743
744
745cpl_error_code sc_lines_scalelines(cpl_table *groups, const cpl_array *varpar,
746 const cpl_parameterlist *parlist)
747{
768 const cpl_parameter *p;
769 cpl_boolean isoutrange = CPL_FALSE;
770 int nlin = 0, nfeat = 0, i = 0, feat = 0;
771 const double *corr = NULL;
772 double z = 0., xz = 0., trans = 0., flux = 0.;
773
774 /* Get number of lines and variability classes */
775 nlin = cpl_table_get_nrow(groups);
776 nfeat = cpl_array_get_size(varpar);
777
778 /* Get pointer to CPL array of flux correction factors */
779 corr = cpl_array_get_data_double_const(varpar);
780
781 /* Get and convert altitude in deg into zenith distance in rad */
782 p = cpl_parameterlist_find_const(parlist, "telalt_val");
783 z = (90. - cpl_parameter_get_double(p)) * CPL_MATH_RAD_DEG;
784
785 /* Use airmass approximation of Rozenberg (1966) for molecular
786 absorption correction */
787 xz = 1 / (cos(z) + 0.025 * exp(-11 * cos(z)));
788
789 /* Write info message */
790// cpl_msg_debug(cpl_func, "Adapt line list");
791
792 /* Correct line fluxes depending on line type and reduce fluxes due to
793 airmass-dependent atmospheric absorption */
794 for (i = 0; i < nlin; i++) {
795 feat = cpl_table_get(groups, "feat", i, NULL);
796 if (feat > nfeat) {
797 feat = 1;
798 isoutrange = CPL_TRUE;
799 }
800 trans = pow(cpl_table_get(groups, "trans", i, NULL), xz);
801 flux = cpl_table_get(groups, "flux", i, NULL);
802 cpl_table_set(groups, "flux", i, flux * corr[feat-1] * trans);
803 }
804
805 /* Print warning if the read line type is too high
806 -> Value is substituted by 1 */
807 if (isoutrange == CPL_TRUE) {
808 cpl_msg_warning(cpl_func, "Variability class too high -> "
809 "Take class 1");
810 }
811
812 return CPL_ERROR_NONE;
813}
814
815
816cpl_error_code sc_lines_vactoair(cpl_table *groups,
817 const cpl_parameterlist *parlist)
818{
836 const cpl_parameter *p;
837 char vac_air[4], errtxt[SC_MAXLEN];
838 int nrow = 0, i = 0;
839 double *lam, sig2 = 0., n = 0.;
840
841 /* Input spectrum: vacuum or air wavelengths? */
842 p = cpl_parameterlist_find_const(parlist, "vac_air");
843 strcpy(vac_air, cpl_parameter_get_string(p));
844
845 /* Check label for wavelength type */
846 if (strncmp(vac_air, "vac", 3) != 0 && strncmp(vac_air, "air", 3) != 0) {
847 sprintf(errtxt, "%s: cpl_parameterlist *parlist (vac_air neither "
848 "'vac' nor 'air')", SC_ERROR_IOV_TXT);
849 return cpl_error_set_message(cpl_func, (cpl_error_code)SC_ERROR_IOV, "%s", errtxt);
850 }
851
852 /* No conversion in the case of vacuum line wavelengths in the spectrum */
853 if (strncmp(vac_air, "vac", 3) == 0) {
854 return CPL_ERROR_NONE;
855 }
856
857 /* Get number of rows */
858 nrow = cpl_table_get_nrow(groups);
859
860 /* Get pointer to wavelengths */
861 lam = cpl_table_get_data_double(groups, "lambda");
862
863 /* Get refractive index and convert wavelengths */
864 for (i = 0; i < nrow; i++) {
865 sig2 = pow(lam[i], -2);
866 n = 8342.13 + 2406030. / (130. - sig2) + 15997. / (38.9 - sig2);
867 n = 1. + 1e-8 * n;
868 lam[i] /= n;
869 }
870
871 return CPL_ERROR_NONE;
872}
873
#define SC_MAXLEN
Definition: sc_basic.h:94
#define SC_MAXPAR
Definition: sc_basic.h:99
double sc_basic_fracyear2date(int *year, int *month, int *day, int *hh, int *mm, double *ss, const double *fracyear)
Definition: sc_basic.c:206
void sc_basic_abspath(char *out, const char *dir, const char *cwd)
Definition: sc_basic.c:1133
#define SC_LENLINE
Definition: sc_basic.h:92
cpl_error_code sc_basic_readline(FILE *stream, scpar par[], int *npar)
Definition: sc_basic.c:52
cpl_error_code sc_lines(cpl_table *groups, cpl_parameterlist *parlist)
Definition: sc_lines.c:48
cpl_error_code sc_lines_vactoair(cpl_table *groups, const cpl_parameterlist *parlist)
Definition: sc_lines.c:816
cpl_error_code sc_lines_readlist(cpl_table *groups, const cpl_parameterlist *parlist)
Definition: sc_lines.c:107
cpl_error_code sc_lines_readsolflux(cpl_parameterlist *parlist)
Definition: sc_lines.c:417
cpl_error_code sc_lines_readvarpar(cpl_array *varpar, cpl_parameterlist *parlist)
Definition: sc_lines.c:602
cpl_error_code sc_lines_scalelines(cpl_table *groups, const cpl_array *varpar, const cpl_parameterlist *parlist)
Definition: sc_lines.c:745
cpl_error_code sc_lines_getmodelbins(cpl_parameterlist *parlist)
Definition: sc_lines.c:298
#define SC_ERAD
Definition: sc_lines.h:63