Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation of utils #152

Merged
merged 11 commits into from
Jun 5, 2024
2 changes: 1 addition & 1 deletion docs/source/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ User Guide <user/index>
API reference <reference/index>
```

# Seismo Stats
# SeismoStats

Analyse your seismic catalogues with **SeismoStats**, a Python package for seismicity analysis.

Expand Down
1 change: 1 addition & 0 deletions docs/source/reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ catalog
config
plots
analysis
utils
```
54 changes: 54 additions & 0 deletions docs/source/reference/utils.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Utils

```{eval-rst}
.. currentmodule:: seismostats
```

## Binning

```{eval-rst}
.. autosummary::
:toctree: api/

bin_to_precision
utils.get_fmd
utils.get_cum_fmd

```

## Synthetic Magnitude Distributions

```{eval-rst}
.. autosummary::
:toctree: api/

utils.simulate_magnitudes
utils.simulated_magnitudes_binned

```

## Coordinates

```{eval-rst}
.. autosummary::
:toctree: api/

utils.CoordinateTransformer
[//]: <> utils.CoordinateTransformer.to_local_coords
[//]: <> utils.CoordinateTransformer.from_local_coords
[//]: <> utils.CoordinateTransformer.polygon_from_local_coords
[//]: <> utils.CoordinateTransformer.polygon_to_local_coords
utils.bounding_box_to_polygon
utils.polygon_to_bounding_box

```

## Spatial Filtering

```{eval-rst}
.. autosummary::
:toctree: api/

utils.cat_intersect_polygon

```
9 changes: 9 additions & 0 deletions seismostats/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

import pandas as pd
from jinja2 import Template, select_autoescape
from seismostats.utils.binning import (bin_to_precision, # noqa
get_cum_fmd,
get_fmd)
from seismostats.utils.simulate_distributions import ( # noqa
simulate_magnitudes, simulated_magnitudes_binned)
from seismostats.utils.filtering import cat_intersect_polygon # noqa
from seismostats.utils.coordinates import (CoordinateTransformer, # noqa
bounding_box_to_polygon,
polygon_to_bounding_box)


