Skip to content

Commit

Permalink
more on rupture_grouping
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisbc committed Sep 23, 2024
1 parent 4c9f342 commit 3b33f6e
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 26 deletions.
20 changes: 17 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
# Changelog

## [0.13.0] 2024-07-25
## [0.13.0] 2024-09

## Added
- helper module to assist with participation rates
## Changed
- drop_zero_rate differentiates between FSS and IS;
- faster testing (~3 times faster)
- documentation improvements
- abc427e fixing many deprecation warnings; updated geopandas, pandas, numpy, pyvista libs;
- read_csv dtype configuration improvements;
- many old functions are deprecated/migrated to new filter package
- refactor dataframe dtypes
- standardise participation functions API and return columns;

## Added
- new filter package providing classes for filtering solotions
- support for 3d geometry (thanks @voj)
- c3ab6da simplify FSS participation using rate_weighted_mean
- participation performance testing;
- added participation methods to fault_system_solution
- a simple rupture grouping algorithm (can this be a different type of filter??);

## [0.12.3] 2024-07-04
bump version to verify new pypi workflow
Expand Down
39 changes: 21 additions & 18 deletions solvis/fault_system_solution_helper.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Dict, Iterator, List
from typing import Dict, Iterator, List, Iterable

from solvis.inversion_solution.typing import InversionSolutionProtocol

Expand All @@ -12,17 +12,20 @@
"""


def build_rupture_groups(solution: InversionSolutionProtocol) -> Iterator[Dict]:
def build_rupture_groups(
solution: InversionSolutionProtocol, rupture_ids: Iterable[int] = None, min_overlap: float = 0.8
) -> Iterator[Dict]:
dfrs = solution.rupture_sections
ruptures = dfrs['rupture'].unique().tolist()
print(f"there are {len(ruptures)} unique ruptures")
rupture_ids = rupture_ids or dfrs['rupture'].unique().tolist()
print(f"there are {len(rupture_ids)} unique ruptures")
count = 0
sample_sections = None
sample_rupt = None
sample_ruptures: List[int] = []

for rupt_id in ruptures:
for rupt_id in rupture_ids:
sections = dfrs[dfrs.rupture == rupt_id]['section'].tolist()

# first or reset
if sample_rupt is None:
sample_ruptures = []
Expand All @@ -34,19 +37,19 @@ def build_rupture_groups(solution: InversionSolutionProtocol) -> Iterator[Dict]:
if rupt_id is not sample_rupt:
sample_ruptures.append(rupt_id)

# otherwise compare overlap
diff = len(set(sections).symmetric_difference(sample_sections))
overlap = len(set(sections).intersection(sample_sections))

if overlap: # and there must be some non-zero score
score = (sample_len - diff) / sample_len
# compare section overlap
section_overlap = len(set(sections).intersection(sample_sections))

# print(f'rupt_id {rupt_id} score {score} overlap {overlap} sample_len: {sample_len} diff {diff}')
if (score < 0.7) or not overlap: # (overlap < 0.8 * sample_len):
yield {'rupture': sample_rupt, 'ruptures': sample_ruptures, 'sample_sections': sample_len}
if section_overlap: # and there must be some non-zero score
section_diff_count = len(set(sections).symmetric_difference(sample_sections))
score = (sample_len - section_diff_count) / sample_len
if score >= min_overlap:
continue
else:
count += 1
yield {'rupture': sample_rupt, 'ruptures': sample_ruptures, 'sample_sections': sample_len}

# signal reset
sample_rupt = None
count += 1
# signal reset
sample_rupt = None

print(f"built {count} rupture groups")
print(f"built {count} rupture groups from {len(rupture_ids)} unique ruptures.")
2 changes: 1 addition & 1 deletion solvis/solvis.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
The original solvis API helper functions are defined in this module.
NB please be aware that most functions in this module are deprecated and replaced
in the 2nd generation Solvis API.
in the 2nd generation Solvis API (version == 0.13.0)
"""
# from functools import partial
import warnings
Expand Down
4 changes: 4 additions & 0 deletions test/filter/test_fault_system_solution_helper.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import pytest


@pytest.mark.skip("This is not in doing much yet")
def test_explore_zero_rates(crustal_solution_fixture):
solution = crustal_solution_fixture

Expand Down
50 changes: 46 additions & 4 deletions test/test_rupture_representatives.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,54 @@
import pytest

from solvis.fault_system_solution_helper import build_rupture_groups
from solvis.filter.rupture_id_filter import FilterRuptureIds


@pytest.mark.skip("THis is not in use yet")
@pytest.mark.slow
def test_build_rupture_groups(composite_fixture):
fss = composite_fixture._solutions['CRU']

for rep in build_rupture_groups(fss):
print(rep)
# assert 0
reps = list(build_rupture_groups(fss, min_overlap=0.5))
assert len(reps) == 406
assert reps[0] == {'rupture': 0, 'ruptures': [1, 2], 'sample_sections': 2}

reps = list(build_rupture_groups(fss, min_overlap=0.8))
assert len(reps) == 658
assert reps[0] == {'rupture': 0, 'ruptures': [1], 'sample_sections': 2}


@pytest.mark.parametrize(
"min_overlap, expected_len, sample_zero",
[
(0.5, 2, {'rupture': 0, 'ruptures': [1, 2], 'sample_sections': 2}),
(0.8, 4, {'rupture': 0, 'ruptures': [1], 'sample_sections': 2}),
(0.99, 5, {'rupture': 0, 'ruptures': [1], 'sample_sections': 2}),
],
)
def test_build_rupture_groups_fast(small_composite_fixture, min_overlap, expected_len, sample_zero):
fss = small_composite_fixture._solutions['CRU']

reps = list(build_rupture_groups(fss, min_overlap=min_overlap))
assert len(reps) == expected_len
assert reps[0] == sample_zero


@pytest.mark.parametrize(
"min_overlap, expected_len, sample_zero",
[
(0.5, 1, {'rupture': 5, 'ruptures': [6, 7, 8, 9], 'sample_sections': 7}),
(0.8, 1, {'rupture': 5, 'ruptures': [6, 7], 'sample_sections': 7}),
(0.99, 2, {'rupture': 5, 'ruptures': [6], 'sample_sections': 7}),
],
)
def test_build_rupture_groups_filtered(small_composite_fixture, min_overlap, expected_len, sample_zero):
fss = small_composite_fixture._solutions['CRU']

m7less = list(FilterRuptureIds(fss).for_magnitude(max_mag=7.5))

reps = list(build_rupture_groups(fss, rupture_ids=m7less, min_overlap=min_overlap))

print(reps)

assert len(reps) == expected_len
assert reps[0] == sample_zero

0 comments on commit 3b33f6e

Please sign in to comment.