Skip to content

Fingers crossed #27

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

Open
wants to merge 21 commits into
base: master
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
97 changes: 97 additions & 0 deletions analytics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from utils import *

"""
1. Organize the functions that were in point_pattern.py into the appropriate modules.
2. Update the tests to reflect the new structure.
3. Write a function to generate $n$ random points, where the user defines $n$.
4. Write a function that takes $p$ an integer number of permutations. For each
permutation, create $n$ random points and compute the mean nearest neighbor distance.
Let this function default to p=99 and n=100. Make sure that the user can alter these
values if they like.
5. Write a function to compute the critical points in the results returned by the
function you wrote in 4. If p = 99, then the function in 4 should return a list of 99
distances. This function will take that list and find the smallest and largest distances.
These are the critical points of the Monte Carlo test.
6. Write a function that takes the critical points of the Monte Carlo simulation and the
observed value and returns True is the observed distance is significant, i.e., less than
or greater than the observed. Otherwise, return False.
7. Write tests for items 3, 4, 5, and 6.
8. Look at the file, functional_test.py. In that file I have written a single functional
test that ties together all of your previous work. For this test, you should replace the
module and function names with your own values. For example, I assume that all the
necessary methods are in the point_pattern module. Since you refactored the structure of
the code in completing #1, the point_pattern module does not exist. Instead, analytics
and utils do. Additionally,for #3 - 5, you wrote functions. I guessed at what you might
name these, but leave it to you to update the functional test with the names you selected.
"""


def mean_center(points):

x = 0
y = 0

for i in points:
x += i[0]
y += i[1]

x /= len(points)
y /= len(points)

return x, y


def minimum_bounding_rectangle(points):

mbr = [0, 0, 0, 0]
x_min = 0
x_max = 0
y_min = 0
y_max = 0

for p in points:
if p[0] < x_min:
x_min = p[0]
if p[0] > x_max:
x_max = p[0]
if p[1] < y_min:
y_min = p[1]
if p[1] > y_max:
y_max = p[1]
mbr = [x_min, y_min, x_max, y_max]

return mbr


def mbr_area(mbr):

l = mbr[2] - mbr[0]
w = mbr[3] - mbr[1]
area = l * w

return area


def expected_distance(area, n):

expected = 0.5 * (math.sqrt(area / n))

return expected


def compute_critical(points):

l = min(points)
u = max(points)

return l, u


def check_significant(l, u, observed):

if (l < observed) or (observed < u):
result = True
else:
result = False

return result
24 changes: 24 additions & 0 deletions io_geojson.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import json


def read_geojson(input_file):

with open(input_file, 'r') as f:
gj = json.load(f)

return gj


def find_largest_city(gj):

city = None
max_population = 0

for i in gj['features']:
if i['properties']['pop_max'] > max_population:
max_population = i['properties']['pop_max']
city = i['properties']['name']

return city, max_population


18 changes: 9 additions & 9 deletions tests/functional_test.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import random
import unittest
import random

from .. import analytics
from .. import io_geojson
from .. import analytics
from .. import utils


Expand Down Expand Up @@ -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)
self.assertAlmostEqual(0.027, observed_avg, 3)
observed_avg = utils.average_nearest_neighbor_distance(self.points)
self.assertAlmostEqual(0.030, 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)
rand_points = utils.create_random(100)
self.assertEqual(100, len(rand_points))

