Package Organization

pysac.header

SAC header specification, including documentation.

Header names, order, and types, nulls, as well as allowed enumerated values, are specified here. Header name strings, and their array order are contained in separate float, int, and string tuples. Enumerated values, and their allowed string and integer values, are in dictionaries. Header value documentation is in a dictionary, DOC, for reuse throughout the package.

pysac.util

PySAC helper functions and data. Contains functions to validate and convert enumerated values, byteorder consistency checking, and SAC reference time reading.

Two of the most important functions in this module are sac_to_obspy_header and obspy_to_sac_header. These contain the conversion routines between SAC header dictionaries and ObsPy header dictionaries. These functions control the way ObsPy reads and writes SAC files, which was one of the main motivations for authoring this package.

pysac.arrayio

Low-level array interface to the SAC file format.

Functions in this module work directly with numpy arrays that mirror the SAC format, and comprise much of the machinery that underlies the SACTrace class. The 'primitives' in this module are the float, int, and string header arrays, the float data array, and a header dictionary. Convenience functions are provided to convert between header arrays and more user-friendly dictionaries.

These read/write routines are very literal; there is almost no value or type checking, except for byteorder and header/data array length. File- and array- based checking routines are provided for additional checks where desired.

Reading and writing are done with read_sac and write_sac for binary SAC files, and read_sac_ascii and write_sac_ascii for alphanumeric files. Conversions between header dictionaries and the three SAC header arrays are done with the header_arrays_to_dict and dict_to_header_arrays functions. Validation of header values and data is managed by validate_sac_content, which can currently do six different tests.

pysac.sactrace

Contains the SACTrace class, which is the main user-facing interface to the SAC file format.

The SACTrace object maintains consistency between SAC headers and manages header values in a user-friendly way. This includes some value-checking, native Python logicals and nulls instead of SAC's header-dependent logical/null representation.

Reading and writing SAC files

PySAC can read and write evenly-spaced time-series files. It supports big or little-endian binary files, or alphanumeric/ASCII files.

# read from a binary file
sac = SACTrace.read(filename)

# read header only
sac = SACTrace.read(filename, headonly=True)

# write header-only, file must exist
sac.write(filename, headonly=True)

# read from an ASCII file
sac = SACTrace.read(filename, ascii=True)

# write a binary SAC file for a Sun machine
sac.write(filename, byteorder='big')

Headers

In the SACTrace class, SAC headers are implemented as properties, with appropriate getters and setters. The getters/setters translate user-facing native Python values like True, False, and None to the appropriate SAC header values, like 1, 0, -12345, '-12345 ', etc.

Header values that depend on the SAC .data vector are calculated on-the-fly, and fall back to the stored header value.

A convenient read-only dictionary of non-null, raw SAC header values is available as SACTrace._header. Formatted non-null headers are viewable using print(sac) or the .lh() or listhdr() methods. Relative time headers and picks are viewable with lh('picks').

Reference time and relative time header handling

The SAC reference time is built from "nz..." time fields in the header, and it is available as the attribute .reftime, an ObsPy UTCDateTime instance. reftime can be modified in two ways: by resetting it with a new absolute UTCDateTime instance, or by adding/subtracting seconds from it. Modifying the reftime will also modify all relative time headers such that they are still correct in an absolute sense. This includes a, b, e, f, o, and t1-t9. This means that adjusting the reference time does not invalidate the origin time, the first sample time, or any picks!

Here, we build a 100-second SACTrace that starts at Y2K.

sac = SACTrace(nzyear=2000, nzjday=1, nzhour=0, nzmin=0, nzsec=0, nzmsec=0,
               t1=23.5, data=numpy.arange(101))

sac.reftime
sac.b, sac.e, sac.t1
2000-01-01T00:00:00.000000Z
(0.0, 100.0, 23.5)

Move reference time by relative seconds, relative time headers are preserved.

sac.reftime -= 2.5
sac.b, sac.e, sac.t1
(2.5, 102.5, 26.0)

Set reference time to new absolute time, two minutes later. Relative time headers are preserved.

sac.reftime = UTCDateTime(2000, 1, 1, 0, 2, 0, 0)
sac.b, sac.e
(-120.0, -20.0, -96.5)