Skip to content

Instantly share code, notes, and snippets.

@davewsmith
Created October 17, 2020 17:14
Show Gist options
  • Save davewsmith/579dde93a0e047ff0922ec92e2cc5da1 to your computer and use it in GitHub Desktop.
Save davewsmith/579dde93a0e047ff0922ec92e2cc5da1 to your computer and use it in GitHub Desktop.
"""
PM2.5 to AQI (Air Quality Index) conversion
This implements the formula in
https://www.airnow.gov/sites/default/files/2020-05/aqi-technical-assistance-document-sept2018.pdf
and uses category names and colors from there.
PurpleAir notes:
In the JSON blob returned from the PurpleAir API, the key 'pm2_5Value' appears
once per sensor. PurpleAir averages the two values when calculating AQI,
unless is determines that one of the sensors is malfunctioning. (See
https://www2.purpleair.com/community/faq#hc-what-does-downgraded-mean-on-the-graph-1)
"""
import sys
def pm2_5_to_aqi(pm2_5):
"""Convert a PM2.5 reading in ug/m^3 to AQI
Returns AQI, the name of the category the range falls in, and the RGB
color for the range.
"""
c = round(pm2_5, 1)
if c <= 12.0:
i = (( 50.0 - 0.0) / ( 12.0 - 0.0)) * (c - 0.0) + 0.0
category = 'Good'
color = '#00e400'
elif c <= 35.4:
i = ((100.0 - 51.0) / ( 35.4 - 12.1)) * (c - 12.1) + 51.0
category = 'Moderate'
color = '#ffff00'
elif c <= 55.4:
i = ((150.0 - 101.0) / ( 55.4 - 35.5)) * (c - 35.5) + 101.0
category = 'Unhealthy for Sensitive Groups'
color = '#ff7e00'
elif c <= 150.4:
i = ((200.0 - 151.0) / (150.4 - 55.5)) * (c - 55.5) + 151.0
category = 'Unhealthy'
color = '#ff0000'
elif c <= 250.4:
i = ((300.0 - 201.0) / (250.4 - 150.5)) * (c - 150.5) + 201.0
category = 'Very unhealthy'
color = '#993f97'
elif c <= 350.4:
i = ((400.0 - 301.0) / (350.4 - 250.5)) * (c - 250.5) + 301.0
category = 'Hazardous'
color = '#7e0023'
else:
i = ((500.0 - 401.0) / (400.4 - 350.5)) * (c - 350.5) + 401.0
category = 'Hazardous'
color = '#7e0023'
return int(i), category, color
if __name__ == '__main__':
try:
pm2_5 = float(sys.argv[1])
epa, category, color = pm2_5_to_aqi(pm2_5)
print("{} -> {} {} {}".format(pm2_5, epa, category, color))
except:
print("usage: {} pm2_5_value".format(sys.argv[0]))
print(" e.g., {} 11.6".format(sys.argv[0]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment