star-hitran

Load line-by-line data from the HITRAN database
git clone git://git.meso-star.fr/star-hitran.git
Log | Files | Refs | README | LICENSE

commit 5fb64482b10af24ec805c7762a980509510f02ce
parent 2751f0b5d60e3d864e93ccc9246708978348d3a8
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 11 Feb 2026 14:17:43 +0100

Check the validity of lines in the shtr tool

Once defined, the new -c option allows you to check the validity of
lines, both in terms of numerical representation and domain of
definition. An error is returned as soon as a line is detected as
invalid. However, all lines are tested so that all lines that need to be
corrected are displayed, not just the first line that causes an error.

This check was previously performed by the line list test, which
accepted files as optional input arguments. This feature has therefore
been removed from the test since shtr now performs this task.

Diffstat:
Mdoc/shtr.1 | 7+++++--
Msrc/shtr_main.c | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/test_shtr_lines.c | 55-------------------------------------------------------
3 files changed, 80 insertions(+), 59 deletions(-)

diff --git a/doc/shtr.1 b/doc/shtr.1 @@ -15,7 +15,7 @@ .\" .\" You should have received a copy of the GNU General Public License .\" along with this program. If not, see <http://www.gnu.org/licenses/>. -.Dd January 23, 2026 +.Dd February 11, 2026 .Dt SHTR 1 .Os .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" @@ -25,7 +25,7 @@ .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .Sh SYNOPSIS .Nm -.Op Fl aHhisv +.Op Fl acHhisv .Op Fl l Ar lines .Op Fl m Ar molparam .Op Fl o Ar output @@ -70,6 +70,9 @@ The options are as follows: .It Fl a Measure line access performance. Both linear and random access are tested. +.It Fl c +Checks the validity of the parameters of the loaded lines, in terms of +numerical values and definition domain. .It Fl H Use suffixes to make memory usage easier to read: the number of consecutive digits is then three or less, using powers of 2 for sizes diff --git a/src/shtr_main.c b/src/shtr_main.c @@ -37,6 +37,7 @@ struct args { char* output; int bench_line_access; + int check_line_data; int internal_format; int verbose; /* Verbosity level */ int print_info; @@ -60,7 +61,7 @@ static INLINE void usage(FILE* stream) { fprintf(stream, -"usage: shtr [-aHhisv] [-l lines] [-m molparam] [-o output]\n"); +"usage: shtr [-acHhisv] [-l lines] [-m molparam] [-o output]\n"); } static res_T @@ -73,9 +74,10 @@ args_init(struct args* args, int argc, char** argv) *args = ARGS_DEFAULT; - while((opt = getopt(argc, argv, "aHhil:m:o:sv")) != -1) { + while((opt = getopt(argc, argv, "acHhil:m:o:sv")) != -1) { switch(opt) { case 'a': args->bench_line_access = 1; break; + case 'c': args->check_line_data = 1; break; case 'H': args->human_readable = 1; break; case 'h': usage(stdout); args->quit = 1; break; case 'i': args->print_info = 1; break; @@ -301,6 +303,73 @@ bench_line_access(struct shtr_line_list* lines) } static res_T +check_line(const struct shtr_line* ln) +{ + /* Check NaN */ + if(ln->wavenumber != ln->wavenumber + || ln->intensity != ln->intensity + || ln->gamma_air != ln->gamma_air + || ln->gamma_self != ln->gamma_self + || ln->lower_state_energy != ln->lower_state_energy + || ln->n_air != ln->n_air + || ln->delta_air != ln->delta_air) { + return RES_BAD_ARG; + } + + if(ln->wavenumber < 0 + || ln->intensity < 0 + || ln->gamma_air < 0 + || ln->gamma_self < 0 + || ln->lower_state_energy < 0 + || ln->molecule_id < 0 + || ln->molecule_id > 99 + || ln->isotope_id_local < 0 + || ln->isotope_id_local > 9) { + return RES_BAD_ARG; + } + + return RES_OK; +} + +static res_T +check_line_list(struct shtr_line_list* list) +{ + size_t nerr = 0; + size_t i, n; + res_T res = RES_OK; + + SHTR(line_list_get_size(list, &n)); + + FOR_EACH(i, 0, n) { + struct shtr_line line = SHTR_LINE_NULL; + + SHTR(line_list_at(list, i, &line)); + if((res = check_line(&line)) != RES_OK) { + ++nerr; + fprintf(stderr, + "invalid line %lu: " + "nu=%-12.4e " + "S=%-12.4e " + "Yair=%-12.4e " + "Yself=%-12.4e " + "E=%-12.4e " + "n=%-12.4e " + "d=%-12.4e\n", + (unsigned long)i, + line.wavenumber, + line.intensity, + line.gamma_air, + line.gamma_self, + line.lower_state_energy, + line.n_air, + line.delta_air); + } + } + + return nerr > 0 ? RES_BAD_ARG : RES_OK; +} + +static res_T cmd_run(const struct cmd* cmd) { struct shtr_isotope_metadata* molparam = NULL; @@ -314,6 +383,10 @@ cmd_run(const struct cmd* cmd) if(cmd->args.lines) { if((res = load_lines(cmd, &lines)) != RES_OK) goto error; if(cmd->args.print_info) lines_info(lines); + if(cmd->args.check_line_data) { + res = check_line_list(lines); + if(res != RES_OK) goto error; + } if(cmd->args.bench_line_access) bench_line_access(lines); if(cmd->args.output) { res = write_lines(cmd, lines); diff --git a/src/test_shtr_lines.c b/src/test_shtr_lines.c @@ -471,55 +471,11 @@ test_deserialization_of_a_subset(struct shtr* shtr) CHK(shtr_line_list_ref_put(list1) == RES_OK); } -static void -check_line(const struct shtr_line* ln) -{ - /* Check NaN */ - CHK(ln->wavenumber == ln->wavenumber); - CHK(ln->intensity == ln->intensity); - CHK(ln->gamma_air == ln->gamma_air); - CHK(ln->gamma_self == ln->gamma_self); - CHK(ln->lower_state_energy == ln->lower_state_energy); - CHK(ln->n_air == ln->n_air); - CHK(ln->delta_air == ln->delta_air); - - CHK(ln->wavenumber > 0); - CHK(ln->intensity > 0); - CHK(ln->gamma_air >= 0); - CHK(ln->gamma_self >= 0); - CHK(ln->lower_state_energy >= 0); - CHK(ln->molecule_id >= 0 && ln->molecule_id < 100); - CHK(ln->isotope_id_local >= 0 && ln->isotope_id_local <= 9); -} - -static void -test_load_file(struct shtr* shtr, const char* path) -{ - struct shtr_line_list_load_args args = SHTR_LINE_LIST_LOAD_ARGS_NULL__; - struct shtr_line_list* list = NULL; - size_t i, n; - CHK(path); - printf("Loading `%s'.\n", path); - args.filename = path; - CHK(shtr_line_list_load(shtr, &args, &list) == RES_OK); - CHK(shtr_line_list_get_size(list, &n) == RES_OK); - printf(" #lines: %lu\n", n); - - FOR_EACH(i, 0, n) { - struct shtr_line line = SHTR_LINE_NULL; - CHK(shtr_line_list_at(list, i, &line) == RES_OK); - check_line(&line); - } - - CHK(shtr_line_list_ref_put(list) == RES_OK); -} - int main(int argc, char** argv) { struct shtr_create_args args = SHTR_CREATE_ARGS_DEFAULT; struct shtr* shtr = NULL; - int i; (void)argc, (void)argv; args.verbose = 1; @@ -531,17 +487,6 @@ main(int argc, char** argv) test_serialization(shtr); test_deserialization_of_a_subset(shtr); - FOR_EACH(i, 1, argc) { - char buf[64]; - struct time t0, t1; - - time_current(&t0); - test_load_file(shtr, argv[i]); - time_sub(&t0, time_current(&t1), &t0); - time_dump(&t0, TIME_ALL, NULL, buf, sizeof(buf)); - printf("%s loaded in %s\n", argv[i], buf); - } - CHK(shtr_ref_put(shtr) == RES_OK); CHK(mem_allocated_size() == 0); return 0;