libmseed 3.1.3
The miniSEED data format library
Loading...
Searching...
No Matches
Examples

Overview

The most basic usage of the library is illustrated in the Tutorial. This page contains full example programs that utilize the library for common tasks. These examples are included in the source distribution and (most) are used in the test suite.

While these are full working programs the aspects not related to library usage, e.g. argument parsing, are often minimized and left uncommented as they will change in real world usage.

Read miniSEED from files

A simple program to read miniSEED from files and print details from each record:

/***************************************************************************
* A simple example of using libmseed to read miniSEED.
*
* Opens a user specified file, parses the miniSEED records and prints
* details for each record.
*
* This file is part of the miniSEED Library.
*
* Copyright (c) 2023 Chad Trabant, EarthScope Data Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <libmseed.h>
#define VERSION "[libmseed " LIBMSEED_VERSION " example]"
#define PACKAGE "mseedview"
static int8_t verbose = 0;
static int8_t ppackets = 0;
static int8_t basicsum = 0;
static int printdata = 0;
static char *inputfile = NULL;
static int parameter_proc (int argcount, char **argvec);
static void usage (void);
int
main (int argc, char **argv)
{
MS3Record *msr = NULL;
uint32_t flags = 0;
int64_t totalrecs = 0;
int64_t totalsamps = 0;
int retcode;
/* Process command line arguments */
if (parameter_proc (argc, argv) < 0)
return -1;
/* Set flag to validate CRCs when reading */
flags |= MSF_VALIDATECRC;
/* Parse byte range from file/URL path name if present */
flags |= MSF_PNAMERANGE;
/* Set flag to unpack data if printing samples */
if (printdata)
flags |= MSF_UNPACKDATA;
/* Enable accumulation of up to 10 error and warning messages */
ms_rloginit (NULL, NULL, NULL, NULL, 10);
/* Loop over the input file record by record */
while ((retcode = ms3_readmsr (&msr, inputfile, flags, verbose)) == MS_NOERROR)
{
totalrecs++;
totalsamps += msr->samplecnt;
msr3_print (msr, ppackets);
/* Print data samples */
if (printdata && msr->numsamples > 0)
{
int line, col, cnt, samplesize;
int lines = (msr->numsamples / 6) + 1;
void *sptr;
if ((samplesize = ms_samplesize (msr->sampletype)) == 0)
{
ms_log (2, "Unrecognized sample type: '%c'\n", msr->sampletype);
}
for (cnt = 0, line = 0; line < lines; line++)
{
for (col = 0; col < 6; col++)
{
if (cnt < msr->numsamples)
{
sptr = (char *)msr->datasamples + (cnt * samplesize);
if (msr->sampletype == 'i')
ms_log (0, "%10d ", *(int32_t *)sptr);
else if (msr->sampletype == 'f')
ms_log (0, "%10.8g ", *(float *)sptr);
else if (msr->sampletype == 'd')
ms_log (0, "%10.10g ", *(double *)sptr);
cnt++;
}
}
ms_log (0, "\n");
/* If only printing the first 6 samples break out here */
if (printdata == 1)
break;
}
}
}
/* Emit all accumulated warning and error messages */
ms_rlog_emit (NULL, 0, verbose);
/* Make sure everything is cleaned up */
ms3_readmsr (&msr, NULL, 0, 0);
if (basicsum)
ms_log (0, "Records: %" PRId64 ", Samples: %" PRId64 "\n",
totalrecs, totalsamps);
return 0;
} /* End of main() */
/***************************************************************************
* parameter_proc():
* Process the command line arguments.
*
* Returns 0 on success, and -1 on failure
***************************************************************************/
static int
parameter_proc (int argcount, char **argvec)
{
int optind;
/* Process all command line arguments */
for (optind = 1; optind < argcount; optind++)
{
if (strcmp (argvec[optind], "-V") == 0)
{
ms_log (1, "%s version: %s\n", PACKAGE, VERSION);
exit (0);
}
else if (strcmp (argvec[optind], "-h") == 0)
{
usage ();
exit (0);
}
else if (strncmp (argvec[optind], "-v", 2) == 0)
{
verbose += strspn (&argvec[optind][1], "v");
}
else if (strncmp (argvec[optind], "-p", 2) == 0)
{
ppackets += strspn (&argvec[optind][1], "p");
}
else if (strncmp (argvec[optind], "-d", 2) == 0)
{
printdata = 1;
}
else if (strncmp (argvec[optind], "-D", 2) == 0)
{
printdata = 2;
}
else if (strcmp (argvec[optind], "-s") == 0)
{
basicsum = 1;
}
else if (strncmp (argvec[optind], "-", 1) == 0 &&
strlen (argvec[optind]) > 1)
{
ms_log (2, "Unknown option: %s\n", argvec[optind]);
exit (1);
}
else if (inputfile == NULL)
{
inputfile = argvec[optind];
}
else
{
ms_log (2, "Unknown option: %s\n", argvec[optind]);
exit (1);
}
}
/* Make sure an input file was specified */
if (!inputfile)
{
ms_log (2, "No input file was specified\n\n");
ms_log (1, "%s version %s\n\n", PACKAGE, VERSION);
ms_log (1, "Try %s -h for usage\n", PACKAGE);
exit (1);
}
/* Add program name and version to User-Agent for URL-based requests */
if (libmseed_url_support() && ms3_url_useragent(PACKAGE, VERSION))
return -1;
/* Report the program version */
if (verbose)
ms_log (1, "%s version: %s\n", PACKAGE, VERSION);
return 0;
} /* End of parameter_proc() */
/***************************************************************************
* usage():
* Print the usage message and exit.
***************************************************************************/
static void
usage (void)
{
fprintf (stderr, "%s version: %s\n\n", PACKAGE, VERSION);
fprintf (stderr, "Usage: %s [options] file\n\n", PACKAGE);
fprintf (stderr,
" ## Options ##\n"
" -V Report program version\n"
" -h Show this usage message\n"
" -v Be more verbose, multiple flags can be used\n"
" -p Print details of header, multiple flags can be used\n"
" -d Print first 6 sample values\n"
" -D Print all sample values\n"
" -s Print a basic summary after processing a file\n"
"\n"
" file File of miniSEED records\n"
"\n");
} /* End of usage() */
#define MSF_PNAMERANGE
[Parsing] Parse and utilize byte range from path name suffix
Definition libmseed.h:1467
#define MSF_UNPACKDATA
[Parsing] Unpack data samples
Definition libmseed.h:1464
#define MSF_VALIDATECRC
[Parsing] Validate CRC (if version 3)
Definition libmseed.h:1466
int libmseed_url_support(void)
Run-time test for URL support in libmseed.
Definition fileutils.c:49
int ms3_readmsr(MS3Record **ppmsr, const char *mspath, uint32_t flags, int8_t verbose)
Read miniSEED records from a file or URL.
Definition fileutils.c:117
int ms3_url_useragent(const char *program, const char *version)
Set User-Agent header for URL-based requests.
Definition fileutils.c:768
#define ms_log(level,...)
Wrapper for ms_rlog(), call as ms_log (level, format, ...)
Definition libmseed.h:1162
void ms_rloginit(void(*log_print)(const char *), const char *logprefix, void(*diag_print)(const char *), const char *errprefix, int maxmessages)
Initialize the global logging parameters.
Definition logging.c:92
int ms_rlog_emit(MSLogParam *logp, int count, int context)
Emit, aka send to print functions, messages from log registry.
Definition logging.c:573
void * datasamples
Data samples, numsamples of type sampletype.
Definition libmseed.h:378
int64_t numsamples
Number of data samples in datasamples.
Definition libmseed.h:380
int64_t samplecnt
Number of samples in record.
Definition libmseed.h:371
char sampletype
Sample type code: t, i, f, d Sample Types.
Definition libmseed.h:381
void msr3_print(const MS3Record *msr, int8_t details)
Print header values of an MS3Record.
Definition msrutils.c:228
miniSEED record container
Definition libmseed.h:358
#define MS_NOERROR
No error.
Definition libmseed.h:1447
uint8_t ms_samplesize(char sampletype)
Determine data sample size for each type.
Definition lookup.c:39

