diff --git a/README.md b/README.md index 0976c0f..539f994 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +Note: Used composition in this case because the Tweet has a geographical location (x,y) not is a geographical location (x,y) + + + + # Week 13 Deliverables (E9) - Due 4/19/16 For this week make sure that you have completed the following: * Fork Assignment 10 to your own github repository. diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/analytics.py b/src/analytics.py new file mode 100644 index 0000000..c47e0bf --- /dev/null +++ b/src/analytics.py @@ -0,0 +1,277 @@ +import math + +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 + """ + #features is a list, so iteration is by position + #if you want to iterate over the features you need to first grab the list out of the dictionary. + + featureList = gj['features'] + # now that you have the features, compare the pop_max fields to find the largest one + max_population = 0 + for featureEntry in featureList: + if featureEntry["properties"]["pop_max"] > max_population: + max_population = featureEntry["properties"]["pop_max"] + city = featureEntry["properties"]["nameascii"] + + + return city, max_population + +def write_your_own(gj): + """ + This function finds the least populated city, pop_min + """ + featureList = gj["features"] + minPop = math.inf + for featureEntry in featureList: + #feature["properties"]["pop_min"] for feature in self.gj["features"] + if featureEntry["properties"]["pop_min"] < minPop: + minPop = featureEntry["properties"]["pop_min"] + city = featureEntry["properties"]["nameascii"] + # minn = min(featureEntry["properties"]["pop_min"]) +# print(minn) + return city, minPop + +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 + """ + + #find the average of all the X points in the list + + # x_sum = sum(points[0]) + #points_length = len(points) + + sums = map(sum,zip(*points)) # returns iterable object of type map + sumsL = list(sums) + avgs = map(lambda xy: xy/len(points),sumsL) + avgsL = list(avgs) + x = avgsL[0] + y = avgsL[1] + + return x,y + +def average_nearest_neighbor_distance(points,mark=None): + """ + Given a set of points, compute the average nearest neighbor. + Parameters + ---------- + points : list + A list of Points in the form of (x,y,mark) or points with (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. + """ + markList = [] + if not mark: #If mark is empty, then you're computing the distance of all the points + shDistL =[] #list of shortest distances + + #now the points are numbered... so if the points + #have the same counter number attached also, then they + #are self-neighbors, but if num1 != num2, then they are + # coincident points, with distance = 0 + printXonce = False + for num1, point in enumerate(points): + shortestDistance = math.inf + for num2, dpoint in enumerate(points): + if num1 != num2: + if printXonce == False: + print(point.x) + epoint1 = (point.x,point.y) + epoint2 = (dpoint.x,dpoint.y) + dist = utils.euclidean_distance(epoint1, epoint2) #changed input parameters because cannot pass in Point + if(shortestDistance > dist): + shortestDistance = dist + printXonce = True + #now add the shortest distance of that point before it moves on to a new point + shDistL.append(shortestDistance) + # print(shDistL) + sums = sum(shDistL) + mean_d = sums/len(shDistL) + #compute the average nearest neighbor distance of only those that share the mark + else: + for p in points: + if p.mark in mark: #passed in a list of possible marks + markList.append(p) + shDistL =[] #list of shortest distances + + #now the points are numbered... so if the points + #have the same counter number attached also, then they + #are self-neighbors, but if num1 != num2, then they are + # coincident points, with distance = 0 + for num1, point in enumerate(markList): + shortestDistance = math.inf + for num2, dpoint in enumerate(markList): + if num1 != num2: + dist = utils.euclidean_distance((point.x,point.y), (dpoint.x,dpoint.y)) + if(shortestDistance > dist): + shortestDistance = dist + #now add the shortest distance of that point before it moves on to a new point + shDistL.append(shortestDistance) + #print(shDistL) + sums = sum(shDistL) + mean_d = sums/len(shDistL) + print(mean_d) + 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] + """ + # a minimum bounding rectangle would be on the extremes of x/y + + xmin = math.inf + ymin = math.inf + xmax = -9999999999 + ymax = -9999999999 + for point in points: + if point[0] < xmin: + xmin = point[0] + if point[1] < ymin: + ymin = point[1] + if point[0] > xmax: + xmax = point[0] + if point[1] > ymax: + ymax = point[1] + mbr = [xmin,ymin,xmax,ymax] + print("This is the mbr:") + print(mbr) + return mbr + +def mbr_area(mbr): + """ + Compute the area of a minimum bounding rectangle + """ + length = mbr[2] - mbr[0] + width = mbr[3] - mbr[1] + 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 permutation_nearest_distance(mark=[],p=99,n=100): + """ + Finds the nearest neighbor distance for p permutations with n + random points + :param p: permutation number of times you want to try different + simulations for monte carlo + :param n: random point number + :param mark: Passes in a list of marks if the permutation to be found is of Points + :return LDist: list of distances, length p + """ + # if mark == None: + # LDist = [] + # for x in range(p): #loop from 0 to p + # #create n random Points + # points = n_random_points(n) # returns [(x,y),(a,b)..] + # #compute mean neighbor distance +# mean_d = average_nearest_neighbor_distance(points) + # LDist.append(mean_d) + + LDist = [] + for x in range(p): #loop from 0 to p + #create n random Points + marks = ['lavender','orange','rose','ash','violet','magenta','cerulean'] + points = utils.n_random_Points(n,marks) # returns [(x,y),(a,b)..] + #print("print the points array: ") + #print(points) + #print(type(points)) + #compute mean neighbor distance + mean_d = average_nearest_neighbor_distance(points) + LDist.append(mean_d) + + return LDist + +def critical_points(LDist): + """ + Find the critical points, the largest/smallest distances + :param LDist: the list of mean distances + :return CList: list containing critical points + """ + CList = [] + #aList = [] + #for p in LDist: + # print(p) + smallest = min(LDist) + largest = max(LDist) + CList.append(smallest) + CList.append(largest) + #print(CList) + return CList + +def significant(CList,distance): + """ + Returns True if the observed distance is significant + :param CList: list of critical points + :param distance: the observed distance + :return result: True/False + """ + + if distance < CList[0] or distance > CList[1]: + result = True + else: + result = False + return result + + +import math + +from . import utils \ No newline at end of file diff --git a/src/io_geojson.py b/src/io_geojson.py new file mode 100644 index 0000000..ea3ba32 --- /dev/null +++ b/src/io_geojson.py @@ -0,0 +1,44 @@ +import json + +#In the io_geojson module write a function that ingests the twitter data and returns a dictionary. Note that you could write this from scratch or, +#if a suitable library exists (maybe a built-in), utilize someone else's library. + +def read_twitter_data(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 file: + gj = json.load(file) + 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 file: + gj = json.load(file) + return gj diff --git a/src/point.py b/src/point.py new file mode 100644 index 0000000..3496d48 --- /dev/null +++ b/src/point.py @@ -0,0 +1,35 @@ +class Point(object): + def __init__(self,x,y,mark=[]): + self.x = x + self.y = y + self.mark = mark + + #implement magic method to add points (x,y)'s + def __add__(self,other): + return Point(self.x + other.x,self.y + other.y) + def __radd__(self,other): + return Point(self.x + other, self.y + other) + def __sub__(self, other): #implements 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 __neq__(self,other): + return self.x != other.x or self.y != other.y + + def patched_coincident(self,point2): + point1 = (self.x,self.y) + + return utils.check_coincident(point1,point2) + + def patched_shift(self,x_shift,y_shift): + point = (self.x,self.y) + self.x,self.y = utils.shift_point(point,x_shift,y_shift) + + #Add an attribute to your Point class that returns an array [x,y] + def return_array(self): + arrayy = [self.x,self.y] + return arrayy + + +from . import utils \ No newline at end of file diff --git a/src/pointPattern.py b/src/pointPattern.py new file mode 100644 index 0000000..8ffac4f --- /dev/null +++ b/src/pointPattern.py @@ -0,0 +1,241 @@ +import random +import math +from . import point +from . import analytics +from . import utils +import numpy as np +import scipy.spatial as ss + + +class PointPattern(object): + #initialize to list of points + def __init__(self): + self.points = [] + self.marks = ['lavender','orange','rose','ash','violet','magenta','cerulean'] + + def add_point(self,point): + self.points.append(point) + + def remove_point(self,index): + del(self.points[index]) + + def average_nearest_neighbor(self,mark=None): + return analytics.average_nearest_neighbor_distance(self.points,mark) + + #find the number of coincident points + def coin_count(self): + count = 0 + clist = [] + for num1, point1 in enumerate(self.points): + for num2, point2 in enumerate(self.points): + #check that you're not comparing the same point + if num1 != num2 and num2 not in clist: # if they are not the same point, and already counted + if point1 == point2: + count = count +1 + clist.append(num2) + return count + + + #list all the different marks + def mark_list(self): + markList = [] + + #go through each point and add a new mark to the mark listss + for point in self.points: + if point.mark not in markList: + markList.append(point.mark) + return markList + + #return a subset of point by mark type + def mark_subset(self,mark): + subset = [] + for p in self.points: + if p.mark == mark: + subset.append(p) + return subset + + #where n is either provided by the user or equal to the current size of pointPattern + def create_n_random_points(self,n =None): + randomPoints = [] + if(n is None): + n = len(self.points) + + for i in range(n): + randomPoints.append(point.Point(random.randint(1,100),random.randint(1,100),random.choice(self.marks))) + + return randomPoints + + #simulate k random points patterns for Monte Carlo + def create_k_patterns(self,k): + return analytics.permutation_nearest_distance(self.marks,k) + + def critical_points(self): + return analytics.critical_points(self.create_k_patterns(99)) + #return analytics.critical_points(self.points) + + def compute_g(self,nsteps,mark=None): + """ + Parameters + ---------- + nsteps: The numer of discrete d that are used to compute G(d) + Returns + ------- + """ + point_array = [] + if not mark: + for p in self.points: + point_array.append(p.return_array()) + else: + #that means a mark(s) was passed in + for p in self.points: + if p.mark in mark: + point_array.append(p.return_array()) + shDistL = [] # list keeps track of all the nearest neighbor distances for each point + gFuncL = [] + #for pointPattern range 0-5, the highest distance between them is < 8 + ds = np.linspace(0,8,nsteps) + sums = 0 + N = np.point_array.size() #get a count of how many points there are + for dstep in ds: #for every distance band dstep + for num1, p in enumerate(point_array): + shortestDistance = math.inf + for num2, dp in enumerate(point_array): + if num1 != num2: #if they aren't the same point, find the distance between the two points + p1 = (p.x,p.y) + p2 = (dp.x,dp.y) + dist = utils.euclidean_distance(p1, p2) + if(shortestDistance > dist): + shortestDistance = dist + #now add the shortest distance of that point before it moves on to a new point + shDistL.append(shortestDistance) + #now you have the minimum nearest neighbor distances of each point stored in shDistL. + #Check how many of those distances are less than the current distance band: + for d in shDistL: + count = 0 + if d < dstep: #then it should be included in the count + count = count + 1 + #now I've got the count, compute the g function: + gFuncL.append(count/N) + return gFuncL + + +#utilize a scipy.spatial.KDTree to compute the nearest neighbor distance + + def kDTree_nearest_neighbor(self,mark=None): + point_array = [] # is the "tuple" that holds the arrays to be stacked + if not mark: + #then you dont want to look for a specific mark, and you can just find the average nearest neighbor of everything + for p in self.points: #add every point to the point_array + point_array.append(p.return_array()) + else: + #that means that there was something passed into mark and you have to only computer the nearest neighbor with that mark + for p in self.points: + for m in mark: # passed in a possible list of marks + if m in p.mark: + point_array.append(p.return_array()) + break #so that you don't add duplicates if it has both marks for example + + #now you have the vstack parameter: + point_ndarray = np.vstack(point_array) + + #now you have the ndarray needed for kdtree, create your tree: + kdTree = ss.KDTree(point_array) + + #now computer the nearest neighbors: + nn_dist = [] + for p in point_ndarray: + nearest_neighbor_distance, nearest_neighbor_point = kdTree.query(p,k=2) + nn_dist.append(nearest_neighbor_distance[1]) #appending the second one to allow for self-neighbor + + average = np.mean(nn_dist) + return average + + #compute the nearest neighbor distance using numpy (ndarray and mean) + def numpy_nearest_neighbor(self,mark=None): + shDistL = [] + point_array = [] + if not mark: + for p in self.points: + point_array.append(p.return_array()) + else: + #that means a mark was passed in + for p in self.points: + if mark in p.mark: + point_array.append(p.return_array()) + + #point_array = [ [1,2],[3,4],[5,6],[7.8] ] + #using the same logic that's in analytics: + for num1, p in enumerate(point_array): # p = [1,2] + shortestDistance = math.inf + for num2, dp in enumerate(point_array): + if num1 != num2: + dist = ss.distance.euclidean(p,dp) + if(shortestDistance > dist): + shortestDistance = dist + #now add the shortest distance of that point before it moves on to a new point: + shDistL.append(shortestDistance) + mean_d = np.mean(shDistL) #returns the average of the array of elements, so pass in shDistL + + return mean_d + + #compute the G function using numpy + def numpy_compute_g(self,nsteps,mark=None): + point_array = [] + if not mark: + for p in self.points: + point_array.append(p.return_array()) + else: + #that means a mark(s) was passed in + for p in self.points: + for m in mark: + if m in p.mark: + point_array.append(p.return_array()) + break # so that you don't add duplicates if it has both marks for example + shDistL = [] # list keeps track of all the nearest neighbor distances for each point + gFuncL = [] + + #first get the nearest neighbor distance for each point: + for num1, p in enumerate(point_array): + shortestDistance = math.inf + for num2, dp in enumerate(point_array): + if num1 != num2: + # print(p) + # print(dp) + # p1 = (p.x,p.y) + # p2 = (dp.x,dp.y) + # dist = utils.euclidean_distance(p1, p2) + dist = ss.distance.euclidean(p,dp) + if(shortestDistance > dist): + shortestDistance = dist + shDistL.append(shortestDistance) + # print("the shortest distance: ",shortestDistance) + #now you have the minimum nearest neighbor distances of each point stored in shDistL. + #use that to compute the steps: + min = np.amin(shDistL) + max = np.amax(shDistL)*1.5 #so that the last max distance on the g function will fall under a distance band just a little bit larger. + ds = np.linspace(min,max,nsteps) + N = np.size(point_array) #get a count of how many points there are + + #now calculate the g function for every distance band: + for dstep in ds: + count = np.where(shDistL < dstep) + count = len(count[0]) + #now you have the count of observations under that distance band. + #divide by N and add it to the gFuncL. + gFuncL.append(count/N) + return gFuncL, ds + + + #Generate random points within some domain + def random_points_domain(self,numPoints = 2,start=0,stop=1,seed =None): + randomp = None + pointsList = [] + if seed is None: #meaning no passed in starting value + randomp = np.random + else: + randomp = np.random.RandomState(seed) #instantiate seed + random.seed(seed) + points = randomp.uniform(start,stop, (numPoints,2)) #create ndarray + for x in range(points): #for all the points + pointsList.append(point.Point(points[x][0],points[x][1],np.random.choice(self.marks))) + return pointsList \ No newline at end of file diff --git a/src/temp/__init__.py b/src/temp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/temp/tweet_map.html b/src/temp/tweet_map.html new file mode 100644 index 0000000..ec6cdb9 --- /dev/null +++ b/src/temp/tweet_map.html @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + \ No newline at end of file diff --git a/src/tweet.py b/src/tweet.py new file mode 100644 index 0000000..bebed61 --- /dev/null +++ b/src/tweet.py @@ -0,0 +1,58 @@ +#Create a new Tweet class or extend the existing Point class to store: +import src.point +import numpy as np +import random + +class Tweet(object): + def __init__(self,tweet_dictionary): + #want pass in the tweet dictionary so that you can actually store it + #the tweet text: + self.tweetText = tweet_dictionary['text'] # get the "text field" + numberoftweetsmapped= 0 + if tweet_dictionary['geo'] is not None: #(long,lat) + #that means that there was a geo value associated with the tweet, so just use that: + #Point coordinates are in x, y order (easting, northing for projected coordinates, longitude, latitude for geographic coordinates): + #"geo": {"coordinates": [33.46719916, -112.073], "type": "Point"} + self.latitude = tweet_dictionary['geo']['coordinates'][0] + self.longitude = tweet_dictionary['geo']['coordinates'][1] + print("geo!") + print(tweet_dictionary['geo']['coordinates'][0]) + print(tweet_dictionary['geo']['coordinates'][1]) + + else: + #then get the data from the bounding box, pick a point from there: + print("bounding box") + print(tweet_dictionary['place']['bounding_box']['coordinates']) + print(tweet_dictionary['place']['bounding_box']['coordinates'][0]) + #coordinates[0] = [[-111.842244, 33.204608], [-111.842244, 33.385822], [-111.634889, 33.385822], [-111.634889, 33.204608]] + + + #So, the trick is to get the minimum and maximum values from the bounding box: + toStack = tweet_dictionary['place']['bounding_box']['coordinates'][0] + coorStack = np.vstack(toStack) + #now find the max and min of the longitude/latitude + coorMax = np.amax(coorStack,axis=0) #[x,y] + coorMin = np.amin(coorStack,axis=0) + + #now randomly distribute the points within the polygon: + self.longitude = random.uniform(coorMin[0],coorMax[0]) + self.latitude = random.uniform(coorMin[1],coorMax[1]) + + # self.longitude = tweet_dictionary['place']['bounding_box']['coordinates'][0][0][0] + # self.latitude = tweet_dictionary['place']['bounding_box']['coordinates'][0][0][1] + + + + + print("long and lat: ") + print(self.longitude) + print(self.latitude) + + + self.geoPoint = src.point.Point(self.latitude,self.longitude) + #now pick 3 other interesting ones: + self.user_name = tweet_dictionary['user']['screen_name'] + self.follower_count = tweet_dictionary['user']['followers_count'] + self.retweeted = tweet_dictionary['retweeted'] + + diff --git a/src/utils.py b/src/utils.py new file mode 100644 index 0000000..a19e7ac --- /dev/null +++ b/src/utils.py @@ -0,0 +1,142 @@ +def n_random_Points(n,marks=[]): + + PointList = [point.Point(random.uniform(0,1),random.uniform(0,1),random.choice(marks)) for x in range(n)] + + return PointList + + +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(points, 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 + ------- + >>> points = (0,0) + >>> shift_point(points, 1, 2) + (1,2) + """ + x = getx(points) + y = gety(points) + + 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(points, 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 points in point_list + + +def getx(points): + """ + 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 points[0] + + +def gety(points): + """ + 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 points[1] + +from . import point +import math +import random \ No newline at end of file diff --git a/temp/folium_map.html b/temp/folium_map.html new file mode 100644 index 0000000..9085612 --- /dev/null +++ b/temp/folium_map.html @@ -0,0 +1,5668 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + \ No newline at end of file diff --git a/tweets.PNG b/tweets.PNG new file mode 100644 index 0000000..70fcfa3 Binary files /dev/null and b/tweets.PNG differ diff --git a/view.py b/view.py new file mode 100644 index 0000000..97bf434 --- /dev/null +++ b/view.py @@ -0,0 +1,134 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +ZetCode PyQt4 tutorial + +This program creates a skeleton of +a classic GUI application with a menubar, +toolbar, statusbar and a central widget. + +author: Jan Bodnar +website: zetcode.com +last edited: September 2011 +""" + +import sys +from PyQt4 import QtGui, QtWebKit, QtCore +import folium +import os +import src.tweet +import src.io_geojson + + +class View(QtGui.QMainWindow): + + def __init__(self): #calling the parent constructor + super(View, self).__init__() + + self.initUI() + + + def initUI(self): + + self.resize(350,250) + self.center() + os.makedirs('temp',exist_ok=True) #for saving directory + #textEdit = QtGui.QTextEdit() #adding a QTextEdit as the central widget + self.web_view = QtWebKit.QWebView() + self.map_dir = 'temp/folium_map.html' #so it knows where to save + + #now embed the folium map + #self.map = folium.Map(location=[-112.323914,-33.29026],zoom_start=10) + self.map = folium.Map(location=[33.29026,-112.323914],zoom_start=10) + self.map.save(self.map_dir) + self.web_view.load(QtCore.QUrl(self.map_dir)) + + self.setCentralWidget(self.web_view) + + #creates a toolbar to exit, along with adding a keyboard shortcut + exitAction = QtGui.QAction('Exit', self) + exitAction.setShortcut('Ctrl+Q') + exitAction.setStatusTip('Exit application') + exitAction.triggered.connect(self.close) + + openAction = QtGui.QAction('Open Tweets',self) + openAction.setShortcut('Ctrl+O') + openAction.setStatusTip('Load tweets for marker display in map') + openAction.triggered.connect(self.openAndDisplayMarkers) + + + #added a ready message to the status bar + self.statusBar().showMessage('Ready') + + #creating the file menu, and adding exit as an option + menubar = self.menuBar() + fileMenu = menubar.addMenu('&File') + fileMenu.addAction(exitAction) + + #creating a toolbar with an exit function + toolbar = self.addToolBar('Exit') + toolbar.addAction(exitAction) + toolbar.addAction(openAction) + + #setting the window name + self.setWindowTitle('Tweet Map') + self.show() + + #making it appear in the center of the screen + def center(self): + qr = self.frameGeometry() + cp = QtGui.QDesktopWidget().availableGeometry().center() + qr.moveCenter(cp) + self.move(qr.topLeft()) + + def openAndDisplayMarkers(self): + print("openAndDisplayMarkers") + file = QtGui.QFileDialog.getOpenFileName(self,caption='Open tweet file',filter='*.json') # for only json's + if not file: #nothing selected, can't do anything + return; + + tweets = [] + tweet_dict = src.io_geojson.read_twitter_data(file) + for t in tweet_dict: # for every tweet in the tweet dictionary + tweets.append(src.tweet.Tweet(t)) + + #now that you've created an list of tweets implementing the Tweet class, use the saved + #array to actually create the markers and get the latitude/longitude values from the points: + long_sum = 0 + lat_sum = 0 + i = 0 + for t1 in tweets: #Going through each Tweet class element + markerPoint = [t1.latitude,t1.longitude] + if i < 5: + print(markerPoint) + #now create the actual marker: + markerToAdd = folium.Marker(markerPoint) + markerToAdd.add_to(self.map) + + #you need to recenter the map at the mean center of the points. That means that you have to calculate the mean center + #as you go through all the points: + long_sum = long_sum + markerPoint[0] + lat_sum = lat_sum + markerPoint[1] + i = i + 1 + + print(len(tweets)) + mean_center_long = long_sum/len(tweets) + mean_center_lat = lat_sum/len(tweets) + mean_center = [mean_center_long,mean_center_lat] + #now change the map location to there: + self.map.location= mean_center + + self.map.save(self.map_dir) + self.web_view.load(QtCore.QUrl(self.map_dir)) + + +def main(): + + app = QtGui.QApplication(sys.argv) + ex = View() + sys.exit(app.exec_()) + + +if __name__ == '__main__': + main() \ No newline at end of file