Skip to content

Instantly share code, notes, and snippets.

@chrislkeller
Last active July 12, 2019 18:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrislkeller/23536e5dcaa19111e919b32bd848fc6e to your computer and use it in GitHub Desktop.
Save chrislkeller/23536e5dcaa19111e919b32bd848fc6e to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%pip install requests \n",
"%pip install pytz\n",
"%pip install shapely\n",
"%pip install geojson"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#! /usr/bin/env python\n",
"# -*- coding: utf-8 -*-\n",
"\n",
"\"\"\"Download earthquake data from USGS.\"\"\"\n",
"\n",
"import logging\n",
"import csv\n",
"import datetime\n",
"import pandas as pd\n",
"import geopandas as gpd\n",
"import requests\n",
"import pytz\n",
"from shapely.geometry import box, Point\n",
"import geojson\n",
"from geojson import Feature, FeatureCollection\n",
"import json\n",
"import altair as alt\n",
"import altair_latimes as lat\n",
"\n",
"alt.themes.register('latimes', lat.theme)\n",
"alt.themes.enable('latimes')\n",
"alt.data_transformers.enable('default', max_rows=None)\n",
"\n",
"logger = logging.getLogger(\"root\")\n",
"logging.basicConfig(\n",
" format=\"\\033[1;36m%(levelname)s: %(filename)s (def %(funcName)s %(lineno)s): \\033[1;37m %(message)s\",\n",
" level=logging.DEBUG\n",
")\n",
"\n",
"\n",
"class UsgsApi(object):\n",
"\n",
" request_headers = {\n",
" \"From\": \"chris.keller@latimes.com\",\n",
" \"User-Agent\": \"Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) \\\n",
" AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.53 Safari/525.19\"\n",
" }\n",
"\n",
" all_past_day = 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson'\n",
" all_past_hour = 'http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson'\n",
" all_past_day = 'http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson'\n",
" all_past_seven = 'http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson'\n",
" all_past_thirty = 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson'\n",
"\n",
" pacific = pytz.timezone(\"US/Pacific\")\n",
"\n",
" utc = pytz.UTC\n",
"\n",
" # Create our Ridgecrest bounding box\n",
" bounding_box = box(-118.936915, 34.769758, -116.105189, 36.143359)\n",
"\n",
" start_date = datetime.datetime(2019, 7, 3, 7, 00, 00, 00, pytz.UTC)\n",
"\n",
" end_date = datetime.datetime(2019, 7, 13, 7, 00, 00, 00, pytz.UTC)\n",
" \n",
" geojson_name = '/Users/user/_programming/_lat/_jupyter_notebooks/_projects/2019-07-04-ridgecrest-earthquakes-processing/ridgecrest-earthquake-sequence.geojson'\n",
" \n",
" csv_name = '/Users/user/_programming/_lat/_jupyter_notebooks/_projects/2019-07-04-ridgecrest-earthquakes-processing/ridgecrest-earthquake-sequence.csv'\n",
"\n",
" csv_columns = [\n",
" 'title',\n",
" 'lon',\n",
" 'lat',\n",
" 'place',\n",
" 'mag',\n",
" 'mag_round',\n",
" 'raw_time',\n",
" 'time_utc',\n",
" 'time_pacific',\n",
" 'mag_difference',\n",
" 'style_size',\n",
" ]\n",
"\n",
" csv_data = []\n",
"\n",
" alt_data = csv_name\n",
"\n",
" max_mag = None\n",
" \n",
" min_mag = None\n",
" \n",
" def get_data(self, *args, **kwargs):\n",
"\n",
" data = self.get_api_response(self.all_past_thirty)\n",
"\n",
" # If we get something back\n",
" if data:\n",
"\n",
" # Figure out which earthqaukes are in California\n",
" target_features = self.test(data)\n",
"\n",
" # Process data and add calculated fields\n",
" self.csv_data = self.process(target_features)\n",
"\n",
" # Write it to a file\n",
" self.create_pandas_dataframe(self.csv_data, self.csv_columns)\n",
"\n",
" # Convert it to GeoJSON\n",
" features = [Feature(\n",
" geometry=Point(map(float, [d['properties']['lon'], d['properties']['lat']])),\n",
" properties=d\n",
" ) for d in self.csv_data]\n",
"\n",
" # Write it to a file\n",
" with open(self.geojson_name, 'w') as f:\n",
" geojson.dump(FeatureCollection(features), f)\n",
"\n",
" logging.debug('script is complete')\n",
"\n",
" def test(self, data):\n",
" target_features = []\n",
" for d in data['features']:\n",
" timestamp = datetime.datetime.utcfromtimestamp(d['properties']['time'] / 1e3)\n",
" d['properties']['aware_timestamp'] = timestamp.replace(tzinfo=pytz.UTC)\n",
"\n",
" # Find earthqukes between 10 a.m. July 4 and 10 a.m. July 9\n",
" if d['properties']['aware_timestamp'] >= self.start_date and d['properties']['aware_timestamp'] <= self.end_date:\n",
" d['properties']['lon'] = d['geometry']['coordinates'][0]\n",
" d['properties']['lat'] = d['geometry']['coordinates'][1]\n",
" earthquake_point = Point(map(float, [d['properties']['lon'], d['properties']['lat']]))\n",
" if self.bounding_box.contains(earthquake_point):\n",
" target_features.append(d)\n",
" else:\n",
" pass\n",
" logger.debug('Found %s features' % (len(target_features)))\n",
" return target_features\n",
"\n",
" def process(self, features_list):\n",
" # Make some adjustments that will help us later on in life\n",
"\n",
" # Find the largest and smallest earthquake in the data\n",
" items = [x['properties']['mag'] for x in features_list] \n",
" self.max_mag = max(items)\n",
" self.min_mag = min(items) \n",
" for d in features_list:\n",
" d['lon'] = d['properties']['lon']\n",
" d['lat'] = d['properties']['lat']\n",
" d['title'] = d['properties']['title']\n",
" d['place'] = d['properties']['place']\n",
" d['mag'] = d['properties']['mag']\n",
" d['mag_round'] = round(d['mag'], 1) \n",
" d['raw_time'] = int(d['properties']['time'] / 1000)\n",
" d['time_utc'] = d['properties']['aware_timestamp'].isoformat()\n",
" d['time_pacific'] = d['properties']['aware_timestamp'].astimezone(self.pacific).isoformat()\n",
" d['properties']['aware_timestamp'] = d['properties']['aware_timestamp'].isoformat()\n",
" try:\n",
" d['mag_difference'] = float(10**(d['properties']['mag']-self.min_mag))\n",
" d['style_size'] = d['mag_difference']\n",
" except:\n",
" d['mag_difference'] = None\n",
" d['style_size'] = None\n",
" return features_list\n",
"\n",
" def get_api_response(self, url):\n",
" \"\"\"Get response from usgs api.\"\"\"\n",
" try:\n",
" response = requests.get(url, headers=self.request_headers)\n",
" if response.status_code == 200:\n",
" response_data = response.json()\n",
" return response_data\n",
" else:\n",
" logger.debug(response.status_code)\n",
" except requests.exceptions as exception:\n",
" logger.error('%s: %s' % (exception))\n",
" return False\n",
"\n",
" def create_pandas_dataframe(self, list, column_names):\n",
" output = pd.DataFrame(list, columns=column_names)\n",
" output.to_csv(self.csv_name, encoding = 'utf-8')\n",
"\n",
"\n",
"if __name__ == '__main__':\n",
" task_run = UsgsApi()\n",
" task_run.get_data()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"config = {\n",
" 'alt_sources': 'Source: USGS',\n",
" 'proj_root': '/Users/user/_programming/_lat/_jupyter_notebooks/_projects/2019-07-04-ridgecrest-earthquakes-processing/',\n",
" 'proj_data': 'ridgecrest-earthquake-sequence.csv',\n",
"}\n",
"\n",
"data_source = '{}{}'.format(config['proj_root'], config['proj_data'])\n",
"\n",
"# Use Pandas to bring in the data\n",
"source = pd.read_csv(data_source)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Convert to dataframe\n",
"data = pd.DataFrame(source)\n",
"\n",
"# chart title\n",
"title = 'Ridgecrest aftershocks tapering off'\n",
"\n",
"# calculate seconds per day with 60*60*24\n",
"tick_range = list(range(1562137200, 1563001180, 86400))\n",
"\n",
"# Configure the chart\n",
"frequency_chart = alt.Chart(\n",
" source,\n",
" title=title\n",
").mark_circle().encode(\n",
" size=alt.Size(\n",
" 'style_size:Q',\n",
" legend=None\n",
" ),\n",
" opacity=alt.value(1),\n",
" x=alt.X(\n",
" 'raw_time:T',\n",
" title=config['alt_sources'],\n",
" scale=alt.Scale(\n",
" domain=[1562137200, 1563001180]\n",
" ),\n",
" axis=alt.Axis(\n",
" ticks=True,\n",
" tickCount=10,\n",
" values=tick_range,\n",
" domain=True,\n",
" grid=False,\n",
" labels=True,\n",
" formatType='time',\n",
" format=('%A'),\n",
" ),\n",
" ),\n",
" y=alt.Y(\n",
" 'mag:Q',\n",
" title=None,\n",
" axis=alt.Axis(\n",
" domain=False,\n",
" ticks=True,\n",
" grid=True,\n",
" ),\n",
" )\n",
").properties(\n",
" width=800,\n",
" height=400\n",
").configure_view(\n",
" strokeWidth=0\n",
")\n",
"\n",
"frequency_chart"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment