Skip to content

Commit

Permalink
utils: better nsl handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Marius Isken committed May 19, 2024
1 parent 71be4c3 commit 5ff007a
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 11 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-added-large-files
- id: mixed-line-ending
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.3.2
rev: v0.4.4
hooks:
- id: ruff
- id: ruff-format
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@ Key features are of the earthquake detection and localisation framework are:
* 1D Layered velocity model
* 3D fast-marching velocity model (NonLinLoc compatible)
* Extraction of earthquake event features:
* Local magnitudes
* Ground motion attributes
* Moment Magnitudes (MW) based on modelled peak ground motions
* Local magnitudes (ML), different models
* Ground motion attributes (e.g. PGA, PGV, ...)
* Automatic extraction of modelled and picked travel times
* Calculation and application of station corrections / station delay times
* Station Corrections
* station specific corrections (SST)
* source specific station corrections (SSST)

Qseek is built on top of [Pyrocko](https://pyrocko.org).

Expand Down
39 changes: 33 additions & 6 deletions src/qseek/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def match(self, other: NSL) -> bool:
return self.network == other.network

@classmethod
def parse(cls, nsl: str | NSL | list[str]) -> NSL:
def parse(cls, nsl: str | NSL | list[str] | tuple[str, str, str]) -> NSL:
"""Parse the given NSL string and return an NSL object.
Args:
Expand All @@ -132,22 +132,49 @@ def parse(cls, nsl: str | NSL | list[str]) -> NSL:
raise ValueError("invalid empty NSL")
if type(nsl) is _NSL:
return nsl
if isinstance(nsl, list):
if isinstance(nsl, (list, tuple)):
return cls(*nsl)
if not isinstance(nsl, str):
raise ValueError(f"invalid NSL {nsl}")

parts = nsl.split(".")
n_parts = len(parts)
if n_parts >= 3:
return cls(*parts[:3])
if n_parts == 2:
return cls(parts[0], parts[1], "")
if n_parts == 1:
return cls(parts[0], "", "")
raise ValueError(f"invalid NSL {nsl}")
raise ValueError(
f"invalid NSL `{nsl}`, expecting `<net>.<sta>.<loc>`, "
"e.g. `6A.STA130.00`, `6A.STA130` or `.STA130`"
)

def _check(self) -> None:
"""Check if the current NSL object matches another NSL object.
Args:
nsl (NSL): The NSL object to compare with.
Returns:
bool: True if the objects match, False otherwise.
"""
if len(self.network) > 2:
raise ValueError(
f"invalid network {self.network} for {self.pretty},"
" expected 0-2 characters for network code"
)
if len(self.station) > 5 or len(self.station) < 1:
raise ValueError(
f"invalid station {self.station} for {self.pretty},"
" expected 1-5 characters for station code"
)
if len(self.location) > 2:
raise ValueError(
f"invalid location {self.location} for {self.pretty},"
" expected 0-2 characters for location code"
)


NSL = Annotated[_NSL, BeforeValidator(_NSL.parse)]
NSL = Annotated[_NSL, BeforeValidator(_NSL.parse), AfterValidator(_NSL._check)]


class _Range(NamedTuple):
Expand Down
22 changes: 22 additions & 0 deletions test/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import pytest
from pydantic import BaseModel
from qseek.utils import NSL

Expand All @@ -23,3 +24,24 @@ class Model(BaseModel):
}
"""
Model.model_validate_json(json)

json = """
{
"nsl": "6E.TE234.",
"nsl_list": [".TE232"]
}
"""
Model.model_validate_json(json)

json_tpl = """
{{
"nsl": "{code}",
"nsl_list": []
}}
"""

invalid_codes = ["6E", "6E5.", "6E.", "6E.TE123112"]

for code in invalid_codes:
with pytest.raises(ValueError):
Model.model_validate_json(json_tpl.format(code=code))

0 comments on commit 5ff007a

Please sign in to comment.