Reading with selections

Read miniSEED with Data Selections used to limit what is read. Additionally, this program reads data into a Trace List and illustrates traversing the entries.

/***************************************************************************
* A program for reading miniSEED using data selections to limit which
* data is read. This program also illustrates traversing a trace
* list.
*
* This file is part of the miniSEED Library.
*
* Copyright (c) 2023 Chad Trabant, EarthScope Data Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
#include <libmseed.h>
int
main (int argc, char **argv)
{
MS3Selections *selections = NULL;
MS3TraceList *mstl = NULL;
MS3TraceID *tid = NULL;
MS3TraceSeg *seg = NULL;
char *mseedfile = NULL;
char *selectionfile = NULL;
char starttimestr[30];
char endtimestr[30];
uint32_t flags = 0;
int8_t verbose = 0;
int rv;
if (argc != 3)
{
ms_log (2, "Usage: %s <mseedfile> <selectionfile>\n",argv[0]);
return -1;
}
mseedfile = argv[1];
selectionfile = argv[2];
/* Read data selections from specified file */
if (ms3_readselectionsfile (&selections, selectionfile) < 0)
{
ms_log (2, "Cannot read data selection file\n");
return -1;
}
/* Set bit flags to validate CRC and unpack data samples */
flags |= MSF_VALIDATECRC;
flags |= MSF_UNPACKDATA;
/* Read all miniSEED into a trace list, limiting to selections */
rv = ms3_readtracelist_selection (&mstl, mseedfile, NULL,
selections, 0, flags, verbose);
if (rv != MS_NOERROR)
{
ms_log (2, "Cannot read miniSEED from file: %s\n", ms_errorstr(rv));
return -1;
}
/* Traverse trace list structures and print summary information */
tid = mstl->traces.next[0];
while (tid)
{
if (!ms_nstime2timestr (tid->earliest, starttimestr, SEEDORDINAL, NANO_MICRO_NONE) ||
!ms_nstime2timestr (tid->latest, endtimestr, SEEDORDINAL, NANO_MICRO_NONE))
{
ms_log (2, "Cannot create time strings\n");
starttimestr[0] = endtimestr[0] = '\0';
}
ms_log (0, "TraceID for %s (%d), earliest: %s, latest: %s, segments: %u\n",
tid->sid, tid->pubversion, starttimestr, endtimestr, tid->numsegments);
seg = tid->first;
while (seg)
{
if (!ms_nstime2timestr (seg->starttime, starttimestr, SEEDORDINAL, NANO_MICRO_NONE) ||
!ms_nstime2timestr (seg->endtime, endtimestr, SEEDORDINAL, NANO_MICRO_NONE))
{
ms_log (2, "Cannot create time strings\n");
starttimestr[0] = endtimestr[0] = '\0';
}
ms_log (0, " Segment %s - %s, samples: %" PRId64 ", sample rate: %g, sample type: %c\n",
starttimestr, endtimestr, seg->numsamples, seg->samprate,
(seg->sampletype) ? seg->sampletype : ' ');
seg = seg->next;
}
tid = tid->next[0];
}
/* Make sure everything is cleaned up */
if (mstl)
mstl3_free (&mstl, 0);
if (selections)
ms3_freeselections (selections);
return 0;
}
int ms3_readselectionsfile(MS3Selections **ppselections, const char *filename)
Read data selections from a file.
Definition selection.c:428
void ms3_freeselections(MS3Selections *selections)
Free all memory associated with a MS3Selections.
Definition selection.c:665
Data selection structure definition containers.
Definition libmseed.h:445
int ms3_readtracelist_selection(MS3TraceList **ppmstl, const char *mspath, const MS3Tolerance *tolerance, const MS3Selections *selections, int8_t splitversion, uint32_t flags, int8_t verbose)
Read miniSEED from a file into a trace list, with selection filtering.
Definition fileutils.c:676
struct MS3TraceID * next[MSTRACEID_SKIPLIST_HEIGHT]
Next trace ID at first pointer, NULL if the last.
Definition libmseed.h:575
int64_t numsamples
Number of data samples in datasamples.
Definition libmseed.h:557
nstime_t endtime
Time of last sample.
Definition libmseed.h:552
struct MS3TraceSeg * first
Pointer to first of list of segments.
Definition libmseed.h:573
nstime_t latest
Time of latest sample.
Definition libmseed.h:570
struct MS3TraceID traces
Head node of trace skip list, first entry at traces.next[0].
Definition libmseed.h:582
uint8_t pubversion
Largest contributing publication version.
Definition libmseed.h:568
nstime_t earliest
Time of earliest sample.
Definition libmseed.h:569
char sampletype
Sample type code, see Sample Types.
Definition libmseed.h:558
char sid[LM_SIDLEN]
Source identifier as URN, max length LM_SIDLEN.
Definition libmseed.h:567
double samprate
Nominal sample rate (Hz)
Definition libmseed.h:553
struct MS3TraceSeg * next
Pointer to next segment, NULL if the last.
Definition libmseed.h:562
nstime_t starttime
Time of first sample.
Definition libmseed.h:551
uint32_t numsegments
Number of segments for this ID.
Definition libmseed.h:572
void mstl3_free(MS3TraceList **ppmstl, int8_t freeprvtptr)
Free all memory associated with a MS3TraceList.
Definition tracelist.c:89
Container for a trace ID, linkable.
Definition libmseed.h:566
Container for a collection of continuous trace segment, linkable.
Definition libmseed.h:580
Container for a continuous trace segment, linkable.
Definition libmseed.h:550
const char * ms_errorstr(int errorcode)
Descriptive string for library Return codes.
Definition lookup.c:205

