Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Pytest

on:
push:
branches: [ "main", "dev" ]
pull_request:
branches: [ "main", "dev" ]

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

steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel pytest
if [ -f pyproject.toml ]; then pip install -e . ; fi

- name: Test with pytest
run: |
pytest pytests/
75 changes: 75 additions & 0 deletions .github/workflows/release-on-published.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Release On Published

on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: "Release tag to publish"
required: true
type: string

permissions:
contents: read

jobs:
validate-tag:
uses: ./.github/workflows/validate-tag.yml
with:
tag: ${{ github.event.release.tag_name || inputs.tag }}
permissions:
contents: read

validate-zenodo:
needs: validate-tag
uses: ./.github/workflows/validate-zenodo.yml
with:
ref: ${{ needs.validate-tag.outputs.ref }}
permissions:
contents: read

build:
runs-on: ubuntu-latest
needs: [validate-tag, validate-zenodo]

steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ needs.validate-tag.outputs.ref }}
fetch-depth: 0
fetch-tags: true

- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.11"

- name: Build distributions
run: |
python -m pip install --upgrade pip
python -m pip install build twine
python -m build
python -m twine check dist/*

- name: Verify distribution version
shell: bash
run: |
expected="${{ needs.validate-tag.outputs.version }}"
test -f "dist/pynetdesign-${expected}.tar.gz" || {
echo "Expected sdist dist/pynetdesign-${expected}.tar.gz was not built"
ls -la dist
exit 1
}
compgen -G "dist/pynetdesign-${expected}-*.whl" > /dev/null || {
echo "Expected wheel dist/pynetdesign-${expected}-*.whl was not built"
ls -la dist
exit 1
}

- name: Upload built artifacts
uses: actions/upload-artifact@v7
with:
name: dist-release-published
path: dist/
68 changes: 68 additions & 0 deletions .github/workflows/validate-tag.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: Validate Tag

on:
workflow_call:
inputs:
tag:
required: true
type: string
outputs:
tag:
description: "Validated tag name"
value: ${{ jobs.validate.outputs.tag }}
ref:
description: "Validated tag ref"
value: ${{ jobs.validate.outputs.ref }}
version:
description: "Validated version without leading v"
value: ${{ jobs.validate.outputs.version }}

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.tag.outputs.tag }}
ref: ${{ steps.tag.outputs.ref }}
version: ${{ steps.tag.outputs.version }}

steps:
- name: Checkout tag
uses: actions/checkout@v6
with:
ref: ${{ inputs.tag }}
fetch-depth: 0
fetch-tags: true

- name: Validate strict semver tag
id: tag
shell: bash
run: |
TAG="${{ inputs.tag }}"
if [[ "$TAG" == refs/tags/* ]]; then
TAG="${TAG##*/}"
fi
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Invalid tag '$TAG'. Expected strict semver format: vMAJOR.MINOR.PATCH"
exit 1
fi
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "ref=refs/tags/$TAG" >> "$GITHUB_OUTPUT"
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"

- name: Ensure tag points to main history
shell: bash
run: |
TAG="${{ steps.tag.outputs.tag }}"
git fetch origin main
TAG_COMMIT="$(git rev-list -n 1 "$TAG")"
if [[ -z "$TAG_COMMIT" ]]; then
echo "Unable to resolve commit for tag '$TAG'"
exit 1
fi
if ! git merge-base --is-ancestor "$TAG_COMMIT" origin/main; then
echo "Tag '$TAG' does not point to a commit contained in main"
exit 1
fi
35 changes: 35 additions & 0 deletions .github/workflows/validate-zenodo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Validate Zenodo Metadata

on:
push:
branches: ["main", "dev"]
pull_request:
branches: ["main", "dev"]
workflow_call:
inputs:
ref:
required: false
type: string
workflow_dispatch:
inputs:
ref:
description: "Optional branch, tag, or SHA to validate"
required: false
type: string

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || github.ref }}

- name: Validate Zenodo Metadata
uses: vsoch/zenodo-validator@main
with:
path: ".zenodo.json"
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,11 @@ cython_debug/

# PyPI configuration file
.pypirc


