Skip to content

Commit

Permalink
Merge pull request PSLmodels#2852 from martinholmer/fix-growfactors-use
Browse files Browse the repository at this point in the history
Remove incorrect use of GrowFactors() in Policy and Parameters classes
  • Loading branch information
jdebacker authored Dec 16, 2024
2 parents 0411f9c + f71b8b1 commit df06211
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 42 deletions.
2 changes: 1 addition & 1 deletion taxcalc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
from taxcalc.utils import *
from taxcalc.cli import *

__version__ = '4.3.4'
__version__ = '4.3.4a'
__min_python3_version__ = 10
__max_python3_version__ = 12
10 changes: 7 additions & 3 deletions taxcalc/calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1110,7 +1110,7 @@ def read_json_param_objects(reform, assump):
return param_dict

@staticmethod
def reform_documentation(params, policy_dicts=None):
def reform_documentation(params, growfactors, policy_dicts=None):
"""
Generate reform documentation versus current-law policy.
Expand All @@ -1120,6 +1120,9 @@ def reform_documentation(params, policy_dicts=None):
dictionary is structured like dict returned from
the static Calculator.read_json_param_objects() method
growfactors: GrowFactors
GrowFactors object used to construct Calculator Policy object
policy_dicts : list of dict or None
each dictionary in list is a params['policy'] dictionary
representing second and subsequent elements of a compound
Expand Down Expand Up @@ -1255,13 +1258,14 @@ def lines(text, num_indent_spaces, max_line_length=77):
# create Policy object with current-law-policy values
gdiff_base = GrowDiff()
gdiff_base.update_growdiff(params['growdiff_baseline'])
gfactors_clp = GrowFactors()
assert isinstance(growfactors, GrowFactors)
gfactors_clp = copy.deepcopy(growfactors)
gdiff_base.apply_to(gfactors_clp)
clp = Policy(gfactors=gfactors_clp)
# create Policy object with post-reform values
gdiff_resp = GrowDiff()
gdiff_resp.update_growdiff(params['growdiff_response'])
gfactors_ref = GrowFactors()
gfactors_ref = copy.deepcopy(growfactors)
gdiff_base.apply_to(gfactors_ref)
gdiff_resp.apply_to(gfactors_ref)
ref = Policy(gfactors=gfactors_ref)
Expand Down
12 changes: 5 additions & 7 deletions taxcalc/parameters.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import copy
import os
import re
import copy
from collections import defaultdict
from typing import Union, Mapping, Any, List

import marshmallow as ma
import paramtools as pt
import numpy as np
import requests

import taxcalc
from taxcalc.growfactors import GrowFactors


Expand Down Expand Up @@ -249,7 +246,6 @@ def adjust_with_indexing(self, params_or_path, **kwargs):
label_to_extend = self.label_to_extend
array_first = self.array_first
self.array_first = False
self._gfactors = GrowFactors()

params = self.read_params(params_or_path)

Expand Down Expand Up @@ -508,12 +504,14 @@ def set_rates(self):

def wage_growth_rates(self, year=None):
if year is not None:
return self._wage_growth_rates[year - self.start_year]
syr = max(self.start_year, self._gfactors.first_year)
return self._wage_growth_rates[year - syr]
return self._wage_growth_rates or []

def inflation_rates(self, year=None):
if year is not None:
return self._inflation_rates[year - self.start_year]
syr = max(self.start_year, self._gfactors.first_year)
return self._inflation_rates[year - syr]
return self._inflation_rates or []

# alias methods below
Expand Down
33 changes: 10 additions & 23 deletions taxcalc/policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import os
import json
from pathlib import Path
import numpy as np
from taxcalc.parameters import Parameters
from taxcalc.growfactors import GrowFactors

Expand Down Expand Up @@ -148,32 +147,20 @@ def parameter_list():
return [k for k in defaults if k != "schema"]

def set_rates(self):
"""Initialize taxcalc indexing data."""
"""
Initialize policy parameter indexing rates.
"""
cpi_vals = [
vo["value"] for
vo in self._data["parameter_indexing_CPI_offset"]["value"]
]
# extend parameter_indexing_CPI_offset values through budget window
# if they have not been extended already.
cpi_vals = cpi_vals + cpi_vals[-1:] * (
self.end_year - self.start_year + 1 - len(cpi_vals)
# policy_current_law.json should not specify any non-zero values
# for the parameter_indexing_CPI_offset parameter, so check this
assert any(cpi_vals) is False
syr = max(self.start_year, self._gfactors.first_year)
self._inflation_rates = self._gfactors.price_inflation_rates(
syr, self.end_year
)
cpi_offset = {
(self.start_year + ix): val
for ix, val in enumerate(cpi_vals)
}

self._gfactors = GrowFactors()

self._inflation_rates = [
np.round(rate + cpi_offset[self.start_year + ix], 4)
for ix, rate in enumerate(
self._gfactors.price_inflation_rates(
self.start_year, self.end_year
)
)
]

self._wage_growth_rates = self._gfactors.wage_growth_rates(
self.start_year, self.end_year
syr, self.end_year
)
11 changes: 8 additions & 3 deletions taxcalc/taxcalcio.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def __init__(self, input_data, tax_year, baseline, reform, assump,
outdir=None):
# pylint: disable=too-many-arguments,too-many-locals
# pylint: disable=too-many-branches,too-many-statements
self.gf_reform = None
self.errmsg = ''
# check name and existence of INPUT file
inp = 'x'
Expand Down Expand Up @@ -288,6 +289,7 @@ def init(self, input_data, tax_year, baseline, reform, assump,
gfactors_ref = GrowFactors()
gdiff_baseline.apply_to(gfactors_ref)
gdiff_response.apply_to(gfactors_ref)
self.gf_reform = copy.deepcopy(gfactors_ref)
# create Policy objects:
# ... the baseline Policy object
base = Policy(gfactors=gfactors_base)
Expand Down Expand Up @@ -571,10 +573,13 @@ def write_doc_file(self):
Write reform documentation to text file.
"""
if len(self.policy_dicts) <= 1:
doc = Calculator.reform_documentation(self.param_dict)
doc = Calculator.reform_documentation(
self.param_dict, self.gf_reform
)
else:
doc = Calculator.reform_documentation(self.param_dict,
self.policy_dicts[1:])
doc = Calculator.reform_documentation(
self.param_dict, self.gf_reform, self.policy_dicts[1:]
)
doc_fname = self._output_filename.replace('.csv', '-doc.text')
with open(doc_fname, 'w', encoding='utf-8') as dfile:
dfile.write(doc)
Expand Down
8 changes: 5 additions & 3 deletions taxcalc/tests/test_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import pytest
import numpy as np
import pandas as pd
from taxcalc import Policy, Records, Calculator, Consumption
from taxcalc import GrowFactors, Policy, Records, Calculator, Consumption


