diff --git a/analytics.py b/analytics.py new file mode 100644 index 0000000..f355ad1 --- /dev/null +++ b/analytics.py @@ -0,0 +1,249 @@ +''' +Created on Feb 23, 2016 + +@author: Max Ruiz +''' + +import math + +''' +Function List +------------- +find_largest_city(gj) +mean_center(points) +average_nearest_neighbor_distance(points) +minimum_bounding_rectangle(points) +mbr_area(mbr) +expected_distance(area, n) +euclidean_distance(a, b) # also in utils.py + +compute_critical(p) +check_significant(lower,upper,observed) +''' + +'''Assignment 5 functions''' + +def compute_critical(p): + """ + Given a list, p, of distances (constants), determine the upper and lower + bound (or max and min value) of the set. The values in p are assumed floats. + + Parameter(s): list p + + Return(s): float lower, float upper + """ + lower = min(p) + upper = max(p) + return lower, upper + +def check_significant(lower, upper, observed): + """ + Check if given observed point is outside or within a given lower and upper + bound. + + Parameter(s): float lower, float upper, float observed. + + Return(s): boolean + """ + return observed < lower or observed > upper + +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 + """ + + max_population = 0 + for feat in gj['features']: + test_max_pop = feat['properties']['pop_max'] + if test_max_pop > max_population: + max_population = test_max_pop + city = feat['properties']['name'] + + return city, max_population + +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 + """ + sumx = 0.0 + sumy = 0.0 + for coord in points: + sumx += coord[0] + sumy += coord[1] + x = sumx / len(points) + y = sumy / len(points) + + return x, y + + +def average_nearest_neighbor_distance_tuples(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. + """ + min_dist_sum = 0 + for coord_n in points: + first = True + for coord_m in points: + if coord_n == coord_m: + continue + else: + d = euclidean_distance(coord_n, coord_m) + if first: + min_dist = d + first = False + else: + if d < min_dist: + min_dist = d + min_dist_sum += min_dist + + mean_d = min_dist_sum / len(points) + + return mean_d + +def average_nearest_neighbor_distance(points, mark = None): + if mark != None: + pointsWithMark = list() + for x in range(len(points)): + if points[x].getMark() == mark: + pointsWithMark.append(points[x].getPoint()) + else: + continue + return average_nearest_neighbor_distance_tuples(pointsWithMark) + else: + allPoints = list(points[x].getPoint() for x in range(len(points))) + return average_nearest_neighbor_distance_tuples(allPoints) + +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] + """ + xmin = 0 + xmax = 0 + ymin = 0 + ymax = 0 + for coord in points: + if coord[0] < xmin: + xmin = coord[0] + elif coord[0] > xmax: + xmax = coord[0] + + if coord[1] < ymin: + ymin = coord[1] + elif coord[1] > ymax: + ymax = coord[1] + + xcorner = xmax - xmin + ycorner = ymax - ymin + mbr = [0,0,xcorner,ycorner] + + return mbr + + +def mbr_area(mbr): + """ + Compute the area of a minimum bounding rectangle + """ + 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.5 * math.sqrt(area / n) + return expected + +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 diff --git a/io_geojson.py b/io_geojson.py new file mode 100644 index 0000000..efa1028 --- /dev/null +++ b/io_geojson.py @@ -0,0 +1,33 @@ +''' +Created on Feb 23, 2016 + +@author: Max Ruiz +''' +import json + +''' +Function List +------------- +read_geojson(input_file) +''' + +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 f: + gj = json.load(f) + return gj diff --git a/point.py b/point.py new file mode 100644 index 0000000..3c32240 --- /dev/null +++ b/point.py @@ -0,0 +1,41 @@ +''' +Created on Mar 15, 2016 + +@author: Max Ruiz +''' + + +class Point(object): + + def __init__(self, x, y, mark = None): + self.x = x + self.y = y + self.mark = mark + + def __add__(self, other): + return Point(self.x + other.x, self.y + other.y) + + def __eq__(self, other): + return self.x == other.x and self.y == other.y + + def __neg__(self): + return Point(-self.x, -self.y) + + def check_coincident(self, point): + return (self.x == point[0] and self.y == point[1]) + + def shift_point(self, x_shift, y_shift): + self.x += x_shift + self.y += y_shift + + def getx(self): + return self.x + + def gety(self): + return self.y + + def getPoint(self): + return (self.x, self.y) + + def getMark(self): + return self.mark diff --git a/point_pattern.py b/point_pattern.py new file mode 100644 index 0000000..159471e --- /dev/null +++ b/point_pattern.py @@ -0,0 +1,92 @@ + + +from point import Point +import analytics +import utils +import random +import numpy as np + +class PointPattern(object): + def __init__(self): + self.points = [] + + def add_point(self, point): + self.points.append(point) + + def remove_point(self, index): + try: + del(self.points[index]) + except: + pass + + def average_nearest_neighbor_distance(self, mark=None): + return analytics.average_nearest_neighbor_distance(self.points, mark) + + def num_of_coincident(self): + numCoin = 0 + accounted = [] + + + for i in range(len(self.points)): + for j in range(len(self.points)): + if i in accounted: + continue + if i == j: + continue + if self.points[i] == self.points[j]: + numCoin += 1 + accounted.append(j) + + return numCoin + + def list_marks(self): + marks = [] + for point in self.points: + if point.mark != None and point.mark not in marks: + marks.append(point.mark) + return marks + + def find_subset_with_mark(self, mark): + marked_points = [] + for points in self.points: + if points.mark == mark: + marked_points.append(points) + return marked_points + + def generate_random_points(self, n=None): + if n is None: + n = len(self.points) + rndmPoints = [] + self.marks = ['burrito', 'chimichanga', 'steak', 'burger', 'chillidog', + 'sweetpotatofries', 'beans', 'bacon', 'beijingbeef', 'friedeggs', + 'icecream', 'brownies', 'cookie', 'bananasplit', 'almondjoy'] + + for i in range(n): + rndmPoints.append(Point(round(random.random(), 2), round(random.random(), 2), random.choice(self.marks))) + return rndmPoints + + def generate_realizations(self, k): + return utils.permutations(k) + + def get_critical_points(self): + return analytics.compute_critical(self.generate_realizations(100)) + + def compute_g(self, nsteps): + discStep = np.linspace(0, 1, nsteps) + sum = 0 + for i in range(nsteps): + i_step = discStep[i] + minDist = -1 + for j in range(len(discStep)): + if i == j: + continue + if minDist == -1: + minDist = abs(discStep[j] - i_step) + else: + if abs(discStep[j] - i_step) < minDist: + minDist = abs(discStep[j] - i_step) + else: + minDist = minDist + sum += minDist + + return sum / nsteps diff --git a/test_point_pattern.py b/test_point_pattern.py new file mode 100644 index 0000000..89c8436 --- /dev/null +++ b/test_point_pattern.py @@ -0,0 +1,38 @@ + +import unittest +#from point_pattern import PointPattern +#from point import Point + +from point_pattern import PointPattern +from point import Point + + +class TestPointPattern(unittest.TestCase): + def setUp(self): + self.point_pattern = PointPattern() + self.point_pattern.add_point(Point(1, 2, 'burrito')) + self.point_pattern.add_point(Point(2, 1, 'burrito')) + self.point_pattern.add_point(Point(1, 2, 'burger')) + self.point_pattern.add_point(Point(1, 2)) + + def test_coincident(self): + self.assertEqual(self.point_pattern.num_of_coincident(), 2) + + def test_list_marks(self): + self.assertEqual(self.point_pattern.list_marks(), ['burrito', 'burger']) + + def test_find_subset_with_mark(self): + self.assertEqual(len(self.point_pattern.find_subset_with_mark('burrito')), 2) + self.assertEqual(len(self.point_pattern.find_subset_with_mark('burger')), 1) + + def test_generate_random(self): + self.assertEqual(len(self.point_pattern.generate_random_points()), 4) + self.assertEqual(len(self.point_pattern.generate_random_points(10)), 10) + + def test_generate_realizations(self): + self.assertEqual(len(self.point_pattern.generate_realizations(100)), 100) + + def test_compute_g(self): + self.assertAlmostEqual(self.point_pattern.compute_g(10), 0.111, places=3) + self.assertAlmostEqual(self.point_pattern.compute_g(100), 0.010, places=3) + self.assertAlmostEqual(self.point_pattern.compute_g(1000), 0.001, places=3) diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..899230f --- /dev/null +++ b/utils.py @@ -0,0 +1,213 @@ +''' +Created on Feb 23, 2016 + +@author: Max Ruiz +''' +import math +import random +#import analytics +from analytics import average_nearest_neighbor_distance +from point import Point + +''' +Function List +------------- +manhattan_distance(a, b) +euclidean_distance(a, b) +shift_point(point, x_shift, y_shift) +check_coincident(a, b) +check_in(point, point_list) +getx(point) +gety(point) + +create_random(n) +permutations(p) +''' + + +def create_random_marked_points(n, marks=[]): + random.seed() + randPoints = list() + for x in range(n): + _x = random.randint(0,100) + _y = random.randint(0,100) + if marks is None: + randPoints.append(Point(_x, _y)) + else: + if len(marks) == 0: + randPoints.append(Point(_x, _y)) + else: + rndmark = random.choice(marks) + randPoints.append(Point(_x, _y, rndmark)) + return randPoints + +def permutations(p=99, n=100, marks = None): + """ + Calculate p number of average_nearest_neighbor_distances from n number + of randomly generated points. Return list of size p with distance values. + + Parameter(s): integer p, integer n + + Return(s): list perm + """ + perm = [] + for x in range(p): + points = create_random_marked_points(n, marks) + avg_nnd = average_nearest_neighbor_distance(points) + perm.append(avg_nnd) + + return perm + +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]