# As above, update the module and function name.
permutations = point_pattern.permutations(99)
permutations = utils.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 = utils.compute_critical(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.check_significant(lower, upper, observed_avg)
self.assertTrue(significant)

self.assertTrue(False)
self.assertTrue(False)
17 changes: 16 additions & 1 deletion tests/test_analytics.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import os
import sys
import unittest

sys.path.insert(0, os.path.abspath('..'))

from .. import analytics


class TestAnalytics(unittest.TestCase):

def setUp(self):
pass

pass

def test_compute_critical(self):

self.assertTrue(self.l == 0)
self.assertTrue(self.u == 9)

def test_check_significant(self):

significant = [analytics.check_significant(self.l, self.u, self.observed)]

self.assertTrue(significant[0])
self.assertFalse(significant[1])
15 changes: 9 additions & 6 deletions tests/test_io_geojson.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import os
import sys
import unittest
sys.path.insert(0, os.path.abspath('..'))

from .. import io_geojson
import io_geojson


class TestIoGeoJson(unittest.TestCase):

def setUp(self):
pass
@classmethod
def setUp(cls):
cls.gj = io_geojson.read_geojson('data/us_cities.geojson')

def read_geojson(self):
self.assertIsInstance(self.gj, dict)

17 changes: 11 additions & 6 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import os
import sys
import unittest
sys.path.insert(0, os.path.abspath('..'))

from .. import utils
from ..import utils

class TestUtils(unittest.TestCase):

class TestUtils(unittest.TestCase):
def setUp(self):
pass
self.random_points = utils.create_random_points(100)
self.permutations = utils.permutation(99)

def test_create_random(self):
self.assertEqual(100, len(self.random_points))

def test_permutation(self):
self.assertEqual(len(self.permutation), 99)
self.assertNotEqual(self.permutation[0], self.permutation[1])
110 changes: 110 additions & 0 deletions utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import math
import random

"""
1. Organize the functions that were in point_pattern.py into the appropriate modules.
2. Update the tests to reflect the new structure.
3. Write a function to generate $n$ random points, where the user defines $n$.
4. Write a function that takes $p$ an integer number of permutations. For each
permutation, create $n$ random points and compute the mean nearest neighbor distance.
Let this function default to p=99 and n=100. Make sure that the user can alter these
values if they like.
5. Write a function to compute the critical points in the results returned by the
function you wrote in 4. If p = 99, then the function in 4 should return a list of 99
distances. This function will take that list and find the smallest and largest distances.
These are the critical points of the Monte Carlo test.
6. Write a function that takes the critical points of the Monte Carlo simulation and the
observed value and returns True is the observed distance is significant, i.e., less than
or greater than the observed. Otherwise, return False.
7. Write tests for items 3, 4, 5, and 6.
8. Look at the file, functional_test.py. In that file I have written a single functional
test that ties together all of your previous work. For this test, you should replace the
module and function names with your own values. For example, I assume that all the
necessary methods are in the point_pattern module. Since you refactored the structure of
the code in completing #1, the point_pattern module does not exist. Instead, analytics
and utils do. Additionally,for #3 - 5, you wrote functions. I guessed at what you might
name these, but leave it to you to update the functional test with the names you selected.
"""


def manhattan_distance(a, b):

distance = abs(a[0] - b[0]) + abs(a[1] - b[1])
return distance


def euclidean_distance(a, b):

distance = math.sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2)
return distance


def shift_point(point, x_shift, y_shift):

x = getx(point)
y = gety(point)

x += x_shift
y += y_shift

return x, y


def check_coincident(a, b):

return a == b


def check_in(point, point_list):

return point in point_list


def getx(point):

return point[0]


def gety(point):

return point[1]


def average_nearest_neighbor_distance(points):

mean_d = 0
nearest_neighbor = math.inf

for point in points:
for otherPoint in points:
if check_coincident(point, otherPoint):
continue
current_distance = euclidean_distance(point, otherPoint)
if nearest_neighbor is None:
nearest_neighbor = current_distance
elif nearest_neighbor > current_distance:
nearest_neighbor = current_distance

mean_d += nearest_neighbor
nearest_neighbor = None

mean_d /= len(points)

return mean_d


def create_random_points(n):

random_points = [(random.uniform(0, 1), random.uniform(0, 1)) in range(n)]

return random_points


def permutation(p=99, n=100):

per = []
for x in range(p):
per.append(average_nearest_neighbor_distance(create_random_points(n)))

return per