%pylab inline
rcParams['figure.figsize'] = (16,9)
Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline]. For more information, type 'help(pylab)'.
from twython import Twython
from credentials import CONSUMER_KEY, CONSUMER_SECRET
twitter = Twython(CONSUMER_KEY, CONSUMER_SECRET)
auth = twitter.get_authentication_tokens()
OAUTH_TOKEN = auth['oauth_token']
OAUTH_TOKEN_SECRET = auth['oauth_token_secret']
from IPython.core.display import HTML
HTML('Please <a target="_blank" href="{0}">authenticate</a>.'.format(auth['auth_url']))
# Set this to the PIN from the auth URL
PIN = '1734078'
twitter = Twython(CONSUMER_KEY, CONSUMER_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET)
final_step = twitter.get_authorized_tokens(PIN)
OAUTH_TOKEN = final_step['oauth_token']
OAUTH_TOKEN_SECRET = final_step['oauth_token_secret']
twitter = Twython(CONSUMER_KEY, CONSUMER_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET)
import json
print(json.dumps(twitter.get_user_timeline(screen_name='stephenfry')[0], indent=2))
{ "contributors": null, "truncated": false, "text": "@russellcrowe Perfect choice. Great cricketer & cricketing brain. Is going to make the series all the better. Brilliant Jor-El by the way", "in_reply_to_status_id": 349302248628682752, "id": 349304966269239299, "favorite_count": 38, "source": "<a href=\"http://twitterrific.com\" rel=\"nofollow\">Twitterrific for Mac</a>", "retweeted": false, "coordinates": null, "entities": { "symbols": [], "user_mentions": [ { "id": 133093395, "indices": [ 0, 13 ], "id_str": "133093395", "screen_name": "russellcrowe", "name": "Russell Crowe" } ], "hashtags": [], "urls": [] }, "in_reply_to_screen_name": "russellcrowe", "id_str": "349304966269239299", "retweet_count": 21, "in_reply_to_user_id": 133093395, "favorited": false, "user": { "follow_request_sent": false, "profile_use_background_image": false, "default_profile_image": false, "id": 15439395, "verified": true, "profile_text_color": "333333", "profile_image_url_https": "https://si0.twimg.com/profile_images/344513261579148157/ba4807791ef9cce28dc0d4aa2ce9372c_normal.jpeg", "profile_sidebar_fill_color": "48CCF4", "entities": { "url": { "urls": [ { "url": "http://t.co/4Kht71pdlB", "indices": [ 0, 22 ], "expanded_url": "http://www.stephenfry.com/", "display_url": "stephenfry.com" } ] }, "description": { "urls": [] } }, "followers_count": 5902582, "profile_sidebar_border_color": "FFFFFF", "id_str": "15439395", "profile_background_color": "A5E6FA", "listed_count": 55632, "profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/797461062/0ec127e26ce9be73cdafb2afca999cd6.jpeg", "utc_offset": 0, "statuses_count": 16302, "description": "British Actor, Writer, Lord of Dance, Prince of Swimwear & Blogger. NEVER reads Direct Messages: Instagram - stephenfryactually", "friends_count": 51546, "location": "London", "profile_link_color": "1C83A6", "profile_image_url": "http://a0.twimg.com/profile_images/344513261579148157/ba4807791ef9cce28dc0d4aa2ce9372c_normal.jpeg", "following": null, "geo_enabled": true, "profile_banner_url": "https://pbs.twimg.com/profile_banners/15439395/1360662717", "profile_background_image_url": "http://a0.twimg.com/profile_background_images/797461062/0ec127e26ce9be73cdafb2afca999cd6.jpeg", "screen_name": "stephenfry", "lang": "en", "profile_background_tile": false, "favourites_count": 78, "name": "Stephen Fry", "notifications": null, "url": "http://t.co/4Kht71pdlB", "created_at": "Tue Jul 15 11:45:30 +0000 2008", "contributors_enabled": false, "time_zone": "London", "protected": false, "default_profile": false, "is_translator": false }, "geo": null, "in_reply_to_user_id_str": "133093395", "lang": "en", "created_at": "Mon Jun 24 23:16:08 +0000 2013", "in_reply_to_status_id_str": "349302248628682752", "place": null }
from twython import TwythonStreamer
class SourceStreamer(TwythonStreamer):
def __init__(self, *args):
super(SourceStreamer, self).__init__(*args)
self.coords = {
'android': [], 'iOS': [],
}
def on_success(self, data):
"""If tweet has geo-information, add it to the list."""
try:
source = data['source']
if 'Android' in source:
self.coords['android'].append(data['geo']['coordinates'])
elif 'iOS' in source or 'iPhone' in source or 'iPad' in source:
self.coords['iOS'].append(data['geo']['coordinates'])
except (AttributeError, KeyError, TypeError):
pass
def on_error(self, status_code, data):
"""On error, print the error code and disconnect ourselves."""
print('Error: {0}'.format(status_code))
self.disconnect()
from threading import Thread
class StreamThread(Thread):
def run(self):
self.stream = SourceStreamer(
CONSUMER_KEY, CONSUMER_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET
)
self.stream.statuses.filter(locations='-180,-90,180,90')
t = StreamThread()
t.daemon = True
t.start()
t.stream.disconnect()
len(t.stream.coords['android'])
170435
from osgeo import gdal, osr
map_ds = gdal.Open('world-map-gall.tiff')
map_image = np.transpose(map_ds.ReadAsArray(), (1,2,0))
ox, xs, _, oy, _, ys = map_ds.GetGeoTransform()
map_extent = ( ox, ox + xs * map_ds.RasterXSize, oy + ys * map_ds.RasterYSize, oy )
map_proj = osr.SpatialReference()
map_proj.ImportFromProj4('+proj=cea +lon_0=0 +lat_ts=45 +x_0=0 +y_0=0 +ellps=WGS84 +units=m +no_defs')
wgs84_proj = osr.SpatialReference()
wgs84_proj.ImportFromEPSG(4326)
wgs84_to_map_trans = osr.CoordinateTransformation(wgs84_proj, map_proj)
def coord_to_pixel(coords):
"""Transform a sequence of co-ordinates in latitude, longitude
pairs into map pixel co-ordinates."""
# Transfrom from lat, lngs -> lng, lats
latlngs = np.array(coords)
lnglats = latlngs[:,(1,0)]
# Transform from lng, lats -> map projection
map_coords = np.array(wgs84_to_map_trans.TransformPoints(lnglats))
# Transform from map projection -> pixel coord
map_coords[:,0] = (map_coords[:,0] - ox) / xs
map_coords[:,1] = (map_coords[:,1] - oy) / ys
return map_coords[:,:2]
from scipy.stats import norm
kern_row = norm.pdf(np.linspace(-4, 4, 15))
kern_row /= np.sum(kern_row)
plot(kern_row)
[<matplotlib.lines.Line2D at 0xc1254b50>]
kernel = np.outer(kern_row, kern_row)
imshow(kernel, interpolation='nearest')
<matplotlib.image.AxesImage at 0xa67ae890>
def coord_histogram(coords, down_scale = 2):
pixel_locs = coord_to_pixel(coords)
histogram, _, _ = np.histogram2d(pixel_locs[:,1], pixel_locs[:,0],
bins=[int(map_image.shape[0]/down_scale), int(map_image.shape[1]/down_scale)],
range=[[0, map_image.shape[0]], [0, map_image.shape[1]]])
return histogram
android = coord_histogram(t.stream.coords['android'])
ios = coord_histogram(t.stream.coords['iOS'])
imshow(np.sqrt(ios), cmap=cm.spectral)
tight_layout()
axis('off')
(-0.5, 639.5, 392.5, -0.5)
from scipy.signal import convolve2d
imshow(np.sqrt(convolve2d(android, kernel, mode='same')), cmap=cm.spectral)
axis('off')
(-0.5, 639.5, 392.5, -0.5)
figure(figsize=(12,9))
imshow(map_image, extent=map_extent)
imshow(np.sqrt(convolve2d(android, kernel, mode='same')), extent=map_extent, alpha=0.5, cmap=cm.spectral)
axis('off')
title('Android usage as measured by Twitter ({0:,} tweets)'.format(int(android.sum())))
tight_layout()
savefig('android-usage.png')
figure(figsize=(12,9))
imshow(map_image, extent=map_extent)
imshow(np.sqrt(convolve2d(ios, kernel, mode='same')), extent=map_extent, alpha=0.5, cmap=cm.spectral)
axis('off')
title('iOS usage as measured by Twitter ({0:,} tweets)'.format(int(ios.sum())))
tight_layout()
savefig('ios-usage.png')
figure(figsize=(12,6))
# Compute a preference matrix varying from -1 == iOS to +1 == Android
A = convolve2d(android/android.sum() - ios/ios.sum(), kernel, mode='same')
A /= max(A.max(), -A.min())
# Squash the *magnitude* of A by taking a square root
A = np.sign(A) * np.sqrt(np.abs(A))
# Show the base map
gca().set_axis_bgcolor('black')
imshow(map_image, extent=map_extent, alpha=0.5)
# Compute the coloured preference image and set alpha value based on preference
pref_cmap = cm.RdYlBu
pref_im = pref_cmap(0.5 * (A + 1))
pref_im[:,:,3] = np.minimum(1, np.abs(A) * 10)
# Draw preference image
imshow(pref_im, extent=map_extent, cmap=pref_cmap, clim=(-1,1))
# Draw a colour bar
cb = colorbar()
cb.set_ticks((-1, -0.5, 0, 0.5, 1))
cb.set_ticklabels(('Strong iOS', 'Weak iOS', 'No preference', 'Weak Android', 'Strong Android'))
# Set up plot axes, title and layout
gca().get_xaxis().set_visible(False)
gca().get_yaxis().set_visible(False)
title('Geographic preferences for Android vs. iOS')
tight_layout()
savefig('preferences.png')