sac-format 0.6.0
C++20 SAC (Seismic Analysis Code) File Library
Loading...
Searching...
No Matches
Basic Documentation

This section provides a brief overview of functionality and usage.

Trace class

The Trace class provides easy access to SAC-files in C++. Each SAC-file is a Trace; therefore, each Trace object is a seismic trace (seismogram).

Reading SAC

SAC-files can be read in by using the parameterized constructor with a std::filesystem::path (<filesystem>) or a std::string (<string>) variable that corresponds to the location of the SAC-file.

For example:

#include <sac_foramt.hpp>
#include <filesystem>
int main() {
std::filesystem::path my_file{"/home/user/data/ANMO.SAC"};
sacfmt::Trace anmo{my_file};
return EXIT_SUCCESS;
}
The Trace class.
Definition sac_format.hpp:1080

Writing SAC

Writing SAC files can be done using one of two write functions.

v7 files

Use write (for example trace.write(filename)).

v6 files

Use legacy_write (for example trace.legacy_write(filename)).

Getters and Setters

Every SAC variable is accessed via getters and setters of the same name.

Example Getters

  • trace.npts()
  • trace.data1()
  • trace.kstnm()

Example Setters

  • trace.kevnm("Event 1")
  • trace.evla(32.89)
  • trace.mag(3.21)

Setter rules

Most of the setters are only constrained by the parameter type (single-precision, double-precision, boolean, etc.). Some setters are constrained by additional rules.

Required for sanity

Rules here are required because the sac-format library assumes them (not strictly required by the SAC format standard). For instance, the geometric functions assume certain bounds on latitudes and longitudes.

sac-format automatically imposes these rules.

stla(input)

Limited to [-90, 90] degrees, input that is outside that range is reduced using circular symmetry.

stlo(input)

Limited to [-180, 180] degrees, input that is outside that range is reduced using circular symmetry.

evla(input)

Limited to [-90, 90] degrees, input that is outside that range is reduced using circular symmetry.

evlo(input)

Limited to [-180, 180] degrees, input that is outside that range is reduced using circular symmetry.

Required for safety

Rules here are required by the SAC format standard. sac-format automatically imposes these rules to prevent the creation of corrupt sac-files.

npts(input)

Because npts defines the size of the data vectors, changing this value will change the size of data1 and data2∗. Increasing npts resizes the vectors (std::vector::resize) by placing zeros at the end of the vectors. Reducing npts resizes the vectors down to the first npts values.

Therefore, care must be taken to maintain separate copies of data1 and data2∗ if you plan to manipulate the original data after resizing.

∗ data2 has npts only if it is legal, otherwise it is of size 0.

leven(input)

Changing the value of leven potentially changes the legality of data2, it also potentially affects the value of iftype.

If iftype>1, then leven must be true (evenly sampled data). Therefore, if leven is made false in this scenario (unevenly sampled data) then iftype becomes unset∗.

If changing leven makes data2 legal∗∗, then data2 is qresized to have npts zeros.

∗ The SAC format defines the unset values for all data-types. For integers (like iftype) it is the integer value -12345.

∗∗ If data2 was already legal, then it is unaffected.

iftype(input)

Changing the value of iftype poentially changes the legality of data2, it also potentially affects the value of leven.

If leven is false, then iftype must be either 1 or unset. Therefore, changing iftype to have a value >1 requires that leven becomes true (evenly sampled data).

If changing iftype makes data2 legal∗, then data2 is resized to have npts zeros.

∗ If data2 was already legal, then it is unaffected.

data1(input)

If the size of data1 is changed, then npts must change to reflect the new size. If data2 is legal, this adjusts its size to match as well.

data2(input)

If the size of data2 is changed to be larger than 0 and it is illegal, it is made legal by setting iftype(2) (spectral-data).

When the size of data2 changes, npts is updated to the new size and data1 is resized to match.

If data2 is made illegal, its size is reduced to 0 while npts and data1 are unaffected.

Convenience Methods

calc_geometry

Calculate gcarc, dist, az, and baz assuming spherical Earth.

trace.stla(45.3);
trace.stlo(34.5);
trace.evla(18.5);
trace.evlo(-34);
trace.calc_geometry();
std::cout << "GcArc: " << trace.gcarc() << '\n';
std::cout << "Dist: " << trace.dist() << '\n';
std::cout << "Azimuth: " << trace.az() << '\n';
std::cout << "BAzimuth: " << trace.baz() << '\n';

frequency