Reading with record lists

Read miniSEED a file in 2 passes:

  1. Read the file and construct a Trace List without unpacking the data samples and constructing a Record List
  2. Unpack the data samples for each segment individually.

This pattern allows the caller to selectively unpack the data by segment if desired.

While this example unpacks the data into a buffer allocated by the library, the unpacking routine mstl3_unpack_recordlist() also allows data samples to be placed directly into caller-specified memory buffers.

While this example uses ms3_readtracelist() for reading data from a file, the same functionality exists in mstl3_readbuffer() for reading data from a memory buffer.

/***************************************************************************
* A program for reading miniSEED into a trace list followed by
* unpacking from an associated record list.
*
* This file is part of the miniSEED Library.
*
* Copyright (c) 2023 Chad Trabant, EarthScope Data Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
#include <stdio.h>
#include <sys/stat.h>
#include <limits.h>
#include <errno.h>
#include <libmseed.h>
int
main (int argc, char **argv)
{
MS3TraceList *mstl = NULL;
MS3TraceID *tid = NULL;
MS3TraceSeg *seg = NULL;
MS3RecordPtr *recptr = NULL;
char *mseedfile = NULL;
char starttimestr[30];
char endtimestr[30];
char bufferptrstr[30];
char fileptrstr[30];
uint32_t flags = 0;
int8_t verbose = 0;
uint64_t idx;
int rv;
char printdata = 0;
int64_t unpacked;
uint8_t samplesize;
char sampletype;
uint64_t lineidx;
uint64_t lines;
int col;
void *sptr;
if (argc < 2)
{
ms_log (2, "Usage: %s <mseedfile> [-v] [-d] [-D]\n",argv[0]);
return -1;
}
mseedfile = argv[1];
/* Simplistic argument parsing */
for (idx = 2; (int)idx < argc; idx++)
{
if (strncmp (argv[idx], "-v", 2) == 0)
verbose += strspn (&argv[idx][1], "v");
else if (strncmp (argv[idx], "-d", 2) == 0)
printdata = 'd';
else if (strncmp (argv[idx], "-D", 2) == 0)
printdata = 'D';
}
/* Set bit flag to validate CRC */
flags |= MSF_VALIDATECRC;
/* Set bit flag to build a record list */
flags |= MSF_RECORDLIST;
/* Read all miniSEED into a trace list, limiting to selections */
rv = ms3_readtracelist (&mstl, mseedfile, NULL, 0, flags, verbose);
if (rv != MS_NOERROR)
{
ms_log (2, "Cannot read miniSEED from file: %s\n", ms_errorstr(rv));
return -1;
}
/* Traverse trace list structures and print summary information */
tid = mstl->traces.next[0];
while (tid)
{
ms_log (0, "TraceID for %s (%d), segments: %u\n",
tid->sid, tid->pubversion, tid->numsegments);
seg = tid->first;
while (seg)
{
if (!ms_nstime2timestr (seg->starttime, starttimestr, ISOMONTHDAY, NANO) ||
!ms_nstime2timestr (seg->endtime, endtimestr, ISOMONTHDAY, NANO))
{
ms_log (2, "Cannot create time strings\n");
starttimestr[0] = endtimestr[0] = '\0';
}
ms_log (0, " Segment %s - %s, samples: %" PRId64 ", sample rate: %g\n",
starttimestr, endtimestr, seg->samplecnt, seg->samprate);
if (seg->recordlist)
{
ms_log (0, " Record list:\n");
/* Traverse record list print summary information */
recptr = seg->recordlist->first;
while (recptr)
{
if (recptr->bufferptr == NULL)
strcpy (bufferptrstr, "NULL");
else
snprintf (bufferptrstr, sizeof(bufferptrstr), "%" PRIu64, (uint64_t)recptr->bufferptr);
if (recptr->fileptr == NULL)
strcpy (fileptrstr, "NULL");
else
snprintf (fileptrstr, sizeof(fileptrstr), "%" PRIu64, (uint64_t)recptr->fileptr);
ms_log (0, " RECORD: bufferptr: %s, fileptr: %s, filename: %s, fileoffset: %"PRId64"\n",
bufferptrstr, fileptrstr, recptr->filename, recptr->fileoffset);
ms_nstime2timestr (recptr->msr->starttime, starttimestr, ISOMONTHDAY_Z, NANO);
ms_nstime2timestr (recptr->endtime, endtimestr, ISOMONTHDAY_Z, NANO);
ms_log (0, " Start: %s, End: %s\n", starttimestr, endtimestr);
recptr = recptr->next;
}
}
/* Unpack and print samples for this trace segment */
if (printdata && seg->recordlist && seg->recordlist->first)
{
/* Determine sample size and type based on encoding of first record */
ms_encoding_sizetype (seg->recordlist->first->msr->encoding, &samplesize, &sampletype);
/* Unpack data samples using record list.
* No data buffer is supplied, so it will be allocated and assigned to the segment.
* Alternatively, a user-specified data buffer can be provided here. */
unpacked = mstl3_unpack_recordlist (tid, seg, NULL, 0, verbose);
if (unpacked != seg->samplecnt)
{
ms_log (2, "Cannot unpack samples for %s\n", tid->sid);
}
else
{
ms_log (0, "DATA (%" PRId64 " samples) of type '%c':\n", seg->numsamples, seg->sampletype);
if (sampletype == 't')
{
printf ("%*s",
(seg->numsamples > INT_MAX) ? INT_MAX : (int)seg->numsamples,
(char *)seg->datasamples);
}
else
{
lines = (unpacked / 6) + 1;
for (idx = 0, lineidx = 0; lineidx < lines; lineidx++)
{
for (col = 0; col < 6 && (int64_t)idx < seg->numsamples; col++)
{
sptr = (char *)seg->datasamples + (idx * samplesize);
if (sampletype == 'i')
ms_log (0, "%10d ", *(int32_t *)sptr);
else if (sampletype == 'f')
ms_log (0, "%10.8g ", *(float *)sptr);
else if (sampletype == 'd')
ms_log (0, "%10.10g ", *(double *)sptr);
idx++;
}
ms_log (0, "\n");
if (printdata == 'd')
break;
}
}
}
}
seg = seg->next;
}
tid = tid->next[0];
}
/* Make sure everything is cleaned up */
if (mstl)
mstl3_free (&mstl, 0);
return 0;
}
#define MSF_RECORDLIST
[TraceList] Build a MS3RecordList for each MS3TraceSeg
Definition libmseed.h:1472
int ms3_readtracelist(MS3TraceList **ppmstl, const char *mspath, const MS3Tolerance *tolerance, int8_t splitversion, uint32_t flags, int8_t verbose)
Read miniSEED from a file into a trace list.
Definition fileutils.c:587
int16_t encoding
Data encoding format, see Data Encodings.
Definition libmseed.h:369
nstime_t starttime
Record start time (first sample)
Definition libmseed.h:367
struct MS3RecordPtr * next
Pointer to next entry, NULL if the last.
Definition libmseed.h:502
int64_t fileoffset
Offset into file to record for fileptr or filename.
Definition libmseed.h:497
const char * filename
Pointer to file name containing record, NULL if not used.
Definition libmseed.h:496
MS3RecordPtr * first
Pointer to first entry, NULL if the none.
Definition libmseed.h:509
MS3Record * msr
Pointer to MS3Record for this record.
Definition libmseed.h:498
const char * bufferptr
Pointer in buffer to record, NULL if not used.
Definition libmseed.h:494
FILE * fileptr
Pointer to open FILE containing record, NULL if not used.
Definition libmseed.h:495
nstime_t endtime
End time of record, time of last sample.
Definition libmseed.h:499
A miniSEED record pointer and metadata.
Definition libmseed.h:493
struct MS3RecordList * recordlist
List of pointers to records that contributed.
Definition libmseed.h:560
void * datasamples
Data samples, numsamples of type sampletype.
Definition libmseed.h:555
int64_t samplecnt
Number of samples in trace coverage.
Definition libmseed.h:554
int64_t mstl3_unpack_recordlist(MS3TraceID *id, MS3TraceSeg *seg, void *output, uint64_t outputsize, int8_t verbose)
Unpack data samples in a Record List associated with a MS3TraceList.
Definition tracelist.c:1614
int ms_encoding_sizetype(uint8_t encoding, uint8_t *samplesize, char *sampletype)
Return sample size and/or type for given encoding value.
Definition lookup.c:74

