dssrr 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dssrr-0.1.0/LICENSE +21 -0
- dssrr-0.1.0/MANIFEST.in +41 -0
- dssrr-0.1.0/PKG-INFO +483 -0
- dssrr-0.1.0/README.md +434 -0
- dssrr-0.1.0/docs/CLI.md +167 -0
- dssrr-0.1.0/docs/images/icon.png +0 -0
- dssrr-0.1.0/docs/images/pipeline.svg +78 -0
- dssrr-0.1.0/dssrr/__init__.py +231 -0
- dssrr-0.1.0/dssrr/cli.py +305 -0
- dssrr-0.1.0/dssrr/config.py +175 -0
- dssrr-0.1.0/dssrr/core.py +553 -0
- dssrr-0.1.0/dssrr/discovery.py +204 -0
- dssrr-0.1.0/dssrr/gui/__init__.py +33 -0
- dssrr-0.1.0/dssrr/gui/__main__.py +21 -0
- dssrr-0.1.0/dssrr/gui/batch_repair.py +782 -0
- dssrr-0.1.0/dssrr/gui/depulse_dialog.py +2718 -0
- dssrr-0.1.0/dssrr/gui/export_report_dialog.py +658 -0
- dssrr-0.1.0/dssrr/gui/i18n.py +413 -0
- dssrr-0.1.0/dssrr/gui/icons/__init__.py +39 -0
- dssrr-0.1.0/dssrr/gui/icons/dssrr-128.png +0 -0
- dssrr-0.1.0/dssrr/gui/icons/dssrr-16.png +0 -0
- dssrr-0.1.0/dssrr/gui/icons/dssrr-24.png +0 -0
- dssrr-0.1.0/dssrr/gui/icons/dssrr-256.png +0 -0
- dssrr-0.1.0/dssrr/gui/icons/dssrr-32.png +0 -0
- dssrr-0.1.0/dssrr/gui/icons/dssrr-48.png +0 -0
- dssrr-0.1.0/dssrr/gui/icons/dssrr-64.png +0 -0
- dssrr-0.1.0/dssrr/gui/icons/dssrr.ico +0 -0
- dssrr-0.1.0/dssrr/gui/icons/dssrr.png +0 -0
- dssrr-0.1.0/dssrr/gui/icons/dssrr.svg +24 -0
- dssrr-0.1.0/dssrr/gui/icons/make_icon.py +209 -0
- dssrr-0.1.0/dssrr/gui/main.py +846 -0
- dssrr-0.1.0/dssrr/gui/manual_repair.py +1077 -0
- dssrr-0.1.0/dssrr/gui/nav_hint.py +182 -0
- dssrr-0.1.0/dssrr/gui/plot_text_editor.py +505 -0
- dssrr-0.1.0/dssrr/gui/translations_zh.py +665 -0
- dssrr-0.1.0/dssrr/gui/viewer.py +3008 -0
- dssrr-0.1.0/dssrr/i18n.py +122 -0
- dssrr-0.1.0/dssrr/paths.py +121 -0
- dssrr-0.1.0/dssrr/repair_lib/__init__.py +38 -0
- dssrr-0.1.0/dssrr/repair_lib/anomaly_repair/__init__.py +55 -0
- dssrr-0.1.0/dssrr/repair_lib/anomaly_repair/config.py +26 -0
- dssrr-0.1.0/dssrr/repair_lib/anomaly_repair/layered_reference_spectrum.py +506 -0
- dssrr-0.1.0/dssrr/repair_lib/anomaly_repair/moonquake_protected_spike.py +371 -0
- dssrr-0.1.0/dssrr/repair_lib/anomaly_repair/reference_spectrum.py +42 -0
- dssrr-0.1.0/dssrr/repair_lib/anomaly_repair/spectral.py +22 -0
- dssrr-0.1.0/dssrr/repair_lib/anomaly_repair/synthesizer.py +29 -0
- dssrr-0.1.0/dssrr/repair_lib/anomaly_repair/verifier.py +21 -0
- dssrr-0.1.0/dssrr/repair_lib/apollo_catalog/gagnepian_2006_catalog.csv +59 -0
- dssrr-0.1.0/dssrr/repair_lib/apollo_catalog/lognonne_2003_catalog.csv +60 -0
- dssrr-0.1.0/dssrr/repair_lib/depulse_advanced.py +973 -0
- dssrr-0.1.0/dssrr/repair_lib/depulse_nn.py +187 -0
- dssrr-0.1.0/dssrr/repair_lib/e7_detector.py +622 -0
- dssrr-0.1.0/dssrr/repair_lib/e7_repair_build.py +1719 -0
- dssrr-0.1.0/dssrr/repair_lib/moonquake_catalog.json +9515 -0
- dssrr-0.1.0/dssrr/repair_lib/repair_engine.py +673 -0
- dssrr-0.1.0/dssrr/repair_lib/repair_settings.py +139 -0
- dssrr-0.1.0/dssrr/repair_lib/report_plot.py +913 -0
- dssrr-0.1.0/dssrr/spectral.py +209 -0
- dssrr-0.1.0/dssrr/synthesizer.py +716 -0
- dssrr-0.1.0/dssrr/verifier.py +309 -0
- dssrr-0.1.0/dssrr.egg-info/PKG-INFO +483 -0
- dssrr-0.1.0/dssrr.egg-info/SOURCES.txt +96 -0
- dssrr-0.1.0/dssrr.egg-info/dependency_links.txt +1 -0
- dssrr-0.1.0/dssrr.egg-info/entry_points.txt +3 -0
- dssrr-0.1.0/dssrr.egg-info/requires.txt +26 -0
- dssrr-0.1.0/dssrr.egg-info/top_level.txt +1 -0
- dssrr-0.1.0/examples/01_quickstart.py +149 -0
- dssrr-0.1.0/examples/02_long_gap_baseline.py +158 -0
- dssrr-0.1.0/examples/03_real_apollo_mseed.py +198 -0
- dssrr-0.1.0/examples/04_report_plot.py +133 -0
- dssrr-0.1.0/examples/05_batch_cli.py +136 -0
- dssrr-0.1.0/examples/README.md +46 -0
- dssrr-0.1.0/examples/data/01/XA.S12.19760101.mseed +0 -0
- dssrr-0.1.0/examples/data/01/XA.S12.19760102.mseed +0 -0
- dssrr-0.1.0/examples/data/01/XA.S12.19760103.mseed +0 -0
- dssrr-0.1.0/examples/data/01/XA.S12.19760104.mseed +0 -0
- dssrr-0.1.0/examples/data/01/XA.S12.19760105.mseed +0 -0
- dssrr-0.1.0/examples/data/01/XA.S12.19760106.mseed +0 -0
- dssrr-0.1.0/examples/data/01/XA.S12.19760107.mseed +0 -0
- dssrr-0.1.0/examples/data/01/XA.S12.19760108.mseed +0 -0
- dssrr-0.1.0/examples/data/01/XA.S12.19760109.mseed +0 -0
- dssrr-0.1.0/examples/data/01/XA.S12.19760110.mseed +0 -0
- dssrr-0.1.0/examples/data/01/XA.S12.19760111.mseed +0 -0
- dssrr-0.1.0/examples/data/01/XA.S12.19760112.mseed +0 -0
- dssrr-0.1.0/examples/data/01/XA.S12.19760113.mseed +0 -0
- dssrr-0.1.0/examples/data/README.md +72 -0
- dssrr-0.1.0/examples/data/XA.S12.01.MHZ.19760113_070152-19760113_190149.mseed +0 -0
- dssrr-0.1.0/examples/data/XA.S15.01.MHZ.19760113_070152-19760113_190149.mseed +0 -0
- dssrr-0.1.0/examples/data/XA.S16.01.MHZ.19760113_070152-19760113_190149.mseed +0 -0
- dssrr-0.1.0/pyproject.toml +110 -0
- dssrr-0.1.0/setup.cfg +4 -0
- dssrr-0.1.0/setup.py +11 -0
- dssrr-0.1.0/tests/test_basic.py +62 -0
- dssrr-0.1.0/tests/test_gui_i18n.py +379 -0
- dssrr-0.1.0/tests/test_language_defaults.py +182 -0
- dssrr-0.1.0/tests/test_repair_engine.py +111 -0
- dssrr-0.1.0/tests/test_resolve_paths.py +179 -0
- dssrr-0.1.0/tests/test_single_source_of_truth.py +95 -0
dssrr-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shipeng Yu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
dssrr-0.1.0/MANIFEST.in
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------
|
|
2
|
+
# MANIFEST.in — what goes into the *source* distribution (sdist).
|
|
3
|
+
#
|
|
4
|
+
# The wheel is governed by [tool.setuptools.package-data] in pyproject.toml and
|
|
5
|
+
# only ever contains the importable ``dssrr`` package. The sdist is the
|
|
6
|
+
# "everything you need to reproduce the work" artefact: source, tests,
|
|
7
|
+
# documentation, runnable examples and their fixtures.
|
|
8
|
+
# ---------------------------------------------------------------------------
|
|
9
|
+
|
|
10
|
+
# Licence + top-level project documents
|
|
11
|
+
include LICENSE
|
|
12
|
+
include README.md
|
|
13
|
+
include pyproject.toml
|
|
14
|
+
include setup.py
|
|
15
|
+
|
|
16
|
+
# Package source and the data files that ship inside the installed package
|
|
17
|
+
# (GUI icons, moonquake catalogue). ``recursive-include`` covers subpackages
|
|
18
|
+
# such as dssrr.gui and dssrr.repair_lib.
|
|
19
|
+
recursive-include dssrr *.py
|
|
20
|
+
recursive-include dssrr *.json *.csv *.svg *.png *.ico
|
|
21
|
+
|
|
22
|
+
# Human-facing documentation (CLI guide, pipeline figure)
|
|
23
|
+
recursive-include docs *.md *.svg *.png
|
|
24
|
+
|
|
25
|
+
# Runnable examples and the Apollo MiniSEED fixtures they run against.
|
|
26
|
+
# The fixtures live in examples/ only — they are never installed.
|
|
27
|
+
recursive-include examples *.py *.md
|
|
28
|
+
recursive-include examples/data *.mseed *.md
|
|
29
|
+
|
|
30
|
+
# Regression test suite
|
|
31
|
+
recursive-include tests *.py
|
|
32
|
+
|
|
33
|
+
# --- Never ship build artefacts, caches or runtime output -------------------
|
|
34
|
+
global-exclude *.py[cod]
|
|
35
|
+
global-exclude __pycache__
|
|
36
|
+
prune examples/data_repaired
|
|
37
|
+
prune examples/__pycache__
|
|
38
|
+
prune tests/__pycache__
|
|
39
|
+
prune catalogs
|
|
40
|
+
prune .vscode
|
|
41
|
+
prune .pytest_cache
|
dssrr-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dssrr
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Dual-Sided Spectral Reference Reconstruction: training-free long-gap repair for planetary/seismic time series
|
|
5
|
+
Author-email: Shipeng Yu <ysp@cug.edu.cn>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/YSP0Github/DSSRR
|
|
8
|
+
Project-URL: Documentation, https://github.com/YSP0Github/DSSRR#readme
|
|
9
|
+
Project-URL: Source Code, https://github.com/YSP0Github/DSSRR
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/YSP0Github/DSSRR/issues
|
|
11
|
+
Keywords: seismology,lunar seismology,apollo,signal processing,gap filling,spectral reconstruction,planetary science,time series,artifact removal
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Astronomy
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
24
|
+
Requires-Python: >=3.9
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: numpy>=1.21
|
|
28
|
+
Requires-Dist: scipy>=1.7
|
|
29
|
+
Provides-Extra: gui
|
|
30
|
+
Requires-Dist: PyQt5>=5.15; extra == "gui"
|
|
31
|
+
Requires-Dist: matplotlib>=3.5; extra == "gui"
|
|
32
|
+
Requires-Dist: obspy>=1.4; extra == "gui"
|
|
33
|
+
Requires-Dist: pandas>=1.3; extra == "gui"
|
|
34
|
+
Provides-Extra: batch
|
|
35
|
+
Requires-Dist: obspy>=1.4; extra == "batch"
|
|
36
|
+
Requires-Dist: pandas>=1.3; extra == "batch"
|
|
37
|
+
Provides-Extra: nn
|
|
38
|
+
Requires-Dist: torch>=1.12; extra == "nn"
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
41
|
+
Requires-Dist: build>=0.10; extra == "dev"
|
|
42
|
+
Requires-Dist: twine>=4.0; extra == "dev"
|
|
43
|
+
Provides-Extra: all
|
|
44
|
+
Requires-Dist: PyQt5>=5.15; extra == "all"
|
|
45
|
+
Requires-Dist: matplotlib>=3.5; extra == "all"
|
|
46
|
+
Requires-Dist: obspy>=1.4; extra == "all"
|
|
47
|
+
Requires-Dist: pandas>=1.3; extra == "all"
|
|
48
|
+
Dynamic: license-file
|
|
49
|
+
|
|
50
|
+
<p align="center">
|
|
51
|
+
<img src="dssrr/gui/icons/dssrr.png" width="120" alt="DSSRR">
|
|
52
|
+
</p>
|
|
53
|
+
|
|
54
|
+
<h1 align="center">DSSRR — Dual-Sided Spectral Reference Reconstruction</h1>
|
|
55
|
+
|
|
56
|
+
<p align="center">
|
|
57
|
+
<b>Training-free, statistically faithful long-gap repair for planetary and seismic time series.</b>
|
|
58
|
+
</p>
|
|
59
|
+
|
|
60
|
+
<p align="center">
|
|
61
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
|
|
62
|
+
<img src="https://img.shields.io/badge/python-3.9%2B-blue.svg" alt="Python 3.9+">
|
|
63
|
+
<img src="https://img.shields.io/badge/core%20deps-numpy%20%2B%20scipy-success.svg" alt="numpy + scipy">
|
|
64
|
+
</p>
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
DSSRR fills corrupted or missing intervals in a time series by fusing power
|
|
69
|
+
spectral density (PSD) estimates taken from the healthy data on **both** sides
|
|
70
|
+
of the gap, synthesising a replacement with realistic waveform texture, and
|
|
71
|
+
blending it seamlessly into the surrounding trace.
|
|
72
|
+
|
|
73
|
+
No training data, no model fitting, no learned weights. It stays stable for
|
|
74
|
+
gaps from a few seconds to over **90 minutes**, where interpolation, SSA and
|
|
75
|
+
plain FFT extrapolation degrade sharply.
|
|
76
|
+
|
|
77
|
+
The method was developed for **Apollo lunar seismic (PSE) records** and ships
|
|
78
|
+
with the detection / batch-repair pipeline and the desktop tooling used to
|
|
79
|
+
produce the results in the accompanying paper.
|
|
80
|
+
|
|
81
|
+
## Table of contents
|
|
82
|
+
|
|
83
|
+
- [How it works](#how-it-works)
|
|
84
|
+
- [Installation](#installation)
|
|
85
|
+
- [Quick start](#quick-start)
|
|
86
|
+
- [Examples](#examples)
|
|
87
|
+
- [Desktop GUI](#desktop-gui)
|
|
88
|
+
- [Batch repair from the command line](#batch-repair-from-the-command-line)
|
|
89
|
+
- [Parameters](#parameters)
|
|
90
|
+
- [Key features](#key-features)
|
|
91
|
+
- [Limitations](#limitations)
|
|
92
|
+
- [Repository layout](#repository-layout)
|
|
93
|
+
- [Sample data, provenance and acknowledgements](#sample-data-provenance-and-acknowledgements)
|
|
94
|
+
- [FAQ](#faq)
|
|
95
|
+
- [Citation](#citation)
|
|
96
|
+
- [License](#license)
|
|
97
|
+
|
|
98
|
+
## How it works
|
|
99
|
+
|
|
100
|
+

|
|
101
|
+
|
|
102
|
+
1. **Locate the anomaly core.** You pass inclusive sample indices `[start, end]`.
|
|
103
|
+
2. **Extract two reference windows.** One before and one after the gap, each of
|
|
104
|
+
length `L = clip(anomaly/2, 120 s, 600 s)` by default
|
|
105
|
+
(see [`auto_reference_length`](#reference-length)). A safety gap (default
|
|
106
|
+
1 s) separates the anomaly from each reference so the anomaly never leaks in.
|
|
107
|
+
3. **Fuse a target PSD.** Welch estimates from both references are combined
|
|
108
|
+
into a single target spectrum, so a non-stationary neighbour on one side
|
|
109
|
+
cannot dominate.
|
|
110
|
+
4. **Synthesise the replacement.** Reference blocks with randomised phase are
|
|
111
|
+
overlap-added and rescaled to match the target spectrum's energy — this
|
|
112
|
+
is what gives the fill realistic texture instead of a smooth line.
|
|
113
|
+
5. **Align and blend.** The low-frequency trend is bridged across the gap and
|
|
114
|
+
the edges are cross-faded so no step is visible at the joins.
|
|
115
|
+
6. **Optional quantisation.** For raw integer counts (e.g. the Apollo archive)
|
|
116
|
+
the repaired samples can be rounded back onto the original integer grid.
|
|
117
|
+
7. **Verify.** Spectral, envelope, DC, autocorrelation and energy diagnostics
|
|
118
|
+
are returned alongside the data.
|
|
119
|
+
8. **Return.** A repaired copy plus a full report. **Every sample outside the
|
|
120
|
+
anomaly interval is copied through bit-identically.**
|
|
121
|
+
|
|
122
|
+
> **The one thing DSSRR cannot do:** recover the original phase inside the gap.
|
|
123
|
+
> It reproduces second-order statistics (PSD, autocorrelation, energy
|
|
124
|
+
> distribution). A one-off transient that happened during the dropout is
|
|
125
|
+
> unrecoverable — by any method.
|
|
126
|
+
|
|
127
|
+
## Installation
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
pip install dssrr
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The scientific core needs only **numpy + scipy**. Everything else is an
|
|
134
|
+
optional extra:
|
|
135
|
+
|
|
136
|
+
| Extra | Adds | For |
|
|
137
|
+
|---|---|---|
|
|
138
|
+
| *(none)* | numpy, scipy | library + CLI batch repair |
|
|
139
|
+
| `dssrr[batch]` | obspy, pandas | reading MiniSEED, writing catalog CSVs |
|
|
140
|
+
| `dssrr[gui]` | PyQt5, matplotlib, obspy, pandas | the desktop application |
|
|
141
|
+
| `dssrr[nn]` | torch | neural-network inpainting (optional repair method) |
|
|
142
|
+
| `dssrr[dev]` | pytest + tooling | running the test suite |
|
|
143
|
+
| `dssrr[all]` | gui + batch extras | everything except the optional torch backend |
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
pip install "dssrr[gui]" # desktop app
|
|
147
|
+
pip install "dssrr[all]" # everything
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
From a source checkout:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
git clone https://github.com/YSP0Github/DSSRR.git dssrr && cd dssrr
|
|
154
|
+
pip install -e ".[gui]"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Quick start
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
import numpy as np
|
|
161
|
+
from dssrr import DSSRR, auto_reference_length
|
|
162
|
+
|
|
163
|
+
sr = 6.625 # Apollo long-period sampling rate
|
|
164
|
+
data = ... # 1-D array, your trace
|
|
165
|
+
|
|
166
|
+
start, end = 12_000, 16_000 # inclusive anomaly sample indices
|
|
167
|
+
|
|
168
|
+
# Pick a reference window from the anomaly length (120-600 s protocol)
|
|
169
|
+
ref = auto_reference_length(end - start + 1, sr)
|
|
170
|
+
|
|
171
|
+
model = DSSRR(sr=sr, reference_sec=ref, seed=42)
|
|
172
|
+
repaired = model.repair(data, start, end) # numpy array, same shape
|
|
173
|
+
|
|
174
|
+
# Or get the full provenance / quality report too:
|
|
175
|
+
repaired, report = model.repair_with_report(data, start, end, random_seed=42)
|
|
176
|
+
print(report["verification"]["energy_ratio"])
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Two guarantees you can rely on:
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
assert repaired.shape == data.shape
|
|
183
|
+
assert np.array_equal(repaired[:start], data[:start]) # outside untouched
|
|
184
|
+
assert np.array_equal(repaired[end + 1:], data[end + 1:])
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Integer-count data (`quantize`)
|
|
188
|
+
|
|
189
|
+
By default the repaired segment stays **floating point**, which is correct for
|
|
190
|
+
physical-unit traces (velocity / displacement / acceleration). If your input is
|
|
191
|
+
**raw integer counts** — such as Apollo archival data on a 10-bit grid —
|
|
192
|
+
enable `quantize` so the repaired samples land on the same discrete grid as the
|
|
193
|
+
rest of the record:
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
model = DSSRR(sr=sr, reference_sec=300, quantize=True)
|
|
197
|
+
repaired = model.repair(data, start, end) # integer output
|
|
198
|
+
repaired = model.repair(data, start, end, quantize=True) # or per call
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Rounding is `np.rint` (round-half-to-even) and is applied **only inside the
|
|
202
|
+
anomaly interval**; everything outside stays bit-identical.
|
|
203
|
+
|
|
204
|
+
### Reference length
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
from dssrr import auto_reference_length
|
|
208
|
+
ref_sec = auto_reference_length(anomaly_samples, sr) # clip(anom/2, 120, 600)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Half the anomaly duration is enough for a stable spectral estimate; the bounds
|
|
212
|
+
keep the window short enough to stay locally stationary.
|
|
213
|
+
|
|
214
|
+
## Examples
|
|
215
|
+
|
|
216
|
+
Five runnable, heavily commented scripts live in [`examples/`](examples/) —
|
|
217
|
+
see [`examples/README.md`](examples/README.md) for the full index.
|
|
218
|
+
|
|
219
|
+
| Script | What it shows |
|
|
220
|
+
|---|---|
|
|
221
|
+
| [`01_quickstart.py`](examples/01_quickstart.py) | Smallest possible call; the two invariants; the report dict |
|
|
222
|
+
| [`02_long_gap_baseline.py`](examples/02_long_gap_baseline.py) | DSSRR vs linear interpolation vs FFT extrapolation on a 10-min gap |
|
|
223
|
+
| [`03_real_apollo_mseed.py`](examples/03_real_apollo_mseed.py) | Repair a real Apollo record, scored against the held-out truth |
|
|
224
|
+
| [`04_report_plot.py`](examples/04_report_plot.py) | Publication-style repair report figure |
|
|
225
|
+
| [`05_batch_cli.py`](examples/05_batch_cli.py) | Drive the batch pipeline from Python |
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
python examples/01_quickstart.py
|
|
229
|
+
python examples/03_real_apollo_mseed.py --data-dir /path/to/mseed --sr 6.625
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Desktop GUI
|
|
233
|
+
|
|
234
|
+
A PyQt5 application with a two-page main window: a **Repaired DB Viewer**
|
|
235
|
+
(compare the raw and repaired archives) and a **Manual Repair** panel
|
|
236
|
+
(select an interval with the mouse, try repair methods, preview, export).
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
pip install "dssrr[gui]"
|
|
240
|
+
dssrr-gui # console script
|
|
241
|
+
python -m dssrr.gui # equivalent module entry point
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
On Windows a helper launcher is provided at the repository root
|
|
245
|
+
(`启动DSSRR.bat`); on Unix use `./launch_gui.sh`. Both honour a `DSSRR_PYTHON`
|
|
246
|
+
environment variable if you need a specific interpreter.
|
|
247
|
+
|
|
248
|
+
Both database roots can also be preset from the environment, which is handy for
|
|
249
|
+
scripted launches and editor run configurations:
|
|
250
|
+
|
|
251
|
+
| Variable | Effect |
|
|
252
|
+
|---|---|
|
|
253
|
+
| `DSSRR_RAW_ROOT` | Pre-fills the **Raw DB** field on both the viewer and the Batch Repair page |
|
|
254
|
+
| `DSSRR_FIX_ROOT` | Pre-fills the **Repaired DB** field (otherwise it is derived as `<raw>_repaired`) |
|
|
255
|
+
| `DSSRR_PYTHON` | Interpreter used by `launch_gui.sh` / `启动DSSRR.bat` |
|
|
256
|
+
| `DSSRR_LANG` | Language of the whole interface (and of the exported report). Defaults to `en`; set to `zh` for Chinese. A language picked with the sidebar button overrides it |
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
DSSRR_RAW_ROOT=examples/data DSSRR_FIX_ROOT=examples/data_repaired python -m dssrr.gui
|
|
260
|
+
DSSRR_LANG=zh python -m dssrr.gui # Chinese interface + Chinese report figure
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Language
|
|
264
|
+
|
|
265
|
+
The GUI is **bilingual (English / 中文)**. Use the `Language: 中文` button at the
|
|
266
|
+
bottom of the sidebar to switch; the choice is remembered in
|
|
267
|
+
`QSettings(APP_ORG, APP_NAME)` under `UI/Language` and restored on the next start.
|
|
268
|
+
Switching re-labels every open panel immediately, including the matplotlib
|
|
269
|
+
navigation toolbars (which are third-party widgets whose text is not routed
|
|
270
|
+
through `self.tr()`).
|
|
271
|
+
|
|
272
|
+
How it works — there is no `.qm` toolchain involved:
|
|
273
|
+
|
|
274
|
+
* `dssrr/gui/translations_zh.py` is a plain `{english source: chinese}` dict
|
|
275
|
+
(423 entries covering 100% of the `self.tr()` / `QCoreApplication.translate()`
|
|
276
|
+
string constants under `dssrr/gui/`).
|
|
277
|
+
* `dssrr/gui/i18n.py` installs a `QTranslator` **subclass** that looks `source`
|
|
278
|
+
up in that dict and ignores `context`. Because it sits on the `QApplication`,
|
|
279
|
+
all ~580 existing `self.tr()` call sites work untouched, and any new one you
|
|
280
|
+
write is translated for free.
|
|
281
|
+
* A missing entry must return `None` (a null `QString`) so Qt falls back to the
|
|
282
|
+
English source. Returning `""` would be treated as a real, empty translation
|
|
283
|
+
and blank out the whole English interface — `tests/test_gui_i18n.py`
|
|
284
|
+
locks this down.
|
|
285
|
+
|
|
286
|
+
Text that lives outside the widget tree (report figures, axis labels, the
|
|
287
|
+
severity/recommendation strings in the diagnostics panel, the export-settings
|
|
288
|
+
dialog) is resolved by `dssrr.i18n.resolve_language()`, in this order:
|
|
289
|
+
|
|
290
|
+
1. an explicit `lang=` argument (e.g. `RepairReportPlotter(sr=..., lang="zh")`),
|
|
291
|
+
2. the process-level language set by the sidebar button (`dssrr.i18n.set_language`),
|
|
292
|
+
3. the `DSSRR_LANG` environment variable,
|
|
293
|
+
4. **English**.
|
|
294
|
+
|
|
295
|
+
The system locale is deliberately *not* consulted — earlier releases guessed
|
|
296
|
+
from it, which made a Chinese Windows show a Chinese export dialog inside an
|
|
297
|
+
otherwise English interface.
|
|
298
|
+
|
|
299
|
+
### Segment selection and the zoom/pan mode
|
|
300
|
+
|
|
301
|
+
Dragging on the waveform selects an anomaly segment, but matplotlib's Pan and
|
|
302
|
+
Zoom modes take `canvas.widgetlock`, which silently swallows the selection
|
|
303
|
+
events. When either mode is active the hint next to the navigation toolbar turns
|
|
304
|
+
into a warning — *"Zoom/pan is active — segment selection is disabled.
|
|
305
|
+
Click Zoom or Pan again to turn it off, then drag to select."* — and
|
|
306
|
+
switches back to the normal instructions once you leave the mode.
|
|
307
|
+
|
|
308
|
+
The batch page and the manual panel call **the same algorithms** as the library
|
|
309
|
+
— there is a single source of truth for the repair maths
|
|
310
|
+
(`tests/test_single_source_of_truth.py` enforces it).
|
|
311
|
+
|
|
312
|
+
## Batch repair from the command line
|
|
313
|
+
|
|
314
|
+
Cross-platform, no PyQt required — suitable for headless servers:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
dssrr-batch \
|
|
318
|
+
--raw-root /data/apollo/raw \
|
|
319
|
+
--fix-root /data/apollo/repair \
|
|
320
|
+
--stations S12,S15 \
|
|
321
|
+
--d0 19760101 --d1 19760131
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
It runs the full pipeline: E7 anomaly detection → multi-level repair →
|
|
325
|
+
moonquake-catalogue protection → per-month catalog CSV → automatic
|
|
326
|
+
verification → summary JSON. Exit status is `0` when verification passes for
|
|
327
|
+
every repaired file.
|
|
328
|
+
|
|
329
|
+
Full option list, directory conventions and worked examples:
|
|
330
|
+
[`docs/CLI.md`](docs/CLI.md).
|
|
331
|
+
|
|
332
|
+
```python
|
|
333
|
+
from dssrr.cli import quick_scan, batch_repair
|
|
334
|
+
|
|
335
|
+
print(quick_scan("/data/raw", ["S12"], 19760101, 19760131)["files"])
|
|
336
|
+
|
|
337
|
+
summary = batch_repair("/data/raw", "/data/repair", ["S12"],
|
|
338
|
+
19760101, 19760131)
|
|
339
|
+
print(summary["verify"]["ok"])
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## Parameters
|
|
343
|
+
|
|
344
|
+
`DSSRR(...)` constructor arguments:
|
|
345
|
+
|
|
346
|
+
| Parameter | Default | Meaning |
|
|
347
|
+
|---|---|---|
|
|
348
|
+
| `sr` | — | Sampling rate in Hz (must be positive) |
|
|
349
|
+
| `reference_sec` | `300.0` | Reference window length **per side**, in seconds |
|
|
350
|
+
| `seed` | `42` | Seed for deterministic synthesis; `None` = fresh randomness |
|
|
351
|
+
| `quantize` | `False` | Round the repaired samples back to integers |
|
|
352
|
+
| `config` | `None` | Overrides merged onto `dssrr.config.DEFAULT_CONFIG` |
|
|
353
|
+
|
|
354
|
+
`repair(...)` / `repair_with_report(...)` keywords: `reference_before_sec`,
|
|
355
|
+
`reference_after_sec`, `safety_gap_sec`, `random_seed`, `quantize`.
|
|
356
|
+
|
|
357
|
+
All thresholds — detection, spectral estimation, synthesis, layered
|
|
358
|
+
synthesis, joining, verification — live in one place:
|
|
359
|
+
[`dssrr/config.py`](dssrr/config.py). Pass `config={"verification": {...}}` to
|
|
360
|
+
override any of them.
|
|
361
|
+
|
|
362
|
+
```python
|
|
363
|
+
from dssrr import get_config
|
|
364
|
+
cfg = get_config()
|
|
365
|
+
cfg["synthesis"]["random_seed"] = 7
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## Key features
|
|
369
|
+
|
|
370
|
+
- **No training required** — no labelled data, no learned weights, works out
|
|
371
|
+
of the box on any locally stationary seismic time series.
|
|
372
|
+
- **Statistical fidelity** — preserves PSD, autocorrelation structure and
|
|
373
|
+
energy distribution, not just pointwise smoothness.
|
|
374
|
+
- **Robust for long gaps** — stable up to 90+ minutes, where simple methods
|
|
375
|
+
collapse.
|
|
376
|
+
- **Seamless boundaries** — trend alignment and phase-constrained edge
|
|
377
|
+
blending remove visible steps at the joins.
|
|
378
|
+
- **Non-destructive** — data outside the anomaly interval is never touched.
|
|
379
|
+
- **Lightweight core** — numpy + scipy only; importing `dssrr` never pulls
|
|
380
|
+
in a GUI toolkit.
|
|
381
|
+
- **Three tiers, one implementation** — library, CLI and GUI share the same
|
|
382
|
+
code path.
|
|
383
|
+
|
|
384
|
+
## Limitations
|
|
385
|
+
|
|
386
|
+
- DSSRR reproduces **second-order statistics**, not the original phase inside the
|
|
387
|
+
gap. A transient event during the dropout cannot be reconstructed.
|
|
388
|
+
- It assumes the signal inside the gap is statistically similar to the adjacent
|
|
389
|
+
healthy segments (local stationarity). A regime change across the gap biases
|
|
390
|
+
the fused target spectrum.
|
|
391
|
+
- Reference windows shorter than ~120 s (at 6.625 Hz) give poor low-frequency
|
|
392
|
+
resolution.
|
|
393
|
+
- The bundled `QualityVerifier.spectral_continuity` compares **raw**
|
|
394
|
+
(unsmoothed) periodograms over 0.5–3 Hz, so its absolute value is
|
|
395
|
+
realisation-dependent: two independent draws from the same process score
|
|
396
|
+
~0.5 rather than ~1.0. Treat it as a diagnostic, not an absolute
|
|
397
|
+
pass/fail gate — the batch pipeline's structural acceptance checks
|
|
398
|
+
(`dssrr.repair_lib.e7_repair_build.verify_file`) are the authoritative ones.
|
|
399
|
+
|
|
400
|
+
## Repository layout
|
|
401
|
+
|
|
402
|
+
```
|
|
403
|
+
dssrr/
|
|
404
|
+
├── core.py the DSSRR pipeline (ReferenceSpectrumReplacer)
|
|
405
|
+
├── spectral.py two-sided PSD estimation and fusion
|
|
406
|
+
├── synthesizer.py reference-block overlap-add synthesis
|
|
407
|
+
├── verifier.py quality diagnostics
|
|
408
|
+
├── config.py every threshold in one dict (DEFAULT_CONFIG)
|
|
409
|
+
├── cli.py dssrr-batch entry point
|
|
410
|
+
├── paths.py canonical user file locations (+ legacy fallback)
|
|
411
|
+
├── gui/ PyQt5 desktop application
|
|
412
|
+
│ ├── main.py integrated main window (viewer + manual repair)
|
|
413
|
+
│ ├── viewer.py raw/repaired archive comparison viewer
|
|
414
|
+
│ ├── manual_repair.py interactive interval repair
|
|
415
|
+
│ ├── depulse_dialog.py the multi-method repair panel
|
|
416
|
+
│ ├── batch_repair.py batch page
|
|
417
|
+
│ └── icons/ app icon (SVG + rasterised PNG/ICO)
|
|
418
|
+
└── repair_lib/ Apollo-specific detection + repair pipeline
|
|
419
|
+
├── e7_detector.py anomaly detection (MISSING/FREEZE/SAT/SPIKE/…)
|
|
420
|
+
├── e7_repair_build.py per-file multi-level repair + verification
|
|
421
|
+
├── repair_engine.py ObsPy glue for the GUI
|
|
422
|
+
├── depulse_advanced.py Isolation Forest / LOF / NN inpainting
|
|
423
|
+
├── report_plot.py repair report figures
|
|
424
|
+
└── anomaly_repair/ the three public replacers (+ re-export shims)
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## Sample data, provenance and acknowledgements
|
|
428
|
+
|
|
429
|
+
`examples/data/` contains three 12-hour **Apollo 12 / 15 / 16** long-period
|
|
430
|
+
vertical records (network `XA`, channel `MHZ`, 6.625 Hz, 1976-01-13) so that the
|
|
431
|
+
examples and tests can run against real archival data with no download step.
|
|
432
|
+
They are small, freely redistributable fixtures and are **not** installed with
|
|
433
|
+
the Python package. See [`examples/data/README.md`](examples/data/README.md) for
|
|
434
|
+
the full provenance and licensing statement.
|
|
435
|
+
|
|
436
|
+
The batch pipeline ships a merged moonquake catalogue assembled from:
|
|
437
|
+
|
|
438
|
+
- Gagnepain-Beyneix, J., et al. (2006), *A seismic model of the lunar mantle and
|
|
439
|
+
constraints on Moon's composition*, PEPI.
|
|
440
|
+
- Lognonné, P., et al. (2003), *Moon meteoritic seismic hum: steady state
|
|
441
|
+
prediction*, JGR.
|
|
442
|
+
- The Apollo PSE Long-Period Event Catalog (rev. 1008c).
|
|
443
|
+
|
|
444
|
+
Apollo lunar seismic data were produced by NASA's Apollo Lunar Surface
|
|
445
|
+
Experiments Package (ALSEP) and are distributed openly through the
|
|
446
|
+
[IRIS / EarthScope Data Management Center](https://ds.iris.edu/ds/nodes/dmc/).
|
|
447
|
+
This project is not affiliated with or endorsed by NASA or IRIS.
|
|
448
|
+
|
|
449
|
+
## FAQ
|
|
450
|
+
|
|
451
|
+
**Does DSSRR need a GPU or training?**
|
|
452
|
+
No. It is a classical spectral method — numpy + scipy only. The optional
|
|
453
|
+
`[nn]` extra adds a neural inpainting *alternative*, but it is not used by the
|
|
454
|
+
default DSSRR path.
|
|
455
|
+
|
|
456
|
+
**Will it change my data outside the gap?**
|
|
457
|
+
Never. The repaired array is a copy in which only `[start, end]` differs.
|
|
458
|
+
|
|
459
|
+
**Why does my result differ between runs?**
|
|
460
|
+
The synthesis phase is randomised. Pass a fixed `seed` / `random_seed` for
|
|
461
|
+
reproducible output; `None` deliberately requests fresh randomness.
|
|
462
|
+
|
|
463
|
+
**Can I use it on non-Apollo data?**
|
|
464
|
+
Yes — pass your own `sr` and choose the reference length with
|
|
465
|
+
`auto_reference_length`. The `repair_lib` detection pipeline, however, is tuned
|
|
466
|
+
for Apollo MHZ records and its anomaly classes (MISSING / FREEZE / SAT / SPIKE /
|
|
467
|
+
STEP / BURST) assume that instrument.
|
|
468
|
+
|
|
469
|
+
**A long gap got left unrepaired in batch mode.**
|
|
470
|
+
Gaps longer than `max_repair_sec` are intentionally **not** reconstructed: DSSRR
|
|
471
|
+
marks them in the catalog rather than fabricating data.
|
|
472
|
+
|
|
473
|
+
## Citation
|
|
474
|
+
|
|
475
|
+
If you use this code, please cite:
|
|
476
|
+
|
|
477
|
+
> Yu, S., Li, X. (2026). Dual-Sided Spectral Reference Reconstruction for
|
|
478
|
+
> long-duration artifact repair in Apollo lunar seismic records.
|
|
479
|
+
> *Seismological Research Letters* (submitted).
|
|
480
|
+
|
|
481
|
+
## License
|
|
482
|
+
|
|
483
|
+
MIT — see [LICENSE](LICENSE).
|