Calculate frequency from delta.

double frequency{trace.frequency()};

date

Return std::string formatted as YYYY-JJJ from nzyear and nzjday.

std::string date{trace.date()};

time

Return std::string formatted as HH:MM:SS.xxx from nzhour, nzmin, nzsec, and nzmsec.

std::string time{trace.time()};

Exceptions

sac-format throws exceptions of type sacfmt::io_error (inherits std::exception) in the event of a failure to read/write a SAC-file.

Convenience Functions

degrees_to_radians

Convert decimal degrees to radians.

double radians{sacfmt::degrees_to_radians(degrees)};
double degrees_to_radians(double degrees) noexcept
Convert decimal degrees to radians.
Definition sac_format.cpp:659

radians_to_degrees

Convert radians to decimal degrees.

double degrees{sacfmt::radians_to_degrees(radians)};
double radians_to_degrees(double radians) noexcept
Convert radians to decimal degrees.
Definition sac_format.cpp:673

gcarc

Calculate great-circle arc distance (spherical planet).

const point location1{coord{latitude1}, coord{longitude1}};
const point location2{coord{latitude2}, coord{longitude2}};
double gcarc{sacfmt::gcarc(location1, location2)};
double gcarc(point location1, point location2) noexcept
Calculate great circle arc distance in decimal degrees between two points.
Definition sac_format.cpp:735

azimuth

Calculate azimuth between two points (spherical planet).

const point location1{coord{latitude1}, coord{longitude1}};
const point location2{coord{latitude2}, coord{longitude2}};
double azimuth{sacfmt::azimuth(location2, location1)};
double back_azimuth{sacfmt::azimuth(location1, location2)};
double azimuth(point location1, point location2) noexcept
Calculate azimuth between two points.
Definition sac_format.cpp:766

limit_360

Take arbitrary value of degrees and unwrap to [0, 360].

double degrees_limited{sacfmt::limit_360(degrees)};
double limit_360(double degrees) noexcept
Takes a decimal degree value and constrains it to full circle using symmetry.
Definition sac_format.cpp:794

limit_180

Take arbitrary value of degrees and unwrap to [-180, 180]. Useful for longitude.

double degrees_limited{sacfmt::limit_180(degrees)};
double limit_180(double degrees) noexcept
Takes a decimal degree value and constrains it to a half circle using symmetry.
Definition sac_format.cpp:820

limit_90

Take arbitrary value of degrees and unwrap to [-90, 90]. Useful for latitude.

double degrees_limited{sacfmt::limit_90(degrees)};
double limit_90(double degrees) noexcept
Takes a decimal degree value and constrains it to a quarter circle using symmetry.
Definition sac_format.cpp:840

Low-Level I/O

Low-level I/O functions are discussed below.

Binary conversion

int_to_binary and binary_to_int

Conversion pair for binary representation of integer values.

const int input{10};
// sacfmt::word_one is alias for std::bitset<32> (one word)
const int output{sacfmt::binary_to_int(binary)};
std::cout << (input == output) << '\n';
word_one int_to_binary(int num) noexcept
Convert integer to 32-bit (one word) binary bitset.
Definition sac_format.cpp:67
int binary_to_int(word_one bin) noexcept
Convert 32-bit (one word) binary bitset to integer.
Definition sac_format.cpp:88
std::bitset< binary_word_size > word_one
One binary word (useful for non-strings).
Definition sac_format.hpp:84

float_to_binary and binary_to_float

Conversion pair for binary representation of floating-point values.

const float input{5F};
const float output{sacfmt::binary_to_float(binary)};
std::cout << (input == output) << '\n';
float binary_to_float(const word_one &bin) noexcept
Convert 32-bit (one word) binary bitset to a floating-point value.
Definition sac_format.cpp:127
word_one float_to_binary(float num) noexcept
Convert floating-point value to 32-bit (one word) binary bitset.
Definition sac_format.cpp:111

double_to_binary and binary_to_double

Conversion pair for binary representation of double-precision values.

const double input{1e5};
// sacfmt::word_two is alias for std::bitset<64> (two words)
const double output{sacfmt::binary_to_double(binary)};
std::cout << (input == output) << '\n';
word_two double_to_binary(double num) noexcept
Convert double-precision value to 64-bit (two words) binary bitset.
Definition sac_format.cpp:143
std::bitset< static_cast< size_t >(2) *binary_word_size > word_two
Two binary words (useful for strings).
Definition sac_format.hpp:86
double binary_to_double(const word_two &bin) noexcept
Convert 64-bit (two words) binary bitset to double-precision value.
Definition sac_format.cpp:159