Reading from memory buffers

Read miniSEED from memory buffers. In this case a file is read into a buffer simply to illustrate reading from a buffer. In practice this would functionality would be used with data received via a network connection or some other, non-file, mechanism.

/***************************************************************************
* A program illustrating reading miniSEED from buffers
*
* This file is part of the miniSEED Library.
*
* Copyright (c) 2023 Chad Trabant, EarthScope Data Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#include <libmseed.h>
int
main (int argc, char **argv)
{
struct stat sb = {0};
int64_t records = 0;
FILE *fh;
MS3TraceList *mstl = NULL;
char *buffer = NULL;
uint64_t bufferlength = 0;
int8_t splitversion = 0;
uint32_t flags = 0;
int8_t verbose = 0;
if (argc != 2)
{
ms_log (2, "%s requires a single file name argument\n", argv[0]);
return -1;
}
/* Read specified file into buffer */
if (!(fh = fopen (argv[1], "rb")))
{
ms_log (2, "Error opening %s: %s\n", argv[1], strerror (errno));
return -1;
}
if (fstat (fileno (fh), &sb))
{
ms_log (2, "Error stating %s: %s\n", argv[1], strerror (errno));
return -1;
}
if (!(buffer = (char *)malloc (sb.st_size)))
{
ms_log (2, "Error allocating buffer of %" PRIsize_t " bytes\n",
(sb.st_size >= 0) ? (size_t)sb.st_size : 0);
return -1;
}
if (fread (buffer, sb.st_size, 1, fh) != 1)
{
ms_log (2, "Error reading file\n");
return -1;
}
fclose (fh);
bufferlength = sb.st_size;
/* Set bit flags to validate CRC and unpack data samples */
flags |= MSF_VALIDATECRC;
flags |= MSF_UNPACKDATA;
mstl = mstl3_init (NULL);
if (!mstl)
{
ms_log (2, "Error allocating MS3TraceList\n");
return -1;
}
/* Read all miniSEED in buffer, accumulate in MS3TraceList */
records = mstl3_readbuffer (&mstl, buffer, bufferlength,
splitversion, flags, NULL, verbose);
if (records < 0)
{
ms_log (2, "Problem reading miniSEED from buffer: %s\n", ms_errorstr (records));
}
/* Print summary */
mstl3_printtracelist (mstl, ISOMONTHDAY, 1, 1, 0);
ms_log (1, "Total records: %" PRId64 "\n", records);
/* Make sure everything is cleaned up */
if (mstl)
mstl3_free (&mstl, 0);
free (buffer);
return 0;
}
void mstl3_printtracelist(const MS3TraceList *mstl, ms_timeformat_t timeformat, int8_t details, int8_t gaps, int8_t versions)
Print trace list summary information for a MS3TraceList.
Definition tracelist.c:2120
int64_t mstl3_readbuffer(MS3TraceList **ppmstl, const char *buffer, uint64_t bufferlength, int8_t splitversion, uint32_t flags, const MS3Tolerance *tolerance, int8_t verbose)
Parse miniSEED from a buffer and populate a MS3TraceList.
Definition tracelist.c:816
MS3TraceList * mstl3_init(MS3TraceList *mstl)
Initialize a MS3TraceList container.
Definition tracelist.c:54
#define PRIsize_t
A printf() macro for portably printing size_t values.
Definition libmseed.h:70

Reading files in parallel

Read miniSEED in parallel using re-entrant interfaces and POSIX threading.

