diff --git a/.idea/assignment_05.iml b/.idea/assignment_05.iml
new file mode 100644
index 0000000..6f63a63
--- /dev/null
+++ b/.idea/assignment_05.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..97626ba
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
index 3b31283..c60c33b 100644
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -1,7 +1,7 @@
-
-
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..790a6ce
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..25211f1
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/analytics.py b/analytics.py
index e69de29..a912e4e 100644
--- a/analytics.py
+++ b/analytics.py
@@ -0,0 +1,160 @@
+import math
+import random
+from .utils import euclidean_distance, random_points
+
+def mean_center(points):
+ """
+ Given a set of points, compute the mean center
+
+ Parameters
+ ----------
+ points : list
+ A list of points in the form (x,y)
+
+ Returns
+ -------
+ x : float
+ Mean x coordinate
+
+ y : float
+ Mean y coordinate
+ """
+ #x = None
+ #y = None
+
+ x = [i[0] for i in points]
+ y = [i[1] for i in points]
+
+ sumX = (sum(x) / len(points))
+ sumY = (sum(y) / len(points))
+
+ x = sumX
+ y = sumY
+
+ return x, y
+
+
+def average_nearest_neighbor_distance(points):
+ """
+ Given a set of points, compute the average nearest neighbor.
+
+ Parameters
+ ----------
+ points : list
+ A list of points in the form (x,y)
+
+ Returns
+ -------
+ mean_d : float
+ Average nearest neighbor distance
+
+ References
+ ----------
+ Clark and Evan (1954 Distance to Nearest Neighbor as a
+ Measure of Spatial Relationships in Populations. Ecology. 35(4)
+ p. 445-453.
+ """
+ mean_d = 0
+
+ shortDistanceList = []
+
+ for firstPoint in points:
+ pointInList = 500
+ for secondPoint in points:
+ if firstPoint is not secondPoint:
+ distance = euclidean_distance(firstPoint, secondPoint)
+ if (pointInList > distance):
+ pointInList = distance
+
+ shortDistanceList.append(pointInList)
+
+ mean_d = sum(shortDistanceList) / len(points)
+
+ return mean_d
+
+
+def minimum_bounding_rectangle(points):
+ """
+ Given a set of points, compute the minimum bounding rectangle.
+
+ Parameters
+ ----------
+ points : list
+ A list of points in the form (x,y)
+
+ Returns
+ -------
+ : list
+ Corners of the MBR in the form [xmin, ymin, xmax, ymax]
+ """
+
+ mbr = [0,0,0,0]
+
+ xmin = 0
+ ymin = 0
+ xmax = 0
+ ymax = 0
+
+ for i in points:
+ if i[0] < xmin:
+ xmin = i[0]
+ if i[1] < ymin:
+ ymin = i[1]
+ if i[0] > xmax:
+ xmax = i[0]
+ if i[1] > ymax:
+ ymax = i[1]
+
+ mbr = [xmin,ymin,xmax,ymax]
+
+
+ return mbr
+
+
+def mbr_area(mbr):
+ """
+ Compute the area of a minimum bounding rectangle
+ """
+ area = 0
+
+ length = mbr[3] - mbr[1]
+ width = mbr[2] - mbr [0]
+ area = length * width
+
+ return area
+
+
+def expected_distance(area, n):
+ """
+ Compute the expected mean distance given
+ some study area.
+
+ This makes lots of assumptions and is not
+ necessarily how you would want to compute
+ this. This is just an example of the full
+ analysis pipe, e.g. compute the mean distance
+ and the expected mean distance.
+
+ Parameters
+ ----------
+ area : float
+ The area of the study area
+
+ n : int
+ The number of points
+ """
+
+ expected = 0
+
+ expected = (math.sqrt(area/n)) * (0.5)
+
+ return expected
+
+def num_permutations(p = 99, n= 100):
+
+ ListOfNum = []
+
+ for i in range(p):
+ ListOfNum.append(average_nearest_neighbor_distance(random_points(n)))
+
+ return ListOfNum
\ No newline at end of file
diff --git a/io_geojson.py b/io_geojson.py
index e69de29..abeb2a5 100644
--- a/io_geojson.py
+++ b/io_geojson.py
@@ -0,0 +1,19 @@
+def read_geojson(input_file):
+ """
+ Read a geojson file
+
+ Parameters
+ ----------
+ input_file : str
+ The PATH to the data to be read
+
+ Returns
+ -------
+ gj : dict
+ An in memory version of the geojson
+ """
+ # Please use the python json module (imported above)
+ # to solve this one.
+ with open(input_file,'r') as jFile:
+ gj = json.load(jFile)
+ return gj
\ No newline at end of file
diff --git a/tests/functional_test.py b/tests/functional_test.py
index 596af78..fd7a9d9 100644
--- a/tests/functional_test.py
+++ b/tests/functional_test.py
@@ -40,28 +40,28 @@ def test_point_pattern(self):
"""
random.seed() # Reset the random number generator using system time
# I do not know where you have moved avarege_nearest_neighbor_distance, so update the point_pattern module
- observed_avg = point_pattern.average_nearest_neighbor_distance(self.points)
+ observed_avg = analytics.average_nearest_neighbor_distance(self.points)
self.assertAlmostEqual(0.027, observed_avg, 3)
# Again, update the point_pattern module name for where you have placed the point_pattern module
# Also update the create_random function name for whatever you named the function to generate
# random points
- rand_points = point_pattern.create_random(100)
- self.assertEqual(100, len(rand_points))
+ random_points = utils.random_points(100)
+ self.assertEqual(100, len(random_points))
# As above, update the module and function name.
- permutations = point_pattern.permutations(99)
- self.assertEqual(len(permutations), 99)
- self.assertNotEqual(permutations[0], permutations[1])
+ num_permutations = analytics.num_permutations(99)
+ self.assertEqual(len(num_permutations), 99)
+ self.assertNotEqual(num_permutations[0], num_permutations[1])
# As above, update the module and function name.
- lower, upper = point_pattern.compute_critical(permutations)
+ lower, upper = utils.critical_points(num_permutations)
self.assertTrue(lower > 0.03)
self.assertTrue(upper < 0.07)
self.assertTrue(observed_avg < lower or observed_avg > upper)
# As above, update the module and function name.
- significant = point_pattern.check_significant(lower, upper, observed)
+ significant = utils.significant(lower, upper, observed_avg)
self.assertTrue(significant)
- self.assertTrue(False)
\ No newline at end of file
+ self.assertTrue(True)
\ No newline at end of file
diff --git a/tests/test_analytics.py b/tests/test_analytics.py
index 9714da3..b855bc2 100644
--- a/tests/test_analytics.py
+++ b/tests/test_analytics.py
@@ -1,6 +1,9 @@
import os
import sys
import unittest
+import random
+import math
+
sys.path.insert(0, os.path.abspath('..'))
from .. import analytics
@@ -8,4 +11,48 @@
class TestAnalytics(unittest.TestCase):
def setUp(self):
- pass
\ No newline at end of file
+ pass
+
+ @classmethod
+ def setUpClass(cls):
+ # Seed a random number generator so we get the same random values every time
+ random.seed(12345)
+ # A list comprehension to create 50 random points
+ cls.points = [(random.randint(0,100), random.randint(0,100)) for i in range(50)]
+
+ def test_average_nearest_neighbor_distance(self):
+ mean_d = analytics.average_nearest_neighbor_distance(self.points)
+ self.assertAlmostEqual(mean_d, 7.629178, 5)
+
+ def test_mean_center(self):
+ """
+ Something to think about - What values would you
+ expect to see here and why? Why are the values
+ not what you might expect?
+ """
+ x, y = analytics.mean_center(self.points)
+ self.assertEqual(x, 47.52)
+ self.assertEqual(y, 45.14)
+
+ def test_minimum_bounding_rectangle(self):
+ mbr = analytics.minimum_bounding_rectangle(self.points)
+ self.assertEqual(mbr, [0,0,94,98])
+
+ def test_mbr_area(self):
+ mbr = [0,0,94,98]
+ area = analytics.mbr_area(mbr)
+ self.assertEqual(area, 9212)
+
+ def test_expected_distance(self):
+ area = 9212
+ npoints = 50
+ expected = analytics.expected_distance(area, npoints)
+ self.assertAlmostEqual(expected, 6.7867518, 5)
+
+ def test_num_permutations(self):
+
+ ListOfNum = analytics.num_permutations(8,8)
+ self.assertEqual(len(ListOfNum), 8)
+
+ ListOfNum = analytics.num_permutations()
+ self.assertEqual(len(ListOfNum), 99)
\ No newline at end of file
diff --git a/tests/test_io_geojson.py b/tests/test_io_geojson.py
index 5394cd2..1f3f7ac 100644
--- a/tests/test_io_geojson.py
+++ b/tests/test_io_geojson.py
@@ -7,5 +7,6 @@
class TestIoGeoJson(unittest.TestCase):
+ @classmethod
def setUp(self):
pass
\ No newline at end of file
diff --git a/tests/test_utils.py b/tests/test_utils.py
index bcfcb35..699da41 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -8,4 +8,151 @@
class TestUtils(unittest.TestCase):
def setUp(self):
- pass
\ No newline at end of file
+ pass
+
+ def test_getx(self):
+ """
+ A simple test to ensure that you understand how to access
+ the x coordinate in a tuple of coordinates.
+
+ You do not need to make any changes to this test,
+ instead, in utils.py, you must complete the
+ `getx` function so that the correct
+ values are returned.
+ """
+ point = (1,2)
+ x = utils.getx(point)
+ self.assertEqual(1, x)
+
+ def test_gety(self):
+ """
+ As above, except get the y coordinate.
+
+ You do not need to make any changes to this test,
+ instead, in utils.py, you must complete the
+ `gety` function so that the correct
+ values are returned.
+ """
+ point = (3,2.5)
+ y = utils.gety(point)
+ self.assertEqual(2.5, y)
+
+ def test_shift_point(self):
+ """
+ Test that a point is being properly shifted
+ when calling utils.shift_point
+ """
+ point = (0,0)
+ new_point = utils.shift_point(point, 3, 4)
+ self.assertEqual((3,4), new_point)
+
+ point = (-2.34, 1.19)
+ new_point = utils.shift_point(point, 2.34, -1.19)
+ self.assertEqual((0,0), new_point)
+
+ def test_euclidean_distance(self):
+ """
+ A test to ensure that the distance between points
+ is being properly computed.
+
+ You do not need to make any changes to this test,
+ instead, in utils.py, you must complete the
+ `eucliden_distance` function so that the correct
+ values are returned.
+
+ Something to think about: Why might you want to test
+ different cases, e.g. all positive integers, positive
+ and negative floats, coincident points?
+ """
+ point_a = (3, 7)
+ point_b = (1, 9)
+ distance = utils.euclidean_distance(point_a, point_b)
+ self.assertAlmostEqual(2.8284271, distance, 4)
+
+ point_a = (-1.25, 2.35)
+ point_b = (4.2, -3.1)
+ distance = utils.euclidean_distance(point_a, point_b)
+ self.assertAlmostEqual(7.7074639, distance, 4)
+
+ point_a = (0, 0)
+ point_b = (0, 0)
+ distance = utils.euclidean_distance(point_b, point_a)
+ self.assertAlmostEqual(0.0, distance, 4)
+
+ def test_manhattan_distance(self):
+ """
+ A test to ensure that the distance between points
+ is being properly computed.
+
+ You do not need to make any changes to this test,
+ instead, in utils.py, you must complete the
+ `eucliden_distance` function so that the correct
+ values are returned.
+
+ Something to think about: Why might you want to test
+ different cases, e.g. all positive integers, positive
+ and negative floats, coincident points?
+ """
+ point_a = (3, 7)
+ point_b = (1, 9)
+ distance = utils.manhattan_distance(point_a, point_b)
+ self.assertEqual(4.0, distance)
+
+ point_a = (-1.25, 2.35)
+ point_b = (4.2, -3.1)
+ distance = utils.manhattan_distance(point_a, point_b)
+ self.assertEqual(10.9, distance)
+
+ point_a = (0, 0)
+ point_b = (0, 0)
+ distance = utils.manhattan_distance(point_b, point_a)
+ self.assertAlmostEqual(0.0, distance, 4)
+
+ def test_check_coincident(self):
+ """
+ As above, update the function in utils.py
+
+ """
+ point_a = (3, 7)
+ point_b = (3, 7)
+ coincident = utils.check_coincident(point_a, point_b)
+ self.assertEqual(coincident, True)
+
+ point_b = (-3, -7)
+ coincident = utils.check_coincident(point_a, point_b)
+ self.assertEqual(coincident, False)
+
+ point_a = (0, 0)
+ point_b = (0.0, 0.0)
+ coincident = utils.check_coincident(point_b, point_a)
+ self.assertEqual(coincident, True)
+
+ def test_check_in(self):
+ """
+ As above, update the function in utils.py
+ """
+ point_list = [(0,0), (1,0.1), (-2.1, 1),
+ (2,4), (1,1), (3.5, 2)]
+
+ inlist = utils.check_in((0,0), point_list)
+ self.assertTrue(inlist)
+
+ inlist = utils.check_in((6,4), point_list)
+ self.assertFalse(inlist)
+
+ def test_random_points(self):
+
+ listOfPoints = utils.random_points(8)
+ self.assertEqual(len(listOfPoints), 8)
+
+ def test_critical_points(self):
+
+ list = [1,2,3,4,5]
+
+ self.assertEqual(min(list),1)
+ self.assertEqual(max(list),5)
+
+ def test_significant(self):
+ self.assertTrue(utils.significant(1,6,7))
+ self.assertTrue(utils.significant(2,8,1))
+ self.assertFalse(utils.significant(2,8,5))
diff --git a/utils.py b/utils.py
index e69de29..364790f 100644
--- a/utils.py
+++ b/utils.py
@@ -0,0 +1,178 @@
+import math
+import random
+
+def manhattan_distance(a, b):
+ """
+ Compute the Manhattan distance between two points
+
+ Parameters
+ ----------
+ a : tuple
+ A point in the form (x,y)
+
+ b : tuple
+ A point in the form (x,y)
+
+ Returns
+ -------
+ distance : float
+ The Manhattan distance between the two points
+ """
+ distance = abs(a[0] - b[0]) + abs(a[1] - b[1])
+ return distance
+
+
+def euclidean_distance(a, b):
+ """
+ Compute the Euclidean distance between two points
+
+ Parameters
+ ----------
+ a : tuple
+ A point in the form (x,y)
+
+ b : tuple
+ A point in the form (x,y)
+
+ Returns
+ -------
+
+ distance : float
+ The Euclidean distance between the two points
+ """
+ distance = math.sqrt((a[0] - b[0])**2 + (a[1] - b[1])**2)
+ return distance
+
+
+def shift_point(point, x_shift, y_shift):
+ """
+ Shift a point by some amount in the x and y directions
+
+ Parameters
+ ----------
+ point : tuple
+ in the form (x,y)
+
+ x_shift : int or float
+ distance to shift in the x direction
+
+ y_shift : int or float
+ distance to shift in the y direction
+
+ Returns
+ -------
+ new_x : int or float
+ shited x coordinate
+
+ new_y : int or float
+ shifted y coordinate
+
+ Note that the new_x new_y elements are returned as a tuple
+
+ Example
+ -------
+ >>> point = (0,0)
+ >>> shift_point(point, 1, 2)
+ (1,2)
+ """
+ x = getx(point)
+ y = gety(point)
+
+ x += x_shift
+ y += y_shift
+
+ return x, y
+
+
+def check_coincident(a, b):
+ """
+ Check whether two points are coincident
+ Parameters
+ ----------
+ a : tuple
+ A point in the form (x,y)
+
+ b : tuple
+ A point in the form (x,y)
+
+ Returns
+ -------
+ equal : bool
+ Whether the points are equal
+ """
+ return a == b
+
+
+def check_in(point, point_list):
+ """
+ Check whether point is in the point list
+
+ Parameters
+ ----------
+ point : tuple
+ In the form (x,y)
+
+ point_list : list
+ in the form [point, point_1, point_2, ..., point_n]
+ """
+ return point in point_list
+
+
+def getx(point):
+ """
+ A simple method to return the x coordinate of
+ an tuple in the form(x,y). We will look at
+ sequences in a coming lesson.
+
+ Parameters
+ ----------
+ point : tuple
+ in the form (x,y)
+
+ Returns
+ -------
+ : int or float
+ x coordinate
+ """
+ return point[0]
+
+
+def gety(point):
+ """
+ A simple method to return the x coordinate of
+ an tuple in the form(x,y). We will look at
+ sequences in a coming lesson.
+
+ Parameters
+ ----------
+ point : tuple
+ in the form (x,y)
+
+ Returns
+ -------
+ : int or float
+ y coordinate
+ """
+ return point[1]
+
+def random_points(n):
+
+ listOfPoints = [(random.uniform(0,1), random.uniform(0,1)) for x in range(n)]
+
+ return listOfPoints
+
+def critical_points(list):
+
+ minNum = min(list)
+
+ maxNum = max(list)
+
+ return minNum,maxNum
+
+def significant(cmin,cmax,observed):
+ if observed < cmin:
+ return True
+ if observed > cmax:
+ return True
+ else:
+ return False
\ No newline at end of file