From 2a41f93d7459e02410a824d9660a38dca628e97b Mon Sep 17 00:00:00 2001 From: Alexander Blanchette Date: Fri, 8 Dec 2023 13:48:35 -0800 Subject: [PATCH 1/2] Linked parameters (mostly headers) now update in tandem: npts, data1, leven, iftype, and data2. This is reflected in the documentation under the section Setter rules. New unit-tests to complement these changes. This now means that sac-format *should not* be capable of writing corrupted sac-files due to user error. Next update will include tests to ensure it cannot output malformed sac-files due to user error. --- docs/index.html | 143 +++++++++++++--------- docs/sac-format_manual.pdf | Bin 117198 -> 122748 bytes src/docs/index.org | 102 +++++++++++++++- src/sac_format.cpp | 68 ++++++++++- src/sac_format.hpp | 3 + src/utests.cpp | 238 +++++++++++++++++++++++++++++++++++++ todo.org | 23 +++- 7 files changed, 513 insertions(+), 64 deletions(-) diff --git a/docs/index.html b/docs/index.html index 6514510..4cb52f0 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,52 +1,54 @@ sac-format -

sac-format
C++20 SAC-file Library
V0.4.0
User Manual

Windows 2022 Build Status +

sac-format
C++20 SAC-file Library
V0.4.0
User Manual

Windows 2022 Build Status Ubuntu 22.04 Build Status macOS 13 Build Status Code Coverage Codacy grade CodeFactor -CPP-Linter Results

1. Introduction

sac-format is a single-header statically linked library designed to make working +CPP-Linter Results

1. Introduction

sac-format is a single-header statically linked library designed to make working with binary SAC-files as easy as possible. Written in C++20, it follows a modern and easy to read programming-style while providing the high performance brought -by C++.

sac-format’s developed on GitHub!

Download an offline version of the documentation (PDF).

1.1. Why sac-format

sac-format is Free and Open Source Software (FOSS) released under the MIT +by C++.

sac-format’s developed on GitHub!

Download an offline version of the documentation (PDF).

1.1. Why sac-format

sac-format is Free and Open Source Software (FOSS) released under the MIT license. Anyone can use it, for any purpose (including proprietary software), anywhere in the world. sac-format is operating system agnostic and confirmed -working on Windows, macOS, and Linux systems.

1.1.1. Safe

sac-format is safe—it conforms to a strict set of C++ programming guidelines, +working on Windows, macOS, and Linux systems.

1.1.1. Safe

sac-format is safe—it conforms to a strict set of C++ programming guidelines, chosen to ensure safe code-execution. The guideline conformance list is in cpp-linter.yml and can be cross-referenced against this master list. Results of conformance checking are here.

Testing is an important part of software development; the sac-format library is extensively tested using the Catch2 testing framework. Everything from low-level binary conversions to high-level Trace reading/writing are tested and confirmed -working. Check and run the tests yourself. See the Testing section for more -information.

1.1.2. Fast

sac-format is fast—it’s written in C++, carefully optimized, and extensively +working. Check and run the tests yourself. See the Testing section for more +information.

1.1.2. Fast

sac-format is fast—it’s written in C++, carefully optimized, and extensively benchmarked. You can run the benchmarks yourself to find out how sac-format -performs on your system. See the Benchmarking section for more information.

1.1.3. Easy

sac-format is easy—single-header makes integration in any project simple. +performs on your system. See the Benchmarking section for more information.

1.1.3. Easy

sac-format is easy—single-header makes integration in any project simple. Building is a breeze with CMake, even on different platforms. Object-oriented -design makes use easy and intuitive. See the Quickstart section to get up and -running.

1.1.4. Small

sac-format is small—in total (header + implementation–excluding comments) -it’s fewer than 2000 lines of code. Small size opens the door to using on any -sort of hardware (old or new) and makes it easy to expand upon.

1.1.5. Documented

sac-format is extensively documented—both online and in the code. Nothing’s +design makes use easy and intuitive. See the Quickstart section to get up and +running.

1.1.4. Small

sac-format is small—in total (header + implementation–excluding comments) the +library is under 2100∗ lines of code. Small size opens the door to using on any +sort of hardware (old or new) and makes it easy to expand upon.

∗ This value includes only the library, excluding all testing/benchmarking +and example codes. Including utests.cpp, benchmark.cpp, util.hpp, the example +program (list_sac), and sac-format totals just under 5100 lines of code.

1.1.5. Documented

sac-format is extensively documented—both online and in the code. Nothing’s hidden—nothing’s obscured. Curious how something works? Check the -documentation and in-code comments.

1.1.6. Transparent

sac-format is transparent—all analysis and coverage information is publicly -available online.

1.1.7. Trace Class

sac-format includes the Trace class for seismic traces, providing high-level +documentation and in-code comments.

1.1.6. Transparent

sac-format is transparent—all analysis and coverage information is publicly +available online.

1.1.7. Trace Class

sac-format includes the Trace class for seismic traces, providing high-level object-oriented abstraction to seismic data. With the Trace class, you don’t need to worry about manually reading SAC-files word-by-word. It’s compatible with v6 and v7 SAC-files and can automatically detect the version upon reading. File output defaults to v7 SAC-files and there is a legacy_write function for v6 -output.

1.1.8. Low-Level I/O

If you want to roll your own SAC-file processing workflow you can use the +output.

1.1.8. Low-Level I/O

If you want to roll your own SAC-file processing workflow you can use the low-level I/O functionality built into sac-format. All functions tested and -confirmed working—they’re used to build the Trace class!

2. Quickstart

2.1. Manual Instructions

2.1.1. Build Instructions

Building is as easy as cloning the repository, running CMake for your preferred -build tool, and then building.

  1. GCC
    git clone https://github.com/arbCoding/sac-format.git
    +confirmed working—they’re used to build the Trace class!

2. Quickstart

2.1. Manual Instructions

2.1.1. Build Instructions

Building is as easy as cloning the repository, running CMake for your preferred +build tool, and then building.

  1. GCC
    git clone https://github.com/arbCoding/sac-format.git
     cmake --preset gcc-release
     cmake --build ./build/release/gcc
    -
  2. Clang
    git clone https://github.com/arbCoding/sac-format.git
    +
  3. Clang
    git clone https://github.com/arbCoding/sac-format.git
     cmake --preset clang-release
     cmake --build ./build/release/clang
    -

2.1.2. Use

To use link to the compiled library (libsac-format.a on Linux/macOS, -libsac-format.lib on Windows) and include src/sac_format.hpp.

2.2. Example Programs

2.2.1. list_sac

list_sac is a command line program that takes a single SAC-file as its input +

2.1.2. Use

To use link to the compiled library (libsac-format.a on Linux/macOS, +libsac-format.lib on Windows) and include src/sac_format.hpp.

2.2. Example Programs

2.2.1. list_sac

list_sac is a command line program that takes a single SAC-file as its input argument. It reads the SAC-file and outputs the header/footer information, as -well as the true size of the data1 and data2 vectors.

2.3. CMake Integration

To integrate sac-format into your CMake project, add it to your CMakeLists.txt.

include(FetchContent)
+well as the true size of the data1 and data2 vectors.

2.3. CMake Integration

To integrate sac-format into your CMake project, add it to your CMakeLists.txt.

include(FetchContent)
 set(FETCHCONTENT_UPDATES_DISCONNECTED TRUE)
 FetchContent_Declare(sac-format
     GIT_REPOSITORY https://github.com/arbCoding/sac-format
@@ -63,7 +65,7 @@
 
 target_link_libraries_library(your_executable
     PRIVATE sac-format)
-

2.4. Example

2.4.1. Reading and Writing

#include <filesystem>
+

2.4. Example

2.4.1. Reading and Writing

#include <filesystem>
 #include <iostream>
 #include <sac_format.hpp>
 
@@ -84,8 +86,8 @@
     fs::remove(file);
     return EXIT_SUCCESS;
 }
-

3. Documentation

3.1. 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).

3.1.1. Reading SAC

SAC-files can be read in by using the parameterized constructor with a +

3. Documentation

3.1. 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).

3.1.1. 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 <filesystem>
 #include <sac_foramt.hpp>
@@ -95,9 +97,34 @@
   sacfmt::Trace anmo = Trace(my_file);
   return EXIT_SUCCESS;
 }
-

3.1.2. Writing SAC

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

  1. v7 files

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

  2. v6 files

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

3.1.3. Getters and Setters

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

  1. Example Getters
    • trace.npts()
    • trace.data1()
    • trace.kstnm()
  2. Example Setters
    • trace.kevnm("Event 1")
    • trace.evla(32.89)
    • trace.mag(3.21)

3.1.4. Internal Structure

The SAC-trace stores the data internally in a series of pre-allocated -std::array (<array>) container objects. Getters and setters access these via -a lookup table. The internal components are below:

  1. Lookup Table

    sac_map

  2. floats array
  3. doubles array
  4. ints array
  5. bools array
  6. strings array
  7. data array

3.1.5. Convenience Methods

  • calc_geometry

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

trace.stla(45.3);
+

3.1.2. Writing SAC

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

  1. v7 files

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

  2. v6 files

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

3.1.3. Getters and Setters

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

  1. Example Getters
    • trace.npts()
    • trace.data1()
    • trace.kstnm()
  2. Example Setters
    • trace.kevnm("Event 1")
    • trace.evla(32.89)
    • trace.mag(3.21)
  3. 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.

    1. 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.

      1. stla(input)

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

      2. stlo(input)

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

      3. evla(input)

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

      4. evlo(input)

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

    2. Require 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.

      1. 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.

      2. 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 resized 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.

      3. 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.

      4. 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.

      5. 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.

3.1.4. Internal Structure

The SAC-trace stores the data internally in a series of pre-allocated +std::array (<array>) container objects. Getters and setters access these via +a lookup table. The internal components are below:

  1. Lookup Table

    sac_map

  2. floats array
  3. doubles array
  4. ints array
  5. bools array
  6. strings array
  7. data array

3.1.5. 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);
@@ -110,8 +137,8 @@
 
  • 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()};
-

3.1.6. 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.

3.2. Convenience Functions

  • degrees_to_radians

Convert decimal degrees to radians.

double radians{sacfmt::degrees_to_radians(degrees)};
+

3.1.6. 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.

3.2. Convenience Functions

  • degrees_to_radians

Convert decimal degrees to radians.

double radians{sacfmt::degrees_to_radians(degrees)};
 
  • radians_to_degrees

Convert radians to decimal degrees.

double degrees{sacfmt::radians_to_degrees(radians)};
 
  • gcarc

Calculate great-circle arc distance (spherical planet).

double gcarc{sacfmt::gcarc(latitude1, longitude1, latitude2, longitude2)};
 
  • azimuth

Calculate azimuth between two points (spherical planet).

double azimuth{sacfmt::azimuth(latitude2, longitude2, latitude1, longitude1)};
@@ -120,64 +147,64 @@
 
  • limit_180

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

double degrees_limited{sacfmt::limit_180(degrees)};
 
  • limit_90

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

double degrees_limited{sacfmt::limit_90(degrees)};
-

3.3. Low-Level I/O

Low-level I/O functions are discussed below.

  1. Binary conversion
    1. int_to_binary and binary_to_int

      Conversion pair for binary representation of integer values.

      const int input{10};
      +

3.3. Low-Level I/O