/***************************************************************************
* A simple example of using libmseed to read miniSEED in parallel
* using re-entrant interfaces and POSIX threading.
*
* Windows is not supported.
*
* This file is part of the miniSEED Library.
*
* Copyright (c) 2023 Chad Trabant, EarthScope Data Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <libmseed.h>
/* File read test portability, possibly in the future */
#if defined(LMP_WIN)
#define _access access
#define R_OK 4 /* Test for read permission */
#else
#include <pthread.h>
#include <unistd.h>
#endif
#define VERSION "[libmseed " LIBMSEED_VERSION " example]"
#define PACKAGE "lm_pararead"
static int8_t verbose = 0;
static int8_t printrecs = 0;
static uint32_t readflags = 0;
/* File information structure */
typedef struct FileEntry
{
char *filename;
pthread_t tid;
MS3TraceList *mstl;
uint64_t recordcount;
int result;
struct FileEntry *next;
} FileEntry;
/* List of files to read */
static FileEntry *files = NULL;
/* Thread function to read miniSEED file */
static void *ReadMSFileThread (void *vfe)
{
FileEntry *fe = (FileEntry *)vfe;
MS3FileParam *msfp = NULL;
MS3Record *msr = NULL;
/* NOTE: This example is contrived for illustration.
* The combination of ms3_readmsr_r() with mstl3_addmsr()
* is only needed if you wish to do something for each record.
* Otherwise, consider using ms3_readtracelist() if only
* a MS3TraceList is desired.*/
/* Loop over the input file record by record */
while ((fe->result = ms3_readmsr_r (&msfp, &msr,
fe->filename,
readflags, verbose)) == MS_NOERROR)
{
fe->recordcount++;
if (printrecs > 0)
msr3_print (msr, printrecs - 1);
/* Add record to trace list */
if (mstl3_addmsr (fe->mstl, msr, 0, 1, 0, NULL) == NULL)
{
ms_log (2, "Error adding record to list\n");
fe->result = 1;
}
}
/* Make sure everything is cleaned up */
ms3_readmsr_r (&msfp, &msr, NULL, 0, 0);
return NULL;
}
int
main (int argc, char **argv)
{
FileEntry *fe = NULL;
int idx;
/* Simplistic argument parsing */
for (idx = 1; idx < argc; idx++)
{
if (strncmp (argv[idx], "-v", 2) == 0)
verbose += strspn (&argv[idx][1], "v");
else if (strncmp (argv[idx], "-p", 2) == 0)
printrecs += strspn (&argv[idx][1], "p");
else
{
/* Add read-able files to file entry list */
if (access(argv[idx], R_OK) == 0)
{
if ((fe = (FileEntry *)malloc(sizeof(FileEntry))) == NULL)
{
ms_log (2, "Error allocating memory");
return -1;
}
fe->filename = argv[idx];
fe->mstl = mstl3_init(NULL);
fe->recordcount = 0;
fe->result = 0;
fe->next = files;
files = fe;
}
else
{
ms_log (2, "Cannot find file: %s\n", argv[idx]);
return -1;
}
}
}
/* Make sure input file(s) specified */
if (!files)
{
ms_log (1, "No input file(s) specified\n\n");
ms_log (1, "%s version %s\n\n", PACKAGE, VERSION);
ms_log (1, "Read specified miniSEED files in parallel\n\n");
ms_log (1, "Usage: %s [-p] [-v] file1 [file2 .. fileN]\n", PACKAGE);
ms_log (1, " -v Be more verbose, multiple flags can be used\n");
ms_log (1, " -p Print record details, multiple flags can be used\n\n");
return 0;
}
/* Report the program version */
if (verbose)
ms_log (1, "%s version: %s\n", PACKAGE, VERSION);
/* Add program name and version to User-Agent for URL-based requests */
if (libmseed_url_support() && ms3_url_useragent(PACKAGE, VERSION))
return -1;
/* Set flag to validate CRCs when reading */
readflags |= MSF_VALIDATECRC;
/* Parse byte range from file/URL path name if present */
readflags |= MSF_PNAMERANGE;
/* Create a thread to read each file */
for (fe = files; fe; fe = fe->next)
{
pthread_create (&(fe->tid), NULL, ReadMSFileThread, fe);
}
/* Wait for threads to finish */
for (fe = files; fe; fe = fe->next)
{
pthread_join(fe->tid, NULL);
}
/* Report details for each file */
for (fe = files; fe; fe = fe->next)
{
ms_log (0, "%s: records: %" PRIu64" result: %d\n",
fe->filename, fe->recordcount, fe->result);
if (fe->result == MS_NOERROR || fe->result == MS_ENDOFFILE)
mstl3_printtracelist (fe->mstl, ISOMONTHDAY, 1, 1, 0);
}
return 0;
} /* End of main() */
int ms3_readmsr_r(MS3FileParam **ppmsfp, MS3Record **ppmsr, const char *mspath, uint32_t flags, int8_t verbose)
Read miniSEED records from a file or URL in a thread-safe way.
Definition fileutils.c:144
State container for reading miniSEED records from files or URLs.
Definition libmseed.h:720
#define MS_ENDOFFILE
End of file reached return value.
Definition libmseed.h:1446
#define mstl3_addmsr(mstl, msr, splitversion, autoheal, flags, tolerance)
Add a MS3Record to a MS3TraceList.
Definition libmseed.h:630

Writing miniSEED

An example of creating miniSEED. Static data with known signal is used for input for illustration and testing.

