diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml new file mode 100644 index 0000000..b143a53 --- /dev/null +++ b/.github/workflows/pythonpublish.yml @@ -0,0 +1,26 @@ +name: Upload Python Package + +on: + release: + types: [created] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v1 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel twine + - name: Build and publish + env: + TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + run: | + python setup.py sdist bdist_wheel + twine upload dist/* diff --git a/.gitignore b/.gitignore index 28e5f81..c3eb1f0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,15 @@ - -.vscode/* -venv/* +# Generated files *.pyc -cache.sqlite puepleair_api.egg-info/* purpleair_api.egg-info/* +Purple_Air_API.egg-info/* +purpleair.egg-info/* +build/* +dist/* + +# Requests cache +cache.sqlite + +# Dev env +venv/* +.vscode/* diff --git a/README.md b/README.md index 36aa51b..992398e 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,31 @@ -# purple_air_api +# Purple Air API -A Python 3.7 API Class to turn data from the PurpleAir/ThingSpeak API into a Pandas Dataframe with several utility methods. +A Python 3.x API Class to turn data from the PurpleAir/ThingSpeak API into a Pandas DataFrame with several utility methods. ![](maps/sensor_map.png) ## Installation -* Clone this repo -* `cd` to the folder -* Create a virtual environment ( `python -m venv venv` ) -* Activate the virtual environment ( `source venv/bin/activate` ) -* `python setup.py develop` -* `pip install -r requirements/common.txt` - * Install development requirements with `pip install -r requirements/dev.txt` +* To use + * Create a virtual environment + * `python -m venv venv` + * Activate the virtual environment + * `source venv/bin/activate` + * Install this package + * `pip install purpleair` +* To hack + * Clone this repo + * `cd` to the folder + * Create a virtual environment + * `python -m venv venv` + * Activate the virtual environment + * `source venv/bin/activate` + * Install as dependency in the virtual environment + * `python setup.py develop` + * Install third party dependencies + * Required to run: `pip install -r requirements/common.txt` + * Install development requirements with `pip install -r requirements/dev.txt` + * Install example file requirements with `pip install -r requirements/examples.txt` ## Example code @@ -37,9 +50,12 @@ print(s) # Sensor 2891 at 10834, Canyon Road, Omaha, Douglas County, Nebraska, ```python from purpleair import purpleair df = p.to_dataframe('all') # Other options include 'outdoor' and 'useful' +``` + +Result: -# Will print - age downgraded flagged hidden humidity last_seen ... name parent pm_2.5 pressure temp_c temp_f +```log + age downgraded flagged hidden humidity last_seen ... name parent pm_2.5 pressure temp_c temp_f id ... 24115 36026 False False False 0.15 2019-01-09 20:33:05 ... 2nd South 12th East NaN 0.15 869.14 31.666667 89.0 16791 0 False False False 0.60 2019-02-03 20:59:26 ... DW0435 NaN 1.96 1009.82 30.000000 86.0 @@ -54,8 +70,11 @@ id ... from purpleair import sensor se = sensor.Sensor('2891', parse_location=True) print(se.get_historical(weeks_to_get=1, sensor_channel='a').head()) +``` + +Result: -# Will print +```log created_at PM1 CF=ATM ug/m3 PM25 CF=ATM ug/m3 PM10 CF=ATM ug/m3 Free HEAP memory ADC0 Voltage Sensor Firmware Unused PM25 CF=1 ug/m3 entry_id 536245 2019-01-27 00:00:35+00:00 12.87 17.70 18.39 30032.0 0.02 973.99 NaN 17.70 diff --git a/scripts/plot_city.py b/scripts/plot_city.py index 7549c44..0e6e8f2 100644 --- a/scripts/plot_city.py +++ b/scripts/plot_city.py @@ -2,8 +2,9 @@ Install requirements with `pip install -r requirements/common.txt` """ -from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt +from mpl_toolkits.basemap import Basemap + from purpleair import purpleair # Get the purpleair data @@ -13,7 +14,8 @@ # Store the lat and lon coords to plot lat = df['lat'].values lon = df['lon'].values -colors = df[var_to_viz].values # Variable on which to generate the color gradient +# Variable on which to generate the color gradient +colors = df[var_to_viz].values # Coorinates for Los Angeles, CA m = Basemap(llcrnrlon=-118.5, @@ -23,7 +25,7 @@ lat_0=34., lon_0=-118., projection='lcc', - resolution = 'i', + resolution='i', epsg=3498 # Lookup via https://epsg.io ) diff --git a/scripts/plot_map.py b/scripts/plot_map.py index f0c0732..c080eaf 100644 --- a/scripts/plot_map.py +++ b/scripts/plot_map.py @@ -2,15 +2,14 @@ Install requirements with `pip install -r requirements/common.txt` """ -#%% -from mpl_toolkits.basemap import Basemap -import numpy as np -import matplotlib.pyplot as plt -from purpleair import purpleair import datetime +import matplotlib.pyplot as plt +import numpy as np +from mpl_toolkits.basemap import Basemap + +from purpleair import purpleair -#%% # Get the purpleair data p = purpleair.PurpleAir() df = p.to_dataframe('all') @@ -18,11 +17,11 @@ # Store the lat and lon coords to plot lat = df['lat'].values lon = df['lon'].values -colors = df[var_to_viz].values # Variable on which to generate the color gradient +# Variable on which to generate the color gradient +colors = df[var_to_viz].values print(min(colors), max(colors)) -#%% margin = 0 # buffer to add to the range lat_min = min(lat) - margin lat_max = max(lat) + margin @@ -36,7 +35,7 @@ lat_0=(lat_max - lat_min)/2, lon_0=(lon_max-lon_min)/2, projection='merc', - resolution = 'h', + resolution='h', area_thresh=10000., ) m.drawcoastlines() @@ -44,16 +43,16 @@ m.drawstates() -#%% # Colors water = '#46bcec' land = '#ffffff' m.drawmapboundary(fill_color=water) -m.fillcontinents(color = land, lake_color=water) +m.fillcontinents(color=land, lake_color=water) # convert lat and lon to map projection coordinates lons, lats = m(lon, lat) # plot points as red dots m.scatter(lons, lats, marker='o', c=colors, cmap='plasma', zorder=5, s=2) plt.colorbar().set_label(f'{var_to_viz}', rotation=90) -plt.title(f'Global {var_to_viz} at {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}') +plt.title( + f'Global {var_to_viz} at {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}') plt.savefig('maps/sensor_map.png', dpi=300) diff --git a/setup.py b/setup.py index 8892635..47dca8b 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,28 @@ -from setuptools import setup +from setuptools import setup, find_packages +with open("README.md", "r") as fh: + LONG_DESCRIPTION = fh.read() setup( - name='purpleair_api', - version='1.0', - description='A Python 3.7 PurpleAir API Class.', + name='purpleair', + version='1.0.1', + description='Python API Client to get and transform PurpleAir data.', + long_description=LONG_DESCRIPTION, + long_description_content_type="text/markdown", author='Christopher Sardegna', author_email='github@reagentx.net', - scripts=['scripts/run.py'] + url='https://github.com/ReagentX/purple_air_api/', + packages=find_packages(), + install_requires=['requests', 'requests_cache', 'thingspeak', 'geopy', 'pandas'], + python_requires='>=3.6', + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', + 'Natural Language :: English', + 'Operating System :: OS Independent', + 'Programming Language :: Python :: 3.8', + 'Intended Audience :: Science/Research', + 'Topic :: Scientific/Engineering :: Information Analysis', + 'Topic :: Software Development :: Libraries :: Python Modules', + ] )