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

Add arcus trigonometry functions to templates #25510

Merged
merged 1 commit into from
Aug 9, 2019
Merged
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
43 changes: 43 additions & 0 deletions homeassistant/helpers/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,41 @@ def tangent(value):
return value


def arc_sine(value):
"""Filter to get arc sine of the value."""
try:
return math.asin(float(value))
except (ValueError, TypeError):
return value


def arc_cosine(value):
"""Filter to get arc cosine of the value."""
try:
return math.acos(float(value))
except (ValueError, TypeError):
return value


def arc_tangent(value):
"""Filter to get arc tangent of the value."""
try:
return math.atan(float(value))
except (ValueError, TypeError):
return value


def arc_tangent2(*args):
"""Filter to calculate four quadrant arc tangent of y / x."""
try:
if len(args) == 1 and isinstance(args[0], (list, tuple)):
args = args[0]

return math.atan2(float(args[0]), float(args[1]))
except (ValueError, TypeError):
return args


def square_root(value):
"""Filter to get square root of the value."""
try:
Expand Down Expand Up @@ -872,6 +907,10 @@ def __init__(self, hass):
self.filters["sin"] = sine
self.filters["cos"] = cosine
self.filters["tan"] = tangent
self.filters["asin"] = arc_sine
self.filters["acos"] = arc_cosine
self.filters["atan"] = arc_tangent
self.filters["atan2"] = arc_tangent2
self.filters["sqrt"] = square_root
self.filters["as_timestamp"] = forgiving_as_timestamp
self.filters["timestamp_custom"] = timestamp_custom
Expand Down Expand Up @@ -899,6 +938,10 @@ def __init__(self, hass):
self.globals["pi"] = math.pi
self.globals["tau"] = math.pi * 2
self.globals["e"] = math.e
self.globals["asin"] = arc_sine
self.globals["acos"] = arc_cosine
self.globals["atan"] = arc_tangent
self.globals["atan2"] = arc_tangent2
self.globals["float"] = forgiving_float
self.globals["now"] = dt_util.now
self.globals["utcnow"] = dt_util.utcnow
Expand Down
95 changes: 95 additions & 0 deletions tests/helpers/test_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,101 @@ def test_sqrt(hass):
)


def test_arc_sine(hass):
"""Test arcus sine."""
tests = [
(-2.0, "-2.0"), # value error
(-1.0, "-1.571"),
(-0.5, "-0.524"),
(0.0, "0.0"),
(0.5, "0.524"),
(1.0, "1.571"),
(2.0, "2.0"), # value error
('"error"', "error"),
]

for value, expected in tests:
assert (
template.Template("{{ %s | asin | round(3) }}" % value, hass).async_render()
== expected
)


def test_arc_cos(hass):
"""Test arcus cosine."""
tests = [
(-2.0, "-2.0"), # value error
(-1.0, "3.142"),
(-0.5, "2.094"),
(0.0, "1.571"),
(0.5, "1.047"),
(1.0, "0.0"),
(2.0, "2.0"), # value error
('"error"', "error"),
]

for value, expected in tests:
assert (
template.Template("{{ %s | acos | round(3) }}" % value, hass).async_render()
== expected
)


def test_arc_tan(hass):
"""Test arcus tangent."""
tests = [
(-10.0, "-1.471"),
(-2.0, "-1.107"),
(-1.0, "-0.785"),
(-0.5, "-0.464"),
(0.0, "0.0"),
(0.5, "0.464"),
(1.0, "0.785"),
(2.0, "1.107"),
(10.0, "1.471"),
('"error"', "error"),
]

for value, expected in tests:
assert (
template.Template("{{ %s | atan | round(3) }}" % value, hass).async_render()
== expected
)


def test_arc_tan2(hass):
"""Test two parameter version of arcus tangent."""
tests = [
(-10.0, -10.0, "-2.356"),
(-10.0, 0.0, "-1.571"),
(-10.0, 10.0, "-0.785"),
(0.0, -10.0, "3.142"),
(0.0, 0.0, "0.0"),
(0.0, 10.0, "0.0"),
(10.0, -10.0, "2.356"),
(10.0, 0.0, "1.571"),
(10.0, 10.0, "0.785"),
(-4.0, 3.0, "-0.927"),
(-1.0, 2.0, "-0.464"),
(2.0, 1.0, "1.107"),
('"duck"', '"goose"', "('duck', 'goose')"),
]

for y, x, expected in tests:
assert (
template.Template(
"{{ (%s, %s) | atan2 | round(3) }}" % (y, x), hass
).async_render()
== expected
)
assert (
template.Template(
"{{ atan2(%s, %s) | round(3) }}" % (y, x), hass
).async_render()
== expected
)


def test_strptime(hass):
"""Test the parse timestamp method."""
tests = [
Expand Down