string_to_binary and binary_to_string

Conversion pair for binary representation of two-word (regular) string values.

const std::string input{"NmlStrng"};
const std::string output{sacfmt::binary_to_string(binary)};
std::cout << (input == output) << '\n';
word_two string_to_binary(std::string str) noexcept
Convert string to a 64-bit (two word) binary bitset.
Definition sac_format.cpp:282
std::string binary_to_string(const word_two &str) noexcept
Convert a 64-bit (two word) binary bitset to a string.
Definition sac_format.cpp:298

long_string_to_binary and binary_to_long_string

Conversion pair for binary representation of four-word (only kstnm string values.

const std::string input{"The Long String"};
// sacfmt::word_four is alias for std::bitset<128> (four words)
const std::string output{sacfmt::binary_to_long_string(binary)};
std::cout << (input == output) << '\n';
word_four long_string_to_binary(std::string str) noexcept
Convert a string to a 128-bit (four word) binary bitset.
Definition sac_format.cpp:315
std::string binary_to_long_string(const word_four &str) noexcept
Convert a 128-bit (four word) binary bitset to a string.
Definition sac_format.cpp:332
std::bitset< static_cast< size_t >(4) *binary_word_size > word_four
Four binary words (kEvNm only).
Definition sac_format.hpp:88

Reading/Writing

NOTE that care must be taken when using them to ensure that safe input is provided; the Trace class ensures safe I/O, low-level I/O functions do not necessarily ensure safety.

read_word, read_two_words, read_four_words, and read_data

Functions to read one-, two-, and four-word variables (depending on the header) and an arbitrary amount of binary data (exclusive to data1 and data2).

convert_to_word, convert_to_words, and bool_to_word

Takes objects and converts them into std::vector<char> (convert_to_word and bool_to_word) or std::array<char, N> (convert_to_words, N = # of words).

write_words

Writes input words (as std::vector<char>) to a binary SAC-file.

Utility

concat_words

Concatenates words taking into account the system endianness.

bits_string and string_bits

Template function that performs conversion of binary strings of arbitrary length to an arbitrary number of words.

remove_leading_spaces and remove_trailing_spaces

Remove leading and trailing blank spaces from strings assuming ASCII convention (space character is integer 32, below that value are control characters that also appear as blank spaces).

string_cleaning

Ensures string does not contain an internal termination character (\0) and removes it if present, then removes blank spaces.

prep_string

Performs string_cleaning followed by string truncation/padding to the necessary length.

equal_within_tolerance

Floating-point/double-precision equality within a provided tolerance (default is f_eps, defined in sac_format.hpp).

Testing

Unit- and integration-tests (using Catch2) are contained in the tests folder. They include:

  • binary_conversions.cpp confirms that conversion to/from binary functions correctly.
  • constants.cpp confirms constant values (e.g. SAC magic numbers) are correct.
  • datetime.cpp confirms date and time functions work correctly.
  • geometry.cpp confirms that geometric calculations are correct (azimuth, greater-circle arc-length, etc.).
  • trace.cpp confirms that the trace class is functioning correctly (I/O, exceptions, bounded headers, etc.).

The tests compile to the following programs:

  • basic_tests (binary conversions and constants).
  • datetime_tests
  • geometry_tests
  • trace_tests

Test coverage details are visible on CodeCov.io and Codacy.com. All tests can be locally-run to ensure full functionality and compliance.

Errors only

By default each test prints out a pass summary, without details unless an error is encountered.

Full output

By passing the --success flag you can see the full results of all tests.

Compact output

The full output is verbose, using the compact reporter will condense the test results (--reporter=compact).

Additional options

To see additional options, run -?.

Using ctest

If you have CMake install, you can run the tests using ctest.

Benchmarking

benchmark.cpp contains the benchmarks. Running it locally will provide information on how long each function takes; benchmarks start with the low-level I/O function and build up to Trace reading, writing, and equality comparison.

To view available optional flags, run becnhmark -?.

Source File List

Core

The two core files are split in the standard interface (hpp)/implementation (cpp) format.

sac_format.hpp

Interface: function declarations and constants.

sac_format.cpp

Implementation: function details.

Testing and Benchmarking

util.hpp

Utility functions and constants exclusive to testing and benchmarking. Not split into interface/implementation.

utests.cpp

benchmark.cpp

Example programs

list_sac.cpp