diff --git a/README.md b/README.md index 2960224..2da0313 100644 --- a/README.md +++ b/README.md @@ -37,13 +37,3 @@ pip install git+https://github.com/swiss-seismological-service/SeismoStats.git@f # update it once the repo has changed: pip install --force-reinstall git+https://github.com/swiss-seismological-service/SeismoStats.git ``` - -## Problems with geos - -``` -1. geos_c.h not found -Solutions (Mac): -brew install geos -Solutions: -sudo apt-get libgeos-dev -``` diff --git a/docs/source/index.md b/docs/source/index.md index 86cb9d7..6f86ffb 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -5,9 +5,9 @@ User Guide API reference ``` -# Seismo Stats +# SeismoStats -Measure your seismicity with **SeismoStats**, a Python package for seismicity analysis. +Analyse your seismic catalogues with **SeismoStats**, a Python package for seismicity analysis. Check out the {doc}`user/usage` section for further information, or the {doc}`reference/index` for a technical reference. diff --git a/docs/source/reference/index.md b/docs/source/reference/index.md index 28dba38..77c2e27 100644 --- a/docs/source/reference/index.md +++ b/docs/source/reference/index.md @@ -7,4 +7,5 @@ catalog config plots analysis +utils ``` \ No newline at end of file diff --git a/docs/source/reference/utils.md b/docs/source/reference/utils.md new file mode 100644 index 0000000..430d5ec --- /dev/null +++ b/docs/source/reference/utils.md @@ -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 + +``` \ No newline at end of file diff --git a/docs/source/user/getting_started.md b/docs/source/user/getting_started.md new file mode 100644 index 0000000..ec9769e --- /dev/null +++ b/docs/source/user/getting_started.md @@ -0,0 +1,35 @@ +# Getting started + +`Seismostats` is a Python library but doesn't require extensive knowledge of Python. The statistical analysis of a catalog can be achieved easily without any coding expertise by following the step by step guide ({doc}`examples`). + +## Required packages and libraries + +We didn't reinvent the wheel and rely on existing libraries and packages to perform basic routines. + +### GEOS +The plotting of the seismicity requires [GEOS](https://libgeos.org/), a C/C++ library for computational geometry. If `GEOS` is not installed on your machine, you will need to get it, for example on a linux machine with +```terminal +sudo apt-get libgeos-dev +``` +or on a mac with +```terminal +brew install geos +``` + +## Using SeismoStats in another code + +### Install from source +This way of installing `SeismoStats` in another environement allows you to use the static version. +```terminal +pip install git+https://github.com/swiss-seismological-service/SeismoStats.git +``` + +If you want to install a specific branch: +```terminal +pip install git+https://github.com/swiss-seismological-service/SeismoStats.git@feature/branch +``` + +To update your environment to the latest version of `SeismoStats`: +```terminal +pip install --force-reinstall git+https://github.com/swiss-seismological-service/SeismoStats.git +``` \ No newline at end of file diff --git a/docs/source/user/index.md b/docs/source/user/index.md index 8c28b13..b0dda04 100644 --- a/docs/source/user/index.md +++ b/docs/source/user/index.md @@ -3,6 +3,8 @@ ```{toctree} :maxdepth: 2 +what_is_seismostats +getting_started usage docs ``` \ No newline at end of file diff --git a/docs/source/user/what_is_seismostats.md b/docs/source/user/what_is_seismostats.md new file mode 100644 index 0000000..9745deb --- /dev/null +++ b/docs/source/user/what_is_seismostats.md @@ -0,0 +1,5 @@ +# What is SeismoStats? + +SeismoStats is a python library for statistical analysis of seismicity. The library provides a {doc}`../reference/catalog` object, as well as routines to compute the statistical parameters as well as plot the seismicity catalogs and their statistical features. + +This library aims to provide a user friendly way to analyse seismic catalogs, with reliable and documented methods. \ No newline at end of file diff --git a/seismostats/utils/__init__.py b/seismostats/utils/__init__.py index 23a5d56..fa26052 100644 --- a/seismostats/utils/__init__.py +++ b/seismostats/utils/__init__.py @@ -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, diff --git a/seismostats/utils/binning.py b/seismostats/utils/binning.py index be22e0e..78240c8 100644 --- a/seismostats/utils/binning.py +++ b/seismostats/utils/binning.py @@ -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: @@ -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: @@ -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 @@ -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) @@ -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 @@ -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: diff --git a/seismostats/utils/coordinates.py b/seismostats/utils/coordinates.py index aa27291..6cf966b 100644 --- a/seismostats/utils/coordinates.py +++ b/seismostats/utils/coordinates.py @@ -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. @@ -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 @@ -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) @@ -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 @@ -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) @@ -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, @@ -125,6 +143,16 @@ 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) @@ -132,5 +160,14 @@ def bounding_box_to_polygon(x_min, x_max, y_min, y_max, srid=None) -> Polygon: 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) diff --git a/seismostats/utils/filtering.py b/seismostats/utils/filtering.py index c6e7505..f4a9a13 100644 --- a/seismostats/utils/filtering.py +++ b/seismostats/utils/filtering.py @@ -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. """ diff --git a/seismostats/utils/simulate_distributions.py b/seismostats/utils/simulate_distributions.py index 36dacb7..f2df665 100644 --- a/seismostats/utils/simulate_distributions.py +++ b/seismostats/utils/simulate_distributions.py @@ -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 @@ -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