# Agents
.agent/
.codex*
AGENTS.md
CLAUDE.md
.claude/
11 changes: 9 additions & 2 deletions .zenodo.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"title": "PyNetDesign: a Python framework for microseismic monitoring network design",
"version": "1.0.0",
"version": "1.0.1",
"license": "MIT",
"upload_type": "software",
"description": "PyNetDesign is an open-source Python library that provides a simple and functional framework for designing and testing microseismic monitoring networks.",
"description": "PyNetDesign is an open-source Python library that provides a simple and functional framework for designing and testing microseismic monitoring networks. Version 1.0.1 is a bugfix release. It corrects the seismic moment calculation, which underestimated the moment by a factor of 2*pi*f because the amplitude-to-displacement spectral conversion was applied twice. Minimum detectable moment magnitudes reported by version 1.0.0 were too low by roughly 1.0 to 1.9 magnitude units, by an amount that varies with the source-receiver distance, so results produced with version 1.0.0 should be recomputed. The release also restores Python 3.9 compatibility of the visualization module, removes a non-functional location uncertainty routine that referenced functions absent from the package, and adds a test module covering the magnitude relations.",
"keywords": [
"earthquakes",
"microseismicity",
Expand All @@ -18,6 +18,13 @@
],
"access_right": "open",
"language": "eng",
"related_identifiers": [
{
"identifier": "10.5281/zenodo.14945917",
"relation": "isNewVersionOf",
"resource_type": "software"
}
],
"creators": [
{
"affiliation": "Center for Integrative Petroleum Research, King Fahd University of Petroleum and Minerals, Dhahran, Saudi Arabia",
Expand Down
24 changes: 23 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [v1.0.1] - 2026-09-09

Bugfix release correcting the seismic moment calculation.

### Fixed

- the seismic moment is no longer underestimated by a factor of `2*pi*f` (#3). `calculate_M0` applied the amplitude-to-displacement spectral conversion a second time, after `retrieve_min_amps` had already applied it through `get_scaling_displacement`. Minimum detectable moment magnitudes reported by v1.0.0 were therefore too low by `dMw = (2/3)*log10(2*pi*f_r)`, which is 1.20 at a representative frequency of 10 Hz and 1.87 at 100 Hz. Because the representative frequency `f_r = min(v*Q/(pi*r), f_c)` depends on the source-receiver distance, the correction varies across the grid and changes the shape of the sensitivity maps, not only their colour scale
- `pynetdesign.visualization` can be imported on Python 3.9 again; `plot_sensitivity_slice` used a `match` statement, which is syntax available only from Python 3.10 onwards

### Changed

- `calculate_M0` now documents the seismic moment relation it evaluates and states that the amplitudes it takes are the displacement amplitude spectrum, with units given for the remaining arguments

### Removed

- `loc_uncertainty_grid`, which called `calculate_pdf` and `get_uncertainty_from_pdf`. Neither function has ever been part of the package, so every call raised `NameError`. Location uncertainty will be reintroduced later together with the functions it depends on

### Added

- `pytests/test_magnitude.py`, covering the seismic moment relation, the moment magnitude conversion and its inverse, the amplitude-type scaling coefficients, the peak frequency and its corner-frequency clamp, and the DAS strain and strain-rate detection thresholds. The closed-form checks fail on the v1.0.0 formula and so guard against a recurrence of #3

## [v1.0.0] - 2025-04-01

Initial public release, archived on Zenodo as
Expand Down Expand Up @@ -35,5 +56,6 @@ code itself is unchanged from the deposited version.
- conda environment files for user and development installations, and Windows installation scripts
- MIT license

[Unreleased]: https://github.com/danikiev/PyNetDesign/compare/v1.0.0...HEAD
[Unreleased]: https://github.com/danikiev/PyNetDesign/compare/v1.0.1...HEAD
[v1.0.1]: https://github.com/danikiev/PyNetDesign/compare/v1.0.0...v1.0.1
[v1.0.0]: https://github.com/danikiev/PyNetDesign/releases/tag/v1.0.0
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# PyNetDesign

[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.14945917.svg)](https://doi.org/10.5281/zenodo.14945917)
[![DOI](https://zenodo.org/badge/958300487.svg)](https://zenodo.org/badge/latestdoi/958300487)
[![Pytest](https://github.com/danikiev/PyNetDesign/actions/workflows/pytest.yml/badge.svg)](https://github.com/danikiev/PyNetDesign/actions/workflows/pytest.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellowgreen.svg)](https://github.com/danikiev/PyNetDesign/blob/main/LICENSE)

PyNetDesign is an open-source Python framework for testing and designing microseismic monitoring networks for homogeneous velocity models.
Expand Down Expand Up @@ -197,7 +198,12 @@ All notable changes are documented in [CHANGELOG.md](CHANGELOG.md), following

## Citing

If you use PyNetDesign in your research, please cite it as follows:
If you use PyNetDesign in your research, please cite the release you used. The DOI badge
at the top of this page always resolves to the most recently archived release, and the
Zenodo record of each release also carries its own version DOI.

Version 1.0.0 was deposited manually, before the automated GitHub–Zenodo integration was
enabled, so it has a DOI of its own:

**Anikiev, D. (2025).** *PyNetDesign: a Python framework for microseismic monitoring network design* (Version v1.0.0) [Computer software]. Zenodo.
<https://doi.org/10.5281/zenodo.14945917>
Expand All @@ -217,6 +223,11 @@ In BibTeX format:
}
```

**Note:** magnitudes computed with version 1.0.0 are affected by an error in the seismic
moment calculation that was corrected in version 1.0.1. If you are citing or reusing
results obtained with 1.0.0, please see [CHANGELOG.md](CHANGELOG.md) and issue
[#3](https://github.com/danikiev/PyNetDesign/issues/3).

## License

PyNetDesign is released under the MIT License. See [LICENSE](LICENSE) for details.
Loading
Loading