Skip to content

Commit

Permalink
fix:
Browse files Browse the repository at this point in the history
- switched from gdf to ndarray for point iteration
- removed rasterio as dep
- added kernels
- finished docstrings

to do:
- tests
- CICD
- README
  • Loading branch information
duncanmartyn committed Mar 22, 2024
1 parent 911bb5e commit f085da6
Show file tree
Hide file tree
Showing 7 changed files with 357 additions and 182 deletions.
8 changes: 7 additions & 1 deletion pre-commit-config.yaml → .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@ repos:
- repo: https://github.com/PyCQA/bandit
rev: 1.7.7
hooks:
- id: bandit
- id: bandit
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.971
hooks:
- id: mypy
types: [python]
args: [--strict]
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## Roadmap
-------
- Add more kernels.
- Implement other methods of distance measurement, e.g. haversine, manhattan.
- Investigate possible alternatives to iterating over points.
- Enable use of single radius and weight values without filling array of the same length as the points GeoDataFrame/GeoSeries. Results in marginal speed up but the current approach may become an issue with large point datasets.
124 changes: 110 additions & 14 deletions geokde/_kernels.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,118 @@
"""Kernels for density estimation.
All kernels accept the following parameters:
Parameters
----------
distance : int | float
Euclidean distance value for a given point from the reference point.
radius : int | float
Search window radius for the reference point.
weight : int | float
Value with which the KDE value for a point will be weighted.
And provide the following return:
Returns
-------
value : float
Specified kernel's density estimation value.
"""

from math import pi

import numpy as np


VALID_KERNELS = [
"epanechnikov",
"quartic",
"triweight",
]


@np.vectorize
def quartic_raw(
distance: int | float,
radius: int | float,
weight: int | float,
) -> float:
"""Raw Quartic kernel."""
if distance:
value = weight * pow(1 - pow(distance / radius, 2), 2)
else:
value = 0.0
return value


@np.vectorize
def quartic_scaled(
distance: int | float,
radius: int | float,
weight: int | float,
) -> float:
"""Scaled Quartic kernel."""
if distance:
norm_const = 116 / (5 * pi * pow(radius, 2))
value = weight * (norm_const * (15 / 16) * pow(1 - pow(distance / radius, 2), 2))
else:
value = 0.0
return value


@np.vectorize
def epanechnikov_raw(
distance: int | float,
radius: int | float,
weight: int | float,
) -> float:
"""Raw Epanechnikov kernel."""
if distance:
value = weight * (1 - pow(distance / radius, 2))
else:
value = 0.0
return value


@np.vectorize
def epanechnikov_scaled(
distance: int | float,
radius: int | float,
weight: int | float,
) -> float:
"""Scaled Epanechnikov kernel."""
if distance:
norm_const = 8 / (3 * pi * pow(radius, 2))
value = weight * (norm_const * (3 / 4) * (1 - pow(distance / radius, 2)))
else:
value = 0.0
return value


@np.vectorize
def triweight_raw(
distance: int | float,
radius: int | float,
weight: int | float,
) -> float:
"""Raw triweight kernel."""
if distance:
value = weight * pow(1 - pow(distance / radius, 2), 3)
else:
value = 0.0
return value


@np.vectorize
def quartic(distance: int | float, radius: int | float, weight: int | float) -> float:
"""Quartic kernel.
Parameters
----------
distance : int | float
radius : int | float
weight : int | float
Returns
-------
value : float
"""
def triweight_scaled(
distance: int | float,
radius: int | float,
weight: int | float,
) -> float:
"""Scaled triweight kernel."""
if distance:
value = weight * ((1 - ((distance / radius) ** 2)) ** 2)
norm_const = 128 / (35 * pi * pow(radius, 2))
value = weight * (norm_const * (35 / 32) * pow(1 - pow(distance / radius, 2), 3))
else:
value = 0.0
return value
Loading

0 comments on commit f085da6

Please sign in to comment.