Conventions
Trust your data
Type annotations form a contract between different parts of your code, not
between your code and the data it processes. Pysmo does not use annotations
to validate data. Instead, it assumes that data arriving at a function is
correct and in the expected format. The recommended approach is to validate
once at the point of ingestion and trust the data from there. This is
straightforward at the class level with e.g. attrs (which pysmo uses
throughout).
SI units
Mismatched units are a common source of errors and tedious format conversions.
Pysmo assumes SI
units throughout, even where other conventions are common in seismology. This
is also consistent with e.g. scipy.constants.
Time
Pysmo uses pandas datetime types throughout. They behave similarly to
built-in datetime objects but integrate better with numpy arrays. Points in
time are always pandas.Timestamp objects with
tzinfo set to
UTC. All times
are absolute — relative offsets from some reference point are avoided.
Time intervals such as sampling rate are always
pandas.Timedelta objects.
SciPy and NumPy parameters
Where scipy or numpy functions are used, pysmo follows their
parameter definitions and ranges rather than seismology conventions. For
example, scipy.signal.windows.tukey defines alpha between 0 and
1, whereas taper functions in seismology typically use 0 to 0.5. Pysmo
uses the SciPy definition. Default parameter values follow SciPy and NumPy as
well, which may produce different results from equivalent functions in other
programs such as SAC.
Avoid None type
Pysmo types are narrow and specific. Optional attributes — those that could
be None — are avoided unless strictly necessary. A Coordinates type,
for example, always has a latitude and a longitude; neither should ever be
None.
Prefer functions over methods
Functions are preferred over methods. Methods on a type create coupling between the type and specific behaviour, which works against reusability. Pysmo types therefore contain almost no methods.
This applies to dunder methods too. Pysmo types are data containers, and
special behaviour via dunder methods would be ambiguous. If
Seismogram had a __len__ method, it
would be unclear whether len(seismogram) returns the number of samples or
something else — whereas len(seismogram.data) is unambiguous.