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

Use shape finder when it's not provided #159

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions kneed/knee_locator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from scipy import interpolate
from scipy.signal import argrelextrema
from typing import Tuple, Optional, Iterable
from shape_detector import find_shape

VALID_CURVE = ["convex", "concave"]
VALID_DIRECTION = ["increasing", "decreasing"]
Expand Down Expand Up @@ -30,9 +31,9 @@ class KneeLocator(object):
:type S: float
:param curve: If 'concave', algorithm will detect knees. If 'convex', it
will detect elbows.
:type curve: str
:type curve: Optional[str]
:param direction: one of {"increasing", "decreasing"}
:type direction: str
:type direction: Optional[str]
:param interp_method: one of {"interp1d", "polynomial"}
:type interp_method: str
:param online: kneed will correct old knee points if True, will return first knee if False
Expand Down Expand Up @@ -133,8 +134,8 @@ def __init__(
x: Iterable[float],
y: Iterable[float],
S: float = 1.0,
curve: str = "concave",
direction: str = "increasing",
curve: Optional[str] = None,
direction: Optional[str] = None,
interp_method: str = "interp1d",
online: bool = False,
polynomial_degree: int = 7,
Expand All @@ -153,6 +154,16 @@ def __init__(
self.online = online
self.polynomial_degree = polynomial_degree

# Use find_shape if it's not provided
if self.curve is None or self.direction is None:
direction, curve = find_shape(self.x, self.y)

if self.curve is None:
self.curve = curve

if self.direction is None:
self.direction = direction

# I'm implementing Look Before You Leap (LBYL) validation for direction
# and curve arguments. This is not preferred in Python. The motivation
# is that the logic inside the conditional once y_difference[j] is less
Expand Down
36 changes: 36 additions & 0 deletions tests/test_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,3 +560,39 @@ def test_find_shape():
direction, curve = find_shape(x, y)
assert direction == "increasing"
assert curve == "convex"


def test_missing_curve():
"""Test that find_shape is used when curve is not provided"""
x, y = dg.concave_increasing()
kl = KneeLocator(x, y)

assert kl.curve is not None
assert kl.curve == "concave"


def test_missing_direction():
"""Test that find_shape is used when direction is not provided"""
x, y = dg.concave_increasing()
kl = KneeLocator(x, y)

assert kl.direction is not None
assert kl.direction == "increasing"


def test_provided_curve():
"""Test that find_shape is not used when curve is provided"""
x, y = dg.concave_increasing()
kl = KneeLocator(x, y, curve="convex")

assert kl.curve is not None
assert kl.curve == "convex"


def test_provided_direction():
"""Test that find_shape is not used when direction is provided"""
x, y = dg.concave_increasing()
kl = KneeLocator(x, y, direction="decreasing")

assert kl.direction is not None
assert kl.direction == "decreasing"
Loading