commit 0e463bb77f376912fcf50604bad9b85d23cd185e
parent 7a18a46e2af2668a2375bf7eb7ffa13955d99aa3
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 9 Jan 2026 15:14:39 +0100
Enable serialization of data loaded by the shtr utility
The -o option defines the file to which the data is written. When
loading lines, the new -z option controls their compression level. The
shtr utility can therefore be used to test the balance between memory
space and compression speed, and as a tool for encoding and compressing
spectroscopic data from HITRAN databases.
Diffstat:
| M | doc/shtr.1 | | | 34 | +++++++++++++++++++++++++++++++--- |
| M | src/shtr_main.c | | | 69 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- |
2 files changed, 93 insertions(+), 10 deletions(-)
diff --git a/doc/shtr.1 b/doc/shtr.1
@@ -15,19 +15,21 @@
.\"
.\" 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 5, 2026
+.Dd January 9, 2026
.Dt SHTR 1
.Os
.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh NAME
.Nm shtr
-.Nd load and print information on HITRAN files
+.Nd process spectroscopic data from HITRAN files
.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh SYNOPSIS
.Nm
.Op Fl hv
.Op Fl l Ar lines
.Op Fl m Ar molparam
+.Op Fl o Ar output
+.Op Fl z Ar compression_level
.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh DESCRIPTION
.Nm
@@ -37,7 +39,11 @@ The data can be either isotopologue metadata or line-by-line parameters.
In fact,
.Nm
is a utility for analyzing the behavior of the Star-HITRAN library with
-regard to the loading and internal structuring of spectroscopic data.
+regard to the loading and its internal structuring of spectroscopic
+data.
+It can also be used to serialize the internal representation of loaded
+data, which is much more compact for lines and therefore faster to reload
+by the library.
.Pp
All isotopologue metadata are loaded.
However, since the number of lines can be very large, only a subset of
@@ -80,6 +86,8 @@ By default, memory usage is displayed in bytes.
Files storing line-by-line parameters to be loaded.
.It Fl m Ar molparam
Files storing isotopologue metadata to be loaded.
+.It Fl o Ar output
+Files in which to serialize the list of loaded lines.
.It Fl v
Make
.Nm
@@ -88,11 +96,31 @@ Multiple
.Fl v
options increase the verbosity.
The maximum is 3.
+.It Fl z Ar compression_level
+Line compression level.
+Must be between 0
+.Pq no compression
+and 9
+.Pq best compression .
+By default, uses an intermediate level that balances speed and
+compression.
.El
.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh EXIT STATUS
.Ex -std
.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.Sh EXAMPLES
+Load a list of lines and serialize the resulting binary representation
+to the file
+.Pa CO2.bin .
+Make the output of
+.Nm
+as detailed as possible and use suffixes when displaying the size of
+memory used to make it easier to read:
+.Bd -literal -offset Ds
+shtr -l /path/to/CO2_lines.hitemp2010 -o CO2.bin -vvv -h
+.Ed
+.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.Sh SEE ALSO
.Rs
.%T The HITRAN Database
diff --git a/src/shtr_main.c b/src/shtr_main.c
@@ -33,11 +33,15 @@
struct args {
char* molparam;
char* lines;
+ char* output;
int verbose; /* Verbosity level */
+ int compression; /* Compression level */
int human_readable;
};
-static const struct args ARGS_DEFAULT = {0};
+static const struct args ARGS_DEFAULT = {
+ NULL, NULL, NULL, 0, SHTR_DEFAULT_COMPRESSION, 0
+};
struct cmd {
struct mem_allocator allocator;
@@ -53,7 +57,8 @@ static const struct cmd CMD_NULL = {0};
static INLINE void
usage(FILE* stream)
{
- fprintf(stream, "usage: shtr [-hv] [-l lines] [-m molparam]\n");
+ fprintf(stream,
+"usage: shtr [-hv] [-l lines] [-m molparam] [-o output] [-z compression_level]\n");
}
static res_T
@@ -66,12 +71,14 @@ args_init(struct args* args, int argc, char** argv)
*args = ARGS_DEFAULT;
- while((opt = getopt(argc, argv, "hl:m:v")) != -1) {
+ while((opt = getopt(argc, argv, "hl:m:o:vz:")) != -1) {
switch(opt) {
case 'h': args->human_readable = 1; break;
case 'l': args->lines = optarg; break;
case 'm': args->molparam = optarg; break;
+ case 'o': args->output = optarg; break;
case 'v': args->verbose += (args->verbose < 3); break;
+ case 'z': res = cstr_to_int(optarg, &args->compression); break;
default: res = RES_BAD_ARG; break;
}
if(res != RES_OK) {
@@ -143,16 +150,45 @@ load_lines(const struct cmd* cmd, struct shtr_line_list** lines)
args.file = stdin;
args.filename = "stdin";
}
+ args.compression_level = cmd->args.compression;
return shtr_line_list_load(cmd->shtr, &args, lines);
}
-static void
+static res_T
+process_molparam(const struct cmd* cmd, struct shtr_isotope_metadata* molparam)
+{
+ FILE* fp = NULL;
+ res_T res = RES_OK;
+ ASSERT(cmd && molparam);
+
+ if(!cmd->args.output) goto exit;
+
+ fp = fopen(cmd->args.output, "w");
+ if(!fp) {
+ fprintf(stderr, "%s: error opening file -- %s\n",
+ cmd->args.output, strerror(errno));
+ res = RES_IO_ERR;
+ goto error;
+ }
+
+ res = shtr_isotope_metadata_write(molparam, fp);
+ if(res != RES_OK) goto error;
+
+exit:
+ if(fp) CHK(fclose(fp) == 0);
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
process_lines(const struct cmd* cmd, const struct shtr_line_list* list)
{
+ FILE* fp = NULL;
struct shtr_line_list_info info = SHTR_LINE_LIST_INFO_NULL;
+ res_T res = RES_OK;
ASSERT(cmd && list);
- (void)cmd;
SHTR(line_list_get_info(list, &info));
@@ -167,6 +203,25 @@ process_lines(const struct cmd* cmd, const struct shtr_line_list* list)
PRINT(n_air);
PRINT(delta_air);
#undef PRINT
+
+ if(!cmd->args.output) goto exit;
+
+ fp = fopen(cmd->args.output, "w");
+ if(!fp) {
+ fprintf(stderr, "%s: error opening file -- %s\n",
+ cmd->args.output, strerror(errno));
+ res = RES_IO_ERR;
+ goto error;
+ }
+
+ res = shtr_line_list_write(list, fp);
+ if(res != RES_OK) goto error;
+
+exit:
+ if(fp) CHK(fclose(fp) == 0);
+ return res;
+error:
+ goto exit;
}
static res_T
@@ -181,11 +236,11 @@ cmd_run(const struct cmd* cmd)
if(cmd->args.molparam) {
if((res = load_molparam(cmd, &molparam)) != RES_OK) goto error;
+ if((res = process_molparam(cmd, molparam)) != RES_OK) goto error;
}
if(cmd->args.lines) {
if((res = load_lines(cmd, &lines)) != RES_OK) goto error;
-
- process_lines(cmd, lines);
+ if((res = process_lines(cmd, lines)) != RES_OK) goto error;
}
sz = MEM_ALLOCATED_SIZE(&cmd->allocator);