riser 1.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.
- riser-1.1.0/LICENSE +21 -0
- riser-1.1.0/PKG-INFO +41 -0
- riser-1.1.0/README.md +117 -0
- riser-1.1.0/pyproject.toml +58 -0
- riser-1.1.0/setup.cfg +4 -0
- riser-1.1.0/src/riser/__init__.py +63 -0
- riser-1.1.0/src/riser/cli/__init__.py +11 -0
- riser-1.1.0/src/riser/cli/add_variables.py +111 -0
- riser-1.1.0/src/riser/cli/calyr_to_age.py +187 -0
- riser-1.1.0/src/riser/cli/compute_slip_rate.py +208 -0
- riser-1.1.0/src/riser/cli/compute_slip_rates.py +211 -0
- riser-1.1.0/src/riser/cli/compute_slip_rates_mc.py +272 -0
- riser-1.1.0/src/riser/cli/divide_variables.py +110 -0
- riser-1.1.0/src/riser/cli/interpolate_pdf.py +111 -0
- riser-1.1.0/src/riser/cli/make_pdf.py +168 -0
- riser-1.1.0/src/riser/cli/multiply_variables.py +110 -0
- riser-1.1.0/src/riser/cli/subtract_variables.py +130 -0
- riser-1.1.0/src/riser/cli/view_displacement_age_history.py +162 -0
- riser-1.1.0/src/riser/cli/view_pdf.py +131 -0
- riser-1.1.0/src/riser/cli/view_pdf_stack.py +140 -0
- riser-1.1.0/src/riser/constants.py +23 -0
- riser-1.1.0/src/riser/integration.py +61 -0
- riser-1.1.0/src/riser/plotting/__init__.py +61 -0
- riser-1.1.0/src/riser/plotting/cdf_plots.py +146 -0
- riser-1.1.0/src/riser/plotting/filter_plots.py +39 -0
- riser-1.1.0/src/riser/plotting/mc_plots.py +61 -0
- riser-1.1.0/src/riser/plotting/pdf_plots.py +421 -0
- riser-1.1.0/src/riser/plotting/variable_pair_plots.py +479 -0
- riser-1.1.0/src/riser/precision.py +56 -0
- riser-1.1.0/src/riser/probability_functions/__init__.py +50 -0
- riser-1.1.0/src/riser/probability_functions/analytics.py +607 -0
- riser-1.1.0/src/riser/probability_functions/interpolation.py +97 -0
- riser-1.1.0/src/riser/probability_functions/metadata.py +190 -0
- riser-1.1.0/src/riser/probability_functions/parametric_functions.py +785 -0
- riser-1.1.0/src/riser/probability_functions/probability_density_function.py +324 -0
- riser-1.1.0/src/riser/probability_functions/readers.py +487 -0
- riser-1.1.0/src/riser/probability_functions/scaling.py +145 -0
- riser-1.1.0/src/riser/probability_functions/value_arrays.py +240 -0
- riser-1.1.0/src/riser/probability_functions/weight_functions.py +205 -0
- riser-1.1.0/src/riser/sampling/__init__.py +29 -0
- riser-1.1.0/src/riser/sampling/filtering.py +275 -0
- riser-1.1.0/src/riser/sampling/mc_sampling.py +279 -0
- riser-1.1.0/src/riser/sampling/pdf_formation.py +214 -0
- riser-1.1.0/src/riser/sampling/sample_statistics.py +101 -0
- riser-1.1.0/src/riser/slip_rates/__init__.py +22 -0
- riser-1.1.0/src/riser/slip_rates/rate_computation.py +392 -0
- riser-1.1.0/src/riser/slip_rates/reporting.py +255 -0
- riser-1.1.0/src/riser/units.py +240 -0
- riser-1.1.0/src/riser/variable_functions/__init__.py +28 -0
- riser-1.1.0/src/riser/variable_functions/compare/__init__.py +20 -0
- riser-1.1.0/src/riser/variable_functions/compare/comparison.py +234 -0
- riser-1.1.0/src/riser/variable_functions/condition/__init__.py +36 -0
- riser-1.1.0/src/riser/variable_functions/condition/bracketing.py +88 -0
- riser-1.1.0/src/riser/variable_functions/condition/combination.py +79 -0
- riser-1.1.0/src/riser/variable_functions/condition/core.py +103 -0
- riser-1.1.0/src/riser/variable_functions/condition/self_constraint.py +118 -0
- riser-1.1.0/src/riser/variable_functions/condition/trimming.py +107 -0
- riser-1.1.0/src/riser/variable_functions/pool/__init__.py +20 -0
- riser-1.1.0/src/riser/variable_functions/pool/pooling.py +93 -0
- riser-1.1.0/src/riser/variable_functions/transform/__init__.py +23 -0
- riser-1.1.0/src/riser/variable_functions/transform/arithmetic.py +585 -0
- riser-1.1.0/src/riser/variable_pairs/__init__.py +25 -0
- riser-1.1.0/src/riser/variable_pairs/dated_marker.py +142 -0
- riser-1.1.0/src/riser/variable_pairs/readers.py +205 -0
- riser-1.1.0/src/riser/variable_pairs/variable_pair.py +108 -0
- riser-1.1.0/src/riser/variable_types.py +69 -0
- riser-1.1.0/src/riser.egg-info/PKG-INFO +41 -0
- riser-1.1.0/src/riser.egg-info/SOURCES.txt +96 -0
- riser-1.1.0/src/riser.egg-info/dependency_links.txt +1 -0
- riser-1.1.0/src/riser.egg-info/entry_points.txt +20 -0
- riser-1.1.0/src/riser.egg-info/requires.txt +14 -0
- riser-1.1.0/src/riser.egg-info/top_level.txt +1 -0
- riser-1.1.0/tests/test_integration.py +48 -0
- riser-1.1.0/tests/test_pdf.py +157 -0
- riser-1.1.0/tests/test_pdf_analytics.py +424 -0
- riser-1.1.0/tests/test_pdf_interpolation.py +121 -0
- riser-1.1.0/tests/test_pdf_metadata.py +280 -0
- riser-1.1.0/tests/test_pdf_parametric_functions.py +363 -0
- riser-1.1.0/tests/test_pdf_readers.py +211 -0
- riser-1.1.0/tests/test_pdf_scaling.py +72 -0
- riser-1.1.0/tests/test_pdf_value_arrays.py +114 -0
- riser-1.1.0/tests/test_precision.py +48 -0
- riser-1.1.0/tests/test_sample_filtering.py +65 -0
- riser-1.1.0/tests/test_sample_statistics.py +59 -0
- riser-1.1.0/tests/test_sampling_mc.py +185 -0
- riser-1.1.0/tests/test_sampling_pdf_formation.py +65 -0
- riser-1.1.0/tests/test_units.py +107 -0
- riser-1.1.0/tests/test_variable_arithmetic.py +359 -0
- riser-1.1.0/tests/test_variable_bracketing.py +110 -0
- riser-1.1.0/tests/test_variable_combination.py +133 -0
- riser-1.1.0/tests/test_variable_comparison.py +163 -0
- riser-1.1.0/tests/test_variable_conditioning.py +72 -0
- riser-1.1.0/tests/test_variable_constraint.py +110 -0
- riser-1.1.0/tests/test_variable_pairs.py +158 -0
- riser-1.1.0/tests/test_variable_pooling.py +113 -0
- riser-1.1.0/tests/test_variable_trimming.py +100 -0
- riser-1.1.0/tests/test_variable_types.py +31 -0
- riser-1.1.0/tests/test_weight_functions.py +202 -0
riser-1.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 rzinke
|
|
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.
|
riser-1.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: riser
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
License: MIT License
|
|
5
|
+
|
|
6
|
+
Copyright (c) 2025 rzinke
|
|
7
|
+
|
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
10
|
+
in the Software without restriction, including without limitation the rights
|
|
11
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
13
|
+
furnished to do so, subject to the following conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be included in all
|
|
16
|
+
copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
SOFTWARE.
|
|
25
|
+
|
|
26
|
+
Requires-Python: >=3.12
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: matplotlib>=3.9.0
|
|
29
|
+
Requires-Dist: numpy>=2.0.0
|
|
30
|
+
Requires-Dist: scipy>=1.13.0
|
|
31
|
+
Requires-Dist: toml>=0.10.2
|
|
32
|
+
Requires-Dist: tqdm>=4.67.1
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: mypy; extra == "dev"
|
|
35
|
+
Requires-Dist: types-toml; extra == "dev"
|
|
36
|
+
Requires-Dist: scipy-stubs; extra == "dev"
|
|
37
|
+
Requires-Dist: types-tqdm; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest; extra == "dev"
|
|
39
|
+
Requires-Dist: ruff; extra == "dev"
|
|
40
|
+
Requires-Dist: sphinx; extra == "dev"
|
|
41
|
+
Dynamic: license-file
|
riser-1.1.0/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# ***R***ejection sampling for ***I***ncremental ***S***lip ***R***ate calculation v.**2** – RISeR2
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
Earthquake fault slip rates describe the displacement accumulation rate across a fault, averaged over some time interval. Slip rates are determined from geologic, geomorphic, or sedimentary markers recording measureable fault slip, and which can be dated using absolute geochronologic methods. Where multiple dateable displacement markers share a common slip history and record different epochs in that history, one can determine *incremental* slip rates. These average over shorter intervals relative to the oldest displacement, and can show the constancy or variability of fault slip over time.
|
|
7
|
+
|
|
8
|
+
**RISeR2** is designed to measure incremental fault slip rates based on the dated displacement history of a fault while fully accounting for uncertainties in the ages, displacements, and derived slip rates. It allows enforcement of Bayesian conditions, including the assumption that the fault did not slip backward at any point in its history. The RISeR2 library hosts a set of analytical functions and sampling tools for computing slip rates; formatting, conditioning, and displaying data; and analyzing the results.
|
|
9
|
+
|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
*Example incremental slip rates. Three incremental rates are computed between pairs of among four dated displacement markers (Marker 01–Marker 04). The exact value of each incremental slip rate is uncertain, therefore possible slip rate values are expressed as probability densities. Blue fields show the most probability 68.2% of values.*
|
|
13
|
+
|
|
14
|
+
## Setup
|
|
15
|
+
RISeR2 can be used as a set of command line tools or as an API. The command line tools form an adaptable pipeline for handling and computing probability density functions, and the API modules form a generalized PDF laboratory.
|
|
16
|
+
|
|
17
|
+
### Installation
|
|
18
|
+
To install RISeR2, simply run the following command in a UNIX shell:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
pip install git+https://github.com/rzinke/RISeR2.git
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Development Setup
|
|
25
|
+
To use these scripts, clone the GitHub repository to a location of your choice and navigate to that folder.
|
|
26
|
+
|
|
27
|
+
Note: It is recommended to use a Python package manager such conda or mamba. Create a new environment with the necessary packages installed and activate it:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
conda env create -n riser -f requirements.yaml
|
|
31
|
+
conda activate riser
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Then install RISeR2 into that environment:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
pip install -e .
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
OR
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
pip install -e ".[dev]"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
if you are developing.
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
## Top-level Functions and Examples
|
|
50
|
+
RISeR2 provides three command line functions for determining slip rates:
|
|
51
|
+
|
|
52
|
+
- `riser-compute-slip-rate`
|
|
53
|
+
- `riser-compute-slip-rates`
|
|
54
|
+
- `riser-compute-slip-rates-mc`
|
|
55
|
+
|
|
56
|
+
Each tool is designed for different scenarios, and to incorporate different assumptions. See [Slip rate determination](#slip-rate-determination).
|
|
57
|
+
|
|
58
|
+
Example data sets and launch scripts can be found in the `RISeR2/examples` folder.
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
## Under the Hood
|
|
62
|
+
For a single dated measurement of fault displacement, a fault **slip rate** measured since the present day is defined as:
|
|
63
|
+
|
|
64
|
+
$\bar{v} = \frac{u}{t}$
|
|
65
|
+
|
|
66
|
+
where $\bar{v}$ is the slip rate averaged over time, $u$ is the displacement across the fault, and $t$ is the time interval over which the displacement accumulated. If multiple dated displacement markers are available along a fault (and all share a common slip history), a displacement-time history or slip history can be determined. For $n$ dated markers, $m = n - 1$ closed intervals in the fault slip history are defined. Slip rates averaged over closed intervals are ***incremental*** **slip rates**, defined as:
|
|
67
|
+
|
|
68
|
+
$\bar{v}_i = \frac{\Delta u_i}{\Delta t_i}$
|
|
69
|
+
|
|
70
|
+
where $i$ is one of the $m$ closed intervals, and $\Delta$ is the change in displacement or time within each interval. RISeR2 is specifically designed to compute incremental slip rates.
|
|
71
|
+
|
|
72
|
+
Often, both the displacement measurement and age of the feature have non-negligible uncertainties. These uncertainties can be expressed as *probability density functions (PDFs)*, which express the *relative likelihood* of any *value* (e.g., time or age, displacement, slip rate, *etc.*) as a function of values. A PDF can take on any shape that adheres to the following criteria:
|
|
73
|
+
- Probability density is never negative. It can be zero or positive over the range of all possible values.
|
|
74
|
+
- The area under the curve is 1.0. I.e., the event is guaranteed to have occurred at some point in the defined values.
|
|
75
|
+
|
|
76
|
+
Strictly defined, a PDF is absolutely continuous (defined over infinitely many values). RISeR2 uses *discrete PDFs*, represented by a discrete and finite vector of possible values, each with a corresponding probability density. The probability density of any value within the vector of PDF values can be determined by linear interpolation between defined probability densities, and values outside the defined vector are assigned zero probability density. Use of discrete PDFs is essential because RISeR2 is designed to work with non-parametric functions (such as calibrated radiocarbon dates) that cannot be described by closed-form equations.
|
|
77
|
+
|
|
78
|
+
**`PDFs`** are the fundamental object in the RISeR2 library. All ages, displacements, and slip rates are expressed as PDFs with the above properties. The PDF can be given a descriptive *name*, and a description of the *variable-type*, e.g., "age", "displacement", "slip rate". The PDF can also be assigned a *unit*—RISeR2 recognizes units consisting of multiples of years (**y**) and meters (**m**).
|
|
79
|
+
|
|
80
|
+

|
|
81
|
+
|
|
82
|
+
*Example of a multi-modal (multi-peaked) PDF. Blue field indicates the most probable 95.4% of values.*
|
|
83
|
+
|
|
84
|
+
Data points defining displacement-time history of a fault are encoded as a **`DatedMarker`**, comprising a PDF representing *age*, and a PDF representing *displacement*. Like a PDF, a DatedMarker can carry a descriptive name. The unit (e.g., "m/y") is determined from the units of the constituent age and displacement PDFs.
|
|
85
|
+
|
|
86
|
+

|
|
87
|
+
|
|
88
|
+
*Example of a series of dated displacement markers, defining the slip history of a hypothetical fault.*
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
### Slip rate determination
|
|
92
|
+
|
|
93
|
+
`riser-compute-slip-rate` is used to determine the slip rate of a fault since present day, based on a single DatedMarker. It uses the analytical formulation (a weighted convolution) of Bird (2007).
|
|
94
|
+
|
|
95
|
+
`riser-compute-slip-rates` is used to compute incremental slip rates between multiple DateMarkers using convolution-based analytical formulas. It assumes that neither the change in age between markers $\Delta t$, nor the change in displacement $\Delta u$ are negative.
|
|
96
|
+
|
|
97
|
+
`riser-compute-slip-rates-mc` invokes Monte Carlo-style sampling of the ages and displacements of multiple DateMarkers in a slip history. The age and displacement PDFs are sampled according to their non-parametric forms using the **Probability Inverse Transform (PIT)** method. Multiple conditions can be enforced on whether the random samples are valid and accepted, or invalid and rejected in the process of **rejection sampling** (discussed in this context in Zinke et al., 2019). Like Gold & Cowgill (2011), `riser-compute-slip-rates-mc` enforces the assumption that the fault did not slip backwards (inversely to its overall kinematics) at any point in its history. This can be especially important in cases where ages and/or displacements uncertainties overlap. A maximum-allowable slip rate may also be provided, to avoid possibilities in which the fault slipped unrealistically fast over multiple earthquake cycles.
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
## References
|
|
101
|
+
- Bird, P. (2007), Uncertainties in long-term geologic offset rates of faults: General principles illustrated with data from California and other western states, *Geosphere, 3*, 577–595, https://doi:10.1130/GES00127.1.
|
|
102
|
+
- Gold, R. D., & Cowgill, E. (2011). Deriving fault-slip histories to test for secular variation in slip, with examples from the Kunlun and Awatere faults. *Earth and Planetary Science Letters, 301*, 52–64. https://doi.org/10.1016/j.epsl.2010.10.011
|
|
103
|
+
- Zinke, R., Dolan, J. F., Rhodes, E. J., Van Dissen, R., McGuire, C. P., Hatem, A. E., et al. (2019). Multimillennial incremental slip rate variability of the Clarnce fault at the Tophouse Road site, Marlborough Fault System, New Zealand. *Geophysical Research Letters, 46*, 717–725. https://doi.org/10.1029/2018GL080688
|
|
104
|
+
- Zinke, R., Dolan, J. F., Rhodes, E. J., Van Dissen, R. J., Hatem, A. E., McGuire, C. P., et al. (2021). Latest Pleistocene–Holocene incremental slip rates of the Wairau fault: Implications for long-distance and long-term coordination of faulting between North and South Island, New Zealand. *Geochemistry, Geophysics, Geosystems, 22*, e2021GC009656. https://doi.org/10.1029/2021GC009656
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
## Citation
|
|
108
|
+
- Zinke, R., Dolan, J. F., Rhodes, E. J., Van Dissen, R. J., Hatem, A. E., McGuire, C. P., et al. (2021). Latest Pleistocene–Holocene incremental slip rates of the Wairau fault: Implications for long-distance and long-term coordination of faulting between North and South Island, New Zealand. *Geochemistry, Geophysics, Geosystems, 22*, e2021GC009656. https://doi.org/10.1029/2021GC009656
|
|
109
|
+
- Zenodo: https://zenodo.org/records/4733235. https://doi.org/10.5281/zenodo.4733235
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
## ⚠️ Disclaimer
|
|
113
|
+
This codebase is provided for research and experimental purposes only.
|
|
114
|
+
It may contain bugs, incomplete features, or incorrect implementations.
|
|
115
|
+
|
|
116
|
+
No warranty is provided, express or implied, regarding the correctness or reliability of the code.
|
|
117
|
+
By using this code, you agree that the authors and contributors are not liable for any damages or issues that may arise.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "riser"
|
|
7
|
+
version = "1.1.0"
|
|
8
|
+
license = {file = "LICENSE"}
|
|
9
|
+
requires-python = ">=3.12"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"matplotlib>=3.9.0",
|
|
12
|
+
"numpy>=2.0.0",
|
|
13
|
+
"scipy>=1.13.0",
|
|
14
|
+
"toml>=0.10.2",
|
|
15
|
+
"tqdm>=4.67.1",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.optional-dependencies]
|
|
19
|
+
dev = [
|
|
20
|
+
"mypy",
|
|
21
|
+
"types-toml",
|
|
22
|
+
"scipy-stubs",
|
|
23
|
+
"types-tqdm",
|
|
24
|
+
"pytest",
|
|
25
|
+
"ruff",
|
|
26
|
+
"sphinx",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.scripts]
|
|
30
|
+
riser-add-variables = "riser.cli.add_variables:main"
|
|
31
|
+
riser-calyr-to-age = "riser.cli.calyr_to_age:main"
|
|
32
|
+
riser-combine-variables = "riser.cli.combine_variables:main"
|
|
33
|
+
riser-compute-gap-probabilities = "riser.cli.compute_gap_probabilities:main"
|
|
34
|
+
riser-compute-ks-statistic = "riser.cli.compute_ks_statistic:main"
|
|
35
|
+
riser-compute-overlap-index = "riser.cli.compute_overlap_index:main"
|
|
36
|
+
riser-compute-slip-rate = "riser.cli.compute_slip_rate:main"
|
|
37
|
+
riser-compute-slip-rates = "riser.cli.compute_slip_rates:main"
|
|
38
|
+
riser-compute-slip-rates-mc = "riser.cli.compute_slip_rates_mc:main"
|
|
39
|
+
riser-cross-correlate-variables = "riser.cli.cross_correlate_variables:main"
|
|
40
|
+
riser-divide-variables = "riser.cli.divide_variables:main"
|
|
41
|
+
riser-interpolate-pdf = "riser.cli.interpolate_pdf:main"
|
|
42
|
+
riser-make-pdf = "riser.cli.make_pdf:main"
|
|
43
|
+
riser-merge-variables = "riser.cli.merge_variables:main"
|
|
44
|
+
riser-multiply-variables = "riser.cli.multiply_variables:main"
|
|
45
|
+
riser-subtract-variables = "riser.cli.subtract_variables:main"
|
|
46
|
+
riser-view-displacement-age-history = "riser.cli.view_displacement_age_history:main"
|
|
47
|
+
riser-view-pdf = "riser.cli.view_pdf:main"
|
|
48
|
+
riser-view-pdf-stack = "riser.cli.view_pdf_stack:main"
|
|
49
|
+
|
|
50
|
+
[tool.ruff]
|
|
51
|
+
line-length = 80
|
|
52
|
+
|
|
53
|
+
[tool.ruff.lint]
|
|
54
|
+
ignore = ["UP009", "RUF022"]
|
|
55
|
+
|
|
56
|
+
[tool.ruff.lint.isort]
|
|
57
|
+
combine-as-imports = true
|
|
58
|
+
lines-after-imports = 2
|
riser-1.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# src/riser/__init__.py
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2025 Rob Zinke. Licensed under the MIT License.
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
RISeR2: Rejection sampling for Incremental Slip Rate calculation.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from importlib.metadata import version as _version
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
__version__ = _version("riser")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# Core modules (no internal dependency)
|
|
17
|
+
from . import ( # noqa: I001
|
|
18
|
+
constants,
|
|
19
|
+
integration,
|
|
20
|
+
precision,
|
|
21
|
+
units,
|
|
22
|
+
variable_types,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# Subpackages (imported in dependency order)
|
|
27
|
+
from . import (
|
|
28
|
+
probability_functions,
|
|
29
|
+
variable_functions,
|
|
30
|
+
variable_pairs,
|
|
31
|
+
sampling,
|
|
32
|
+
slip_rates,
|
|
33
|
+
plotting,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# Commonly used classes
|
|
38
|
+
from .probability_functions import PDF
|
|
39
|
+
from .variable_pairs import DatedMarker, VariablePair
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# Public API
|
|
43
|
+
__all__ = [
|
|
44
|
+
# Core modules and subpackages
|
|
45
|
+
"constants",
|
|
46
|
+
"integration",
|
|
47
|
+
"precision",
|
|
48
|
+
"units",
|
|
49
|
+
"variable_types",
|
|
50
|
+
"probability_functions",
|
|
51
|
+
"variable_functions",
|
|
52
|
+
"sampling",
|
|
53
|
+
"variable_pairs",
|
|
54
|
+
"slip_rates",
|
|
55
|
+
"plotting",
|
|
56
|
+
# Commonly used classes
|
|
57
|
+
"PDF",
|
|
58
|
+
"VariablePair",
|
|
59
|
+
"DatedMarker",
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# end of file
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2025 Rob Zinke. Licensed under the MIT License.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# Import modules
|
|
8
|
+
import argparse
|
|
9
|
+
|
|
10
|
+
import matplotlib.pyplot as plt
|
|
11
|
+
|
|
12
|
+
from riser import (
|
|
13
|
+
plotting,
|
|
14
|
+
probability_functions as PDFs,
|
|
15
|
+
variable_functions as var_fcns,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
#################### ARGUMENT PARSER ####################
|
|
20
|
+
description = "Add two random variables expressed as PDFs."
|
|
21
|
+
|
|
22
|
+
examples = """Examples:
|
|
23
|
+
add_variables.py pdf1.txt pdf2.txt -o pdf12.txt
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def create_parser():
|
|
27
|
+
parser = argparse.ArgumentParser(
|
|
28
|
+
description=description,
|
|
29
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
30
|
+
epilog=examples,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
return parser
|
|
34
|
+
|
|
35
|
+
def cmd_parser(iargs=None):
|
|
36
|
+
parser = create_parser()
|
|
37
|
+
|
|
38
|
+
input_args = parser.add_argument_group("Inputs")
|
|
39
|
+
input_args.add_argument(dest="fname1",
|
|
40
|
+
type=str,
|
|
41
|
+
help="File name of first PDF.")
|
|
42
|
+
input_args.add_argument(dest="fname2",
|
|
43
|
+
type=str,
|
|
44
|
+
help="File name of second PDF.")
|
|
45
|
+
|
|
46
|
+
input_args.add_argument("--name", dest="name",
|
|
47
|
+
type=str,
|
|
48
|
+
help="Name of summed PDF. [None]")
|
|
49
|
+
|
|
50
|
+
output_args = parser.add_argument_group("Outputs")
|
|
51
|
+
output_args.add_argument("-o", "--outname", dest="outname",
|
|
52
|
+
type=str, required=True,
|
|
53
|
+
help="Output file.")
|
|
54
|
+
output_args.add_argument("-v", "--verbose", dest="verbose",
|
|
55
|
+
action="store_true",
|
|
56
|
+
help="Verbose mode.")
|
|
57
|
+
output_args.add_argument("-p", "--plot", dest="plot",
|
|
58
|
+
action="store_true",
|
|
59
|
+
help="Plot distribution.")
|
|
60
|
+
|
|
61
|
+
return parser.parse_args(args=iargs)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
#################### MAIN ####################
|
|
65
|
+
def main() -> None:
|
|
66
|
+
# Parse arguments
|
|
67
|
+
inps = cmd_parser()
|
|
68
|
+
|
|
69
|
+
# Read PDFs from files
|
|
70
|
+
pdf1 = PDFs.readers.read_pdf(inps.fname1, verbose=inps.verbose)
|
|
71
|
+
pdf2 = PDFs.readers.read_pdf(inps.fname2, verbose=inps.verbose)
|
|
72
|
+
|
|
73
|
+
# Sample PDFs on same axis
|
|
74
|
+
pdf1, pdf2 = PDFs.interpolation.interpolate_pdfs(
|
|
75
|
+
[pdf1, pdf2], verbose=inps.verbose
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Compute summed PDF
|
|
79
|
+
sum_pdf = var_fcns.transform.arithmetic.add_variables(
|
|
80
|
+
pdf1, pdf2, name=inps.name, verbose=inps.verbose
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Save to file
|
|
84
|
+
PDFs.readers.save_pdf(inps.outname, sum_pdf, verbose=inps.verbose)
|
|
85
|
+
|
|
86
|
+
# Plot function if requested
|
|
87
|
+
if inps.plot:
|
|
88
|
+
# Initialize figure and axis
|
|
89
|
+
fig, (inpt_ax, sum_ax) = plt.subplots(nrows=2)
|
|
90
|
+
|
|
91
|
+
# Plot input PDFs
|
|
92
|
+
plotting.plot_pdf_filled(inpt_ax, pdf1)
|
|
93
|
+
plotting.plot_pdf_filled(inpt_ax, pdf2)
|
|
94
|
+
|
|
95
|
+
# Plot PDF
|
|
96
|
+
plotting.plot_pdf_labeled(sum_ax, sum_pdf)
|
|
97
|
+
|
|
98
|
+
# Format figure
|
|
99
|
+
inpt_ax.legend()
|
|
100
|
+
inpt_ax.set_title("Inputs")
|
|
101
|
+
sum_ax.set_title("Summed PDF")
|
|
102
|
+
fig.tight_layout()
|
|
103
|
+
|
|
104
|
+
plt.show()
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
main()
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
# end of file
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2025 Rob Zinke. Licensed under the MIT License.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# Import modules
|
|
8
|
+
import argparse
|
|
9
|
+
|
|
10
|
+
import matplotlib.pyplot as plt
|
|
11
|
+
|
|
12
|
+
from riser import (
|
|
13
|
+
plotting,
|
|
14
|
+
probability_functions as PDFs,
|
|
15
|
+
sampling,
|
|
16
|
+
units,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
#################### ARGUMENT PARSER ####################
|
|
21
|
+
description = (
|
|
22
|
+
"Convert an age PDF from calendar years to (kilo)years before present."
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
examples = """Examples:
|
|
26
|
+
riser-calyr-to-age C_date.txt -o C_age.txt
|
|
27
|
+
riser-calyr-to-age C_date.txt --name C14 --smoothing-type mean --smoothing-width 3 -v -p -o C_age.txt
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def create_parser():
|
|
31
|
+
parser = argparse.ArgumentParser(
|
|
32
|
+
description=description,
|
|
33
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
34
|
+
epilog=examples,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
return parser
|
|
38
|
+
|
|
39
|
+
def cmd_parser(iargs=None):
|
|
40
|
+
parser = create_parser()
|
|
41
|
+
|
|
42
|
+
input_args = parser.add_argument_group("Inputs")
|
|
43
|
+
input_args.add_argument(dest="date_fname",
|
|
44
|
+
type=str,
|
|
45
|
+
help="Calendar years file name.")
|
|
46
|
+
|
|
47
|
+
# Metadata
|
|
48
|
+
metadata_args = parser.add_argument_group("Metadata")
|
|
49
|
+
metadata_args.add_argument("--name", dest="name",
|
|
50
|
+
type=str,
|
|
51
|
+
help="Name.")
|
|
52
|
+
metadata_args.add_argument("--variable-type", dest="variable_type",
|
|
53
|
+
type=str, default="age",
|
|
54
|
+
help="Variable type. [age]")
|
|
55
|
+
|
|
56
|
+
# Referencing
|
|
57
|
+
referencing_args = parser.add_argument_group("Referencing")
|
|
58
|
+
referencing_args.add_argument("--reference-date", dest="reference_date",
|
|
59
|
+
type=float, default=1950,
|
|
60
|
+
help="Reference date, e.g., 1950 for radiocarbon, 2000 for OSL, etc. "
|
|
61
|
+
"[1950]")
|
|
62
|
+
referencing_args.add_argument("--limit-zero", dest="limit_zero",
|
|
63
|
+
action="store_true",
|
|
64
|
+
help="Limit youngest value to zero.")
|
|
65
|
+
|
|
66
|
+
# Units
|
|
67
|
+
unit_args = parser.add_argument_group("Units")
|
|
68
|
+
unit_args.add_argument("--input-unit", dest="input_unit",
|
|
69
|
+
type=str, default="y",
|
|
70
|
+
help="Unit of input data. [y]")
|
|
71
|
+
unit_args.add_argument("--output-unit", dest="output_unit",
|
|
72
|
+
type=str, default="ky",
|
|
73
|
+
help="Unit of output data. [ky]")
|
|
74
|
+
|
|
75
|
+
# Smoothing
|
|
76
|
+
smoothing_args = parser.add_argument_group("Smoothing")
|
|
77
|
+
smoothing_args.add_argument("--smoothing-type", dest="smoothing_type",
|
|
78
|
+
type=str, choices=sampling.filtering.FILTER_TYPES,
|
|
79
|
+
help="Smoothing filter type. [None]")
|
|
80
|
+
smoothing_args.add_argument("--smoothing-width", dest="smoothing_width",
|
|
81
|
+
type=int, default=0,
|
|
82
|
+
help="Smoothing kernel width. [0]")
|
|
83
|
+
|
|
84
|
+
# Outputs
|
|
85
|
+
output_args = parser.add_argument_group("Outputs")
|
|
86
|
+
output_args.add_argument("-o", "--outname", dest="outname",
|
|
87
|
+
type=str, required=True,
|
|
88
|
+
help="Output file.")
|
|
89
|
+
output_args.add_argument("-v", "--verbose", dest="verbose",
|
|
90
|
+
action="store_true",
|
|
91
|
+
help="Verbose mode.")
|
|
92
|
+
output_args.add_argument("-p", "--plot", dest="plot",
|
|
93
|
+
action="store_true",
|
|
94
|
+
help="Plot.")
|
|
95
|
+
|
|
96
|
+
return parser.parse_args(args=iargs)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
#################### MAIN ####################
|
|
100
|
+
def main() -> None:
|
|
101
|
+
# Parse arguments
|
|
102
|
+
inps = cmd_parser()
|
|
103
|
+
|
|
104
|
+
# Read calendar years file
|
|
105
|
+
calyr, calpx, metadata = PDFs.readers.read_calendar_file(
|
|
106
|
+
fname=inps.date_fname,
|
|
107
|
+
name=inps.name,
|
|
108
|
+
variable_type=inps.variable_type,
|
|
109
|
+
unit=inps.input_unit,
|
|
110
|
+
verbose=inps.verbose,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Convert calendar year to years before present (ypb)
|
|
114
|
+
if inps.verbose:
|
|
115
|
+
print(f"Shifting dates relative to reference: {inps.reference_date}")
|
|
116
|
+
ybp = inps.reference_date - calyr
|
|
117
|
+
|
|
118
|
+
# Scale from input units to output units
|
|
119
|
+
x = units.scale_values_by_units(
|
|
120
|
+
ybp, metadata["unit"], inps.output_unit, verbose=inps.verbose
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Flip left for right, so age is increasing
|
|
124
|
+
x = x[::-1]
|
|
125
|
+
px = calpx[::-1]
|
|
126
|
+
|
|
127
|
+
# Limit minimum age to zero
|
|
128
|
+
if inps.limit_zero:
|
|
129
|
+
# Non-negative indices
|
|
130
|
+
non_neg_ndx = (x >= 0)
|
|
131
|
+
|
|
132
|
+
# Crop arrays
|
|
133
|
+
x = x[non_neg_ndx]
|
|
134
|
+
px = px[non_neg_ndx]
|
|
135
|
+
|
|
136
|
+
# Form data into PDF
|
|
137
|
+
pdf = PDFs.PDF(
|
|
138
|
+
x=x,
|
|
139
|
+
px=px,
|
|
140
|
+
name=inps.name,
|
|
141
|
+
variable_type=inps.variable_type,
|
|
142
|
+
unit=inps.output_unit,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Smooth data
|
|
146
|
+
if inps.smoothing_width > 0:
|
|
147
|
+
pdf = sampling.filtering.filter_pdf(
|
|
148
|
+
pdf=pdf,
|
|
149
|
+
filter_type=inps.smoothing_type,
|
|
150
|
+
filter_width=inps.smoothing_width,
|
|
151
|
+
edge_padding="zeros",
|
|
152
|
+
verbose=inps.verbose,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Report final stats if requested
|
|
156
|
+
if inps.verbose:
|
|
157
|
+
PDFs.analytics.compute_pdf_statistics(pdf, verbose=True)
|
|
158
|
+
|
|
159
|
+
# Save to file
|
|
160
|
+
PDFs.readers.save_pdf(inps.outname, pdf, verbose=inps.verbose)
|
|
161
|
+
|
|
162
|
+
# Plot function if requested
|
|
163
|
+
if inps.plot:
|
|
164
|
+
# Initialize figure and axis
|
|
165
|
+
fig, (cal_ax, age_ax) = plt.subplots(nrows=2)
|
|
166
|
+
|
|
167
|
+
# Plot calendar years
|
|
168
|
+
cal_ax.plot(calyr, calpx, color="k")
|
|
169
|
+
|
|
170
|
+
# Plot PDF
|
|
171
|
+
plotting.plot_pdf_labeled(age_ax, pdf)
|
|
172
|
+
|
|
173
|
+
# Format plot
|
|
174
|
+
cal_ax.invert_xaxis()
|
|
175
|
+
cal_ax.set_xlabel("Calendar year (CE / BCE)")
|
|
176
|
+
cal_ax.set_ylabel("Probability density")
|
|
177
|
+
|
|
178
|
+
fig.tight_layout()
|
|
179
|
+
|
|
180
|
+
plt.show()
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
if __name__ == "__main__":
|
|
184
|
+
main()
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
# end of file
|