Skip to content

Commit

Permalink
CI/CD (#12)
Browse files Browse the repository at this point in the history
* GA: adding actions

* renaming workflow

* GA: testing cibuildwheel

* CI/CD\

* docs

---------

Co-authored-by: Marius Isken <[email protected]>
  • Loading branch information
miili and Marius Isken authored Mar 12, 2024
1 parent be42d95 commit bdb8bd2
Show file tree
Hide file tree
Showing 16 changed files with 187 additions and 64 deletions.
77 changes: 59 additions & 18 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -1,26 +1,67 @@
name: Build and test
name: Deploy

on: [push]
on:
push:
branches:
- main
tags:
- "*"

jobs:
build:
runs-on: ubuntu-latest
build_wheels:
name: Build wheels on ${{ matrix.os }}

runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.10", "3.11"]
os: [ubuntu-20.04]

steps:
- uses: actions/checkout@v4

- name: Build wheels
uses: pypa/[email protected]
with:
config-file: "{package}/pyproject.toml"

- uses: actions/upload-artifact@v4
with:
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
path: ./wheelhouse/*.whl

make_sdist:
name: Make SDist
runs-on: ubuntu-latest
needs: build_wheels
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Optional, use if you use setuptools_scm
submodules: false # Optional, use if you have submodules

- name: Build SDist
run: pipx run build --sdist

- uses: actions/upload-artifact@v4
with:
name: cibw-sdist
path: dist/*.tar.gz

pypi-publish:
name: Upload release to PyPI
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
needs: [build_wheels, make_sdist]
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/qseek
permissions:
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
- name: Download all the wheels and sdists
uses: actions/download-artifact@v3
with:
python-version: ${{ matrix.python-version }}
cache: "pip" # caching pip dependencies
cache-dependency-path: "**/pyproject.toml"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .[dev]
- name: Test with pytest
run: |
pytest -m "not plot"
pattern: cibw-*
path: dist/
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
9 changes: 5 additions & 4 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
name: docs
name: Deploy Docs

on:
push:
branches:
- main
tags:
- "*"

permissions:
contents: write
jobs:
deploy:
deploy-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down
14 changes: 0 additions & 14 deletions .github/workflows/lint.yaml

This file was deleted.

59 changes: 59 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Pre-commit and Tests

on:
pull_request:
push:
branches:
- main
tags:
- "*"

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
- uses: pre-commit/[email protected]

test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache: "pip" # caching pip dependencies
cache-dependency-path: "**/pyproject.toml"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .[dev]
- name: Test with pytest
run: |
pytest -m "not plot"
build_docs:
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: 3.11
cache: "pip" # caching pip dependencies
cache-dependency-path: "**/pyproject.toml"
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
- uses: actions/cache@v3
with:
key: mkdocs-material-${{ env.cache_id }}
path: .cache
restore-keys: |
mkdocs-material-
- run: pip install .[docs]
- run: mkdocs build
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

[![Build and test](https://github.com/pyrocko/qseek/actions/workflows/build.yaml/badge.svg)](https://github.com/pyrocko/qseek/actions/workflows/build.yaml)
[![Documentation](https://img.shields.io/badge/read-documentation-blue)](https://pyrocko.github.io/qseek/)
![Python 3.10+](https://img.shields.io/badge/python-3.10%203.11-blue.svg)
![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://pre-commit.com/)
<!-- [![PyPI](https://img.shields.io/pypi/v/lassie)](https://pypi.org/project/lassie/) -->
Expand Down
4 changes: 2 additions & 2 deletions docs/benchmark.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ This enables high throughput of seismic data in different scenarios.

| Number Stations | Throughput in MB | Throughput in Waveform data |
| --------------- | ---------------- | ----------------------------|
| 300+ | 40 MB/sec | 12 hours/sec |
| 50 | 30 MB/sec | 6 hours/sec |
| 300+ | 50 MB/sec | 12 hours/sec |
| 50 | 200 MB/sec | 6 hours/sec |

Scanning a 600 GB (~700 years of waveforms) data set costs **~2 days on a 64 cores machine equipped with an Nvidia A100 GPU**.

Expand Down
6 changes: 6 additions & 0 deletions docs/components/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ Also see the [getting started guide](../getting_started.md) for a brief introduc

[General configuration conventions](general.md) are outlines in this guide as well.

!!! tip "Create a fresh config file."

```sh title="Using the CLI"
qseek config
```

## The Search

The search configuration. **This is the entrypoint for the EQ detection and localisation**.
Expand Down
9 changes: 9 additions & 0 deletions docs/components/station_corrections.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@

Station corrections can be extract from previous runs to refine the localisation accuracy. The corrections can also help to improve the semblance find more events in a dataset.

## Station Specific Corrections

![Source specific delay statistic](../images/station-delay-times.webp)
*Statistics of station delay times.*

```python exec='on'
from qseek.utils import generate_docs
from qseek.insights import StationCorrections

print(generate_docs(StationCorrections()))
```

## Source Specific Corrections

![Source specific corrections volume](../images/delay-volume.webp)
*Delay volume for a selected stations.*

```python exec='on'
from qseek.utils import generate_docs
Expand Down
16 changes: 11 additions & 5 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@

## Installation

The installation is straight-forward:
The installation is straight-forward using pip or pipx.

```sh title="From GitHub"
pip install git+https://github.com/pyrocko/qseek
```

or

```sh title="Using pipx"
pipx install git+https://github.com/pyrocko/qseek
```

## Running Qseek

The main entry point in the executeable is the `qseek` command. The provided command line interface (CLI) and a JSON config file is all what is needed to run the program.
Expand All @@ -26,8 +32,8 @@ qseek config > my-search.json

Check out the `my-search.json` config file and add your waveform data and velocity models.

??? abstract "Minimal Configuration Example"
Here is a minimal JSON configuration for Qseek
??? quote "Minimal Configuration Example"
Here is a minimal JSON configuration for Qseek.
```bash exec='on' result='json'
qseek config
```
Expand All @@ -36,8 +42,8 @@ For more details and information about the component, head over to [details of t

## Starting the Search

Once happy, start the `qseek` CLI.
Once happy with the configuration, start the `qseek` CLI.

```sh title="Start earthquake detection"
```sh title="Start the earthquake detection and localization"
qseek search my-search.json
```
14 changes: 6 additions & 8 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Welcome to Qseek 🐕‍🦺
# Welcome to Qseek 🔥

Qseek is an earthquake detection and localisation framework. It combines modern **machine learning phase detection and robust migration and stacking techniques**.

Expand All @@ -7,7 +7,6 @@ The detector is leveraging [Pyrocko](https://pyrocko.org) and [SeisBench](https:
!!! abstract "Citation"
Marius Paul Isken, Peter Niemz, Jannes Münchmeyer, Sebastian Heimann, Simone Cesca, Torsten Dahm, Qseek: A data-driven Framework for Machine-Learning Earthquake Detection, Localization and Characterization, Seismica, 2024, *submitted*


![Reykjanes detections](images/reykjanes-demo.webp)

*Seismic swarm activity at Iceland, Reykjanes Peninsula during a 2020 unrest. 15,000+ earthquakes detected, outlining a dike intrusion, preceeding the 2021 Fagradasfjall eruption. Visualized in [Pyrocko Sparrow](https://pyrocko.org).*
Expand All @@ -17,17 +16,16 @@ The detector is leveraging [Pyrocko](https://pyrocko.org) and [SeisBench](https:
* [x] Earthquake phase detection using machine-learning pickers from [SeisBench](https://github.com/seisbench/seisbench)
* [x] Octree localisation approach for efficient and accurate search
* [x] Different velocity models:
* [x] Constant velocity
* [x] 1D Layered velocity model
* [x] 3D fast-marching velocity model (NonLinLoc compatible)
* [x] Constant velocity
* [x] 1D Layered velocity model
* [x] 3D fast-marching velocity model (NonLinLoc compatible)
* [x] Extraction of earthquake event features:
* [x] Local magnitudes
* [x] Ground motion attributes
* [x] Local magnitudes
* [x] Ground motion attributes
* [x] Automatic extraction of modelled and picked travel times
* [x] Calculation and application of station corrections / station delay times
* [ ] Real-time analytics on streaming data (e.g. SeedLink)


[Get Started!](getting_started.md){ .md-button }

## Build with
Expand Down
5 changes: 4 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ markdown_extensions:
generic: true
- pymdownx.tabbed:
alternate_style: true
- pymdownx.emoji:
emoji_index: !!python/name:material.extensions.emoji.twemoji
emoji_generator: !!python/name:material.extensions.emoji.to_svg
- admonition
- def_list
- attr_list
Expand All @@ -69,7 +72,7 @@ plugins:
- markdown-exec

nav:
- Earthquake Detector:
- The Earthquake Detector:
- Welcome: index.md
- Getting Started 🚀: getting_started.md
- Visualising Detections: visualizing_results.md
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,6 @@ target-version = 'py311'

[tool.pytest.ini_options]
markers = ["plot: plot figures in tests"]

[tool.cibuildwheel.macos]
before-build = "brew install libomp"
7 changes: 1 addition & 6 deletions src/qseek/models/semblance.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ def _populate_table(self, table: Table) -> None:


class SemblanceCache(dict[bytes, np.ndarray]):
_mask: dict[int, np.ndarray] = {}

def get_mask(self, node_hashes: list[bytes]) -> np.ndarray:
"""Get the mask for the node hashes.
Expand All @@ -96,10 +94,7 @@ def get_mask(self, node_hashes: list[bytes]) -> np.ndarray:
np.ndarray: The boolean mask for the node hashes.
"""
# This is a "bit" of a hack to generate a hash from the node_hashes list
n_hashes = len(node_hashes)
if n_hashes not in self._mask:
self._mask[n_hashes] = np.array([hash in self for hash in node_hashes])
return self._mask[n_hashes]
return np.array([hash in self for hash in node_hashes])


class Semblance:
Expand Down
2 changes: 1 addition & 1 deletion src/qseek/octree.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ class Octree(BaseModel):
)
root_node_size: PositiveFloat = Field(
default=2 * KM,
description="Initial size of the root octree node at level 0 in [m].",
description="Initial size of the root octree node at level 0 in meters.",
)
n_levels: int = Field(
default=5,
Expand Down
2 changes: 1 addition & 1 deletion src/qseek/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ class Search(BaseModel):
semblance_sampling_rate: SamplingRate = Field(
default=100,
description="Sampling rate for the semblance image function. "
"Choose from 10, 20, 25, 50, 100 Hz.",
"Choose from `10, 20, 25, 50, 100, 200` Hz.",
)
detection_threshold: PositiveFloat = Field(
default=0.05,
Expand Down
Loading

0 comments on commit bdb8bd2

Please sign in to comment.