Skip to content

Commit

Permalink
#32 draft of PTC module.
Browse files Browse the repository at this point in the history
cczhu committed Jan 17, 2020
1 parent a41841f commit e2018db
Showing 6 changed files with 113 additions and 19 deletions.
17 changes: 9 additions & 8 deletions traffic_prophet/countmatch/growthfactor.py
Original file line number Diff line number Diff line change
@@ -132,9 +132,9 @@ def fit_growth(self, tc):
{'year': aadt.at[0, 'Year'], 'aadt': aadt.at[0, 'AADT']})
growth_factor = np.exp(fit_results.params[0])

return {'fit_type': 'Exponential',
'fit_results': fit_results,
'growth_factor': growth_factor}
tc._growth_fit = {'fit_type': 'Exponential',
'fit_results': fit_results,
'growth_factor': growth_factor}


class GrowthFactorWADTLin(GrowthFactorBase):
@@ -185,9 +185,9 @@ def fit_growth(self, tc):
growth_factor = 1. + (fit_results.params[1] * 52. /
tc.adts['AADT']['AADT'].values[0])

return {'fit_type': 'Linear',
'fit_results': fit_results,
'growth_factor': growth_factor}
tc._growth_fit = {'fit_type': 'Linear',
'fit_results': fit_results,
'growth_factor': growth_factor}


class GrowthFactorComposite(GrowthFactorBase):
@@ -202,5 +202,6 @@ def __init__(self):

def fit_growth(self, tc):
if tc.adts['AADT'].shape[0] > 1:
return self.aadt_exp.fit_growth(tc)
return self.wadt_lin.fit_growth(tc)
self.aadt_exp.fit_growth(tc)
else:
self.wadt_lin.fit_growth(tc)
9 changes: 9 additions & 0 deletions traffic_prophet/countmatch/permcount.py
Original file line number Diff line number Diff line change
@@ -30,12 +30,21 @@ def __init__(self, count_id, centreline_id, direction, data,
perm_years):
super().__init__(count_id, centreline_id, direction, data,
is_permanent=True)
if len(perm_years) == 0:
raise ValueError("cannot have empty perm_years!")
self._perm_years = perm_years
self._growth_fit = None

@property
def perm_years(self):
return self._perm_years

@property
def growth_factor(self):
if self._growth_fit is None:
raise AttributeError("PTC has not had its growth factor fit!")
return self._growth_fit['growth_factor']

@classmethod
def from_count_object(cls, tc, perm_years):
return cls(tc.count_id, tc.centreline_id, tc.direction, tc.data,
2 changes: 1 addition & 1 deletion traffic_prophet/countmatch/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ def cfgcm_test():
'min_counts_in_day': 24,
'min_permanent_months': 12,
'min_permanent_days': 274,
'exclude_ptc_neg': [],
'exclude_ptc_neg': [446378, ],
'exclude_ptc_pos': [],
'derived_vals_calculator': 'Standard',
'derived_vals_settings': {},
2 changes: 1 addition & 1 deletion traffic_prophet/countmatch/tests/test_derivedvals.py
Original file line number Diff line number Diff line change
@@ -132,7 +132,7 @@ def test_get_derived_vals(self, sample_counts, cfgcm_test):
assert 'N_avail_days' in ptc.ratios.keys()

def test_imputer(self, sample_counts, cfgcm_test):
ptc_multiyear = get_single_ptc(sample_counts, cfgcm_test, -104870)
pass


class TestDerivedVals:
32 changes: 23 additions & 9 deletions traffic_prophet/countmatch/tests/test_growthfactor.py
Original file line number Diff line number Diff line change
@@ -91,15 +91,19 @@ def test_exponential_rate_fit(self, slp):
x, y, {"year": x[0], "aadt": y[0]})
assert np.abs(result.params[0] - slp) < 0.01

def test_fit_growth(self, ptc_multiyear):
def test_fit_growth(self, sample_counts, cfgcm_test):
ptc_multiyear = get_single_ptc(sample_counts, cfgcm_test, -104870)

aadt = self.gfc.get_aadt(ptc_multiyear)
fit_ref = sm.OLS(np.log(aadt['AADT'].values / aadt['AADT'].values[0]),
aadt['Year'].values - aadt['Year'].values[0]).fit()

fit_results = self.gfc.fit_growth(ptc_multiyear)
self.gfc.fit_growth(ptc_multiyear)

