From d501d0777cf1daa4414f2fc66e8f1c3b14b584df Mon Sep 17 00:00:00 2001
From: Raphael <raphael.sturgis@gmail.com>
Date: Thu, 4 Nov 2021 12:38:49 +0100
Subject: [PATCH] angular mean and spread

---
 .gitignore                        |  3 +++
 skais/stats/__init__.py           |  0
 skais/stats/angluar.py            | 30 ++++++++++++++++++++++
 skais/tests/stats/test_angular.py | 42 +++++++++++++++++++++++++++++++
 4 files changed, 75 insertions(+)
 create mode 100644 skais/stats/__init__.py
 create mode 100644 skais/stats/angluar.py
 create mode 100644 skais/tests/stats/test_angular.py

diff --git a/.gitignore b/.gitignore
index 1c2d52b..397680e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,4 @@
 .idea/*
+build/
+skais.egg-info/
+*.coverage
\ No newline at end of file
diff --git a/skais/stats/__init__.py b/skais/stats/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/skais/stats/angluar.py b/skais/stats/angluar.py
new file mode 100644
index 0000000..3fbac42
--- /dev/null
+++ b/skais/stats/angluar.py
@@ -0,0 +1,30 @@
+import numpy as np
+
+
+def angular_dispersion(x):
+    n = len(x)
+    X = np.sum(np.cos(x)) / n
+    Y = np.sum(np.sin(x)) / n
+
+    r = np.sqrt(X ** 2 + Y ** 2)
+
+    return r
+
+
+def angular_mean(x):
+    n = len(x)
+    X = np.sum(np.cos(x)) / n
+    Y = np.sum(np.sin(x)) / n
+
+    theta = abs(np.arctan2(X, Y))
+
+    if Y > 0 and X > 0:
+        return theta
+
+    if Y > 0 >= X:
+        return np.pi/2 - theta
+
+    if Y <= 0 < X:
+        return np.pi + theta
+    else:
+        return 2 * np.pi + theta
diff --git a/skais/tests/stats/test_angular.py b/skais/tests/stats/test_angular.py
new file mode 100644
index 0000000..ae524ad
--- /dev/null
+++ b/skais/tests/stats/test_angular.py
@@ -0,0 +1,42 @@
+import unittest
+
+import numpy as np
+
+from skais.stats.angluar import angular_mean
+
+
+class TestAngular(unittest.TestCase):
+    def test_angular_mean_simple(self):
+        x = np.radians(np.array([1, 359]))
+
+        self.assertEqual(0.0, angular_mean(x))
+
+    def test_angular_mean_simple_2(self):
+        x = np.radians(np.array([180, 180, 180, 180, 179, 181]))
+
+        self.assertEqual(np.pi, angular_mean(x))
+
+    def test_angular_mean_simple_3(self):
+        x = np.radians(np.array([0, 0, 0, 0, 359, 1]))
+
+        self.assertEqual(0.0, angular_mean(x))
+
+    def test_angular_mean_first_quadrant(self):
+        x = np.radians(np.array([43, 44, 45, 46, 47]))
+
+        self.assertEqual(np.pi / 4, angular_mean(x))
+
+    def test_angular_mean_second_quadrant(self):
+        x = np.radians(np.array([133, 134, 135, 136, 137]))
+
+        self.assertEqual(3*np.pi / 4, angular_mean(x))
+
+    def test_angular_mean_third_quadrant(self):
+        x = np.radians(np.array([223, 224, 225, 226, 227]))
+
+        self.assertEqual(5*np.pi / 4, angular_mean(x))
+
+    def test_angular_mean_fourth_quadrant(self):
+        x = np.radians(np.array([313, 314, 315, 316, 317]))
+
+        self.assertEqual(7*np.pi / 4, angular_mean(x))
-- 
GitLab