def _check_required_cols(df: pd.DataFrame,
Expand Down
28 changes: 15 additions & 13 deletions seismostats/utils/binning.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def normal_round_to_int(x: float) -> int:

def normal_round(x: float, n: int = 0) -> float:
"""
Rounds a float number x to n number of decimals. If the number
Rounds a float number ``x`` to n number of decimals. If the number
of decimals is not given, we round to an integer.

Args:
Expand All @@ -40,11 +40,11 @@ def normal_round(x: float, n: int = 0) -> float:

def bin_to_precision(x: np.ndarray | list, delta_x: float = 0.1) -> np.ndarray:
"""
Rounds a float number x to a given precision. If precision not given,
assumes 0.1 bin size
Rounds float numbers within the array ``x`` to a given precision. If
precision not given, assumes ``delta_x = 0.1``.

Args:
x: decimal number that needs to be rounded
x: list of decimal numbers that needs to be rounded
delta_x: size of the bin, optional

Returns:
Expand All @@ -63,9 +63,10 @@ def bin_to_precision(x: np.ndarray | list, delta_x: float = 0.1) -> np.ndarray:
def get_fmd(
mags: np.ndarray, delta_m: float, bin_position: str = "center"
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Calculates event counts per magnitude bin. Note that the returned bins
array contains the center point of each bin unless bin_position is
'left'.
"""
Calculates event counts per magnitude bin. Note that the returned bins
array contains the center point of each bin unless
``bin_position = 'left'``.

Args:
mags : array of magnitudes
Expand All @@ -75,8 +76,8 @@ def get_fmd(
returned.
Returns:
bins : array of bin centers (left to right)
counts : counts for each bin ("")
mags : array of magnitudes binned to delta_m
counts : counts for each bin
mags : array of magnitudes binned to ``delta_m``
"""
mags = bin_to_precision(mags, delta_m)
mags_i = bin_to_precision(mags / delta_m - np.min(mags / delta_m), 1)
Expand Down Expand Up @@ -105,9 +106,10 @@ def get_fmd(
def get_cum_fmd(
mags: np.ndarray, delta_m: float, bin_position: str = "center"
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Calculates cumulative event counts across all magnitude units
"""
Calculates cumulative event counts across all magnitude units
(summed from the right). Note that the returned bins array contains
the center point of each bin unless left is True.
the center point of each bin unless ``bin_position = 'left'``.

Args:
mags : array of magnitudes
Expand All @@ -118,8 +120,8 @@ def get_cum_fmd(

Returns:
bins : array of bin centers (left to right)
c_counts: cumulative counts for each bin ("")
mags : array of magnitudes binned to delta_m
c_counts: cumulative counts for each bin
mags : array of magnitudes binned to ``delta_m``
"""

if delta_m == 0:
Expand Down
71 changes: 54 additions & 17 deletions seismostats/utils/coordinates.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class CoordinateTransformer:
Class to transform between a external geographic (default ESPG:4326,
also known as WGS84), and a local cartesian CRS.

Any EPSG code or proj4 string can be used for the local_proj input,
Any EPSG code or proj4 string can be used for the ``local_proj`` input,
for instance 2056 to represent the swiss coordinate system, or
"+proj=utm +zone=32 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"
to represent a UTM coordinate system.
Expand All @@ -30,12 +30,12 @@ def __init__(
external_proj: int | str = 4326):
"""
Constructor of CoordinateTransformer object.

:param local_proj: int (epsg) or string (proj) of local CRS.
:param ref_easting: reference easting for local coordinates.
:param ref_northing: reference northing for local coordinates.
:param ref_altitude: reference altitude for local coordinates.
:param external_proj: int or string of geographic coordinates.
Args:
local_proj: int (epsg) or string (proj) of local CRS.
ref_easting: reference easting for local coordinates.
ref_northing: reference northing for local coordinates.
ref_altitude: reference altitude for local coordinates.
external_proj: int or string of geographic coordinates.
"""
self.ref_easting = ref_easting
self.ref_northing = ref_northing
Expand All @@ -55,10 +55,13 @@ def to_local_coords(self,
"""
Transform geographic coordinates to local coordinates.

:param lon: longitude
:param lat: latitude
:param altitude: altitude
:returns: Easting, northing and altitude in local CRS relative to ref.
Args:
lon: longitude
lat: latitude
altitude: altitude

Returns:
Easting, northing and altitude in local CRS relative to ref.
"""
enu = \
self.transformer_to_local.transform(lon, lat, altitude)
Expand All @@ -80,10 +83,13 @@ def from_local_coords(
"""
Transform local coordinates to geographic coordinates.

:param easting: easting
:param northing: northing
:param altitude: altitude
:returns: longitude, latitude, altitude in local CRS relative to ref.
Args:
easting: easting
northing: northing
altitude: altitude

Returns:
longitude, latitude, altitude in local CRS relative to ref.
"""
easting_0 = np.array(easting) + self.ref_easting
northing_0 = np.array(northing) + self.ref_northing
Expand All @@ -103,7 +109,13 @@ def from_local_coords(

def polygon_to_local_coords(self, polygon: Polygon) -> Polygon:
"""
Transform polygon to local coordinates.
Transform polygon from geographic coordinates to local coordinates.

Args:
polygon: shapely polygon

Returns:
shapely polygon in local coordinates
"""
new_polygon = transform(
self.transformer_to_local.transform, polygon)
Expand All @@ -114,7 +126,13 @@ def polygon_to_local_coords(self, polygon: Polygon) -> Polygon:

def polygon_from_local_coords(self, polygon: Polygon) -> Polygon:
"""
Transform polygon to local coordinates.
Transform polygon from local coordinates to geographic coordinates.

Args:
polygon: shapely polygon

Returns:
shapely polygon in geographic coordinates
"""
translated_polygon = translate(
polygon, xoff=self.ref_easting,
Expand All @@ -125,12 +143,31 @@ def polygon_from_local_coords(self, polygon: Polygon) -> Polygon:


def bounding_box_to_polygon(x_min, x_max, y_min, y_max, srid=None) -> Polygon:
"""
Create a shapely Polygon from a bounding box.

Args:
x_min: minimum x coordinate
x_max: maximum x coordinate
y_min: minimum y coordinate
y_max: maximum y coordinate
srid: spatial reference system identifier
"""
bbox = (x_min, y_min,
x_max, y_max)
return geometry.box(*bbox, ccw=True)


def polygon_to_bounding_box(polygon: Polygon) -> \
tuple[float, float, float, float]:
"""
Get the bounding box of a Polygon.

Args:
polygon: shapely Polygon

Returns:
tuple: The corner coordinates of the Polygon
"""
(minx, miny, maxx, maxy) = polygon.bounds
return (minx, miny, maxx, maxy)
18 changes: 7 additions & 11 deletions seismostats/utils/filtering.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,17 @@

def cat_intersect_polygon(cat: pd.DataFrame, polygon_vertices: list[tuple]
) -> pd.DataFrame:
"""Returns a DataFrame containing
only the rows with points inside a given polygon.
"""
Returns a DataFrame containing only the rows with points inside a given
polygon.

Args:
-----------
cat : pandas.DataFrame
DataFrame with columns 'latitude' and 'longitude'
containing the points to be checked.
polygon_vertices : list of tuples
List of (x, y) tuples representing
the vertices of the polygon to be checked against.
cat : DataFrame with columns 'latitude' and 'longitude' containing the
points to be checked.
polygon_vertices : List of (x, y) tuples representing
the vertices of the polygon to be checked against.

Returns:
--------
pandas.DataFrame
DataFrame containing only the rows with points inside the polygon.

"""
Expand Down
15 changes: 9 additions & 6 deletions seismostats/utils/simulate_distributions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
def simulate_magnitudes(
n: int, beta: float, mc: float, mag_max: float | None = None
) -> np.ndarray:
"""Generates a vector of n elements drawn from an exponential distribution
exp(-beta*M)
"""
Generates a vector of ``n`` elements drawn from an exponential distribution
:math:`f = e^{-beta*M}`.

Args:
n: number of sample magnitudes
Expand Down Expand Up @@ -42,14 +43,16 @@ def simulated_magnitudes_binned(
mag_max: float = None,
b_parameter: str = "b_value",
) -> np.ndarray:
"""simulate magnitudes and bin them to a given precision. input 'b' can be
specified to be beta or the b-value, depending on the 'b_parameter' input
"""
Simulate magnitudes and bin them to a given precision ``delta_m``.
Input ``b`` can be specified to be 'beta' or the 'b-value',
depending on the ``b_parameter`` input.

Args:
n: number of magnitudes to simulate
b: b-value or beta of the distribution from which
magnitudes are simulated. If b is np.ndarray, it must have the
length n. Then each magnitude is simulated from the
magnitudes are simulated. If ``b`` is np.ndarray, it must have
the length ``n``. Then each magnitude is simulated from the
corresponding b-value
mc: completeness magnitude
delta_m: magnitude bin width
Expand Down
Loading