def test_make_calculator(cps_subsample):
Expand Down Expand Up @@ -568,7 +568,8 @@ def test_noreform_documentation():
"""
params = Calculator.read_json_param_objects(reform_json, assump_json)
assert isinstance(params, dict)
actual_doc = Calculator.reform_documentation(params)
gfs = GrowFactors()
actual_doc = Calculator.reform_documentation(params, gfs)
expected_doc = (
'REFORM DOCUMENTATION\n'
'Baseline Growth-Difference Assumption Values by Year:\n'
Expand Down Expand Up @@ -623,7 +624,8 @@ def test_reform_documentation():
params = Calculator.read_json_param_objects(reform_json, assump_json)
assert isinstance(params, dict)
second_reform = {'II_em': {2019: 6500}}
doc = Calculator.reform_documentation(params, [second_reform])
gfs = GrowFactors()
doc = Calculator.reform_documentation(params, gfs, [second_reform])
assert isinstance(doc, str)
dump = False # set to True to print documentation and force test failure
if dump:
Expand Down
5 changes: 3 additions & 2 deletions taxcalc/tests/test_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
Parameters,
Policy,
Consumption,
GrowDiff,
GrowFactors,
is_paramtools_format,
)
from taxcalc.growdiff import GrowDiff


# Test specification and use of simple Parameters-derived class that has
Expand Down Expand Up @@ -244,7 +244,7 @@ def test_json_file_contents(tests_path, fname):
elif fname == "growdiff.json":
o = GrowDiff()
param_list = []
for k in o:
for k in o:
if k[0].isupper(): # find parameters by case of first letter
param_list.append(k)
for param in param_list:
Expand Down Expand Up @@ -395,6 +395,7 @@ def __init__(self, **kwargs):
ArrayParams.NUM_YEARS,
**kwargs
)
self._gfactors = GrowFactors()
self._inflation_rates = [0.02] * self.num_years
self._wage_growth_rates = [0.03] * self.num_years

Expand Down

0 comments on commit df06211

Please sign in to comment.