#!/usr/bin/python3
import os.path as path
def mlo():
""" Yield the monthly parts per million of CO₂ measured on Mauna Loa.
Data from:
http://scrippsco2.ucsd.edu/data/atmospheric_co2.html
"""
for l in open(path.join(
path.dirname(__file__),
'_/monthly_mlo.csv'),
'rt').readlines():
if l.startswith('1') or l.startswith('2'):
s = l.split(',')
year = int(s[0])
assert((1958 <= year) and (year <= 2100))
month = int(s[1])
assert((1 <= month) and (month <= 12))
ppmv = float(s[4])
if ppmv != -99.99:
assert((300 < ppmv) and (ppmv <= 450))
yield year, month, ppmv
def decade(year):
""" Return the decade of a particular year. """
return int(year/10) * 10
def partialPressure(ppmv):
""" Return the partial pressure of a gas in the air at sea level given
its mole fraction in parts per million and assuming standard air
pressure (101.325 kPa).
Result in pascals.
"""
return ppmv/1e6 * 101325
_decades = None # Information on the decades for which we have
# useful data. Found by mloPerDecade when needed.
def mloPerDecade():
""" Yield information about the decades with at least 100 months of data. """
global _decades
# Read in if first time through.
if _decades == None:
# Accumulate data for each of the decades.
decades = {}
for year, _, ppmv in mlo():
d = decade(year)
if not d in decades:
class a: start_year = d; end_year = d + 9; count = 0; total = 0
decades[d] = a
decades[d].total += ppmv
decades[d].count += 1
# Convert dictionary into a sorted list and get rid of the decades with
# not much data.
_decades = sorted(
filter(lambda a: a.count >= 100,
decades.values()),
key=lambda a: a.start_year)
# Calculate averages and average partial pressures.
for a in _decades:
a.ppmv = a.total / a.count
a.pp = partialPressure(a.ppmv)
a.ppmvString = '%3.2f' % a.ppmv
a.ppString = '%3.3f' % a.pp
# Actually return results
for a in _decades:
yield a
def yearRange():
""" Return the range of years for which the MLO data has (nearly) complete
decades of data. """
mloPerDecade()
return _decades[0].start_year, _decades[-1].end_year