Low-level I/O functions are discussed below.

  1. Binary conversion
    1. 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)
       sacfmt::word_one binary{sacfmt::int_to_binary(input)};
       const int output{sacfmt::binary_to_int(binary)};
       std::cout << (input == output) << '\n';
      -
    2. float_to_binary and binary_to_float

      Conversion pair for binary representation of floating-point values.

      const float input{5F};
      +
    3. float_to_binary and binary_to_float

      Conversion pair for binary representation of floating-point values.

      const float input{5F};
       sacfmt::word_one binary{sacfmt::float_to_binary(input)};
       const float output{sacfmt::binary_to_float(binary)};
       std::cout << (input == output) << '\n';
      -
    4. double_to_binary and binary_to_double

      Conversion pair for binary representation of double-precision values.

      const double input{1e5};
      +
    5. 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)
       sacfmt::word_two binary{sacfmt::double_to_binary(input)};
       const double output{sacfmt::binary_to_double(binary)};
       std::cout << (input == output) << '\n';
      -
    6. string_to_binary and binary_to_string

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

      const std::string input{"NmlStrng"};
      +
    7. string_to_binary and binary_to_string

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

      const std::string input{"NmlStrng"};
       sacfmt::word_two binary{sacfmt::string_to_binary(input)};
       const std::string output{sacfmt::binary_to_string(binary)};
       std::cout << (input == output) << '\n';
      -
    8. long_string_to_binary and binary_to_long_string

      Conversion pair for binary representation of four-word (only kstnm) string +

  • 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)
     sacfmt::word_four binary{sacfmt::long_string_to_binary(input)};
     const std::string output{sacfmt::binary_to_long_string(binary)};
     std::cout << (input == output) << '\n';
    -
  • Reading/Writing

    NOTE that care must be taken when using them to ensure that safe input is +

  • 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.

    1. 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).

    2. 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).

    3. write_words

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

  • Utility
    1. concat_words

      Concatenates words taking into account the system endianness.

    2. bits_string and string_bits

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

    3. remove_leading_spaces and remove_trailing_spaces

      Remove leading and trailing blank spaces from strings assuming ASCII convention +necessarily ensure safety.

      1. 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).

      2. 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).

      3. write_words

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

    4. Utility
      1. concat_words

        Concatenates words taking into account the system endianness.

      2. bits_string and string_bits

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

      3. 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).

      4. string_cleaning

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

      5. prep_string

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

      6. equal_within_tolerance

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

  • 3.4. Testing

    utests.cpp contains the unit- and integration-tests, using Catch2. Test coverage +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).

  • 3.4. Testing

    utests.cpp contains the unit- and integration-tests, using Catch2. Test coverage details are visible on CodeCov.io and Codacy.com. All tests can be locally-run -to ensure full functionality and compliance.

    3.4.1. Errors only

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

    3.4.2. Full output

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

    3.4.3. Compact output

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

    3.4.4. Additional options

    To see additional options, run utests -?.

    3.5. Benchmarking

    benchmark.cpp contains the benchmarks. Running it locally will provide +to ensure full functionality and compliance.

    3.4.1. Errors only

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

    3.4.2. Full output

    By passing the --success flag (utests --success) you can see the full results of +all tests.

    3.4.3. Compact output

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

    3.4.4. Additional options

    To see additional options, run utests -?.

    3.5. 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 -?.

    3.6. Source File List

    3.6.1. Core

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

    1. sac_format.hpp

      Interface—function declarations and constants.

    2. sac_format.cpp

      Implementation—function details.

    3.6.2. Testing and Benchmarking

    1. util.hpp

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

    2. utests.cpp
    3. benchmark.cpp

    3.6.3. Example programs

    1. list_sac.cpp

    3.7. Dependencies

    3.7.1. Automatic (CMake)

    1. Xoshiro-cpp v1.12.0 (testing and benchmarking)
    2. Catch2 v3.4.0 (testing and benchmarking)

    3.8. SAC-file format

    The official and up-to-date documentation for the SAC-file format is available +I/O function and build up to Trace reading, writing, and equality comparison.

    To view available optional flags, run becnhmark -?.

    3.6. Source File List

    3.6.1. Core

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

    1. sac_format.hpp

      Interface—function declarations and constants.

    2. sac_format.cpp

      Implementation—function details.

    3.6.2. Testing and Benchmarking

    1. util.hpp

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

    2. utests.cpp
    3. benchmark.cpp

    3.6.3. Example programs

    1. list_sac.cpp

    3.7. Dependencies

    3.7.1. Automatic (CMake)

    1. Xoshiro-cpp v1.12.0 (testing and benchmarking)
    2. Catch2 v3.4.0 (testing and benchmarking)

    3.8. SAC-file format

    The official and up-to-date documentation for the SAC-file format is available from the EarthScope Consortium (formerly IRIS/UNAVCO) here. The following subsections constitute my notes on the format. Below is a quick guide—all credit for the creation of, and documentation for, the SAC file-format belongs -to its developers and maintainers (details here).

    3.8.1. Floating-point (39)

    32-bit (1 word, 4 bytes)

    1. depmin

      Minimum value of the dependent variable -(displacement/velocity/acceleration/volts/counts).

    2. depmen

      Mean value of the dependent variable.

    3. depmax

      Maximum value of the dependent variable.

    4. odelta

      Modified (observational) value of delta.

    5. resp(0--9)

      Instrument response parameters (poles, zeros, and a constant).

      Not used by SAC—they’re free for other purposes.

    6. stel

      Station elevation in meters above sea level (m.a.s.l).

      Not used by SAC—free for other purposes.

    7. stdp

      Station depth in meters below surface (borehole/buried vault).

      Not used by SAC—free for other purposes.

    8. evel

      Event elevation m.a.s.l.

      Not used by SAC—free for other purposes.

    9. evdp

      Event depth in kilometers (previously meters) below surface.

    10. mag

      Event magnitude.

    11. user(0--9)

      Storage for user-defined values.

    12. dist

      Station–Event distance in kilometers.

    13. az

      Azimuth \(\mathrm{\left(Event \to Station\right)}\), decimal degrees from North.

    14. baz

      Back-azimuth \(\mathrm{\left(Station \to Event\right)}\), decimal degrees from -North.

    15. gcarc

      Station–Event great circle arc-length, decimal degrees.

    16. cmpaz

      Instrument measurement azimuth, decimal degrees from North.
      ValueDirection
      North
      90°East
      180°South
      270°West
      Other1/2/3

    17. cmpinc

      Instrument measurement incident angle, decimal degrees from upward vertical +to its developers and maintainers (details here).

      3.8.1. Floating-point (39)

      32-bit (1 word, 4 bytes)

      1. depmin

        Minimum value of the dependent variable +(displacement/velocity/acceleration/volts/counts).

      2. depmen

        Mean value of the dependent variable.

      3. depmax

        Maximum value of the dependent variable.

      4. odelta

        Modified (observational) value of delta.

      5. resp(0--9)

        Instrument response parameters (poles, zeros, and a constant).

        Not used by SAC—they’re free for other purposes.

      6. stel

        Station elevation in meters above sea level (m.a.s.l).

        Not used by SAC—free for other purposes.

      7. stdp

        Station depth in meters below surface (borehole/buried vault).

        Not used by SAC—free for other purposes.

      8. evel

        Event elevation m.a.s.l.

        Not used by SAC—free for other purposes.

      9. evdp

        Event depth in kilometers (previously meters) below surface.

      10. mag

        Event magnitude.

      11. user(0--9)

        Storage for user-defined values.

      12. dist

        Station–Event distance in kilometers.

      13. az

        Azimuth \(\mathrm{\left(Event \to Station\right)}\), decimal degrees from North.

      14. baz

        Back-azimuth \(\mathrm{\left(Station \to Event\right)}\), decimal degrees from +North.

      15. gcarc

        Station–Event great circle arc-length, decimal degrees.

      16. cmpaz

        Instrument measurement azimuth, decimal degrees from North.
        ValueDirection
        North
        90°East
        180°South
        270°West
        Other1/2/3

      17. cmpinc

        Instrument measurement incident angle, decimal degrees from upward vertical (incident 0° = dip -90°).
        ValueDirection
        Up
        90°Horizontal
        180°Down
        270°Horizontal

        NOTE: SEED/MINISEED use dip angle, decimal degrees down from horizontal (dip -0° = incident 90°).

      18. xminimum

        Spectral-only equivalent of depmin (\(f_{0}\) or \(\omega_{0}\)).

      19. xmaximum

        Spectral-only equivalent of depmax (\(f_{max}\) or \(\omega_{max}\)).

      20. yminimum

        Spectral-only equivalent of b.

      21. ymaximum

        Spectral-only equivalent of e.

      3.8.2. Double (22)

      64-bit (2 words, 8 bytes)

      NOTE: in the header section these are floats—they’re doubles in the footer +0° = incident 90°).

    18. xminimum

      Spectral-only equivalent of depmin (\(f_{0}\) or \(\omega_{0}\)).

    19. xmaximum

      Spectral-only equivalent of depmax (\(f_{max}\) or \(\omega_{max}\)).

    20. yminimum

      Spectral-only equivalent of b.

    21. ymaximum

      Spectral-only equivalent of e.

    3.8.2. Double (22)

    64-bit (2 words, 8 bytes)

    NOTE: in the header section these are floats—they’re doubles in the footer section of v7 SAC-files. In memory they’re stored as doubles regardless of the -SAC-file version.

    1. delta

      Increment between evenly spaced samples (\(\Delta t\) for timeseries, \(\Delta f\) -or \(\Delta\omega\) for spectra).

    2. b

      First value (begin) of independent variable (\(t_{0}\)).

    3. e

      Final value (end) of independent variable (\(t_{max}\)).

    4. o

      Event origin time, in seconds relative to the reference time.

    5. a

      Event first arrival time, in seconds relative to the reference time.

    6. t(0--9)

      User defined time values, in seconds relative to the reference time.

    7. f

      Event end (fini) time, in seconds relative to the reference time.

    8. stla

      Station latitude in decimal degrees, N/S–positive/negative.

      sac-format automatically enforces \(\mathrm{stla}\in[-90, 90]\).

    9. stlo

      Station longitude in decimal degrees, E/W–positive/negative.

      sac-format automatically enforces \(\mathrm{stlo}\in[-180, 180]\).

    10. evla

      Event latitude in decimal degrees, N/S–positive/negative.

      sac-format automatically enforces \(\mathrm{evla}\in[-90, 90]\).

    11. evlo

      Event longitude in decimal degrees, E/W–positive/negative.

      sac-format automatically enforces \(\mathrm{evlo}\in[-180, 180]\).

    12. sb

      Original (saved) b value.

    13. sdelta

      Original (saved) delta value.

    3.8.3. Integer (26)

    32-bit (1 word, 4 bytes)

    1. nzyear

      Reference time GMT year.

    2. nzjday

      Reference time GMT day-of-year (often called Julian Date) (1–366).

    3. nzhour

      Reference time GMT hour (00–23).

    4. nzmin

      Reference time GMT minute (0–59).

    5. nzsec

      Reference time GMT second (0–59).

    6. nzmsec

      Reference time GMT Millisecond (0–999).

    7. nvhdr

      SAC-file version.
      VersionDescription
      v7Footer (2020+, sac 102.0+)
      v6No footer (pre-2020, sac 101.6a-)

    8. norid

      Origin ID.

    9. nevid

      Event ID.

    10. npts

      Number of points in data.

    11. nsnpts

      Original (saved) npts.

    12. nwfid

      Waveform ID.

    13. nxsize

      Spectral-only equivalent of npts (length of spectrum).

    14. nysize

      Spectral-only, width of spectrum.

    15. iftype

      File type.
      ValueTypeDescription
      01ITIMETime-series
      02IRLIMSpectral (real/imaginary)
      03IAMPHSpectral (amplitude/phase)
      04IXYGeneral XY file
      ??IXYZ∗General XYZ file

      ∗Value not listed in the standard.

    16. idep

      Dependent variable type.
      ValueTypeDescription
      05IUNKNUnknown
      06IDISPDisplacement (nm)
      07IVELVelocity \(\mathrm{\left(\frac{nm}{s}\right)}\)
      08IACCAcceleration \(\mathrm{\left(\frac{nm}{s^{2}}\right)}\)
      50IVOLTSVelocity (volts)

    17. iztype

      Reference time equivalent.
      ValueTypeDescription
      05IUNKNUnknown
      09IBRecording start time
      10IDAYMidnight reference GMT day
      11IOEvent origin time
      12IAFirst arrival time
      13–22IT(0–9)User defined time (t) pick

    18. iinst

      Recording instrument type.

      Not used by SAC—free for other purposes.

    19. istreg

      Station geographic region.

      Not used by SAC—free for other purposes.

    20. ievreg

      Event geographic region.

      Not used by SAC—free for other purposes.

    21. ievtyp

      Event type.
      ValueTypeDescription
      05IUNKNUnknown
      11IOOther source of known origin
      37INUCLNuclear
      38IPRENNuclear pre-shot
      39IPOSTNNuclear post-shot
      40IQUAKEEarthquake
      41IPREQForeshock
      42IPOSTQAftershock
      43ICHEMChemical explosion
      44IOTHEROther
      72IQBQuarry/mine blast—confirmed by quarry/mine
      73IQB1Quarry/mine blast—designed shot info-ripple fired
      74IQB2Quarry/mine blast—observed shot info-ripple fired
      75IQBXQuarry/mine blast—single shot
      76IQMTQuarry/mining induced events—tremor and rockbursts
      77IEQEarthquake
      78IEQ1Earthquake in a swarm or in an aftershock sequence
      79IEQ2Felt earthquake
      80IMEMarine explosion
      81IEXOther explosion
      82INUNuclear explosion
      83INCNuclear cavity collapse
      85ILLocal event of unknown origin
      86IRRegion event of unknown origin
      87ITTeleseismic event of unknown origin
      88IUUndetermined/conflicting information

    22. iqual

      Quality of data.
      ValueTypeDescription
      44IOTHEROther
      45IGOODGood
      46IGLCHGlitches
      47IDROPDropouts
      48ILOWSNLow signal-to-noise ratio

      Not used by SAC—free for other purposes.

    23. isynth

      Synthetic data flag.
      ValueTypeDescription
      49IRLDATAReal data
      XXSynthetic

      ∗Values and types not listed in the standard.

    24. imagtyp

      Magnitude type.
      ValueTypeDescription
      52IMBBody-wave magnitude (\(M_{b}\))
      53IMSSurface-wave magnitude (\(M_{s}\))
      54IMLLocal magnitude (\(M_{l}\))
      55IMWMoment magnitude (\(M_{w}\))
      56IMDDuration magnitude (\(M_{d}\))
      57IMXUser-defined magnitude (\(M_{x}\))

    25. imagsrc

      Source of magnitude information.
      ValueTypeDescription
      58INEICNational Earthquake Information Center
      61IPDEPreliminary Determination of Epicenter
      62IISCInternation Seismological Centre
      63IREBReviewed Event Bulletin
      64IUSGSU.S. Geological Survey
      65IBRKUC Berkeley
      66ICALTECHCalifornia Institute of Technology
      67ILLNLLawrence Livermore National Laboratory
      68IEVLOCEvent location (computer program)
      69IJSOPJoint Seismic Observation Program
      70IUSERThe user
      71IUNKNOWNUnknown

    26. ibody

      Body/spheroid definition used to calculate distances.
      ValueTypeNameSemi-major axis (a [m])Inverse Flattening (f)
      -12345UNDEFEarth (Historic)6378160.00.00335293
      98ISUNSun696000000.08.189e-6
      99IMERCURYMercury2439700.00.0
      100IVENUSVenus6051800.00.0
      101IEARTHEarth (WGS84)6378137.00.0033528106647474805
      102IMOONMoon1737400.00.0
      103IMARSMars3396190.00.005886007555525457

    3.8.4. Boolean (4)

    32-bit (1 word, 4 bytes) in-file/8-bit (1 byte) in-memory

    1. leven

      REQUIRED

      Evenly-spaced data flag.

      If true, then data is evenly spaced.

    2. lpspol

      Station polarity flag.

      If true, then station has positive-polarity—it follows the left-hand -convention (for example, North-East-Up [NEZ]).

    3. lovrok

      File overwrite flag.

      If true, then it’s okay to overwrite the file.

    4. lcalda

      Calculate geometry flag.

      If true, then calculate dist, az, baz, and gcarc from stla, stlo, -evla, and evlo.

    3.8.5. String (23)

    32/64-bit (2/4 words, 8/16 bytes, 8/16 characters)

    1. kstnm

      Station name.

    2. kevnm

      Event name.

      ∗This is the only four word (16 character) string.

    3. khole

      Nuclear—hole identifier.

      Other—Location identifier (LOCID).

    4. ko

      Text for o.

    5. ka

      Text for a.

    6. kt(0--9)

      Text for t(0--9).

    7. kf

      Text for f.

    8. kuser(0--2)

      Text for the first three of user(0--9).

    9. kdatrd

      Date the data was read onto a computer.

    10. kinst

      Text for iinst.

    3.8.6. Data (2)

    32-bit (2 words, 8 bytes) in-file/64-bit (4 words, 16 bytes) in-memory

    Stored as floating-point (32-bit) values in SAC-files; stored as -double-precision in memory.

    1. data1

      The first data vector---always present in a SAC-file and begins at word 158.

    2. data2

      The second data vector---conditionally present and begins after data1.

      Required if leven is false, or if iftype is spectral/XY/XYZ.

    4. Notes

    4.1. Why C++20 and not C++23

    Compiler restrictions—C++23 support requires GCC-13+ and Clang-16+. Many +SAC-file version.

    1. delta

      Increment between evenly spaced samples (\(\Delta t\) for timeseries, \(\Delta f\) +or \(\Delta\omega\) for spectra).

    2. b

      First value (begin) of independent variable (\(t_{0}\)).

    3. e

      Final value (end) of independent variable (\(t_{max}\)).

    4. o

      Event origin time, in seconds relative to the reference time.

    5. a

      Event first arrival time, in seconds relative to the reference time.

    6. t(0--9)

      User defined time values, in seconds relative to the reference time.

    7. f

      Event end (fini) time, in seconds relative to the reference time.

    8. stla

      Station latitude in decimal degrees, N/S–positive/negative.

      sac-format automatically enforces \(\mathrm{stla}\in[-90, 90]\).

    9. stlo

      Station longitude in decimal degrees, E/W–positive/negative.

      sac-format automatically enforces \(\mathrm{stlo}\in[-180, 180]\).

    10. evla

      Event latitude in decimal degrees, N/S–positive/negative.

      sac-format automatically enforces \(\mathrm{evla}\in[-90, 90]\).

    11. evlo

      Event longitude in decimal degrees, E/W–positive/negative.

      sac-format automatically enforces \(\mathrm{evlo}\in[-180, 180]\).

    12. sb

      Original (saved) b value.

    13. sdelta

      Original (saved) delta value.

    3.8.3. Integer (26)

    32-bit (1 word, 4 bytes)

    1. nzyear

      Reference time GMT year.

    2. nzjday

      Reference time GMT day-of-year (often called Julian Date) (1–366).

    3. nzhour

      Reference time GMT hour (00–23).

    4. nzmin

      Reference time GMT minute (0–59).

    5. nzsec

      Reference time GMT second (0–59).

    6. nzmsec

      Reference time GMT Millisecond (0–999).

    7. nvhdr

      SAC-file version.
      VersionDescription
      v7Footer (2020+, sac 102.0+)
      v6No footer (pre-2020, sac 101.6a-)

    8. norid

      Origin ID.

    9. nevid

      Event ID.

    10. npts

      Number of points in data.

    11. nsnpts

      Original (saved) npts.

    12. nwfid

      Waveform ID.

    13. nxsize

      Spectral-only equivalent of npts (length of spectrum).

    14. nysize

      Spectral-only, width of spectrum.

    15. iftype

      File type.
      ValueTypeDescription
      01ITIMETime-series
      02IRLIMSpectral (real/imaginary)
      03IAMPHSpectral (amplitude/phase)
      04IXYGeneral XY file
      ??IXYZ∗General XYZ file

      ∗Value not listed in the standard.

    16. idep

      Dependent variable type.
      ValueTypeDescription
      05IUNKNUnknown
      06IDISPDisplacement (nm)
      07IVELVelocity \(\mathrm{\left(\frac{nm}{s}\right)}\)
      08IACCAcceleration \(\mathrm{\left(\frac{nm}{s^{2}}\right)}\)
      50IVOLTSVelocity (volts)

    17. iztype

      Reference time equivalent.
      ValueTypeDescription
      05IUNKNUnknown
      09IBRecording start time
      10IDAYMidnight reference GMT day
      11IOEvent origin time
      12IAFirst arrival time
      13–22IT(0–9)User defined time (t) pick

    18. iinst

      Recording instrument type.

      Not used by SAC—free for other purposes.

    19. istreg

      Station geographic region.

      Not used by SAC—free for other purposes.

    20. ievreg

      Event geographic region.

      Not used by SAC—free for other purposes.

    21. ievtyp

      Event type.
      ValueTypeDescription
      05IUNKNUnknown
      11IOOther source of known origin
      37INUCLNuclear
      38IPRENNuclear pre-shot
      39IPOSTNNuclear post-shot
      40IQUAKEEarthquake
      41IPREQForeshock
      42IPOSTQAftershock
      43ICHEMChemical explosion
      44IOTHEROther
      72IQBQuarry/mine blast—confirmed by quarry/mine
      73IQB1Quarry/mine blast—designed shot info-ripple fired
      74IQB2Quarry/mine blast—observed shot info-ripple fired
      75IQBXQuarry/mine blast—single shot
      76IQMTQuarry/mining induced events—tremor and rockbursts
      77IEQEarthquake
      78IEQ1Earthquake in a swarm or in an aftershock sequence
      79IEQ2Felt earthquake
      80IMEMarine explosion
      81IEXOther explosion
      82INUNuclear explosion
      83INCNuclear cavity collapse
      85ILLocal event of unknown origin
      86IRRegion event of unknown origin
      87ITTeleseismic event of unknown origin
      88IUUndetermined/conflicting information

    22. iqual

      Quality of data.
      ValueTypeDescription
      44IOTHEROther
      45IGOODGood
      46IGLCHGlitches
      47IDROPDropouts
      48ILOWSNLow signal-to-noise ratio

      Not used by SAC—free for other purposes.

    23. isynth

      Synthetic data flag.
      ValueTypeDescription
      49IRLDATAReal data
      XXSynthetic

      ∗Values and types not listed in the standard.

    24. imagtyp

      Magnitude type.
      ValueTypeDescription
      52IMBBody-wave magnitude (\(M_{b}\))
      53IMSSurface-wave magnitude (\(M_{s}\))
      54IMLLocal magnitude (\(M_{l}\))
      55IMWMoment magnitude (\(M_{w}\))
      56IMDDuration magnitude (\(M_{d}\))
      57IMXUser-defined magnitude (\(M_{x}\))

    25. imagsrc

      Source of magnitude information.
      ValueTypeDescription
      58INEICNational Earthquake Information Center
      61IPDEPreliminary Determination of Epicenter
      62IISCInternation Seismological Centre
      63IREBReviewed Event Bulletin
      64IUSGSU.S. Geological Survey
      65IBRKUC Berkeley
      66ICALTECHCalifornia Institute of Technology
      67ILLNLLawrence Livermore National Laboratory
      68IEVLOCEvent location (computer program)
      69IJSOPJoint Seismic Observation Program
      70IUSERThe user
      71IUNKNOWNUnknown

    26. ibody

      Body/spheroid definition used to calculate distances.
      ValueTypeNameSemi-major axis (a [m])Inverse Flattening (f)
      -12345UNDEFEarth (Historic)6378160.00.00335293
      98ISUNSun696000000.08.189e-6
      99IMERCURYMercury2439700.00.0
      100IVENUSVenus6051800.00.0
      101IEARTHEarth (WGS84)6378137.00.0033528106647474805
      102IMOONMoon1737400.00.0
      103IMARSMars3396190.00.005886007555525457

    3.8.4. Boolean (4)

    32-bit (1 word, 4 bytes) in-file/8-bit (1 byte) in-memory

    1. leven

      REQUIRED

      Evenly-spaced data flag.

      If true, then data is evenly spaced.

    2. lpspol

      Station polarity flag.

      If true, then station has positive-polarity—it follows the left-hand +convention (for example, North-East-Up [NEZ]).

    3. lovrok

      File overwrite flag.

      If true, then it’s okay to overwrite the file.

    4. lcalda

      Calculate geometry flag.

      If true, then calculate dist, az, baz, and gcarc from stla, stlo, +evla, and evlo.

    3.8.5. String (23)

    32/64-bit (2/4 words, 8/16 bytes, 8/16 characters)

    1. kstnm

      Station name.

    2. kevnm

      Event name.

      ∗This is the only four word (16 character) string.

    3. khole

      Nuclear—hole identifier.

      Other—Location identifier (LOCID).

    4. ko

      Text for o.

    5. ka

      Text for a.

    6. kt(0--9)

      Text for t(0--9).

    7. kf

      Text for f.

    8. kuser(0--2)

      Text for the first three of user(0--9).

    9. kdatrd

      Date the data was read onto a computer.

    10. kinst

      Text for iinst.

    3.8.6. Data (2)

    32-bit (2 words, 8 bytes) in-file/64-bit (4 words, 16 bytes) in-memory

    Stored as floating-point (32-bit) values in SAC-files; stored as +double-precision in memory.

    1. data1

      The first data vector---always present in a SAC-file and begins at word 158.

    2. data2

      The second data vector---conditionally present and begins after data1.

      Required if leven is false, or if iftype is spectral/XY/XYZ.

    4. Notes

    4.1. Why C++20 and not C++23

    Compiler restrictions—C++23 support requires GCC-13+ and Clang-16+. Many systems, still use GCC-12 and Clang-15—which has near complete support for C++20.

    sac-format strives for accessibility, modernity, safety, and speed—C++20 provides the best fit.

    Author: Alexander R. Blanchette

    Validate

    \ No newline at end of file diff --git a/docs/sac-format_manual.pdf b/docs/sac-format_manual.pdf index 490354968362ba675d74138563d4a8518b232399..c582cb567d9055efaf48d3f701df58c1bc7c25b2 100644 GIT binary patch delta 51623 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, then leven must be ~true~ (evenly sampled data). Therefore, if +leven is made ~false~ in this scenario (unevenly sampled data) then iftype becomes +unset\ast{}. + +If changing leven makes data2 legal\ast{}\ast{}, then data2 is resized to have +=npts= zeros. + +\ast{} The SAC format defines the unset values for all data-types. For integers +(like iftype) it is the integer value ~-12345~. + +\ast{}\ast{} 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\ast{}, then data2 is resized to have =npts= zeros. + +\ast{} 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. *** Internal Structure The SAC-trace stores the data internally in a series of pre-allocated diff --git a/src/sac_format.cpp b/src/sac_format.cpp index 2250663..024a812 100644 --- a/src/sac_format.cpp +++ b/src/sac_format.cpp @@ -930,7 +930,11 @@ void Trace::nevid(const int input) noexcept { ints[sac_map.at(name::nevid)] = input; } void Trace::npts(const int input) noexcept { - ints[sac_map.at(name::npts)] = input; + if ((input >= 0) || (input == unset_int)) { + ints[sac_map.at(name::npts)] = input; + const size_t size{static_cast(input >= 0 ? input : 0)}; + resize_data(size); + } } void Trace::nsnpts(const int input) noexcept { ints[sac_map.at(name::nsnpts)] = input; @@ -946,6 +950,12 @@ void Trace::nysize(const int input) noexcept { } void Trace::iftype(const int input) noexcept { ints[sac_map.at(name::iftype)] = input; + const int size{npts() >= 0 ? npts() : 0}; + // Uneven 2D data not supported as not in specification + if ((input > 1) && !leven()) { + leven(true); + } + resize_data2(size); } void Trace::idep(const int input) noexcept { ints[sac_map.at(name::idep)] = input; @@ -983,6 +993,12 @@ void Trace::ibody(const int input) noexcept { // Bools void Trace::leven(const bool input) noexcept { bools[sac_map.at(name::leven)] = input; + const int size{npts() >= 0 ? npts() : 0}; + // Uneven 2D data not supported since not in specification + if (!input && (iftype() > 1)) { + iftype(unset_int); + } + resize_data2(size); } void Trace::lpspol(const bool input) noexcept { bools[sac_map.at(name::lpspol)] = input; @@ -1066,9 +1082,59 @@ void Trace::kinst(const std::string &input) noexcept { // Data void Trace::data1(const std::vector &input) noexcept { data[sac_map.at(name::data1)] = input; + // Propagate change as needed + size_t size{data1().size()}; + size = (((size == 0) && (npts() == unset_int)) ? unset_int : size); + if (static_cast(size) != npts()) { + npts(static_cast(size)); + } } void Trace::data2(const std::vector &input) noexcept { data[sac_map.at(name::data2)] = input; + // Proagate change as needed + size_t size{data2().size()}; + size = (((size == 0) && (npts() == unset_int)) ? unset_int : size); + // Need to make sure this is legal + // If positive size and not-legal, make spectral + if (size > 0) { + // If not legal, make spectral + if (leven() && (iftype() <= 1)) { + iftype(2); + } + // If legal and different from npts, update npts + if ((!leven() || (iftype() > 1)) && (static_cast(size) != npts())) { + npts(static_cast(size)); + } + } +} + +void Trace::resize_data1(const size_t size) noexcept { + if (size != data1().size()) { + std::vector new_data1{data1()}; + new_data1.resize(size, 0.0); + data1(new_data1); + } +} + +void Trace::resize_data2(const size_t size) noexcept { + // Data2 is legal + if (!leven() || (iftype() > 1)) { + if (size != data2().size()) { + std::vector new_data2{data2()}; + new_data2.resize(size, 0.0); + data2(new_data2); + } + } else { + if (!data2().empty()) { + std::vector new_data2{}; + data2(new_data2); + } + } +} + +void Trace::resize_data(const size_t size) noexcept { + resize_data1(size); + resize_data2(size); } //------------------------------------------------------------------------------ // Read diff --git a/src/sac_format.hpp b/src/sac_format.hpp index f63849c..830c68b 100644 --- a/src/sac_format.hpp +++ b/src/sac_format.hpp @@ -737,6 +737,9 @@ class Trace { void calc_az() noexcept; void calc_baz() noexcept; bool geometry_set() const noexcept; + void resize_data1(size_t size) noexcept; + void resize_data2(size_t size) noexcept; + void resize_data(size_t size) noexcept; // Objects // cppcheck-suppress unusedStructMember std::array floats{}; diff --git a/src/utests.cpp b/src/utests.cpp index 941706a..f15cf0c 100644 --- a/src/utests.cpp +++ b/src/utests.cpp @@ -870,6 +870,244 @@ TEST_CASE("Trace Equality") { } } +TEST_CASE("Linked Headers") { + SECTION("LEven") { + Trace trace{}; + // Even non-2D data + trace.leven(true); + trace.iftype(1); + trace.npts(10); + REQUIRE(trace.leven() == true); + REQUIRE(trace.iftype() == 1); + REQUIRE(trace.data2().size() == 0); + // Uneven data + trace.leven(false); + REQUIRE(trace.iftype() == 1); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + // Return to even data + trace.leven(true); + REQUIRE(trace.iftype() == 1); + REQUIRE(trace.data2().size() == 0); + // Spectral even + trace.iftype(2); + REQUIRE(trace.iftype() == 2); + REQUIRE(trace.leven() == true); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + // Uneven + trace.leven(false); + REQUIRE(trace.iftype() == unset_int); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + // Return to even + trace.leven(true); + REQUIRE(trace.iftype() == unset_int); + REQUIRE(trace.data2().size() == 0); + } + SECTION("IFType") { + Trace trace{}; + // Even non-2D data + trace.leven(true); + trace.iftype(1); + trace.npts(10); + REQUIRE(trace.leven() == true); + REQUIRE(trace.iftype() == 1); + REQUIRE(trace.data2().size() == 0); + // Spectral data + trace.iftype(2); + REQUIRE(trace.leven() == true); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + // Return to even non-2D data + trace.iftype(1); + REQUIRE(trace.leven() == true); + REQUIRE(trace.data2().size() == 0); + } + SECTION("Npts") { + SECTION("Without Data2") { + Trace trace{}; + // Even non-2D data + trace.leven(true); + trace.iftype(1); + trace.npts(0); + REQUIRE(trace.npts() == 0); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == 0); + SECTION("Npts 10") { + trace.npts(10); + REQUIRE(trace.npts() == 10); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == 0); + } + SECTION("Grow 10, shrink 5") { + trace.npts(10); + trace.npts(5); + REQUIRE(trace.npts() == 5); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == 0); + } + } + SECTION("With Data2") { + SECTION("Uneven timeseries") { + Trace trace{}; + trace.leven(false); + trace.iftype(1); + trace.npts(0); + REQUIRE(trace.npts() == 0); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + SECTION("Npts 10") { + trace.npts(10); + REQUIRE(trace.npts() == 10); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + } + SECTION("Grow 10, shrink 5") { + trace.npts(10); + trace.npts(5); + REQUIRE(trace.npts() == 5); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + } + } + SECTION("Even Spectral") { + Trace trace{}; + trace.leven(true); + trace.iftype(2); + trace.npts(0); + REQUIRE(trace.npts() == 0); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + SECTION("Npts 10") { + trace.npts(10); + REQUIRE(trace.npts() == 10); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + } + SECTION("Grow 10, shrink 5") { + trace.npts(10); + trace.npts(5); + REQUIRE(trace.npts() == 5); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + } + } + } + } + SECTION("Data1") { + SECTION("Even timeseries") { + Trace trace{}; + trace.leven(true); + trace.iftype(1); + trace.npts(0); + REQUIRE(trace.npts() == 0); + REQUIRE(trace.data1().size() == 0); + REQUIRE(trace.data2().size() == 0); + // Change the vector + std::vector new_data1{}; + new_data1.resize(10); + trace.data1(new_data1); + REQUIRE(trace.npts() == 10); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == 0); + } + SECTION("Uneven timeseries") { + Trace trace{}; + trace.leven(false); + trace.iftype(1); + trace.npts(0); + REQUIRE(trace.npts() == 0); + REQUIRE(trace.data1().size() == 0); + REQUIRE(trace.data2().size() == 0); + // Change the vector + std::vector new_data1{}; + new_data1.resize(10); + trace.data1(new_data1); + REQUIRE(trace.npts() == 10); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + } + SECTION("Spectral") { + Trace trace{}; + trace.leven(true); + trace.iftype(2); + trace.npts(0); + REQUIRE(trace.npts() == 0); + REQUIRE(trace.data1().size() == 0); + REQUIRE(trace.data2().size() == 0); + // Change the vector + std::vector new_data1{}; + new_data1.resize(10); + trace.data1(new_data1); + REQUIRE(trace.npts() == 10); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + } + } + SECTION("Data2") { + SECTION("Even timeseries") { + Trace trace{}; + trace.leven(true); + trace.iftype(1); + trace.npts(0); + REQUIRE(trace.npts() == 0); + REQUIRE(trace.data1().size() == 0); + REQUIRE(trace.data2().size() == 0); + // Change the vector + std::vector new_data2{}; + new_data2.resize(15); + trace.data2(new_data2); + REQUIRE(trace.npts() == 15); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + // Remove data2 + trace.iftype(1); + REQUIRE(trace.npts() == 15); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == 0); + } + SECTION("Uneven timeseries") { + Trace trace{}; + trace.leven(false); + trace.iftype(1); + trace.npts(0); + REQUIRE(trace.npts() == 0); + REQUIRE(trace.data1().size() == 0); + REQUIRE(trace.data2().size() == 0); + // Change the vector + std::vector new_data2{}; + new_data2.resize(25); + trace.data2(new_data2); + REQUIRE(trace.npts() == 25); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + // Remove data2 + trace.leven(true); + REQUIRE(trace.npts() == 25); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == 0); + } + SECTION("Spectral") { + Trace trace{}; + trace.leven(true); + trace.iftype(2); + trace.npts(0); + REQUIRE(trace.npts() == 0); + REQUIRE(trace.data1().size() == 0); + REQUIRE(trace.data2().size() == 0); + // Change the vector + std::vector new_data2{}; + new_data2.resize(12); + trace.data2(new_data2); + REQUIRE(trace.npts() == 12); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == static_cast(trace.npts())); + // Remove data2 + trace.iftype(1); + REQUIRE(trace.npts() == 12); + REQUIRE(trace.data1().size() == static_cast(trace.npts())); + REQUIRE(trace.data2().size() == 0); + } + } +} + TEST_CASE("Unsetting Trace") { Trace trace = gen_fake_trace(); unset_trace(&trace); diff --git a/todo.org b/todo.org index 1d8f267..31210ae 100644 --- a/todo.org +++ b/todo.org @@ -7,18 +7,24 @@ later. Maybe call it =Seismogram=, or for less typing =Trace=. Then it'd be =SAC::Trace= which is nice. ** DONE SacStream constructor should use std::filesystem::path not std::string -** TODO Testing :testing: +** DONE Testing :testing: *** DONE Move Unit tests from PsSp :unit: *** DONE Benchmarks :benchmark: *** DONE data2 read/write :unit: *** DONE not =equal_within_tolerance= :unit: *** DONE =legacy_write= read/write :unit: -*** TODO Corrupt sac-files +*** DONE Corrupt sac-files **** DONE Insufficient header **** DONE Insufficient Data1 **** DONE Insuficcient Data2 **** DONE Insufficient footer -**** TODO File continues past expected end +**** DONE File continues past expected end +*** DONE Linked headers +**** DONE npts +**** DONE leven +**** DONE iftype +**** DONE data1 +**** DONE data2 ** TODO New functionality :functionality: *** Incorporate Ellipticity in geometric calculations @@ -35,6 +41,17 @@ lines ([[https://en.wikipedia.org/wiki/Geographical_distance#Lambert's_formula_f *** DONE Azimuth calculation Assumes spherical earth +*** DONE Ensure NPTS updates when data1/data2 updates +This would aid the user in avoiding writing out sac-files that could then not be +read in. The issue is, let's say the user wants to include data2, I cannot +simply assume level(false) or iftype(value>1). There needs to be a mechanism +that enforces a specification change in the data2 setter. + +That also means that the leven and iftype() setters need a mechanism whereby +leven must be true for iftype(>1), and if leven is false then iftype(<=1). If +leven(false) and iftype(<1), but data2 exists, clear it. +**** DONE data1 and data2 ought to have same size if data2 exists (changing one changes the other and npts) +**** DONE when npts changes, size of data1 and data2 should change *** TODO ASCII read/write support :ascii: **** TODO Fortran style text files. ***** TODO Read in From 3370baf281aea3ad151efe0fe79b40950b62607f Mon Sep 17 00:00:00 2001 From: Alexander Blanchette Date: Fri, 8 Dec 2023 14:45:04 -0800 Subject: [PATCH 2/2] Write/Read tests while juggling linked headers to ensure no corrupt files being written. --- docs/index.html | 138 ++++++++++++++++++------------------- docs/sac-format_manual.pdf | Bin 122748 -> 122739 bytes src/docs/index.org | 7 +- src/utests.cpp | 59 +++++++++++++++- 4 files changed, 133 insertions(+), 71 deletions(-) diff --git a/docs/index.html b/docs/index.html index 4cb52f0..0a59631 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,54 +1,54 @@ sac-format -

    sac-format
    C++20 SAC-file Library
    V0.4.0
    User Manual

    Windows 2022 Build Status +

    sac-format
    C++20 SAC-file Library
    V0.4.0
    User Manual

    Windows 2022 Build Status Ubuntu 22.04 Build Status macOS 13 Build Status Code Coverage Codacy grade CodeFactor -CPP-Linter Results

    1. Introduction

    sac-format is a single-header statically linked library designed to make working +CPP-Linter Results

    1. Introduction

    sac-format is a single-header statically linked library designed to make working with binary SAC-files as easy as possible. Written in C++20, it follows a modern and easy to read programming-style while providing the high performance brought -by C++.

    sac-format’s developed on GitHub!

    Download an offline version of the documentation (PDF).

    1.1. Why sac-format

    sac-format is Free and Open Source Software (FOSS) released under the MIT +by C++.

    sac-format’s developed on GitHub!

    Download an offline version of the documentation (PDF).

    1.1. Why sac-format

    sac-format is Free and Open Source Software (FOSS) released under the MIT license. Anyone can use it, for any purpose (including proprietary software), anywhere in the world. sac-format is operating system agnostic and confirmed -working on Windows, macOS, and Linux systems.

    1.1.1. Safe

    sac-format is safe—it conforms to a strict set of C++ programming guidelines, +working on Windows, macOS, and Linux systems.

    1.1.1. Safe

    sac-format is safe—it conforms to a strict set of C++ programming guidelines, chosen to ensure safe code-execution. The guideline conformance list is in cpp-linter.yml and can be cross-referenced against this master list. Results of conformance checking are here.

    Testing is an important part of software development; the sac-format library is extensively tested using the Catch2 testing framework. Everything from low-level binary conversions to high-level Trace reading/writing are tested and confirmed -working. Check and run the tests yourself. See the Testing section for more -information.

    1.1.2. Fast

    sac-format is fast—it’s written in C++, carefully optimized, and extensively +working. Check and run the tests yourself. See the Testing section for more +information.

    1.1.2. Fast

    sac-format is fast—it’s written in C++, carefully optimized, and extensively benchmarked. You can run the benchmarks yourself to find out how sac-format -performs on your system. See the Benchmarking section for more information.

    1.1.3. Easy

    sac-format is easy—single-header makes integration in any project simple. +performs on your system. See the Benchmarking section for more information.

    1.1.3. Easy

    sac-format is easy—single-header makes integration in any project simple. Building is a breeze with CMake, even on different platforms. Object-oriented -design makes use easy and intuitive. See the Quickstart section to get up and -running.

    1.1.4. Small

    sac-format is small—in total (header + implementation–excluding comments) the +design makes use easy and intuitive. See the Quickstart section to get up and +running.

    1.1.4. Small

    sac-format is small—in total (header + implementation–excluding comments) the library is under 2100∗ lines of code. Small size opens the door to using on any sort of hardware (old or new) and makes it easy to expand upon.

    ∗ This value includes only the library, excluding all testing/benchmarking and example codes. Including utests.cpp, benchmark.cpp, util.hpp, the example -program (list_sac), and sac-format totals just under 5100 lines of code.

    1.1.5. Documented

    sac-format is extensively documented—both online and in the code. Nothing’s +program (list_sac), and sac-format totals just over 5100 lines of code.

    1.1.5. Documented

    sac-format is extensively documented—both online and in the code. Nothing’s hidden—nothing’s obscured. Curious how something works? Check the -documentation and in-code comments.

    1.1.6. Transparent

    sac-format is transparent—all analysis and coverage information is publicly -available online.

    1.1.7. Trace Class

    sac-format includes the Trace class for seismic traces, providing high-level +documentation and in-code comments.

    1.1.6. Transparent

    sac-format is transparent—all analysis and coverage information is publicly +available online.

    1.1.7. Trace Class

    sac-format includes the Trace class for seismic traces, providing high-level object-oriented abstraction to seismic data. With the Trace class, you don’t need to worry about manually reading SAC-files word-by-word. It’s compatible with v6 and v7 SAC-files and can automatically detect the version upon reading. File output defaults to v7 SAC-files and there is a legacy_write function for v6 -output.

    1.1.8. Low-Level I/O

    If you want to roll your own SAC-file processing workflow you can use the +output.

    1.1.8. Low-Level I/O

    If you want to roll your own SAC-file processing workflow you can use the low-level I/O functionality built into sac-format. All functions tested and -confirmed working—they’re used to build the Trace class!

    2. Quickstart

    2.1. Manual Instructions

    2.1.1. Build Instructions

    Building is as easy as cloning the repository, running CMake for your preferred -build tool, and then building.

    1. GCC
      git clone https://github.com/arbCoding/sac-format.git
      +confirmed working—they’re used to build the Trace class!

    2. Quickstart

    2.1. Manual Instructions

    2.1.1. Build Instructions

    Building is as easy as cloning the repository, running CMake for your preferred +build tool, and then building.

    1. GCC
      git clone https://github.com/arbCoding/sac-format.git
       cmake --preset gcc-release
       cmake --build ./build/release/gcc
      -
    2. Clang
      git clone https://github.com/arbCoding/sac-format.git
      +
    3. Clang
      git clone https://github.com/arbCoding/sac-format.git
       cmake --preset clang-release
       cmake --build ./build/release/clang
      -

    2.1.2. Use

    To use link to the compiled library (libsac-format.a on Linux/macOS, -libsac-format.lib on Windows) and include src/sac_format.hpp.

    2.2. Example Programs

    2.2.1. list_sac

    list_sac is a command line program that takes a single SAC-file as its input +

    2.1.2. Use

    To use link to the compiled library (libsac-format.a on Linux/macOS, +libsac-format.lib on Windows) and include src/sac_format.hpp.

    2.2. Example Programs

    2.2.1. list_sac

    list_sac is a command line program that takes a single SAC-file as its input argument. It reads the SAC-file and outputs the header/footer information, as -well as the true size of the data1 and data2 vectors.

    2.3. CMake Integration

    To integrate sac-format into your CMake project, add it to your CMakeLists.txt.

    include(FetchContent)
    +well as the true size of the data1 and data2 vectors.

    2.3. CMake Integration

    To integrate sac-format into your CMake project, add it to your CMakeLists.txt.

    include(FetchContent)
     set(FETCHCONTENT_UPDATES_DISCONNECTED TRUE)
     FetchContent_Declare(sac-format
         GIT_REPOSITORY https://github.com/arbCoding/sac-format
    @@ -65,7 +65,7 @@
     
     target_link_libraries_library(your_executable
         PRIVATE sac-format)
    -

    2.4. Example

    2.4.1. Reading and Writing

    #include <filesystem>
    +

    2.4. Example

    2.4.1. Reading and Writing

    #include <filesystem>
     #include <iostream>
     #include <sac_format.hpp>
     
    @@ -86,8 +86,8 @@
         fs::remove(file);
         return EXIT_SUCCESS;
     }
    -

    3. Documentation

    3.1. 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).

    3.1.1. Reading SAC

    SAC-files can be read in by using the parameterized constructor with a +

    3. Documentation

    3.1. 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).

    3.1.1. 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 <filesystem>
     #include <sac_foramt.hpp>
    @@ -97,34 +97,34 @@
       sacfmt::Trace anmo = Trace(my_file);
       return EXIT_SUCCESS;
     }
    -

    3.1.2. Writing SAC

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

    1. v7 files

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

    2. v6 files

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

    3.1.3. Getters and Setters

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

    1. Example Getters
      • trace.npts()
      • trace.data1()
      • trace.kstnm()
    2. Example Setters
      • trace.kevnm("Event 1")
      • trace.evla(32.89)
      • trace.mag(3.21)
    3. Setter rules

      Most of the setters are only constrained by the parameter type +

    3.1.2. Writing SAC

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

    1. v7 files

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

    2. v6 files

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

    3.1.3. Getters and Setters

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

    1. Example Getters
      • trace.npts()
      • trace.data1()
      • trace.kstnm()
    2. Example Setters
      • trace.kevnm("Event 1")
      • trace.evla(32.89)
      • trace.mag(3.21)
    3. 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.

      1. Required for sanity

        Rules here are required because the sac-format library assumes them (not +constrained by additional rules.

        1. 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.

          1. stla(input)

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

          2. stlo(input)

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

          3. evla(input)

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

          4. evlo(input)

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

        2. Require 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.

          1. npts(input)

            Because npts defines the size of the data vectors, changing this value will +automatically imposes these rules.

            1. stla(input)

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

            2. stlo(input)

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

            3. evla(input)

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

            4. evlo(input)

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

          2. Require 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.

            1. 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.

            2. leven(input)

              Changing the value of leven potentially changes the legality of data2, it also +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.

            3. 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 resized 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.

            4. 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 +(like iftype) it is the integer value -12345.

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

            5. 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.

            6. 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.

            7. data2(input)

              If the size of data2 is changed to be larger than 0 and it is illegal, it is +data).

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

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

            8. 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.

            9. 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.

    3.1.4. Internal Structure

    The SAC-trace stores the data internally in a series of pre-allocated -std::array (<array>) container objects. Getters and setters access these via -a lookup table. The internal components are below:

    1. Lookup Table

      sac_map

    2. floats array
    3. doubles array
    4. ints array
    5. bools array
    6. strings array
    7. data array

    3.1.5. Convenience Methods

    • calc_geometry

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

    trace.stla(45.3);
    +unaffected.

    3.1.4. Internal Structure

    The SAC-trace stores the data internally in a series of pre-allocated +std::array (<array>) container objects. Getters and setters access these via +a lookup table. The internal components are below:

    1. Lookup Table

      sac_map

    2. floats array
    3. doubles array
    4. ints array
    5. bools array
    6. strings array
    7. data array

    3.1.5. 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);
    @@ -137,8 +137,8 @@
     
    • 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()};
    -

    3.1.6. 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.

    3.2. Convenience Functions

    • degrees_to_radians

    Convert decimal degrees to radians.

    double radians{sacfmt::degrees_to_radians(degrees)};
    +

    3.1.6. 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.

    3.2. Convenience Functions

    • degrees_to_radians

    Convert decimal degrees to radians.

    double radians{sacfmt::degrees_to_radians(degrees)};
     
    • radians_to_degrees

    Convert radians to decimal degrees.

    double degrees{sacfmt::radians_to_degrees(radians)};
     
    • gcarc

    Calculate great-circle arc distance (spherical planet).

    double gcarc{sacfmt::gcarc(latitude1, longitude1, latitude2, longitude2)};
     
    • azimuth

    Calculate azimuth between two points (spherical planet).

    double azimuth{sacfmt::azimuth(latitude2, longitude2, latitude1, longitude1)};
    @@ -147,64 +147,64 @@
     
    • limit_180

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

    double degrees_limited{sacfmt::limit_180(degrees)};
     
    • limit_90

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

    double degrees_limited{sacfmt::limit_90(degrees)};
    -

    3.3. Low-Level I/O

    Low-level I/O functions are discussed below.

    1. Binary conversion
      1. int_to_binary and binary_to_int

        Conversion pair for binary representation of integer values.

        const int input{10};
        +

    3.3. Low-Level I/O

    Low-level I/O functions are discussed below.

    1. Binary conversion
      1. 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)
         sacfmt::word_one binary{sacfmt::int_to_binary(input)};
         const int output{sacfmt::binary_to_int(binary)};
         std::cout << (input == output) << '\n';
        -
      2. float_to_binary and binary_to_float

        Conversion pair for binary representation of floating-point values.

        const float input{5F};
        +
      3. float_to_binary and binary_to_float

        Conversion pair for binary representation of floating-point values.

        const float input{5F};
         sacfmt::word_one binary{sacfmt::float_to_binary(input)};
         const float output{sacfmt::binary_to_float(binary)};
         std::cout << (input == output) << '\n';
        -
      4. double_to_binary and binary_to_double

        Conversion pair for binary representation of double-precision values.

        const double input{1e5};
        +
      5. 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)
         sacfmt::word_two binary{sacfmt::double_to_binary(input)};
         const double output{sacfmt::binary_to_double(binary)};
         std::cout << (input == output) << '\n';
        -
      6. string_to_binary and binary_to_string

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

        const std::string input{"NmlStrng"};
        +
      7. string_to_binary and binary_to_string

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

        const std::string input{"NmlStrng"};
         sacfmt::word_two binary{sacfmt::string_to_binary(input)};
         const std::string output{sacfmt::binary_to_string(binary)};
         std::cout << (input == output) << '\n';
        -
      8. long_string_to_binary and binary_to_long_string

        Conversion pair for binary representation of four-word (only kstnm) string +

  • 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)
     sacfmt::word_four binary{sacfmt::long_string_to_binary(input)};
     const std::string output{sacfmt::binary_to_long_string(binary)};
     std::cout << (input == output) << '\n';
    -
  • Reading/Writing

    NOTE that care must be taken when using them to ensure that safe input is +

  • 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.

    1. 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).

    2. 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).

    3. write_words

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

  • Utility
    1. concat_words

      Concatenates words taking into account the system endianness.

    2. bits_string and string_bits

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

    3. remove_leading_spaces and remove_trailing_spaces

      Remove leading and trailing blank spaces from strings assuming ASCII convention +necessarily ensure safety.

      1. 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).

      2. 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).

      3. write_words

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

    4. Utility
      1. concat_words

        Concatenates words taking into account the system endianness.

      2. bits_string and string_bits

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

      3. 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).

      4. string_cleaning

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

      5. prep_string

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

      6. equal_within_tolerance

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

  • 3.4. Testing

    utests.cpp contains the unit- and integration-tests, using Catch2. Test coverage +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).

  • 3.4. Testing

    utests.cpp contains the unit- and integration-tests, using Catch2. Test coverage details are visible on CodeCov.io and Codacy.com. All tests can be locally-run -to ensure full functionality and compliance.

    3.4.1. Errors only

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

    3.4.2. Full output

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

    3.4.3. Compact output

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

    3.4.4. Additional options

    To see additional options, run utests -?.

    3.5. Benchmarking

    benchmark.cpp contains the benchmarks. Running it locally will provide +to ensure full functionality and compliance.

    3.4.1. Errors only

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

    3.4.2. Full output

    By passing the --success flag (utests --success) you can see the full results of +all tests.

    3.4.3. Compact output

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

    3.4.4. Additional options

    To see additional options, run utests -?.

    3.4.5. Using ctest

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

    3.5. 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 -?.

    3.6. Source File List

    3.6.1. Core

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

    1. sac_format.hpp

      Interface—function declarations and constants.

    2. sac_format.cpp

      Implementation—function details.

    3.6.2. Testing and Benchmarking

    1. util.hpp

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

    2. utests.cpp
    3. benchmark.cpp

    3.6.3. Example programs

    1. list_sac.cpp

    3.7. Dependencies

    3.7.1. Automatic (CMake)

    1. Xoshiro-cpp v1.12.0 (testing and benchmarking)
    2. Catch2 v3.4.0 (testing and benchmarking)

    3.8. SAC-file format

    The official and up-to-date documentation for the SAC-file format is available +I/O function and build up to Trace reading, writing, and equality comparison.

    To view available optional flags, run becnhmark -?.

    3.6. Source File List

    3.6.1. Core

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

    1. sac_format.hpp

      Interface—function declarations and constants.

    2. sac_format.cpp

      Implementation—function details.

    3.6.2. Testing and Benchmarking

    1. util.hpp

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

    2. utests.cpp
    3. benchmark.cpp

    3.6.3. Example programs

    1. list_sac.cpp

    3.7. Dependencies

    3.7.1. Automatic (CMake)

    1. Xoshiro-cpp v1.12.0 (testing and benchmarking)
    2. Catch2 v3.4.0 (testing and benchmarking)

    3.8. SAC-file format

    The official and up-to-date documentation for the SAC-file format is available from the EarthScope Consortium (formerly IRIS/UNAVCO) here. The following subsections constitute my notes on the format. Below is a quick guide—all credit for the creation of, and documentation for, the SAC file-format belongs -to its developers and maintainers (details here).

    3.8.1. Floating-point (39)

    32-bit (1 word, 4 bytes)

    1. depmin

      Minimum value of the dependent variable -(displacement/velocity/acceleration/volts/counts).

    2. depmen

      Mean value of the dependent variable.

    3. depmax

      Maximum value of the dependent variable.

    4. odelta

      Modified (observational) value of delta.

    5. resp(0--9)

      Instrument response parameters (poles, zeros, and a constant).

      Not used by SAC—they’re free for other purposes.

    6. stel

      Station elevation in meters above sea level (m.a.s.l).

      Not used by SAC—free for other purposes.

    7. stdp

      Station depth in meters below surface (borehole/buried vault).

      Not used by SAC—free for other purposes.

    8. evel

      Event elevation m.a.s.l.

      Not used by SAC—free for other purposes.

    9. evdp

      Event depth in kilometers (previously meters) below surface.

    10. mag

      Event magnitude.

    11. user(0--9)

      Storage for user-defined values.

    12. dist

      Station–Event distance in kilometers.

    13. az

      Azimuth \(\mathrm{\left(Event \to Station\right)}\), decimal degrees from North.

    14. baz

      Back-azimuth \(\mathrm{\left(Station \to Event\right)}\), decimal degrees from -North.

    15. gcarc

      Station–Event great circle arc-length, decimal degrees.

    16. cmpaz

      Instrument measurement azimuth, decimal degrees from North.
      ValueDirection
      North
      90°East
      180°South
      270°West
      Other1/2/3

    17. cmpinc

      Instrument measurement incident angle, decimal degrees from upward vertical +to its developers and maintainers (details here).

      3.8.1. Floating-point (39)

      32-bit (1 word, 4 bytes)

      1. depmin

        Minimum value of the dependent variable +(displacement/velocity/acceleration/volts/counts).

      2. depmen

        Mean value of the dependent variable.

      3. depmax

        Maximum value of the dependent variable.

      4. odelta

        Modified (observational) value of delta.

      5. resp(0--9)

        Instrument response parameters (poles, zeros, and a constant).

        Not used by SAC—they’re free for other purposes.

      6. stel

        Station elevation in meters above sea level (m.a.s.l).

        Not used by SAC—free for other purposes.

      7. stdp

        Station depth in meters below surface (borehole/buried vault).

        Not used by SAC—free for other purposes.

      8. evel

        Event elevation m.a.s.l.

        Not used by SAC—free for other purposes.

      9. evdp

        Event depth in kilometers (previously meters) below surface.

      10. mag

        Event magnitude.

      11. user(0--9)

        Storage for user-defined values.

      12. dist

        Station–Event distance in kilometers.

      13. az

        Azimuth \(\mathrm{\left(Event \to Station\right)}\), decimal degrees from North.

      14. baz

        Back-azimuth \(\mathrm{\left(Station \to Event\right)}\), decimal degrees from +North.

      15. gcarc

        Station–Event great circle arc-length, decimal degrees.

      16. cmpaz

        Instrument measurement azimuth, decimal degrees from North.
        ValueDirection
        North
        90°East
        180°South
        270°West
        Other1/2/3

      17. cmpinc

        Instrument measurement incident angle, decimal degrees from upward vertical (incident 0° = dip -90°).
        ValueDirection
        Up
        90°Horizontal
        180°Down
        270°Horizontal

        NOTE: SEED/MINISEED use dip angle, decimal degrees down from horizontal (dip -0° = incident 90°).

      18. xminimum

        Spectral-only equivalent of depmin (\(f_{0}\) or \(\omega_{0}\)).

      19. xmaximum

        Spectral-only equivalent of depmax (\(f_{max}\) or \(\omega_{max}\)).

      20. yminimum

        Spectral-only equivalent of b.

      21. ymaximum

        Spectral-only equivalent of e.

      3.8.2. Double (22)

      64-bit (2 words, 8 bytes)

      NOTE: in the header section these are floats—they’re doubles in the footer +0° = incident 90°).

    18. xminimum

      Spectral-only equivalent of depmin (\(f_{0}\) or \(\omega_{0}\)).

    19. xmaximum

      Spectral-only equivalent of depmax (\(f_{max}\) or \(\omega_{max}\)).

    20. yminimum

      Spectral-only equivalent of b.

    21. ymaximum

      Spectral-only equivalent of e.

    3.8.2. Double (22)

    64-bit (2 words, 8 bytes)

    NOTE: in the header section these are floats—they’re doubles in the footer section of v7 SAC-files. In memory they’re stored as doubles regardless of the -SAC-file version.

    1. delta

      Increment between evenly spaced samples (\(\Delta t\) for timeseries, \(\Delta f\) -or \(\Delta\omega\) for spectra).

    2. b

      First value (begin) of independent variable (\(t_{0}\)).

    3. e

      Final value (end) of independent variable (\(t_{max}\)).

    4. o

      Event origin time, in seconds relative to the reference time.

    5. a

      Event first arrival time, in seconds relative to the reference time.

    6. t(0--9)

      User defined time values, in seconds relative to the reference time.

    7. f

      Event end (fini) time, in seconds relative to the reference time.

    8. stla

      Station latitude in decimal degrees, N/S–positive/negative.

      sac-format automatically enforces \(\mathrm{stla}\in[-90, 90]\).

    9. stlo

      Station longitude in decimal degrees, E/W–positive/negative.

      sac-format automatically enforces \(\mathrm{stlo}\in[-180, 180]\).

    10. evla

      Event latitude in decimal degrees, N/S–positive/negative.

      sac-format automatically enforces \(\mathrm{evla}\in[-90, 90]\).

    11. evlo

      Event longitude in decimal degrees, E/W–positive/negative.

      sac-format automatically enforces \(\mathrm{evlo}\in[-180, 180]\).

    12. sb

      Original (saved) b value.

    13. sdelta

      Original (saved) delta value.

    3.8.3. Integer (26)

    32-bit (1 word, 4 bytes)

    1. nzyear

      Reference time GMT year.

    2. nzjday

      Reference time GMT day-of-year (often called Julian Date) (1–366).

    3. nzhour

      Reference time GMT hour (00–23).

    4. nzmin

      Reference time GMT minute (0–59).

    5. nzsec

      Reference time GMT second (0–59).

    6. nzmsec

      Reference time GMT Millisecond (0–999).

    7. nvhdr

      SAC-file version.
      VersionDescription
      v7Footer (2020+, sac 102.0+)
      v6No footer (pre-2020, sac 101.6a-)

    8. norid

      Origin ID.

    9. nevid

      Event ID.

    10. npts

      Number of points in data.

    11. nsnpts

      Original (saved) npts.

    12. nwfid

      Waveform ID.

    13. nxsize

      Spectral-only equivalent of npts (length of spectrum).

    14. nysize

      Spectral-only, width of spectrum.

    15. iftype

      File type.
      ValueTypeDescription
      01ITIMETime-series
      02IRLIMSpectral (real/imaginary)
      03IAMPHSpectral (amplitude/phase)
      04IXYGeneral XY file
      ??IXYZ∗General XYZ file

      ∗Value not listed in the standard.

    16. idep

      Dependent variable type.
      ValueTypeDescription
      05IUNKNUnknown
      06IDISPDisplacement (nm)
      07IVELVelocity \(\mathrm{\left(\frac{nm}{s}\right)}\)
      08IACCAcceleration \(\mathrm{\left(\frac{nm}{s^{2}}\right)}\)
      50IVOLTSVelocity (volts)

    17. iztype

      Reference time equivalent.
      ValueTypeDescription
      05IUNKNUnknown
      09IBRecording start time
      10IDAYMidnight reference GMT day
      11IOEvent origin time
      12IAFirst arrival time
      13–22IT(0–9)User defined time (t) pick

    18. iinst

      Recording instrument type.

      Not used by SAC—free for other purposes.

    19. istreg

      Station geographic region.

      Not used by SAC—free for other purposes.

    20. ievreg

      Event geographic region.

      Not used by SAC—free for other purposes.

    21. ievtyp

      Event type.
      ValueTypeDescription
      05IUNKNUnknown
      11IOOther source of known origin
      37INUCLNuclear
      38IPRENNuclear pre-shot
      39IPOSTNNuclear post-shot
      40IQUAKEEarthquake
      41IPREQForeshock
      42IPOSTQAftershock
      43ICHEMChemical explosion
      44IOTHEROther
      72IQBQuarry/mine blast—confirmed by quarry/mine
      73IQB1Quarry/mine blast—designed shot info-ripple fired
      74IQB2Quarry/mine blast—observed shot info-ripple fired
      75IQBXQuarry/mine blast—single shot
      76IQMTQuarry/mining induced events—tremor and rockbursts
      77IEQEarthquake
      78IEQ1Earthquake in a swarm or in an aftershock sequence
      79IEQ2Felt earthquake
      80IMEMarine explosion
      81IEXOther explosion
      82INUNuclear explosion
      83INCNuclear cavity collapse
      85ILLocal event of unknown origin
      86IRRegion event of unknown origin
      87ITTeleseismic event of unknown origin
      88IUUndetermined/conflicting information

    22. iqual

      Quality of data.
      ValueTypeDescription
      44IOTHEROther
      45IGOODGood
      46IGLCHGlitches
      47IDROPDropouts
      48ILOWSNLow signal-to-noise ratio

      Not used by SAC—free for other purposes.

    23. isynth

      Synthetic data flag.
      ValueTypeDescription
      49IRLDATAReal data
      XXSynthetic

      ∗Values and types not listed in the standard.

    24. imagtyp

      Magnitude type.
      ValueTypeDescription
      52IMBBody-wave magnitude (\(M_{b}\))
      53IMSSurface-wave magnitude (\(M_{s}\))
      54IMLLocal magnitude (\(M_{l}\))
      55IMWMoment magnitude (\(M_{w}\))
      56IMDDuration magnitude (\(M_{d}\))
      57IMXUser-defined magnitude (\(M_{x}\))

    25. imagsrc

      Source of magnitude information.
      ValueTypeDescription
      58INEICNational Earthquake Information Center
      61IPDEPreliminary Determination of Epicenter
      62IISCInternation Seismological Centre
      63IREBReviewed Event Bulletin
      64IUSGSU.S. Geological Survey
      65IBRKUC Berkeley
      66ICALTECHCalifornia Institute of Technology
      67ILLNLLawrence Livermore National Laboratory
      68IEVLOCEvent location (computer program)
      69IJSOPJoint Seismic Observation Program
      70IUSERThe user
      71IUNKNOWNUnknown

    26. ibody

      Body/spheroid definition used to calculate distances.
      ValueTypeNameSemi-major axis (a [m])Inverse Flattening (f)
      -12345UNDEFEarth (Historic)6378160.00.00335293
      98ISUNSun696000000.08.189e-6
      99IMERCURYMercury2439700.00.0
      100IVENUSVenus6051800.00.0
      101IEARTHEarth (WGS84)6378137.00.0033528106647474805
      102IMOONMoon1737400.00.0
      103IMARSMars3396190.00.005886007555525457

    3.8.4. Boolean (4)

    32-bit (1 word, 4 bytes) in-file/8-bit (1 byte) in-memory

    1. leven

      REQUIRED

      Evenly-spaced data flag.

      If true, then data is evenly spaced.

    2. lpspol

      Station polarity flag.

      If true, then station has positive-polarity—it follows the left-hand -convention (for example, North-East-Up [NEZ]).

    3. lovrok

      File overwrite flag.

      If true, then it’s okay to overwrite the file.

    4. lcalda

      Calculate geometry flag.

      If true, then calculate dist, az, baz, and gcarc from stla, stlo, -evla, and evlo.

    3.8.5. String (23)

    32/64-bit (2/4 words, 8/16 bytes, 8/16 characters)

    1. kstnm

      Station name.

    2. kevnm

      Event name.

      ∗This is the only four word (16 character) string.

    3. khole

      Nuclear—hole identifier.

      Other—Location identifier (LOCID).

    4. ko

      Text for o.

    5. ka

      Text for a.

    6. kt(0--9)

      Text for t(0--9).

    7. kf

      Text for f.

    8. kuser(0--2)

      Text for the first three of user(0--9).

    9. kdatrd

      Date the data was read onto a computer.

    10. kinst

      Text for iinst.

    3.8.6. Data (2)

    32-bit (2 words, 8 bytes) in-file/64-bit (4 words, 16 bytes) in-memory

    Stored as floating-point (32-bit) values in SAC-files; stored as -double-precision in memory.

    1. data1

      The first data vector---always present in a SAC-file and begins at word 158.

    2. data2

      The second data vector---conditionally present and begins after data1.

      Required if leven is false, or if iftype is spectral/XY/XYZ.

    4. Notes

    4.1. Why C++20 and not C++23

    Compiler restrictions—C++23 support requires GCC-13+ and Clang-16+. Many +SAC-file version.

    1. delta

      Increment between evenly spaced samples (\(\Delta t\) for timeseries, \(\Delta f\) +or \(\Delta\omega\) for spectra).

    2. b

      First value (begin) of independent variable (\(t_{0}\)).

    3. e

      Final value (end) of independent variable (\(t_{max}\)).

    4. o

      Event origin time, in seconds relative to the reference time.

    5. a

      Event first arrival time, in seconds relative to the reference time.

    6. t(0--9)

      User defined time values, in seconds relative to the reference time.

    7. f

      Event end (fini) time, in seconds relative to the reference time.

    8. stla

      Station latitude in decimal degrees, N/S–positive/negative.

      sac-format automatically enforces \(\mathrm{stla}\in[-90, 90]\).

    9. stlo

      Station longitude in decimal degrees, E/W–positive/negative.

      sac-format automatically enforces \(\mathrm{stlo}\in[-180, 180]\).

    10. evla

      Event latitude in decimal degrees, N/S–positive/negative.

      sac-format automatically enforces \(\mathrm{evla}\in[-90, 90]\).

    11. evlo

      Event longitude in decimal degrees, E/W–positive/negative.

      sac-format automatically enforces \(\mathrm{evlo}\in[-180, 180]\).

    12. sb

      Original (saved) b value.

    13. sdelta

      Original (saved) delta value.

    3.8.3. Integer (26)

    32-bit (1 word, 4 bytes)

    1. nzyear

      Reference time GMT year.

    2. nzjday

      Reference time GMT day-of-year (often called Julian Date) (1–366).

    3. nzhour

      Reference time GMT hour (00–23).

    4. nzmin

      Reference time GMT minute (0–59).

    5. nzsec

      Reference time GMT second (0–59).

    6. nzmsec

      Reference time GMT Millisecond (0–999).

    7. nvhdr

      SAC-file version.
      VersionDescription
      v7Footer (2020+, sac 102.0+)
      v6No footer (pre-2020, sac 101.6a-)

    8. norid

      Origin ID.

    9. nevid

      Event ID.

    10. npts

      Number of points in data.

    11. nsnpts

      Original (saved) npts.

    12. nwfid

      Waveform ID.

    13. nxsize

      Spectral-only equivalent of npts (length of spectrum).

    14. nysize

      Spectral-only, width of spectrum.

    15. iftype

      File type.
      ValueTypeDescription
      01ITIMETime-series
      02IRLIMSpectral (real/imaginary)
      03IAMPHSpectral (amplitude/phase)
      04IXYGeneral XY file
      ??IXYZ∗General XYZ file

      ∗Value not listed in the standard.

    16. idep

      Dependent variable type.
      ValueTypeDescription
      05IUNKNUnknown
      06IDISPDisplacement (nm)
      07IVELVelocity \(\mathrm{\left(\frac{nm}{s}\right)}\)
      08IACCAcceleration \(\mathrm{\left(\frac{nm}{s^{2}}\right)}\)
      50IVOLTSVelocity (volts)

    17. iztype

      Reference time equivalent.
      ValueTypeDescription
      05IUNKNUnknown
      09IBRecording start time
      10IDAYMidnight reference GMT day
      11IOEvent origin time
      12IAFirst arrival time
      13–22IT(0–9)User defined time (t) pick

    18. iinst

      Recording instrument type.

      Not used by SAC—free for other purposes.

    19. istreg

      Station geographic region.

      Not used by SAC—free for other purposes.

    20. ievreg

      Event geographic region.

      Not used by SAC—free for other purposes.

    21. ievtyp

      Event type.
      ValueTypeDescription
      05IUNKNUnknown
      11IOOther source of known origin
      37INUCLNuclear
      38IPRENNuclear pre-shot
      39IPOSTNNuclear post-shot
      40IQUAKEEarthquake
      41IPREQForeshock
      42IPOSTQAftershock
      43ICHEMChemical explosion
      44IOTHEROther
      72IQBQuarry/mine blast—confirmed by quarry/mine
      73IQB1Quarry/mine blast—designed shot info-ripple fired
      74IQB2Quarry/mine blast—observed shot info-ripple fired
      75IQBXQuarry/mine blast—single shot
      76IQMTQuarry/mining induced events—tremor and rockbursts
      77IEQEarthquake
      78IEQ1Earthquake in a swarm or in an aftershock sequence
      79IEQ2Felt earthquake
      80IMEMarine explosion
      81IEXOther explosion
      82INUNuclear explosion
      83INCNuclear cavity collapse
      85ILLocal event of unknown origin
      86IRRegion event of unknown origin
      87ITTeleseismic event of unknown origin
      88IUUndetermined/conflicting information

    22. iqual

      Quality of data.
      ValueTypeDescription
      44IOTHEROther
      45IGOODGood
      46IGLCHGlitches
      47IDROPDropouts
      48ILOWSNLow signal-to-noise ratio

      Not used by SAC—free for other purposes.

    23. isynth

      Synthetic data flag.
      ValueTypeDescription
      49IRLDATAReal data
      XXSynthetic

      ∗Values and types not listed in the standard.

    24. imagtyp

      Magnitude type.
      ValueTypeDescription
      52IMBBody-wave magnitude (\(M_{b}\))
      53IMSSurface-wave magnitude (\(M_{s}\))
      54IMLLocal magnitude (\(M_{l}\))
      55IMWMoment magnitude (\(M_{w}\))
      56IMDDuration magnitude (\(M_{d}\))
      57IMXUser-defined magnitude (\(M_{x}\))

    25. imagsrc

      Source of magnitude information.
      ValueTypeDescription
      58INEICNational Earthquake Information Center
      61IPDEPreliminary Determination of Epicenter
      62IISCInternation Seismological Centre
      63IREBReviewed Event Bulletin
      64IUSGSU.S. Geological Survey
      65IBRKUC Berkeley
      66ICALTECHCalifornia Institute of Technology
      67ILLNLLawrence Livermore National Laboratory
      68IEVLOCEvent location (computer program)
      69IJSOPJoint Seismic Observation Program
      70IUSERThe user
      71IUNKNOWNUnknown

    26. ibody

      Body/spheroid definition used to calculate distances.
      ValueTypeNameSemi-major axis (a [m])Inverse Flattening (f)
      -12345UNDEFEarth (Historic)6378160.00.00335293
      98ISUNSun696000000.08.189e-6
      99IMERCURYMercury2439700.00.0
      100IVENUSVenus6051800.00.0
      101IEARTHEarth (WGS84)6378137.00.0033528106647474805
      102IMOONMoon1737400.00.0
      103IMARSMars3396190.00.005886007555525457

    3.8.4. Boolean (4)

    32-bit (1 word, 4 bytes) in-file/8-bit (1 byte) in-memory

    1. leven

      REQUIRED

      Evenly-spaced data flag.

      If true, then data is evenly spaced.

    2. lpspol

      Station polarity flag.

      If true, then station has positive-polarity—it follows the left-hand +convention (for example, North-East-Up [NEZ]).

    3. lovrok

      File overwrite flag.

      If true, then it’s okay to overwrite the file.

    4. lcalda

      Calculate geometry flag.

      If true, then calculate dist, az, baz, and gcarc from stla, stlo, +evla, and evlo.

    3.8.5. String (23)

    32/64-bit (2/4 words, 8/16 bytes, 8/16 characters)

    1. kstnm

      Station name.

    2. kevnm

      Event name.

      ∗This is the only four word (16 character) string.

    3. khole

      Nuclear—hole identifier.

      Other—Location identifier (LOCID).

    4. ko

      Text for o.

    5. ka

      Text for a.

    6. kt(0--9)

      Text for t(0--9).

    7. kf

      Text for f.

    8. kuser(0--2)

      Text for the first three of user(0--9).

    9. kdatrd

      Date the data was read onto a computer.

    10. kinst

      Text for iinst.

    3.8.6. Data (2)

    32-bit (2 words, 8 bytes) in-file/64-bit (4 words, 16 bytes) in-memory

    Stored as floating-point (32-bit) values in SAC-files; stored as +double-precision in memory.

    1. data1

      The first data vector---always present in a SAC-file and begins at word 158.

    2. data2

      The second data vector---conditionally present and begins after data1.

      Required if leven is false, or if iftype is spectral/XY/XYZ.

    4. Notes

    4.1. Why C++20 and not C++23

    Compiler restrictions—C++23 support requires GCC-13+ and Clang-16+. Many systems, still use GCC-12 and Clang-15—which has near complete support for C++20.

    sac-format strives for accessibility, modernity, safety, and speed—C++20 provides the best fit.

    Author: Alexander R. Blanchette

    Validate

    \ No newline at end of file diff --git a/docs/sac-format_manual.pdf b/docs/sac-format_manual.pdf index c582cb567d9055efaf48d3f701df58c1bc7c25b2..decbdc41cbc2c7b464953a3d57d6ceda44b64e11 100644 GIT binary patch delta 23295 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 E2Gw(trace.npts())); + quick_io_check(tmp_file, trace); // Return to even data trace.leven(true); REQUIRE(trace.iftype() == 1); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); // Spectral even trace.iftype(2); REQUIRE(trace.iftype() == 2); REQUIRE(trace.leven() == true); REQUIRE(trace.data2().size() == static_cast(trace.npts())); + quick_io_check(tmp_file, trace); // Uneven trace.leven(false); REQUIRE(trace.iftype() == unset_int); REQUIRE(trace.data2().size() == static_cast(trace.npts())); + quick_io_check(tmp_file, trace); // Return to even trace.leven(true); REQUIRE(trace.iftype() == unset_int); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); } SECTION("IFType") { Trace trace{}; @@ -908,17 +924,21 @@ TEST_CASE("Linked Headers") { trace.leven(true); trace.iftype(1); trace.npts(10); + trace.nvhdr(7); REQUIRE(trace.leven() == true); REQUIRE(trace.iftype() == 1); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); // Spectral data trace.iftype(2); REQUIRE(trace.leven() == true); REQUIRE(trace.data2().size() == static_cast(trace.npts())); + quick_io_check(tmp_file, trace); // Return to even non-2D data trace.iftype(1); REQUIRE(trace.leven() == true); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); } SECTION("Npts") { SECTION("Without Data2") { @@ -927,14 +947,17 @@ TEST_CASE("Linked Headers") { trace.leven(true); trace.iftype(1); trace.npts(0); + trace.nvhdr(7); REQUIRE(trace.npts() == 0); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); SECTION("Npts 10") { trace.npts(10); REQUIRE(trace.npts() == 10); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); } SECTION("Grow 10, shrink 5") { trace.npts(10); @@ -942,6 +965,7 @@ TEST_CASE("Linked Headers") { REQUIRE(trace.npts() == 5); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); } } SECTION("With Data2") { @@ -950,14 +974,17 @@ TEST_CASE("Linked Headers") { trace.leven(false); trace.iftype(1); trace.npts(0); + trace.nvhdr(7); REQUIRE(trace.npts() == 0); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == static_cast(trace.npts())); + quick_io_check(tmp_file, trace); SECTION("Npts 10") { trace.npts(10); REQUIRE(trace.npts() == 10); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == static_cast(trace.npts())); + quick_io_check(tmp_file, trace); } SECTION("Grow 10, shrink 5") { trace.npts(10); @@ -965,6 +992,7 @@ TEST_CASE("Linked Headers") { REQUIRE(trace.npts() == 5); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == static_cast(trace.npts())); + quick_io_check(tmp_file, trace); } } SECTION("Even Spectral") { @@ -972,14 +1000,17 @@ TEST_CASE("Linked Headers") { trace.leven(true); trace.iftype(2); trace.npts(0); + trace.nvhdr(7); REQUIRE(trace.npts() == 0); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == static_cast(trace.npts())); + quick_io_check(tmp_file, trace); SECTION("Npts 10") { trace.npts(10); REQUIRE(trace.npts() == 10); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == static_cast(trace.npts())); + quick_io_check(tmp_file, trace); } SECTION("Grow 10, shrink 5") { trace.npts(10); @@ -987,6 +1018,7 @@ TEST_CASE("Linked Headers") { REQUIRE(trace.npts() == 5); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == static_cast(trace.npts())); + quick_io_check(tmp_file, trace); } } } @@ -997,9 +1029,11 @@ TEST_CASE("Linked Headers") { trace.leven(true); trace.iftype(1); trace.npts(0); + trace.nvhdr(7); REQUIRE(trace.npts() == 0); REQUIRE(trace.data1().size() == 0); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); // Change the vector std::vector new_data1{}; new_data1.resize(10); @@ -1007,15 +1041,18 @@ TEST_CASE("Linked Headers") { REQUIRE(trace.npts() == 10); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); } SECTION("Uneven timeseries") { Trace trace{}; trace.leven(false); trace.iftype(1); trace.npts(0); + trace.nvhdr(7); REQUIRE(trace.npts() == 0); REQUIRE(trace.data1().size() == 0); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); // Change the vector std::vector new_data1{}; new_data1.resize(10); @@ -1023,15 +1060,18 @@ TEST_CASE("Linked Headers") { REQUIRE(trace.npts() == 10); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == static_cast(trace.npts())); + quick_io_check(tmp_file, trace); } SECTION("Spectral") { Trace trace{}; trace.leven(true); trace.iftype(2); trace.npts(0); + trace.nvhdr(7); REQUIRE(trace.npts() == 0); REQUIRE(trace.data1().size() == 0); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); // Change the vector std::vector new_data1{}; new_data1.resize(10); @@ -1039,6 +1079,7 @@ TEST_CASE("Linked Headers") { REQUIRE(trace.npts() == 10); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == static_cast(trace.npts())); + quick_io_check(tmp_file, trace); } } SECTION("Data2") { @@ -1047,9 +1088,11 @@ TEST_CASE("Linked Headers") { trace.leven(true); trace.iftype(1); trace.npts(0); + trace.nvhdr(7); REQUIRE(trace.npts() == 0); REQUIRE(trace.data1().size() == 0); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); // Change the vector std::vector new_data2{}; new_data2.resize(15); @@ -1057,20 +1100,24 @@ TEST_CASE("Linked Headers") { REQUIRE(trace.npts() == 15); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == static_cast(trace.npts())); + quick_io_check(tmp_file, trace); // Remove data2 trace.iftype(1); REQUIRE(trace.npts() == 15); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); } SECTION("Uneven timeseries") { Trace trace{}; trace.leven(false); trace.iftype(1); trace.npts(0); + trace.nvhdr(7); REQUIRE(trace.npts() == 0); REQUIRE(trace.data1().size() == 0); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); // Change the vector std::vector new_data2{}; new_data2.resize(25); @@ -1078,20 +1125,24 @@ TEST_CASE("Linked Headers") { REQUIRE(trace.npts() == 25); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == static_cast(trace.npts())); + quick_io_check(tmp_file, trace); // Remove data2 trace.leven(true); REQUIRE(trace.npts() == 25); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); } SECTION("Spectral") { Trace trace{}; trace.leven(true); trace.iftype(2); trace.npts(0); + trace.nvhdr(7); REQUIRE(trace.npts() == 0); REQUIRE(trace.data1().size() == 0); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); // Change the vector std::vector new_data2{}; new_data2.resize(12); @@ -1099,11 +1150,13 @@ TEST_CASE("Linked Headers") { REQUIRE(trace.npts() == 12); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == static_cast(trace.npts())); + quick_io_check(tmp_file, trace); // Remove data2 trace.iftype(1); REQUIRE(trace.npts() == 12); REQUIRE(trace.data1().size() == static_cast(trace.npts())); REQUIRE(trace.data2().size() == 0); + quick_io_check(tmp_file, trace); } } } @@ -1247,6 +1300,10 @@ TEST_CASE("Unsetting Trace") { REQUIRE(trace.az() == unset_double); REQUIRE(trace.baz() == unset_double); } + fs::path tmp_dir{fs::temp_directory_path()}; + fs::path tmp_file{tmp_dir / "test.SaC"}; + trace.nvhdr(7); + quick_io_check(tmp_file, trace); } TEST_CASE("Trace Read/Write") {