assert np.isclose(fit_results["growth_factor"],
assert np.isclose(ptc_multiyear._growth_fit["growth_factor"],
np.exp(fit_ref.params[0]))
assert (ptc_multiyear.growth_factor ==
ptc_multiyear._growth_fit["growth_factor"])


class TestGrowthFactorWADTLin:
@@ -117,27 +121,37 @@ def test_linear_rate_fit(self, slp, y0):
result = self.gfc.linear_rate_fit(x, y)
assert np.abs(result.params[1] - slp) < 0.01

def test_fit_growth(self, ptc_oneyear, ptc_multiyear):
def test_fit_growth(self, sample_counts, cfgcm_test):
ptc_oneyear = get_single_ptc(sample_counts, cfgcm_test, -890)
ptc_multiyear = get_single_ptc(sample_counts, cfgcm_test, -104870)

# The multi-year fit is REALLY sketchy, since we end up normalizing
# by the first year's AADT.
for ptc in (ptc_oneyear, ptc_multiyear):
wadt = self.gfc.get_wadt_py(ptc)
fit_ref = sm.OLS(wadt['WADT'].values,
sm.add_constant(wadt['Time'].values)).fit()

fit_results = self.gfc.fit_growth(ptc)
self.gfc.fit_growth(ptc)

assert np.isclose(fit_results["growth_factor"],
assert np.isclose(ptc._growth_fit["growth_factor"],
1. + (fit_ref.params[1] * 52. /
ptc.adts['AADT']['AADT'].values[0]))
assert (ptc.growth_factor ==
ptc._growth_fit["growth_factor"])


class TestGrowthFactorComposite:

def test_growthfactorcomposite(self, ptc_oneyear, ptc_multiyear):
def test_growthfactorcomposite(self, sample_counts, cfgcm_test):
ptc_oneyear = get_single_ptc(sample_counts, cfgcm_test, -890)
ptc_multiyear = get_single_ptc(sample_counts, cfgcm_test, -104870)
gfc = gf.GrowthFactorComposite()
assert gfc.fit_growth(ptc_oneyear)['fit_type'] == 'Linear'
assert gfc.fit_growth(ptc_multiyear)['fit_type'] == 'Exponential'

gfc.fit_growth(ptc_oneyear)
gfc.fit_growth(ptc_multiyear)
assert ptc_oneyear._growth_fit['fit_type'] == 'Linear'
assert ptc_multiyear._growth_fit['fit_type'] == 'Exponential'


class TestGrowthFactor:
70 changes: 70 additions & 0 deletions traffic_prophet/countmatch/tests/test_permcount.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import numpy as np
import pytest

from .. import reader
from .. import base
from .. import permcount as pc
from .. import derivedvals as dv
from .. import growthfactor as gf

from ...data import SAMPLE_ZIP


@pytest.fixture(scope='module')
def pcproc(cfgcm_test):
dvc = dv.DerivedVals('Standard')
gfc = gf.GrowthFactor('Composite')
return pc.PermCountProcessor(dvc, gfc, cfg=cfgcm_test)


class TestPermCount:

def test_permcount(self, sample_counts):
ptc = pc.PermCount.from_count_object(sample_counts.counts[-104870],
[2010, 2012])
assert isinstance(ptc, pc.PermCount)
assert ptc.is_permanent
assert ptc.perm_years == [2010, 2012]

with pytest.raises(ValueError) as excinfo:
ptc = pc.PermCount.from_count_object(
sample_counts.counts[-104870], [])
assert "cannot have empty perm_years" in str(excinfo.value)


class TestPermCountProcessor:

def test_setup(self, pcproc):
assert isinstance(pcproc.dvc, dv.DerivedValsStandard)
assert isinstance(pcproc.gfc, gf.GrowthFactorComposite)
# We passed a custom cfgcm with no excluded IDs.
assert pcproc.excluded_ids == [-446378, ]

def test_partition(self, pcproc, sample_counts):
ptc_oy_permyears = pcproc.partition_years(sample_counts.counts[-890])
assert np.array_equal(ptc_oy_permyears, np.array([2010], dtype=int))
ptc_my_permyears = pcproc.partition_years(
sample_counts.counts[-104870])
assert np.array_equal(ptc_my_permyears,
np.array([2010, 2012], dtype=int))

def test_ptcs_sttcs(self, pcproc, cfgcm_test):
# Can't use the fixture since this test will alter tcs.
tcs = reader.read(SAMPLE_ZIP, cfg=cfgcm_test)
pcproc.get_ptcs_sttcs(tcs)

assert sorted(tcs.ptcs.keys()) == [-104870, -890]
assert (sorted(tcs.sttcs.keys()) ==
[-446378, -1978, -680, -487, -427, -410,
-252, -241, -170, 170, 104870])

for ptc in tcs.ptcs.values():
assert isinstance(ptc, pc.PermCount)
assert (sorted(list(ptc.adts.keys())) ==
['AADT', 'MADT'])
assert (sorted(list(ptc.ratios.keys())) ==
['D_ijd', 'DoM_ijd', 'N_avail_days'])
assert abs(ptc.growth_factor) > 0.

for sttc in tcs.sttcs.values():
assert isinstance(sttc, base.Count)

0 comments on commit e2018db

Please sign in to comment.