requake 0.8.2__tar.gz → 0.8.4__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.
- {requake-0.8.2 → requake-0.8.4}/CHANGELOG.md +82 -0
- {requake-0.8.2 → requake-0.8.4}/PKG-INFO +24 -4
- {requake-0.8.2 → requake-0.8.4}/README.md +20 -2
- {requake-0.8.2 → requake-0.8.4}/pyproject.toml +5 -0
- {requake-0.8.2 → requake-0.8.4}/requake/_version.py +3 -3
- {requake-0.8.2 → requake-0.8.4}/requake/catalog/catalog.py +3 -1
- {requake-0.8.2 → requake-0.8.4}/requake/catalog/print_catalog.py +12 -4
- {requake-0.8.2 → requake-0.8.4}/requake/catalog/read_catalog.py +6 -2
- {requake-0.8.2 → requake-0.8.4}/requake/catalog/read_catalog_from_fdsnws.py +15 -4
- {requake-0.8.2 → requake-0.8.4}/requake/config/configspec.conf +11 -1
- requake-0.8.4/requake/config/generic_printer.py +208 -0
- {requake-0.8.2 → requake-0.8.4}/requake/config/parse_arguments.py +483 -12
- {requake-0.8.2 → requake-0.8.4}/requake/config/rq_setup.py +43 -32
- {requake-0.8.2 → requake-0.8.4}/requake/config/utils.py +181 -10
- {requake-0.8.2 → requake-0.8.4}/requake/database/catalog.py +104 -3
- {requake-0.8.2 → requake-0.8.4}/requake/database/db.py +32 -0
- {requake-0.8.2 → requake-0.8.4}/requake/database/families.py +26 -8
- {requake-0.8.2 → requake-0.8.4}/requake/database/pairs.py +299 -24
- {requake-0.8.2 → requake-0.8.4}/requake/families/__init__.py +1 -0
- {requake-0.8.2 → requake-0.8.4}/requake/families/build_families.py +22 -9
- requake-0.8.4/requake/families/dedup_events.py +431 -0
- {requake-0.8.2 → requake-0.8.4}/requake/families/families.py +13 -6
- {requake-0.8.2 → requake-0.8.4}/requake/families/pairs.py +6 -2
- {requake-0.8.2 → requake-0.8.4}/requake/families/print_families.py +57 -3
- requake-0.8.4/requake/families/print_pairs.py +230 -0
- requake-0.8.4/requake/logo.py +15 -0
- {requake-0.8.2 → requake-0.8.4}/requake/main.py +24 -0
- requake-0.8.4/requake/pager.py +1392 -0
- {requake-0.8.2 → requake-0.8.4}/requake/plot/colormaps.py +13 -13
- requake-0.8.4/requake/plot/map_families.py +38 -0
- requake-0.8.2/requake/plot/map_families.py → requake-0.8.4/requake/plot/map_families_cartopy.py +47 -11
- requake-0.8.4/requake/plot/map_families_folium.py +582 -0
- requake-0.8.4/requake/plot/map_families_utils.py +291 -0
- requake-0.8.4/requake/plot/plot_families.py +996 -0
- requake-0.8.4/requake/scan/parallel_diagnostics.py +273 -0
- {requake-0.8.2 → requake-0.8.4}/requake/scan/scan_catalog.py +51 -38
- requake-0.8.4/requake/scan/scan_catalog_helpers.py +359 -0
- {requake-0.8.2 → requake-0.8.4}/requake/scan/scan_catalog_pairs.py +44 -44
- {requake-0.8.2 → requake-0.8.4}/requake/scan/scan_catalog_workers.py +332 -77
- requake-0.8.4/requake/scan/slurm_diagnostics.py +130 -0
- requake-0.8.4/requake/terminal.py +328 -0
- {requake-0.8.2 → requake-0.8.4}/requake/waveforms/arrivals.py +14 -2
- {requake-0.8.2 → requake-0.8.4}/requake/waveforms/station_metadata.py +110 -13
- {requake-0.8.2 → requake-0.8.4}/requake/waveforms/waveform_pair.py +72 -4
- {requake-0.8.2 → requake-0.8.4}/requake/waveforms/waveforms.py +131 -68
- requake-0.8.4/requake/wfcache/__init__.py +35 -0
- requake-0.8.4/requake/wfcache/commands.py +931 -0
- requake-0.8.4/requake/wfcache/storage.py +765 -0
- {requake-0.8.2 → requake-0.8.4}/requake.egg-info/PKG-INFO +24 -4
- {requake-0.8.2 → requake-0.8.4}/requake.egg-info/SOURCES.txt +13 -1
- {requake-0.8.2 → requake-0.8.4}/requake.egg-info/requires.txt +3 -0
- requake-0.8.2/requake/config/generic_printer.py +0 -65
- requake-0.8.2/requake/families/print_pairs.py +0 -83
- requake-0.8.2/requake/plot/plot_families.py +0 -249
- requake-0.8.2/requake/scan/scan_catalog_helpers.py +0 -317
- {requake-0.8.2 → requake-0.8.4}/CONTRIBUTORS.txt +0 -0
- {requake-0.8.2 → requake-0.8.4}/LICENSE.txt +0 -0
- {requake-0.8.2 → requake-0.8.4}/MANIFEST.in +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/__init__.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/catalog/__init__.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/catalog/read_catalog_from_csv.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/catalog/read_catalog_from_quakeml.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/config/__init__.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/config/config.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/config/configobj/LICENSE +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/config/configobj/__init__.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/config/configobj/_version.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/config/configobj/validate.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/database/__init__.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/database/templates.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/database/trace_metadata.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/families/build_templates.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/families/flag_family.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/formulas/__init__.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/formulas/conversion.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/formulas/moment.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/formulas/slip.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/plot/__init__.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/plot/cached_tiler.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/plot/map_tiles.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/plot/plot_cumulative.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/plot/plot_pair.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/plot/plot_timespans.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/plot/plot_utils.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/scan/__init__.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/scan/scan_templates.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake/waveforms/__init__.py +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake.egg-info/dependency_links.txt +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake.egg-info/entry_points.txt +0 -0
- {requake-0.8.2 → requake-0.8.4}/requake.egg-info/top_level.txt +0 -0
- {requake-0.8.2 → requake-0.8.4}/setup.cfg +0 -0
- {requake-0.8.2 → requake-0.8.4}/setup.py +0 -0
|
@@ -2,6 +2,86 @@
|
|
|
2
2
|
|
|
3
3
|
Copyright (c) 2021-2026 Claudio Satriano <satriano@ipgp.fr>
|
|
4
4
|
|
|
5
|
+
## [0.8.4] - 2026-10-23
|
|
6
|
+
|
|
7
|
+
- ``plot_families``: new ``--mode`` option, to draw the families as a
|
|
8
|
+
heatmap (``--mode heatmap``): one row per event, with the trace
|
|
9
|
+
amplitudes encoded in color and the family average drawn as a wiggle
|
|
10
|
+
below. The default remains the wiggle plot (``--mode wiggle``).
|
|
11
|
+
- ``plot_families``: the family average is now drawn in its own panel
|
|
12
|
+
also in ``--mode wiggle``, and both modes show an extra panel below
|
|
13
|
+
it, where all the traces of the family are drawn stacked on top of
|
|
14
|
+
each other, with the average highlighted on top, so that the waveform
|
|
15
|
+
similarity can be judged at a glance.
|
|
16
|
+
- ``plot_families``: new ``--max-labels`` option (default 15), to set
|
|
17
|
+
the maximum number of traces carrying a label. When a family has more
|
|
18
|
+
traces than that, only a subset of them is labeled (in wiggle mode,
|
|
19
|
+
the labeled traces are also highlighted and the traces are scaled up),
|
|
20
|
+
so that large families remain readable. Use 0 to label every trace.
|
|
21
|
+
- New ``-E``/``--events`` option for ``print_families``, to print one
|
|
22
|
+
row per event (ordered by family number and origin time), instead of
|
|
23
|
+
one row per family; combine with ``-f csv`` to export the list.
|
|
24
|
+
- New ``dedup_events`` command: flags likely duplicate events (event
|
|
25
|
+
pairs with high cross-correlation, close in time and space) with the
|
|
26
|
+
new ``duplicate`` column in the catalog, and marks all the pairs
|
|
27
|
+
involving them as invalid (new ``invalid`` column in ``event_pairs``);
|
|
28
|
+
``build_families`` ignores the invalid pairs. A compact report is
|
|
29
|
+
printed at the end (``-n``/``--dry-run`` only prints it) and
|
|
30
|
+
``--reset`` clears the flags.
|
|
31
|
+
- ``print_pairs`` hides the invalid pairs by default; the new
|
|
32
|
+
``--include-invalid`` option lists them as well.
|
|
33
|
+
- Long operations now show a progress indicator, and long database
|
|
34
|
+
queries can be interrupted with ``Ctrl+C`` (pressed twice): the
|
|
35
|
+
database is closed cleanly (no stray ``-wal``/``-shm`` files) and the
|
|
36
|
+
abort is no longer reported as a bug.
|
|
37
|
+
- Fixed the non-paged table output (``--no-pager``), which dropped all
|
|
38
|
+
the rows but the last batch.
|
|
39
|
+
- Stylized ``◀◀ RƎQuake`` logo, shown in the command line help.
|
|
40
|
+
- Colored terminal output for help and usage messages, log messages,
|
|
41
|
+
errors, table headers and waveform-cache diagnostics. Colors are used
|
|
42
|
+
only on interactive terminals, and are therefore automatically removed
|
|
43
|
+
when the output is piped or redirected. The ``NO_COLOR`` and
|
|
44
|
+
``FORCE_COLOR`` environment variables can be used to force colors off
|
|
45
|
+
or on.
|
|
46
|
+
- New interactive curses pager for all ``print_`` commands
|
|
47
|
+
(``print_catalog``, ``print_pairs``, ``print_families``).
|
|
48
|
+
Automatically activated when output is a terminal; use ``--no-pager``
|
|
49
|
+
to fall back to plain-text output. Requesting a specific output format
|
|
50
|
+
with ``-f``/``--format`` implies ``--no-pager``.
|
|
51
|
+
- New ``-b/--backend`` option for ``map_families``, to plot families on
|
|
52
|
+
an interactive HTML map using
|
|
53
|
+
[folium](https://python-visualization.github.io/folium/), instead of
|
|
54
|
+
the default static Cartopy map. Folium is an optional dependency (not
|
|
55
|
+
installed by default): the folium backend is only used if folium is
|
|
56
|
+
installed.
|
|
57
|
+
- Family marker size is now scaled with a quantity selected with the new
|
|
58
|
+
``-s/--sizeby`` option (default: number of events), and a legend on the
|
|
59
|
+
map explains the marker size. This applies to both the Cartopy and the
|
|
60
|
+
Folium map backends.
|
|
61
|
+
- Clickable URLs in terminal output for compatible terminals, e.g. in the
|
|
62
|
+
help messages and in the bug report.
|
|
63
|
+
- New documentation page on event pairs, covering `print_pairs`,
|
|
64
|
+
`plot_pair` and `dedup_events`.
|
|
65
|
+
|
|
66
|
+
## [0.8.3] - 2026-06-19
|
|
67
|
+
|
|
68
|
+
Note: you should run `requake update_config` to update your config file
|
|
69
|
+
to the latest version.
|
|
70
|
+
|
|
71
|
+
The waveform disk cache is now a single SQLite database
|
|
72
|
+
(`OUTDIR/waveform_cache.sqlite`) with a persistent negative cache that
|
|
73
|
+
remembers failed downloads across runs, eliminating redundant HTTP requests.
|
|
74
|
+
|
|
75
|
+
- New `wfcache` CLI: `prefetch`, `print`/`inspect`, `extract`,
|
|
76
|
+
`reset-failures`.
|
|
77
|
+
- New config: `catalog_waveform_cache_failure_max_retries`,
|
|
78
|
+
`catalog_waveform_cache_failure_backoff_s`,
|
|
79
|
+
`catalog_waveform_require_prefetch`.
|
|
80
|
+
- Several optimization for parallel runs in `scan_catalog` (especially on
|
|
81
|
+
Slurm clusters) and for startup time of `scan_catalog -c` (continue an
|
|
82
|
+
interrupted scan).
|
|
83
|
+
- Extended documentation for `read_catalog`, `scan_catalog` and `wfcache`.
|
|
84
|
+
|
|
5
85
|
## [0.8.2] - 2026-06-03
|
|
6
86
|
|
|
7
87
|
Note: you might want to run `requake update_config` to update your config file
|
|
@@ -187,6 +267,8 @@ Mostly a bugfix release with a slightly improved trace plotting.
|
|
|
187
267
|
|
|
188
268
|
- Initial release, not yet feature complete
|
|
189
269
|
|
|
270
|
+
[0.8.4]: https://github.com/SeismicSource/requake/compare/v0.8.3...v0.8.4
|
|
271
|
+
[0.8.3]: https://github.com/SeismicSource/requake/compare/v0.8.2...v0.8.3
|
|
190
272
|
[0.8.2]: https://github.com/SeismicSource/requake/compare/v0.8.1...v0.8.2
|
|
191
273
|
[0.8.1]: https://github.com/SeismicSource/requake/compare/v0.8...v0.8.1
|
|
192
274
|
[0.8]: https://github.com/SeismicSource/requake/compare/v0.7.3...v0.8
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: requake
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.4
|
|
4
4
|
Summary: Repeating earthquakes search and analysis
|
|
5
5
|
Author-email: Claudio Satriano <satriano@ipgp.fr>
|
|
6
6
|
License-Expression: GPL-3.0-or-later
|
|
@@ -33,11 +33,13 @@ Requires-Dist: argcomplete
|
|
|
33
33
|
Requires-Dist: tqdm
|
|
34
34
|
Requires-Dist: tabulate
|
|
35
35
|
Requires-Dist: pygments
|
|
36
|
+
Provides-Extra: folium
|
|
37
|
+
Requires-Dist: folium; extra == "folium"
|
|
36
38
|
Dynamic: description
|
|
37
39
|
Dynamic: description-content-type
|
|
38
40
|
Dynamic: license-file
|
|
39
41
|
|
|
40
|
-
<img src="https://cdn.jsdelivr.net/gh/SeismicSource/requake@
|
|
42
|
+
<img src="https://cdn.jsdelivr.net/gh/SeismicSource/requake@5cd818d88427140b2705841c2046f72b10612d72/imgs/Requake_logo.svg" width="400">
|
|
41
43
|
|
|
42
44
|
# Requake
|
|
43
45
|
|
|
@@ -167,6 +169,8 @@ Different commands are available:
|
|
|
167
169
|
print_catalog print the event catalog to screen
|
|
168
170
|
scan_catalog scan an existing catalog for earthquake pairs
|
|
169
171
|
print_pairs print pairs to screen
|
|
172
|
+
dedup_events detect and flag duplicate events in the catalog from
|
|
173
|
+
close event pairs
|
|
170
174
|
plot_pair plot traces for a given event pair
|
|
171
175
|
build_families build families of repeating earthquakes from a catalog
|
|
172
176
|
of pairs
|
|
@@ -181,6 +185,8 @@ Different commands are available:
|
|
|
181
185
|
families
|
|
182
186
|
scan_templates scan a continuous waveform stream using one or more
|
|
183
187
|
templates
|
|
188
|
+
wfcache manage persistent waveform cache (prefetch, print,
|
|
189
|
+
inspect, extract, reset_failures)
|
|
184
190
|
|
|
185
191
|
Certain commands (e.g., `plot_pair`) require further arguments (use, e.g.,
|
|
186
192
|
`requake plot_pair -h` to get help).
|
|
@@ -216,6 +222,14 @@ Now, build the catalog of event pairs with:
|
|
|
216
222
|
|
|
217
223
|
requake scan_catalog
|
|
218
224
|
|
|
225
|
+
When relying on FDSN web services for waveform data, it is strongly
|
|
226
|
+
recommended to prefetch all waveform windows before running the scan.
|
|
227
|
+
This downloads every required waveform once and stores it in a local
|
|
228
|
+
SQLite cache, avoiding repeated downloads and dramatically reducing
|
|
229
|
+
overall runtime for large catalogs:
|
|
230
|
+
|
|
231
|
+
requake wfcache prefetch
|
|
232
|
+
|
|
219
233
|
Once done ([it will take time!](#performances)), you are ready to build
|
|
220
234
|
repeating earthquake families:
|
|
221
235
|
|
|
@@ -232,6 +246,12 @@ repeating earthquake families:
|
|
|
232
246
|
performance is typically dominated by waveform download latency rather than
|
|
233
247
|
computation.
|
|
234
248
|
|
|
249
|
+
- For large FDSN-based runs, use `requake wfcache prefetch` before
|
|
250
|
+
`requake scan_catalog` to download all waveforms upfront into a local
|
|
251
|
+
SQLite cache. This eliminates repeated downloads, lets the scan read
|
|
252
|
+
exclusively from disk, and is the single most effective way to speed up
|
|
253
|
+
catalog scanning.
|
|
254
|
+
|
|
235
255
|
- `requake build_families` is fast™.
|
|
236
256
|
|
|
237
257
|
## How to Cite
|
|
@@ -244,7 +264,7 @@ If you used Requake for a scientific paper, please cite it as:
|
|
|
244
264
|
Please replace `X.Y` with the Requake version number you used.
|
|
245
265
|
|
|
246
266
|
You can also cite the following abstract presented at the
|
|
247
|
-
|
|
267
|
+
2021 AGU Fall Meeting:
|
|
248
268
|
|
|
249
269
|
> Satriano, C., Doucet, A. & Bouin, M.-P. (2021).
|
|
250
270
|
> Probing the creep rate along the Lesser Antilles Subduction Zone through repeating earthquakes.
|
|
@@ -260,7 +280,7 @@ You can also cite the following abstract presented at the
|
|
|
260
280
|
[docs-link]: https://requake.readthedocs.io/en/latest/?badge=latest
|
|
261
281
|
[changelog-badge]: https://img.shields.io/badge/Changelog-136CB6.svg
|
|
262
282
|
[changelog-link]: https://github.com/SeismicSource/requake/blob/main/CHANGELOG.md
|
|
263
|
-
[DOI-badge]: https://
|
|
283
|
+
[DOI-badge]: https://img.shields.io/badge/DOI-10.5281%2Fzenodo.10832203-blue.svg
|
|
264
284
|
[DOI-link]: https://doi.org/10.5281/zenodo.10832203
|
|
265
285
|
[Requake GitHub repository]: https://github.com/SeismicSource/requake
|
|
266
286
|
|
|
@@ -128,6 +128,8 @@ Different commands are available:
|
|
|
128
128
|
print_catalog print the event catalog to screen
|
|
129
129
|
scan_catalog scan an existing catalog for earthquake pairs
|
|
130
130
|
print_pairs print pairs to screen
|
|
131
|
+
dedup_events detect and flag duplicate events in the catalog from
|
|
132
|
+
close event pairs
|
|
131
133
|
plot_pair plot traces for a given event pair
|
|
132
134
|
build_families build families of repeating earthquakes from a catalog
|
|
133
135
|
of pairs
|
|
@@ -142,6 +144,8 @@ Different commands are available:
|
|
|
142
144
|
families
|
|
143
145
|
scan_templates scan a continuous waveform stream using one or more
|
|
144
146
|
templates
|
|
147
|
+
wfcache manage persistent waveform cache (prefetch, print,
|
|
148
|
+
inspect, extract, reset_failures)
|
|
145
149
|
|
|
146
150
|
Certain commands (e.g., `plot_pair`) require further arguments (use, e.g.,
|
|
147
151
|
`requake plot_pair -h` to get help).
|
|
@@ -177,6 +181,14 @@ Now, build the catalog of event pairs with:
|
|
|
177
181
|
|
|
178
182
|
requake scan_catalog
|
|
179
183
|
|
|
184
|
+
When relying on FDSN web services for waveform data, it is strongly
|
|
185
|
+
recommended to prefetch all waveform windows before running the scan.
|
|
186
|
+
This downloads every required waveform once and stores it in a local
|
|
187
|
+
SQLite cache, avoiding repeated downloads and dramatically reducing
|
|
188
|
+
overall runtime for large catalogs:
|
|
189
|
+
|
|
190
|
+
requake wfcache prefetch
|
|
191
|
+
|
|
180
192
|
Once done ([it will take time!](#performances)), you are ready to build
|
|
181
193
|
repeating earthquake families:
|
|
182
194
|
|
|
@@ -193,6 +205,12 @@ repeating earthquake families:
|
|
|
193
205
|
performance is typically dominated by waveform download latency rather than
|
|
194
206
|
computation.
|
|
195
207
|
|
|
208
|
+
- For large FDSN-based runs, use `requake wfcache prefetch` before
|
|
209
|
+
`requake scan_catalog` to download all waveforms upfront into a local
|
|
210
|
+
SQLite cache. This eliminates repeated downloads, lets the scan read
|
|
211
|
+
exclusively from disk, and is the single most effective way to speed up
|
|
212
|
+
catalog scanning.
|
|
213
|
+
|
|
196
214
|
- `requake build_families` is fast™.
|
|
197
215
|
|
|
198
216
|
## How to Cite
|
|
@@ -205,7 +223,7 @@ If you used Requake for a scientific paper, please cite it as:
|
|
|
205
223
|
Please replace `X.Y` with the Requake version number you used.
|
|
206
224
|
|
|
207
225
|
You can also cite the following abstract presented at the
|
|
208
|
-
|
|
226
|
+
2021 AGU Fall Meeting:
|
|
209
227
|
|
|
210
228
|
> Satriano, C., Doucet, A. & Bouin, M.-P. (2021).
|
|
211
229
|
> Probing the creep rate along the Lesser Antilles Subduction Zone through repeating earthquakes.
|
|
@@ -221,7 +239,7 @@ You can also cite the following abstract presented at the
|
|
|
221
239
|
[docs-link]: https://requake.readthedocs.io/en/latest/?badge=latest
|
|
222
240
|
[changelog-badge]: https://img.shields.io/badge/Changelog-136CB6.svg
|
|
223
241
|
[changelog-link]: https://github.com/SeismicSource/requake/blob/main/CHANGELOG.md
|
|
224
|
-
[DOI-badge]: https://
|
|
242
|
+
[DOI-badge]: https://img.shields.io/badge/DOI-10.5281%2Fzenodo.10832203-blue.svg
|
|
225
243
|
[DOI-link]: https://doi.org/10.5281/zenodo.10832203
|
|
226
244
|
[Requake GitHub repository]: https://github.com/SeismicSource/requake
|
|
227
245
|
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2026-
|
|
11
|
+
"date": "2026-10-23T18:15:54+0200",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "0.8.
|
|
14
|
+
"full-revisionid": "5cd818d88427140b2705841c2046f72b10612d72",
|
|
15
|
+
"version": "0.8.4"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -26,7 +26,8 @@ class RequakeEvent():
|
|
|
26
26
|
def __init__(self, evid=None, orig_time=None, lon=None, lat=None,
|
|
27
27
|
depth=None, mag_type=None, mag=None, author=None,
|
|
28
28
|
catalog=None, contributor=None, contributor_id=None,
|
|
29
|
-
mag_author=None, location_name=None, trace_id=None
|
|
29
|
+
mag_author=None, location_name=None, trace_id=None,
|
|
30
|
+
duplicate=False):
|
|
30
31
|
"""Initialize an event container."""
|
|
31
32
|
self.evid = evid
|
|
32
33
|
self.orig_time = orig_time
|
|
@@ -42,6 +43,7 @@ class RequakeEvent():
|
|
|
42
43
|
self.mag_author = mag_author
|
|
43
44
|
self.location_name = location_name
|
|
44
45
|
self.trace_id = trace_id
|
|
46
|
+
self.duplicate = duplicate
|
|
45
47
|
self.correlations = {}
|
|
46
48
|
|
|
47
49
|
def __eq__(self, other):
|
|
@@ -10,7 +10,8 @@ Print the event catalog to screen.
|
|
|
10
10
|
(https://www.gnu.org/licenses/gpl-3.0-standalone.html)
|
|
11
11
|
"""
|
|
12
12
|
import logging
|
|
13
|
-
from ..config import rq_exit
|
|
13
|
+
from ..config import rq_exit
|
|
14
|
+
from ..config.generic_printer import _display_table
|
|
14
15
|
from .catalog import read_stored_catalog
|
|
15
16
|
logger = logging.getLogger(__name__.rsplit('.', maxsplit=1)[-1])
|
|
16
17
|
|
|
@@ -30,7 +31,8 @@ def print_catalog():
|
|
|
30
31
|
('latitude', '.4f'),
|
|
31
32
|
('depth\n(km)', '.3f'),
|
|
32
33
|
('mag\ntype', None),
|
|
33
|
-
('mag', '.1f')
|
|
34
|
+
('mag', '.1f'),
|
|
35
|
+
('dup', None)
|
|
34
36
|
]
|
|
35
37
|
rows = [
|
|
36
38
|
[
|
|
@@ -40,8 +42,14 @@ def print_catalog():
|
|
|
40
42
|
ev.lat,
|
|
41
43
|
ev.depth,
|
|
42
44
|
ev.mag_type,
|
|
43
|
-
ev.mag
|
|
45
|
+
ev.mag,
|
|
46
|
+
ev.duplicate
|
|
44
47
|
]
|
|
45
48
|
for ev in catalog
|
|
46
49
|
]
|
|
47
|
-
|
|
50
|
+
_display_table(
|
|
51
|
+
headers_fmt, rows,
|
|
52
|
+
row_label='Events',
|
|
53
|
+
copy_label='evid',
|
|
54
|
+
detail_title='Event Details',
|
|
55
|
+
)
|
|
@@ -13,6 +13,7 @@ import os
|
|
|
13
13
|
import logging
|
|
14
14
|
import contextlib
|
|
15
15
|
from ..config import config, rq_exit
|
|
16
|
+
from ..config.utils import run_with_spinner
|
|
16
17
|
from ..database.db import get_db_path
|
|
17
18
|
from ..database.catalog import write_catalog as write_stored_catalog
|
|
18
19
|
from .catalog import RequakeEvent, RequakeCatalog
|
|
@@ -120,11 +121,14 @@ def read_catalog():
|
|
|
120
121
|
f'{nevs_read:n} events read from db file '
|
|
121
122
|
f'{get_db_path()}'
|
|
122
123
|
)
|
|
123
|
-
logger.
|
|
124
|
+
logger.debug('Reading catalog...')
|
|
124
125
|
input_cat_file = config.args.catalog_file
|
|
125
126
|
if input_cat_file is not None:
|
|
126
127
|
try:
|
|
127
|
-
catalog +=
|
|
128
|
+
catalog += run_with_spinner(
|
|
129
|
+
'Reading catalog...',
|
|
130
|
+
_read_catalog_from_file,
|
|
131
|
+
)
|
|
128
132
|
# Filter catalog based on configuration
|
|
129
133
|
catalog = _filter_catalog(catalog)
|
|
130
134
|
except FileNotFoundError:
|
|
@@ -15,6 +15,7 @@ import urllib.request
|
|
|
15
15
|
from obspy import UTCDateTime
|
|
16
16
|
from obspy.clients.fdsn.header import URL_MAPPINGS
|
|
17
17
|
from ..config import config
|
|
18
|
+
from ..config.utils import run_with_spinner
|
|
18
19
|
from .catalog import RequakeCatalog, RequakeEvent
|
|
19
20
|
logger = logging.getLogger(__name__.rsplit('.', maxsplit=1)[-1])
|
|
20
21
|
|
|
@@ -110,7 +111,19 @@ def read_catalog_from_fdsnws():
|
|
|
110
111
|
:return: Event catalog.
|
|
111
112
|
:rtype: requake.catalog.RequakeCatalog
|
|
112
113
|
"""
|
|
113
|
-
|
|
114
|
+
download_message = 'Downloading events from FDSN web services...'
|
|
115
|
+
logger.debug(download_message)
|
|
116
|
+
event_list = run_with_spinner(
|
|
117
|
+
download_message,
|
|
118
|
+
_download_catalog_events,
|
|
119
|
+
)
|
|
120
|
+
catalog = RequakeCatalog(event_list)
|
|
121
|
+
logger.info(f'{len(catalog)} events downloaded')
|
|
122
|
+
return catalog
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _download_catalog_events():
|
|
126
|
+
"""Download events for all the configured FDSN web services."""
|
|
114
127
|
cat_info = zip(
|
|
115
128
|
config.catalog_fdsn_event_urls,
|
|
116
129
|
config.catalog_start_times,
|
|
@@ -135,6 +148,4 @@ def read_catalog_from_fdsnws():
|
|
|
135
148
|
f'Unable to download events from {url} for period '
|
|
136
149
|
f'{start_time} - {end_time}. {msg}'
|
|
137
150
|
)
|
|
138
|
-
|
|
139
|
-
logger.info(f'{len(catalog)} events downloaded')
|
|
140
|
-
return catalog
|
|
151
|
+
return event_list
|
|
@@ -76,9 +76,19 @@ catalog_waveform_cache_size = integer(min=2, default=5000)
|
|
|
76
76
|
## Set to 0 to derive it automatically from catalog_waveform_cache_size.
|
|
77
77
|
catalog_waveform_cache_size_parallel = integer(min=0, default=0)
|
|
78
78
|
## Keep a persistent copy of fetched event waveforms on disk to speed up
|
|
79
|
-
## reruns. This on-disk cache lives in OUTDIR/waveform_cache and is
|
|
79
|
+
## reruns. This on-disk cache lives in OUTDIR/waveform_cache.sqlite and is
|
|
80
80
|
## limited by catalog_waveform_cache_size.
|
|
81
81
|
catalog_waveform_disk_cache_enabled = boolean(default=true)
|
|
82
|
+
## Maximum number of retries for a failed waveform download before
|
|
83
|
+
## suppressing new attempts for the same cache key.
|
|
84
|
+
catalog_waveform_cache_failure_max_retries = integer(min=0, default=3)
|
|
85
|
+
## Base backoff in seconds for persistent waveform download failures.
|
|
86
|
+
## The retry delay grows exponentially with each failure.
|
|
87
|
+
catalog_waveform_cache_failure_backoff_s = float(min=0, default=600)
|
|
88
|
+
## When True, skip live downloads for events absent from both positive
|
|
89
|
+
## and negative cache, trusting a prior prefetch run to have covered
|
|
90
|
+
## all fetchable events. Requires disk cache to be enabled.
|
|
91
|
+
catalog_waveform_require_prefetch = boolean(default=false)
|
|
82
92
|
## Number of worker processes for catalog scan.
|
|
83
93
|
## 0 means automatic selection; 1 disables parallelism.
|
|
84
94
|
catalog_scan_nprocs = integer(min=0, default=0)
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# -*- coding: utf8 -*-
|
|
2
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
3
|
+
"""
|
|
4
|
+
Generic printer functions for Requake.
|
|
5
|
+
|
|
6
|
+
:copyright:
|
|
7
|
+
2021-2026 Claudio Satriano <satriano@ipgp.fr>
|
|
8
|
+
:license:
|
|
9
|
+
GNU General Public License v3.0 or later
|
|
10
|
+
(https://www.gnu.org/licenses/gpl-3.0-standalone.html)
|
|
11
|
+
"""
|
|
12
|
+
import sys
|
|
13
|
+
import os
|
|
14
|
+
import csv
|
|
15
|
+
import contextlib
|
|
16
|
+
import logging
|
|
17
|
+
from tabulate import tabulate
|
|
18
|
+
from ..terminal import color_enabled, style
|
|
19
|
+
from .config import config
|
|
20
|
+
logger = logging.getLogger(__name__.rsplit('.', maxsplit=1)[-1])
|
|
21
|
+
|
|
22
|
+
# Characters appearing in a ``tabulate`` separator (or divider) line.
|
|
23
|
+
_TABLE_SEPARATOR_CHARS = frozenset('-|=+: ')
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _is_separator_line(line):
|
|
27
|
+
"""Return True if ``line`` is a table separator (or divider) line."""
|
|
28
|
+
stripped = line.strip()
|
|
29
|
+
return bool(stripped) and set(stripped) <= _TABLE_SEPARATOR_CHARS
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _style_table(text, has_header=True):
|
|
33
|
+
"""
|
|
34
|
+
Colorize a plain-text table produced by :func:`tabulate`.
|
|
35
|
+
|
|
36
|
+
Header lines are highlighted in bold cyan, separator lines are
|
|
37
|
+
dimmed, and data rows are left untouched.
|
|
38
|
+
|
|
39
|
+
:param text: table text
|
|
40
|
+
:type text: str
|
|
41
|
+
:param has_header: whether the table starts with a header
|
|
42
|
+
:type has_header: bool
|
|
43
|
+
|
|
44
|
+
:return: colorized table text
|
|
45
|
+
:rtype: str
|
|
46
|
+
"""
|
|
47
|
+
if not color_enabled():
|
|
48
|
+
return text
|
|
49
|
+
lines = text.split('\n')
|
|
50
|
+
separator_index = next(
|
|
51
|
+
(i for i, line in enumerate(lines) if _is_separator_line(line)),
|
|
52
|
+
None,
|
|
53
|
+
)
|
|
54
|
+
if separator_index is None:
|
|
55
|
+
separator_index = 1 if has_header else 0
|
|
56
|
+
styled_lines = []
|
|
57
|
+
for index, line in enumerate(lines):
|
|
58
|
+
if _is_separator_line(line):
|
|
59
|
+
styled_lines.append(style(line, 'dim'))
|
|
60
|
+
elif has_header and index < separator_index:
|
|
61
|
+
styled_lines.append(style(line, 'bold', 'cyan'))
|
|
62
|
+
else:
|
|
63
|
+
styled_lines.append(line)
|
|
64
|
+
return '\n'.join(styled_lines)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _drop_header_block(text):
|
|
68
|
+
"""
|
|
69
|
+
Return ``text`` without the table header and its separator line.
|
|
70
|
+
|
|
71
|
+
Used for continuation batches, which must not repeat the header
|
|
72
|
+
but must keep all their data rows.
|
|
73
|
+
|
|
74
|
+
:param text: table text
|
|
75
|
+
:type text: str
|
|
76
|
+
:return: table text without the header block
|
|
77
|
+
:rtype: str
|
|
78
|
+
"""
|
|
79
|
+
lines = text.split('\n')
|
|
80
|
+
separator_index = next(
|
|
81
|
+
(i for i, line in enumerate(lines) if _is_separator_line(line)),
|
|
82
|
+
None,
|
|
83
|
+
)
|
|
84
|
+
if separator_index is None:
|
|
85
|
+
return '\n'.join(lines[1:])
|
|
86
|
+
return '\n'.join(lines[separator_index + 1:])
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def generic_printer(rows, headers_fmt, print_headers=True):
|
|
90
|
+
"""
|
|
91
|
+
Print rows using the configured output format.
|
|
92
|
+
|
|
93
|
+
:param rows: Rows to print.
|
|
94
|
+
:type rows: list of rows
|
|
95
|
+
:param headers_fmt: Headers and format strings.
|
|
96
|
+
:type headers_fmt: list of tuples of str
|
|
97
|
+
"""
|
|
98
|
+
headers = [h[0] for h in headers_fmt]
|
|
99
|
+
# Replace None with a safe default so tabulate never receives
|
|
100
|
+
# None as a format specifier (crashes on float columns).
|
|
101
|
+
floatfmt = [
|
|
102
|
+
h[1] if h[1] is not None else '.6g' for h in headers_fmt
|
|
103
|
+
]
|
|
104
|
+
tablefmt = config.args.format
|
|
105
|
+
if tablefmt == 'csv':
|
|
106
|
+
writer = csv.writer(sys.stdout)
|
|
107
|
+
if print_headers:
|
|
108
|
+
# replace newlines with spaces in headers
|
|
109
|
+
headers = [h.replace('\n', ' ') for h in headers]
|
|
110
|
+
writer.writerow(headers)
|
|
111
|
+
elif tablefmt == 'markdown':
|
|
112
|
+
headers = [h.replace('\n', '<br>') for h in headers]
|
|
113
|
+
if tablefmt == 'csv':
|
|
114
|
+
try:
|
|
115
|
+
writer.writerows(rows)
|
|
116
|
+
except BrokenPipeError:
|
|
117
|
+
# Redirect remaining output to devnull to avoid another
|
|
118
|
+
# BrokenPipeError at shutdown
|
|
119
|
+
devnull = os.open(os.devnull, os.O_WRONLY)
|
|
120
|
+
os.dup2(devnull, sys.stdout.fileno())
|
|
121
|
+
else:
|
|
122
|
+
format_dict = {
|
|
123
|
+
'simple': 'simple',
|
|
124
|
+
'markdown': 'github'
|
|
125
|
+
}
|
|
126
|
+
tablefmt = format_dict[config.args.format]
|
|
127
|
+
with contextlib.suppress(BrokenPipeError):
|
|
128
|
+
kwargs = {
|
|
129
|
+
'headers': headers,
|
|
130
|
+
'floatfmt': floatfmt,
|
|
131
|
+
'tablefmt': tablefmt
|
|
132
|
+
}
|
|
133
|
+
line = tabulate(rows, **kwargs)
|
|
134
|
+
if not print_headers:
|
|
135
|
+
line = _drop_header_block(line)
|
|
136
|
+
if not line:
|
|
137
|
+
return
|
|
138
|
+
print(_style_table(line, has_header=print_headers))
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _display_table(headers_fmt, rows=None, data_source=None,
|
|
142
|
+
row_label='Rows', copy_label=None,
|
|
143
|
+
copy_fn=None, detail_title='Row Details',
|
|
144
|
+
print_headers=True):
|
|
145
|
+
"""
|
|
146
|
+
Display a table using the interactive curses pager.
|
|
147
|
+
|
|
148
|
+
When stdout is a TTY (and ``--no-pager`` is not set), the
|
|
149
|
+
interactive pager is used. Otherwise the table is printed
|
|
150
|
+
to stdout via :func:`generic_printer`.
|
|
151
|
+
|
|
152
|
+
:param headers_fmt: Headers and format strings
|
|
153
|
+
(list of (name, fmt) tuples).
|
|
154
|
+
:param rows: In-memory rows (list of lists). Ignored when
|
|
155
|
+
*data_source* is given.
|
|
156
|
+
:param data_source: Optional :class:`~requake.pager.DataSource`
|
|
157
|
+
for database-backed pagination.
|
|
158
|
+
:param row_label: Label for rows in the pager status bar.
|
|
159
|
+
:param copy_label: Label for the copy-to-clipboard message.
|
|
160
|
+
:param copy_fn: Optional callable ``copy_fn(row) -> str`` for
|
|
161
|
+
custom copy behaviour.
|
|
162
|
+
:param detail_title: Title for the detail popup.
|
|
163
|
+
:param print_headers: Whether to include the header row
|
|
164
|
+
(used for iterative printing fallback).
|
|
165
|
+
"""
|
|
166
|
+
# Determine whether to use the pager
|
|
167
|
+
use_pager = sys.stdout.isatty()
|
|
168
|
+
if use_pager:
|
|
169
|
+
no_pager = getattr(config.args, 'no_pager', False)
|
|
170
|
+
if no_pager:
|
|
171
|
+
use_pager = False
|
|
172
|
+
|
|
173
|
+
if use_pager:
|
|
174
|
+
from ..pager import (
|
|
175
|
+
display_table_pager,
|
|
176
|
+
PagerException,
|
|
177
|
+
ListDataSource,
|
|
178
|
+
)
|
|
179
|
+
with contextlib.suppress(PagerException):
|
|
180
|
+
if data_source is not None:
|
|
181
|
+
ds = data_source
|
|
182
|
+
else:
|
|
183
|
+
fields = [h[0].replace('\n', ' ') for h in headers_fmt]
|
|
184
|
+
ds = ListDataSource(fields, rows or [])
|
|
185
|
+
display_table_pager(
|
|
186
|
+
ds,
|
|
187
|
+
row_label=row_label,
|
|
188
|
+
copy_label=copy_label,
|
|
189
|
+
copy_fn=copy_fn,
|
|
190
|
+
detail_title=detail_title,
|
|
191
|
+
)
|
|
192
|
+
return
|
|
193
|
+
# Fallback: plain-text output via generic_printer
|
|
194
|
+
if data_source is not None:
|
|
195
|
+
# For DB-backed sources, stream rows via generic_printer
|
|
196
|
+
fields = data_source.fields
|
|
197
|
+
total = data_source.total_count
|
|
198
|
+
batch_size = 1000
|
|
199
|
+
for offset in range(0, total, batch_size):
|
|
200
|
+
batch = data_source.get_rows(offset, batch_size, None, True)
|
|
201
|
+
# Rebuild headers_fmt for generic_printer
|
|
202
|
+
batch_headers_fmt = [(f, None) for f in fields]
|
|
203
|
+
generic_printer(
|
|
204
|
+
batch, batch_headers_fmt,
|
|
205
|
+
print_headers=(offset == 0 and print_headers)
|
|
206
|
+
)
|
|
207
|
+
else:
|
|
208
|
+
generic_printer(rows, headers_fmt, print_headers)
|