diff --git a/GIS321_E10.png b/GIS321_E10.png new file mode 100644 index 0000000..5dda08c Binary files /dev/null and b/GIS321_E10.png differ diff --git a/Tweet.py b/Tweet.py new file mode 100644 index 0000000..981fb41 --- /dev/null +++ b/Tweet.py @@ -0,0 +1,31 @@ +''' +Created on Apr 19, 2016 + +@author: Max Ruiz +''' + +import utils +import random + +class Tweet(object): + def __init__(self, tweet_json_obj): + + self.twText = tweet_json_obj["text"] + self.twBoundingBox = tweet_json_obj["place"]["bounding_box"]["coordinates"][0] + self.twID = tweet_json_obj["id"] + self.twRetweetCount = tweet_json_obj["retweet_count"] + self.twRepliedTo = tweet_json_obj["in_reply_to_screen_name"] + self.twScreenName = tweet_json_obj["user"]["screen_name"] + self.twDate = tweet_json_obj["created_at"] + + + def getLatitude(self, corner): + return self.twBoundingBox[corner][1] + + def getLongitude(self, corner): + return self.twBoundingBox[corner][0] + + def getRandPointInBoundingBox(self): + latitude = random.uniform(self.getLatitude(0), self.getLatitude(1)) + longitude = random.uniform(self.getLongitude(0), self.getLongitude(2)) + return latitude, longitude 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..2bdd3a1 --- /dev/null +++ b/io_geojson.py @@ -0,0 +1,18 @@ +''' +Created on Apr 19, 2016 + +@author: Max Ruiz +''' +import json + +def read_geojson(input_file): + # 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 processTweets(tweets): + with open(tweets, 'r') as f: + jfile = json.load(f) + return jfile diff --git a/osm_map.html b/osm_map.html new file mode 100644 index 0000000..0fc7f37 --- /dev/null +++ b/osm_map.html @@ -0,0 +1,168 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/point.py b/point.py new file mode 100644 index 0000000..8c737c2 --- /dev/null +++ b/point.py @@ -0,0 +1,44 @@ +''' +Created on Mar 15, 2016 + +@author: Max Ruiz +''' +import numpy as np +import scipy as sp +import pysal as ps + + +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/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] diff --git a/view.py b/view.py new file mode 100644 index 0000000..476e5b5 --- /dev/null +++ b/view.py @@ -0,0 +1,103 @@ +from PyQt5 import QtCore, QtWidgets, QtWebKitWidgets +import sys +import folium +import io_geojson +import Tweet +import random + + +phx_coords = [33.441957, -112.072913] + +class Ui_MainWindow(object): + def __init__(self, MainWindow): + self.MainWindow = MainWindow + self.MainWindow.setObjectName("MainWindow") + self.MainWindow.resize(434, 316) + + self.map = folium.Map(location=phx_coords) + self.map.zoom_start = 8 + self.mapFile = "osm_map.html" + self.map.save(self.mapFile) + + self.setupUi() + + def setupUi(self): + + self.setupMenuBar() + self.setupStatusBar() + + + # place widgets here + self.webView = QtWebKitWidgets.QWebView(MainWindow) + self.webView.setHtml(open(self.mapFile,'r').read()) + + + + self.MainWindow.setCentralWidget(self.webView) + + def setupMenuBar(self): + + # Exit + exitAction = QtWidgets.QAction(self.MainWindow) + exitAction.setText('Exit') + exitAction.setShortcut('Ctrl+Q') + exitAction.setStatusTip('Exit Application') + exitAction.triggered.connect(QtWidgets.qApp.quit) + + # Open + openAction = QtWidgets.QAction(self.MainWindow) + openAction.setText('Open') + openAction.setShortcut('Ctrl+O') + openAction.setStatusTip('Open a tweet .json file') + openAction.triggered.connect(self.openJFile) + + menubar = QtWidgets.QMenuBar(self.MainWindow) + menuFile = QtWidgets.QMenu(menubar) + menuFile.setTitle('File') + self.MainWindow.setMenuBar(menubar) + + menuFile.addAction(exitAction) + menuFile.addAction(openAction) + menubar.addAction(menuFile.menuAction()) + + def setupStatusBar(self): + self.statusbar = QtWidgets.QStatusBar(self.MainWindow) + self.MainWindow.setStatusBar(self.statusbar) + + def openJFile(self): + try: + jfile = QtWidgets.QFileDialog.getOpenFileName(parent=MainWindow, caption='Open a tweet .json file',filter='*.json')[0] + + except: + return + + self.processTweetFile(jfile) + + def processTweetFile(self, jfile): + tweetObjs = [] + tweets = io_geojson.processTweets(jfile) + for t in tweets: + tweetObjs.append(Tweet.Tweet(t)) + + random.seed(1212) + + # create new map for new file + self.map = folium.Map(location=phx_coords) + self.map.zoom_start = 8 + + for tw in tweetObjs: + latitude, longitude = tw.getRandPointInBoundingBox() + folium.Marker([latitude, longitude], popup=tw.twScreenName).add_to(self.map) + + self.map.save(self.mapFile) + self.webView.setHtml(open(self.mapFile,'r').read()) + + + + +if __name__ == '__main__': + app = QtWidgets.QApplication(sys.argv) + MainWindow = QtWidgets.QMainWindow() + ui = Ui_MainWindow(MainWindow) + MainWindow.show() + sys.exit(app.exec_())