/***************************************************************************
* A program for libmseed packing tests.
*
* This file is part of the miniSEED Library.
*
* Copyright (c) 2023 Chad Trabant, EarthScope Data Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <libmseed.h>
#define VERSION "[libmseed " LIBMSEED_VERSION " example]"
#define PACKAGE "lm_pack"
static flag verbose = 0;
static int reclen = -1;
static int encoding = 10;
static int msformat = 3;
static char *outfile = NULL;
static int parameter_proc (int argcount, char **argvec);
static void usage (void);
/****************************************************************************
* An expanding sinusoid of 500 samples.
*
* When truncated to integers:
* - Signed differences in samples needing all bit lengths 3-31s.
* - ONLY the last difference requires 31 bits, all others are <= 30
* - Contain sequences of differences matching all Steim 1 and 2 encoding possibilities
*
* Values 1 through up to 220 do not require more than 16-bits.
***************************************************************************/
#define SINE_DATA_SAMPLES 500
static float fsinedata[SINE_DATA_SAMPLES] =
{0.000000,6.109208,10.246826,10.609957,6.764728,-0.075704,-7.409461,-12.346208,
-12.731430,-8.062958,0.182060,8.985442,14.875067,15.276420,9.609196,-0.328370,
-10.895428,-17.921131,-18.329336,-11.450576,0.526448,13.209973,21.590023,21.991385,
13.643140,-0.791247,-16.014492,-26.008907,-26.383901,-16.253504,1.141655,19.412378,
31.330871,31.652348,19.360848,-1.601465,-23.528777,-37.740204,-37.971107,-23.059260,
2.200591,28.515156,45.458753,45.549217,27.460529,-2.976569,-34.554817,-54.753559,
-54.637244,-32.697448,3.976416,41.869576,65.946052,65.535525,38.927729,-5.258928,
-50.727832,-79.423116,-78.604029,-46.338644,6.897516,61.454325,95.650397,94.274177,
55.152523,-8.983716,-74.441929,-115.188314,-113.063003,-65.633259,11.631511,
90.165916,138.711322,135.590105,78.094013,-14.982665,-109.201193,-167.031082,
-162.597954,-92.906331,19.213290,132.243134,201.124338,194.976222,110.510935,
-24.541940,-160.132765,-242.166440,-233.790899,-131.430478,31.239561,193.887193,
291.571675,280.319178,156.284630,-39.641741,-234.736391,-351.041770,-336.091216,
-185.807912,50.163757,284.167632,422.624233,402.940140,220.870763,-63.319072,
-343.979194,-508.782510,-483.061913,-262.504429,79.742042,416.345244,612.480366,
579.087014,311.930343,-100.215795,-503.894220,-737.283353,-694.166245,-370.594813,
125.706429,609.803540,887.480834,832.073438,440.209940,-157.404955,-737.913996,
-1068.232708,-997.328409,-522.801872,196.778712,892.867950,1285.745847,1195.344115,
620.767701,-245.634371,-1080.276240,-1547.486227,-1432.602775,-736.942489,
306.195102,1306.919790,1862.433994,1716.866654,874.678227,-381.195062,-1580.993078,
-2241.390126,-2057.430298,-1037.936774,473.995052,1912.398180,2697.345105,2465.422369,
1231.399220,-588.724017,-2313.099844,-3245.922143,-2954.166800,-1460.594493,
730.452133,2797.554253,3905.910007,3539.614901,1732.050527,-905.402443,-3383.226729,
-4699.903513,-4240.862333,-2053.471832,1121.209554,4091.216806,5655.073452,
5080.767553,2433.947965,-1387.235765,-4947.012887,-6804.092030,-6086.691631,
-2884.198121,1714.957253,5981.403297,8186.245216,7291.383170,3416.857907,-2118.435721,
-7231.576094,-9848.769674,-8734.036728,-4046.815355,2614.894255,8742.446660,
11848.459577,10461.558685,4791.604321,-3225.420222,-10568.260176,-14253.597692,
-12530.081077,-5671.864737,3975.823020,12774.525771,17146.276092,15006.771888,
6711.880612,-4897.680529,-15440.350897,-20625.184991,-17971.999652,-7940.208402,
6029.615451,18661.258563,24808.964001,21521.921578,9390.410233,-7418.851697,
-22552.587165,-29840.229074,-25771.577789,-11101.908663,9123.111793,27253.593143,
35890.411153,30858.590420,13120.982075,-11212.929535,-32932.401520,-43165.569941,
-36947.585456,-15501.922592,13774.468128,39791.979238,51913.378983,44235.478131,
18308.381438,-16912.953578,-48077.342225,-62431.517747,-52957.790070,-21614.930138,
20756.856764,58084.250586,75077.753677,63396.198979,25508.869716,-25462.986446,
-70169.698634,-90282.054065,-75887.560674,-30092.324242,31222.690356,84764.569627,
108561.135815,90834.689747,35484.659605,-38269.404043,-102388.901147,-130535.943080,
-108719.240618,-41825.273267,46887.838631,123670.298781,156952.641109,130117.096987,
49276.805933,-57425.161274,-149366.146307,-188707.832667,-155716.756615,-58028.831480,
70304.598043,180390.393831,226878.845103,186341.292651,68302.086980,-86041.981200,
-217845.865904,-272760.106197,-222974.585037,-80353.310040,105265.874749,
263063.225186,327906.831053,266792.649626,94480.755768,-128742.047924,-317647.960457,
-394187.487304,-319201.052420,-111030.470003,157403.231090,383537.048821,
473846.799900,381879.586964,130403.398591,-192385.288422,-463067.280664,
-569581.409624,-456835.620147,-153063.413757,235071.184227,559057.643966,
684630.722900,546467.782541,179546.337116,-287144.413901,-674908.656359,-822885.998573,
-653642.002301,-210470.033463,350653.927224,814722.125712,989021.327043,781782.266485,
246545.638548,-428093.004245,-983445.533844,-1188650.888674,-934978.952245,
-288589.965744,522495.068481,1187046.097893,1428517.756157,1118118.116795,
337539.108116,-637550.058001,-1432720.599829,-1716720.558561,-1337035.786123,
-394463.210730,777745.745791,1729148.322568,2062985.588205,1598702.057951,
460582.328770,-948539.335064,-2086795.934450,-2478993.447111,-1911440.758239,
-537283.204837,1156565.787585,2518284.974613,2978771.147961,2285191.490698,
626136.686773,-1409890.715316,-3038834.772892,-3579162.765425,-2731822.228828,
-728915.356799,1718317.328563,3666796.264850,4300394.349825,3265502.159830,
847610.742696,-2093758.948552,-4424295.326464,-5166751.952850,-3903146.346575,
-984449.218292,2550691.033230,5338008.063395,6207395.378498,4664945.984099,
1141905.356234,-3106699.622013,-6440095.078674,-7457334.785992,-5575000.657492,
-1322711.048944,3783146.686785,7769327.268660,8958602.684417,6662072.138144,
1529858.136359,-4605977.214406,-9372442.351616,-10761660.350202,-7960482.979376,
-1766591.537123,5606698.099533,11305779.346088,12927085.482769,9511187.602536,
2036388.930375,-6823565.288237,-13637247.864482,-15527597.247686,-11363048.833756,
-2342921.824577,8303023.316062,16448700.704063,18650486.048610,13574359.117581,
2689991.311114,-10101450.710498,-19838792.204081,-22400528.788313,-16214653.084049,
-3081429.850680,12287276.018778,23926421.676653,26903486.467518,19366867.002831,
3520957.976311,-14943542.889821,-28854881.491245,-32310300.258257,-23129911.185536,
-4011981.690190,18171019.183242,34796853.797034,38802125.311214,27621733.908111,
4557312.422997,-22091965.102165,-41960429.245394,-46596369.274924,-32982970.290335,
-5158786.517383,26854699.579994,50596356.438136,55953935.730766,39381287.228525,
5816755.047390,-32639133.476996,-61006773.393892,-67187912.573574,-47016556.451947,
-6529407.091211,39663473.627686,73555723.560159,80673993.102082,56127012.680548,
7291879.963058,-48192344.715084,-88681820.564997,-96862974.793882,-66996583.433046,
-8095097.920129,58546627.892657,106913500.120816,116295749.303753,79963612.136585,
8924265.924556,-71115377.915425,-128887386.814358,-139621279.391140,
-95431237.847443,-9756926.457174,86370256.557591,155370411.011265,167618156.945886,
113879744.320966,10560464.285645,-104883012.041142,-187286440.462195,
-201220454.267134,-135881249.803956,-11288915.420918,127346645.407973,
225748346.861610,241548722.121826,162117178.463787,11878900.943144,
-154601039.263161,-272096614.921471,-289947157.492990,-193399036.824020,
-12244462.331299,187663986.962885,327945826.905572,348028166.863781,
230693116.321629,12270520.408649,-227768756.995135,-395240626.753420,
-417725794.004062,-275149858.943091,-11804612.586023,276409565.108355,
476323094.198962,501359772.474058,328138760.150134,10646479.758475,
-335396614.264246,-574013851.836865,-601712311.942546,-391289845.886545,
-8534971.317913,406922710.094078,691709700.348455,722120145.317499,
466542952.987464,5131609.783276,-493643879.751773,-833501145.234545,
-866584864.231526,-556206270.243475,0.00000};
static char *textdata =
"I've seen things you people wouldn't believe. Attack ships on fire off the shoulder of Orion. "
"I watched C-beams glitter in the dark near the Tannhäuser Gate. All those moments will be lost "
"in time, like tears...in...rain. Time to die.";
/* Binary I/O for Windows platforms */
#ifdef LMP_WIN
#include <fcntl.h>
unsigned int _CRT_fmode = _O_BINARY;
#endif
int
main (int argc, char **argv)
{
MS3Record *msr = NULL;
uint32_t flags = 0;
int32_t sinedata[SINE_DATA_SAMPLES];
double dsinedata[SINE_DATA_SAMPLES];
int idx;
int rv;
/* Create integer and double sine data sets */
for (idx = 0; idx < SINE_DATA_SAMPLES; idx++)
{
sinedata[idx] = (int32_t)(fsinedata[idx]);
dsinedata[idx] = (double)(fsinedata[idx]);
}
/* Process command line arguments */
if (parameter_proc (argc, argv) < 0)
return -1;
if (!(msr = msr3_init (msr)))
{
ms_log (2, "Could not allocate MS3Record, out of memory?\n");
return -1;
}
/* Set up record parameters */
strcpy (msr->sid, "FDSN:XX_TEST__X_Y_Z");
msr->reclen = reclen;
msr->pubversion = 1;
msr->starttime = ms_timestr2nstime ("2012-01-01T00:00:00");
msr->samprate = 1.0;
msr->encoding = encoding;
if (encoding == DE_TEXT)
{
msr->numsamples = strlen (textdata);
msr->datasamples = textdata;
msr->sampletype = 't';
}
else if (encoding == DE_FLOAT32)
{
msr->numsamples = SINE_DATA_SAMPLES;
msr->datasamples = fsinedata;
msr->sampletype = 'f';
}
else if (encoding == DE_FLOAT64)
{
msr->numsamples = SINE_DATA_SAMPLES;
msr->datasamples = dsinedata;
msr->sampletype = 'd';
}
else if (encoding == DE_INT16)
{
msr->numsamples = 220; /* The first 220 samples can be represented in 16-bits */
msr->datasamples = sinedata;
msr->sampletype = 'i';
}
else if (encoding == DE_INT32)
{
msr->numsamples = SINE_DATA_SAMPLES;
msr->datasamples = sinedata;
msr->sampletype = 'i';
}
else if (encoding == DE_STEIM1)
{
msr->numsamples = SINE_DATA_SAMPLES;
msr->datasamples = sinedata;
msr->sampletype = 'i';
}
else if (encoding == DE_STEIM2)
{
msr->numsamples = SINE_DATA_SAMPLES - 1; /* Steim-2 can represent all but the last difference */
msr->datasamples = sinedata;
msr->sampletype = 'i';
}
else
{
ms_log (2, "Unsupported encoding: %d\n", encoding);
return -1;
}
msr->samplecnt = msr->numsamples;
/* Set data flush flag */
flags |= MSF_FLUSHDATA;
/* Set miniSEED v2 if requested */
if (msformat == 2)
flags |= MSF_PACKVER2;
rv = msr3_writemseed (msr, outfile, 1, flags, verbose);
if (rv < 0)
ms_log (2, "Error (%d) writing miniSEED to %s\n", rv, outfile);
/* Make sure everything is cleaned up */
msr->datasamples = NULL;
msr3_free (&msr);
return 0;
} /* End of main() */
/***************************************************************************
* parameter_proc:
*
* Process the command line arguments.
*
* Returns 0 on success, and -1 on failure
***************************************************************************/
static int
parameter_proc (int argcount, char **argvec)
{
int optind;
/* Process all command line arguments */
for (optind = 1; optind < argcount; optind++)
{
if (strcmp (argvec[optind], "-V") == 0)
{
ms_log (1, "%s version: %s\n", PACKAGE, VERSION);
exit (0);
}
else if (strcmp (argvec[optind], "-h") == 0)
{
usage ();
exit (0);
}
else if (strncmp (argvec[optind], "-v", 2) == 0)
{
verbose += strspn (&argvec[optind][1], "v");
}
else if (strcmp (argvec[optind], "-F") == 0)
{
msformat = strtol (argvec[++optind], NULL, 10);
}
else if (strcmp (argvec[optind], "-r") == 0)
{
reclen = strtol (argvec[++optind], NULL, 10);
}
else if (strcmp (argvec[optind], "-e") == 0)
{
encoding = strtol (argvec[++optind], NULL, 10);
}
else if (strcmp (argvec[optind], "-o") == 0)
{
outfile = argvec[++optind];
}
else
{
ms_log (2, "Unknown option: %s\n", argvec[optind]);
exit (1);
}
}
/* Make sure an outfile was specified */
if (!outfile)
{
ms_log (2, "No output file was specified\n\n");
ms_log (1, "Try %s -h for usage\n", PACKAGE);
exit (1);
}
if (msformat != 2 && msformat != 3)
{
ms_log (1, "Specified format must be 2 or 3, version %d is not supported\n", msformat);
exit (1);
}
/* Report the program version */
if (verbose)
ms_log (1, "%s version: %s\n", PACKAGE, VERSION);
return 0;
} /* End of parameter_proc() */
/***************************************************************************
* usage:
* Print the usage message and exit.
***************************************************************************/
static void
usage (void)
{
fprintf (stderr, "%s version: %s\n\n", PACKAGE, VERSION);
fprintf (stderr, "Usage: %s [options] -o outfile\n\n", PACKAGE);
fprintf (stderr,
" ## Options ##\n"
" -V Report program version\n"
" -h Show this usage message\n"
" -v Be more verbose, multiple flags can be used\n"
" -F format Specify miniSEED version format, default is v3\n"
" -r bytes Specify maximum record length in bytes, default 4096\n"
" -e encoding Specify encoding format\n"
"\n"
" -o outfile Specify the output file, required\n"
"\n"
"This program packs static, test data into miniSEED\n"
"\n");
} /* End of usage() */
#define MSF_PACKVER2
[Packing] Pack as miniSEED version 2 instead of 3
Definition libmseed.h:1471
#define MSF_FLUSHDATA
[Packing] Pack all available data even if final record would not be filled
Definition libmseed.h:1470
#define DE_STEIM1
Steim-1 compressed integers.
Definition libmseed.h:1421
#define DE_FLOAT32
32-bit float (IEEE)
Definition libmseed.h:1419
#define DE_FLOAT64
64-bit float (IEEE)
Definition libmseed.h:1420
#define DE_TEXT
Text encoding (UTF-8)
Definition libmseed.h:1416
#define DE_STEIM2
Steim-2 compressed integers.
Definition libmseed.h:1422
#define DE_INT32
32-bit integer
Definition libmseed.h:1418
#define DE_INT16
16-bit integer
Definition libmseed.h:1417
int64_t msr3_writemseed(MS3Record *msr, const char *mspath, int8_t overwrite, uint32_t flags, int8_t verbose)
Write miniSEED from an MS3Record container to a file.
Definition fileutils.c:899
int32_t reclen
Length of miniSEED record in bytes.
Definition libmseed.h:360
double samprate
Nominal sample rate as samples/second (Hz) or period (s)
Definition libmseed.h:368
char sid[LM_SIDLEN]
Source identifier as URN, max length LM_SIDLEN.
Definition libmseed.h:364
uint8_t pubversion
Publication version.
Definition libmseed.h:370
MS3Record * msr3_init(MS3Record *msr)
Initialize and return an MS3Record.
Definition msrutils.c:44
void msr3_free(MS3Record **ppmsr)
Free all memory associated with a MS3Record.
Definition msrutils.c:89
int8_t flag
Definition libmseed.h:1347

