diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/analytics.py b/analytics.py new file mode 100644 index 0000000..d94e6dc --- /dev/null +++ b/analytics.py @@ -0,0 +1,149 @@ +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 new file mode 100644 index 0000000..49ca42c --- /dev/null +++ b/io_geojson.py @@ -0,0 +1,37 @@ +import json + +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 + +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 \ No newline at end of file diff --git a/point.py b/point.py new file mode 100644 index 0000000..d150d56 --- /dev/null +++ b/point.py @@ -0,0 +1,40 @@ +from . import utils +import random +import analytics +import numpy as np +import scipy.spatial as ss +import pysal as ps + +class Point(object): + def __init__(self, x, y, mark={}): + self.x = x + self.y = y + self.mark = mark + + #implement magic methods + + 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 coincidentPoint(self, point1): + point2 = (self.x, self.y) + return utils.check_coincident(point1, point2) + + def shiftPoint(self,xShift, yShift): + thePoint = (self.x, self.y) + self.x, self.y = utils.shift_point(thePoint,xShift,yShift) + + def numpyPoint(self, x = 0, y = 0, n = 1000): + numpyArray = np.random.uniform(x, y, (n, 2)) + list = [] + marks = ['James', 'Sarah', 'Nick', 'Michael'] + for i in range(len(numpyArray)): + list.append(Point(numpyArray[i][0])) + numpyArray[i][1], random.choice(marks) + return list \ No newline at end of file diff --git a/pointPattern.py b/pointPattern.py new file mode 100644 index 0000000..3065c64 --- /dev/null +++ b/pointPattern.py @@ -0,0 +1,91 @@ +import math +import random +from . point import Point +from . import analytics +from . import utils +import numpy as np + +class PointPattern(object): + + def __init__(self): + self.thePoints = [] + + def averageNearestNeighborDistance(self, marks=None): + return analytics.average_nearest_neighbor_distance(self.points, marks) + + def coincidentPoints(self): + counter = 0 + coincidentList = [] + + for c in range(len(self.thePoints)): + for o in range(len(self.thePoints)): + if c in coincidentList: + continue + elif c == o: + continue + elif self.thePoints[c] == self.thePoints[o]: + counter = counter + 1; + coincidentList.append(o) + + return counter + + def listMarks(self): + markList = [] + + for points in self.thePoints: + if points.mark not in markList: + markList.append(points.mark) + + return markList + + def subsetPoints(self, mark): + subsetList = [] + + for points in self.thePoints: + if points.mark == mark: + subsetList.append(points) + + return subsetList + + def randomPoints(self, none = None): + randomList = [] + + if none is None: + none = len(self.thePoints) + self.marks = ['James', 'Paul', 'Sarah', 'Michael', 'Nancy', 'Henry'] + + for n in range(none): + randomList.append(Point(random.randint(1,50), random.randint(1,50), random.choice(self.marks))) + + return randomList + + def realizationPoints(self, k): + return analytics.num_permutations(self.marks, k) + + def criticalPoints(self, marks): + return utils.critical_points(self.realizationPoints(50)) + + def add(self, points): + self.thePoints.append(points) + + def Gfunction(self, nsteps): + ds = np.linspace(0, 50, nsteps) + sum = 0 + + for s in range(nsteps): + oI = ds[s] + minimumDistance = None + for g in range(len(ds)): + temp = abs(g - oI) + + if g is not s: + continue + if minimumDistance is None: + minimumDistance = temp + if minimumDistance > temp: + minimumDistance = temp + else: + continue + sum = sum + minimumDistance + + return sum / nsteps \ No newline at end of file diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..a3465a9 --- /dev/null +++ b/utils.py @@ -0,0 +1,159 @@ +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 + +from . import utils \ No newline at end of file