+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/__pycache__/__init__.cpython-35.pyc b/__pycache__/__init__.cpython-35.pyc
new file mode 100644
index 0000000..085b987
Binary files /dev/null and b/__pycache__/__init__.cpython-35.pyc differ
diff --git a/__pycache__/analytics.cpython-35.pyc b/__pycache__/analytics.cpython-35.pyc
new file mode 100644
index 0000000..b8adbd2
Binary files /dev/null and b/__pycache__/analytics.cpython-35.pyc differ
diff --git a/__pycache__/io_geojson.cpython-35.pyc b/__pycache__/io_geojson.cpython-35.pyc
new file mode 100644
index 0000000..0d13cf1
Binary files /dev/null and b/__pycache__/io_geojson.cpython-35.pyc differ
diff --git a/__pycache__/point.cpython-35.pyc b/__pycache__/point.cpython-35.pyc
new file mode 100644
index 0000000..127e54b
Binary files /dev/null and b/__pycache__/point.cpython-35.pyc differ
diff --git a/analytics.py b/analytics.py
index e69de29..46bfe7e 100644
--- a/analytics.py
+++ b/analytics.py
@@ -0,0 +1,278 @@
+import math # For all of the math used
+# import utils
+
+from utils import generate_rand_points
+# ------------------------------------------------------------------
+#
+# Joseph Cruz
+# analytics.py
+#
+# Stores the functions from point_pattern.py that perform analysis
+# on data.
+# ------------------------------------------------------------------
+
+# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#
+# function mean_nearest_neighbors_randomPoints
+#
+# Determines the mean nearest neighbor of randomly generated points
+# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+
+def permutations(p = 99, n = 100):
+ list_means = []
+
+ for i in range(p):
+ # randPoints = utils.generate_rand_points(n)
+ rand_points = generate_rand_points(n)
+ newMean = average_nearest_neighbor_distance(rand_points)
+ list_means.append(newMean)
+
+ return list_means
+
+#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#
+# function find_crit_points
+#
+# Finds the critical points (min and max) of a list
+#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+
+def find_crit_points(list_means):
+ entries = list_means
+ maxEntry = 0
+ minEntry = 2
+ for i in range(len(list_means)):
+ if entries[i] > maxEntry:
+ maxEntry = entries[i]
+ if entries[i] < minEntry:
+ minEntry = entries[i]
+
+ return minEntry,maxEntry
+
+#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#
+# function crit_point_check
+#
+# Checks if the observed value is within the range of the min and max
+#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+
+def crit_point_check(minEntry, maxEntry, observed):
+ if observed < minEntry or observed > maxEntry:
+ return True
+ else:
+ return False
+
+
+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 = 0
+ y = 0
+ numOfPoints = len(points)
+
+ for i in range(numOfPoints):
+ x = x + points[i][0]
+ y = y + points[i][1]
+
+ x = x/numOfPoints
+ y = y/numOfPoints
+
+ 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
+ total = 0
+ local_nn = 0
+ numOfPoints = len(points)
+
+ for i in range(numOfPoints):
+ local_nn = 0 #reset local_nn for the new point
+ for j in range(numOfPoints):
+ if i != j:
+ newDistance = euclidean_distance(points[i],points[j])
+ if local_nn == 0:
+ local_nn = newDistance
+ elif newDistance < local_nn:
+ local_nn = newDistance
+
+ total = total + local_nn
+
+ mean_d = total/numOfPoints
+
+
+ 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]
+ numOfPoints = len(points)
+ for i in range(numOfPoints):
+ #Check for min and max x
+ if points[i][0] < mbr[0]:
+ mbr[0] = points[i][0]
+ if points[i][0] > mbr[2]:
+ mbr[2] = points[i][0]
+ #Check for min and max y
+ if points[i][1] < mbr[1]:
+ mbr[1] = points[i][1]
+ if points[i][1] > mbr[3]:
+ mbr[3] = points[i][1]
+
+ return mbr
+
+
+def mbr_area(mbr):
+ """
+ Compute the area of a minimum bounding rectangle
+ """
+ area = (mbr[2] - mbr[0])*(mbr[3] - mbr[1])
+
+ 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 = (1/2)*math.sqrt(area/n)
+ return expected
+
+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 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
+
diff --git a/io_geojson.py b/io_geojson.py
index e69de29..4e945c5 100644
--- a/io_geojson.py
+++ b/io_geojson.py
@@ -0,0 +1,83 @@
+import json #for the geojson stuff
+
+#------------------------------------------------------------------
+#
+# Joseph Cruz
+# io_geojson.py
+#
+# Stores the functions from point_pattern.py that are a form of u-
+# tility needed for use in other functions
+#------------------------------------------------------------------
+
+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) as iFile:
+ gj = json.load(iFile)
+ return gj
+
+
+def find_largest_city(gj):
+ """
+ Iterate through a geojson feature collection and
+ find the largest city. Assume that the key
+ to access the maximum population is 'pop_max'.
+
+ Parameters
+ ----------
+ gj : dict
+ A GeoJSON file read in as a Python dictionary
+
+ Returns
+ -------
+ city : str
+ The largest city
+
+ population : int
+ The population of the largest city
+ """
+ gj_features = gj['features']
+ city = None
+ max_population = 0
+
+ for nextFeature in gj_features:
+ if nextFeature['pop_max'] > max_population:
+ city = nextFeature['name']
+ max_population = nextFeature['pop_max']
+
+ return city, max_population
+
+
+def write_your_own(gj):
+ """
+ Here you will write your own code to find
+ some attribute in the supplied geojson file.
+
+ Take a look at the attributes available and pick
+ something interesting that you might like to find
+ or summarize. This is totally up to you.
+
+ Do not forget to write the accompanying test in
+ tests.py!
+ """
+ #Counts the number of world cities
+ gj_features = gj['features']
+ numWorldCities = 0
+
+ for nextFeature in gj_features:
+ if nextFeature['worldcity'] != 0:
+ numWorldCities += 1
+ return numWorldCities
diff --git a/point.py b/point.py
index e69de29..fb6ba23 100644
--- a/point.py
+++ b/point.py
@@ -0,0 +1,108 @@
+import random
+import math
+
+
+class Point:
+ """
+ For whatever reason, cannot get import to work, just moved functionality
+ into this file instead.
+ """
+ def __init__(self,x = 0,y = 0,mark = ""):
+ self.x = x
+ self.y = y
+ self.mark = mark
+
+ def shift_point(self,x_move,y_move):
+ this_point = (self.x,self.y)
+ self.x += x_move
+ self.y += y_move
+
+ def coincident(self, check_point):
+ if check_point.x == self.x and check_point.y == self.y:
+ return True
+ else:
+ return False
+
+
+def create_random_marked_points(n, marks = []):
+ list_of_tuples = [(random.uniform(0,1), random.uniform(0,1)) for i in range(n)]
+ list_of_marks = [random.choice(marks) for i in range(n)]
+ list_of_points = []
+ for j in range(n):
+ new_point = Point(list_of_tuples[j][0],list_of_tuples[j][1],list_of_marks[j])
+ list_of_points.append(new_point)
+
+ return list_of_points
+
+
+def euclidean_distance(a, b):
+ distance = math.sqrt((a.x - b.x)**2 + (a.y - b.y)**2)
+ return distance
+
+
+def average_nearest_neighbor_distance(points, mark=""):
+ mean_d = 0
+ total = 0
+ local_nn = 0
+ num_of_points = len(points)
+
+ if not mark:
+ for i in range(num_of_points):
+ local_nn = 0
+ for j in range(num_of_points):
+ if i != j:
+ new_distance = euclidean_distance(points[i],points[j])
+ if local_nn == 0:
+ local_nn = new_distance
+ elif new_distance < local_nn:
+ local_nn = new_distance
+
+ total += local_nn
+
+ else:
+ for i in range(num_of_points):
+ local_nn = 0
+ for j in range(num_of_points):
+ if i != j and points[i].mark == points[j].mark:
+ new_distance = euclidean_distance(points[i],points[j])
+ if local_nn == 0:
+ local_nn = new_distance
+ elif new_distance < local_nn:
+ local_nn = new_distance
+
+ total += local_nn
+
+ mean_d = total/num_of_points
+ return mean_d
+
+
+def permutations(p = 99, n = 100):
+ list_means = []
+
+ for i in range(p):
+ marks = ["elf", "dwarf", "human", "orc"]
+ rand_points = create_random_marked_points(n, marks)
+ newMean = average_nearest_neighbor_distance(rand_points)
+ list_means.append(newMean)
+
+ return list_means
+
+
+def find_crit_points(list_means):
+ entries = list_means
+ maxEntry = 0
+ minEntry = 2
+ for i in range(len(list_means)):
+ if entries[i] > maxEntry:
+ maxEntry = entries[i]
+ if entries[i] < minEntry:
+ minEntry = entries[i]
+
+ return minEntry,maxEntry
+
+
+def crit_point_check(minEntry, maxEntry, observed):
+ if observed < minEntry or observed > maxEntry:
+ return True
+ else:
+ return False
\ No newline at end of file
diff --git a/tests/__pycache__/__init__.cpython-35.pyc b/tests/__pycache__/__init__.cpython-35.pyc
new file mode 100644
index 0000000..d46027b
Binary files /dev/null and b/tests/__pycache__/__init__.cpython-35.pyc differ
diff --git a/tests/__pycache__/functional_test.cpython-35.pyc b/tests/__pycache__/functional_test.cpython-35.pyc
new file mode 100644
index 0000000..9b183fa
Binary files /dev/null and b/tests/__pycache__/functional_test.cpython-35.pyc differ
diff --git a/tests/__pycache__/point_test.cpython-35.pyc b/tests/__pycache__/point_test.cpython-35.pyc
new file mode 100644
index 0000000..b1c218c
Binary files /dev/null and b/tests/__pycache__/point_test.cpython-35.pyc differ
diff --git a/tests/functional_test.py b/tests/functional_test.py
index 596af78..ba33050 100644
--- a/tests/functional_test.py
+++ b/tests/functional_test.py
@@ -1,9 +1,8 @@
import random
import unittest
-from .. import analytics
from .. import io_geojson
-from .. import utils
+from .. import point
class TestFunctionalPointPattern(unittest.TestCase):
@@ -11,9 +10,14 @@ class TestFunctionalPointPattern(unittest.TestCase):
def setUp(self):
random.seed(12345)
i = 0
+ marks = ["elf", "dwarf", "human", "orc"]
+ rand_marks = []
+ for i in range(100):
+ rand_marks.append(random.choice(marks))
+
self.points = []
while i < 100:
- seed = (round(random.random(),2), round(random.random(),2))
+ seed = point.Point(round(random.random(),2), round(random.random(),2), rand_marks[i])
self.points.append(seed)
n_additional = random.randint(5,10)
i += 1
@@ -22,7 +26,7 @@ def setUp(self):
for j in range(n_additional):
x_offset = random.randint(0,10) / 100
y_offset = random.randint(0,10) / 100
- pt = (round(seed[0] + x_offset, 2), round(seed[1] + y_offset,2))
+ pt = point.Point(round(seed.x + x_offset, 2), round(seed.y + y_offset,2), random.choice(marks))
self.points.append(pt)
i += 1
if i == 100:
@@ -38,30 +42,35 @@ def test_point_pattern(self):
nearest neighbor distance computed using a random realization of
the point process.
"""
+ marks = ["elf", "dwarf", "human", "orc"]
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)
- self.assertAlmostEqual(0.027, observed_avg, 3)
-
+ observed_avg_elf = point.average_nearest_neighbor_distance(self.points,"elf")
+ self.assertAlmostEqual( 0.02555, observed_avg_elf, 3)
+ observed_avg_dwarf = point.average_nearest_neighbor_distance(self.points,"dwarf")
+ self.assertAlmostEqual( 0.02555, observed_avg_dwarf, 3)
+ observed_avg_human = point.average_nearest_neighbor_distance(self.points,"human")
+ self.assertAlmostEqual( 0.02555, observed_avg_human, 3)
+ observed_avg_orc = point.average_nearest_neighbor_distance(self.points,"orc")
+ self.assertAlmostEqual( 0.02555, observed_avg_orc, 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)
+ rand_points = point.create_random_marked_points(100,marks)
self.assertEqual(100, len(rand_points))
# As above, update the module and function name.
- permutations = point_pattern.permutations(99)
+ permutations = point.permutations(99)
self.assertEqual(len(permutations), 99)
self.assertNotEqual(permutations[0], permutations[1])
# As above, update the module and function name.
- lower, upper = point_pattern.compute_critical(permutations)
+ lower, upper = point.find_crit_points(permutations)
self.assertTrue(lower > 0.03)
self.assertTrue(upper < 0.07)
- self.assertTrue(observed_avg < lower or observed_avg > upper)
+ self.assertTrue(observed_avg_elf < lower or observed_avg_elf > upper)
# As above, update the module and function name.
- significant = point_pattern.check_significant(lower, upper, observed)
+ significant = point.crit_point_check(lower, upper, observed_avg_elf)
self.assertTrue(significant)
- self.assertTrue(False)
\ No newline at end of file
diff --git a/tests/point_test.py b/tests/point_test.py
new file mode 100644
index 0000000..454b963
--- /dev/null
+++ b/tests/point_test.py
@@ -0,0 +1,71 @@
+from .. import point
+import unittest
+import random
+
+
+class TestPointClass(unittest.TestCase):
+
+ def set_up(self):
+ pass
+
+ def test_point_pattern(self):
+ random.seed(12345)
+ rand_tuple = (random.randint(0,10),random.randint(0,10))
+ check_point = point.Point(rand_tuple[0],rand_tuple[1],"some mark")
+ """ Tests that the point is being set correctly """
+ self.assertEqual(check_point.x, 6)
+ self.assertEqual(check_point.y, 0)
+
+ """ Tests to insure coincidence is read properly """
+ rand_tuple2 = (random.randint(0,10),random.randint(0,10))
+ copy_point = point.Point(6,0,"balrog")
+ check_point2 = point.Point(rand_tuple2[0],rand_tuple2[1],"some other mark")
+ self.assertTrue(check_point.coincident(copy_point))
+ self.assertFalse(check_point.coincident(check_point2))
+
+ """ Tests for shift_point """
+ pos_shift_point = point.Point(rand_tuple[0],rand_tuple[1],"some mark")
+ neg_shift_point = point.Point(rand_tuple[0],rand_tuple[1],"some mark")
+
+ pos_shift_point.shift_point(rand_tuple2[0],rand_tuple2[1])
+ self.assertTrue(pos_shift_point.x == 10 and pos_shift_point.y == 5)
+
+ neg_shift_point.shift_point(-rand_tuple2[0],-rand_tuple2[1])
+ self.assertTrue(neg_shift_point.x == 2 and neg_shift_point.y == -5)
+
+ def test_marks(self):
+ list_of_points = []
+ marks = ["elf", "dwarf", "human", "orc"]
+ random.seed(12345)
+ list_of_points = point.create_random_marked_points(20,marks)
+
+ elf_counter = 0
+ human_counter = 0
+ dwarf_counter = 0
+ orc_counter = 0
+
+ for i in range(len(list_of_points)):
+ if list_of_points[i].mark == "elf":
+ elf_counter += 1
+ elif list_of_points[i].mark == "human":
+ human_counter += 1
+ elif list_of_points[i].mark == "dwarf":
+ dwarf_counter += 1
+ elif list_of_points[i].mark == "orc":
+ orc_counter += 1
+
+ self.assertEqual(elf_counter, 4)
+ self.assertEqual(human_counter, 5)
+ self.assertEqual(dwarf_counter, 8)
+ self.assertEqual(orc_counter, 3)
+
+ def test_nearest_neightbor(self):
+ random.seed(12345)
+ marks = ["elf", "dwarf", "human", "orc"]
+ list_of_points = point.create_random_marked_points(20,marks)
+
+ distance_no_mark = point.average_nearest_neighbor_distance(list_of_points)
+ distance_with_mark = point.average_nearest_neighbor_distance(list_of_points,"orc")
+
+ self.assertAlmostEqual(distance_no_mark, 0.13861788961152158, 5)
+ self.assertAlmostEqual(distance_with_mark, 0.253406515134334, 5)
\ No newline at end of file
diff --git a/utils.py b/utils.py
index e69de29..51adb31 100644
--- a/utils.py
+++ b/utils.py
@@ -0,0 +1,99 @@
+import math #For all of the math used
+import random # For random used
+# ------------------------------------------------------------------
+#
+# Joseph Cruz
+# utils.py
+#
+# Stores the functions from point_pattern.py that are a form of
+# utility needed for use in other functions
+# ------------------------------------------------------------------
+
+# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+#
+# function generate_rand_points()
+#
+# Generates an integer number of random points based on user input
+# Points will be within the domain [0,1]
+# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+def generate_rand_points(n):
+ rng = random.Random()
+ listofPoints = [(random.uniform(0,1), random.uniform(0,1)) for i in range(n)]
+
+ return listofPoints
+
+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 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]