Writing miniSEED with rolling buffer

An example of creating miniSEED using a MS3TraceList as a rolling buffer of data. This pattern is useful for generating miniSEED in a streaming fashion for scenarios where holding all data in memory is not possible or practical. For example, very large data sets or continuous, streaming data.

An input file of miniSEED is used as a convenient data source. MS3Record containers can be constructed for any arbitrary data and follow the same pattern of record generation.

/***************************************************************************
* A program for illustrating the use of a Trace List as an
* intermediate, rolling buffer for production of data records.
*
* An input file of miniSEED is used as a convenient data source.
* MS3Records can be constructed for any arbitrary data and follow the
* same pattern of record generation.
*
* This file is part of the miniSEED Library.
*
* Copyright (c) 2023 Chad Trabant, EarthScope Data Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
#include <libmseed.h>
/***************************************************************************
*
* A simple record handler callback function that parses and prints records
*
***************************************************************************/
void
record_handler (char *record, int reclen, void *handlerdata)
{
(void)handlerdata;
MS3Record *msr = NULL;
if (!msr3_parse (record, reclen, &msr, 0, 0))
{
msr3_print (msr, 0);
}
else
{
fprintf (stderr, "%s() Error parsing record\n", __func__);
}
msr3_free (&msr);
}
int
main (int argc, char **argv)
{
MS3Record *msr = NULL;
MS3TraceList *mstl = NULL;
char *inputfile = NULL;
uint32_t flags = 0;
int8_t verbose = 0;
int retcode;
int64_t psamples;
int precords;
int reclen = 256; /* Desired maximum record length */
uint8_t encoding = DE_STEIM2; /* Desired data encoding */
if (argc != 2)
{
ms_log (2, "Usage: %s <mseedfile>\n", argv[0]);
return 1;
}
inputfile = argv[1];
mstl = mstl3_init(NULL);
if (mstl == NULL)
{
ms_log (2, "Cannot allocate memory\n");
return 1;
}
/* Set bit flags to validate CRC and unpack data samples */
flags |= MSF_VALIDATECRC;
flags |= MSF_UNPACKDATA;
/* Loop over the input file as a source of data */
while ((retcode = ms3_readmsr (&msr, inputfile, flags, verbose)) == MS_NOERROR)
{
if (mstl3_addmsr (mstl, msr, 0, 1, flags, NULL) == NULL)
{
ms_log (2, "mstl2_addmsr() had problems\n");
break;
}
/* Attempt to pack data in the Trace List buffer.
* Only filled, or complete, records will be generated. */
ms_log (0, "Calling mstl3_pack() to generate records\n");
precords = mstl3_pack (mstl, // Pack data in this trace list
record_handler, // Callback function that will handle records
NULL, // Callback function data, none in this case
reclen, // Maximum record length
encoding, // Data encoding
&psamples, // Packed sample count
flags, // Flags to control packing
verbose, // Verbosity
NULL // Extra headers to inject, none in this case
);
ms_log (0, "mstl3_pack() created %d records containing %" PRId64 " samples\n",
precords, psamples);
}
if (retcode != MS_ENDOFFILE)
ms_log (2, "Error reading %s: %s\n", inputfile, ms_errorstr (retcode));
/* Final call to flush data buffers, adding MSF_FLUSHDATA flag */
ms_log (0, "Calling mstl3_pack() with MSF_FLUSHDATA flag\n");
precords = mstl3_pack (mstl, // Pack data in this trace list
record_handler, // Callback function that will handle records
NULL, // Callback function data, none in this case
reclen, // Maximum record length
encoding, // Data encoding
&psamples, // Packed sample count
(flags | MSF_FLUSHDATA), // Flags to control packing, adding flush flag
verbose, // Verbosity
NULL // Extra headers to inject, none in this case
);
ms_log (0, "Final mstl3_pack() created %d records containing %" PRId64 " samples\n",
precords, psamples);
/* Make sure everything is cleaned up */
ms3_readmsr (&msr, NULL, flags, 0);
if (msr)
msr3_free (&msr);
if (mstl)
mstl3_free (&mstl, 0);
return 0;
}
int msr3_parse(const char *record, uint64_t recbuflen, MS3Record **ppmsr, uint32_t flags, int8_t verbose)
Parse miniSEED from a buffer.
Definition parseutils.c:61
int64_t mstl3_pack(MS3TraceList *mstl, void(*record_handler)(char *, int, void *), void *handlerdata, int reclen, int8_t encoding, int64_t *packedsamples, uint32_t flags, int8_t verbose, char *extra)
Pack MS3TraceList data into miniSEED records.
Definition tracelist.c:1936

Working with Source Identifiers

An example of mapping between source identifiers (SIDs) and SEED identifier codes.

/***************************************************************************
* A program illustrating mapping source identifiers and SEED codes
*
* This file is part of the miniSEED Library.
*
* Copyright (c) 2023 Chad Trabant, EarthScope Data Services
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
#include <libmseed.h>
int
map_sid (char *original_sid)
{
char sid[LM_SIDLEN];
char network[11];
char station[11];
char location[11];
char channel[31];
int rv;
/* Parse network, station, location and channel from SID */
rv = ms_sid2nslc (original_sid, network, station, location, channel);
if (rv)
{
printf ("Error returned ms_sid2nslc()\n");
return -1;
}
/* Construct SID from network, station, location and channel */
rv = ms_nslc2sid (sid, sizeof(sid), 0, network, station, location, channel);
if (rv <= 0)
{
printf ("Error returned ms_nslc2sid()\n");
return -1;
}
printf ("Original SID: '%s'\n", original_sid);
printf (" network: '%s', station: '%s', location: '%s', channel: '%s'\n",
network, station, location, channel);
printf (" SID: '%s'\n", sid);
return 0;
}
int
main (int argc, char **argv)
{
char *sid;
int idx;
sid = "FDSN:NET_STA_LOC_C_H_N";
if (map_sid (sid))
{
printf ("Error with map_sid()\n");
return 1;
}
/* Map each value give on the command line */
if (argc > 1)
{
for (idx = 1; idx < argc; idx++)
{
if (map_sid (argv[idx]))
{
printf ("Error with map_sid()\n");
return 1;
}
}
}
return 0;
}
int ms_sid2nslc(const char *sid, char *net, char *sta, char *loc, char *chan)
Parse network, station, location and channel from an FDSN Source ID.
Definition genutils.c:183
int ms_nslc2sid(char *sid, int sidlen, uint16_t flags, const char *net, const char *sta, const char *loc, const char *chan)
Convert network, station, location and channel to an FDSN Source ID.
Definition genutils.c:314
#define LM_SIDLEN
Length of source ID string.
Definition libmseed.h:140