Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename dropq directory/files as tbi and refactor run_nth_year_*_model functions #1577

Merged
merged 12 commits into from
Oct 10, 2017
Merged
2 changes: 1 addition & 1 deletion .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ omit =
taxcalc/functions.py
taxcalc/*.json
taxcalc/cli/*
taxcalc/dropq/*
taxcalc/tbi/*
taxcalc/tests/*
taxcalc/validation/*
3 changes: 3 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ Release 0.12.0 on 2017-??-??
- Remove arrays_not_lists argument from read_json_param_objects
[[#1568](https://github.com/open-source-economics/Tax-Calculator/pull/1568)
by Martin Holmer]
- Rename dropq as tbi (taxbrain interface) and refactor run_nth_year_*_model functions
[[#1577](https://github.com/open-source-economics/Tax-Calculator/pull/1577)
by Martin Holmer]

**New Features**
- Add Calculator.reform_documentation that generates plain text documentation of a reform
Expand Down
12 changes: 6 additions & 6 deletions read-the-docs/source/public_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,6 @@ taxcalc.decorators
.. automodule:: taxcalc.decorators
:members:

taxcalc.dropq.dropq
-------------------

.. automodule:: taxcalc.dropq.dropq
:members:

taxcalc.functions
-----------------

Expand Down Expand Up @@ -108,6 +102,12 @@ taxcalc.TaxCalcIO
.. autoclass:: taxcalc.TaxCalcIO
:members:

taxcalc.tbi.tbi
-------------------

.. automodule:: taxcalc.tbi.tbi
:members:

taxcalc.utils
-------------

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
'cmdclass': cmdclass,
'license': 'MIT',
'packages': ['taxcalc', 'taxcalc.filings', 'taxcalc.filings.forms',
'taxcalc.dropq', 'taxcalc.cli'],
'taxcalc.tbi', 'taxcalc.cli'],
'include_package_data': True,
'name': 'taxcalc',
'install_requires': ['numpy', 'pandas'],
Expand Down
2 changes: 1 addition & 1 deletion taxcalc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from taxcalc.taxcalcio import *
from taxcalc.utils import *
from taxcalc.macro_elasticity import *
from taxcalc.dropq import *
from taxcalc.tbi import *
from taxcalc.cli import *

from taxcalc._version import get_versions
Expand Down
4 changes: 0 additions & 4 deletions taxcalc/dropq/__init__.py

This file was deleted.

2 changes: 1 addition & 1 deletion taxcalc/macro_elasticity.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# pylint --disable=locally-disabled macro_elasticity.py


def proportional_change_gdp(calc1, calc2, elasticity=0.0):
def proportional_change_gdp(calc1, calc2, elasticity):
'''
This function harnesses econometric estimates of the historic relationship
between tax policy and the macroeconomy to predict the effect of tax
Expand Down
6 changes: 3 additions & 3 deletions taxcalc/records.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def __init__(self,
@staticmethod
def cps_constructor(data=None,
exact_calculations=False,
growfactors=Growfactors()):
gfactors=Growfactors()):
"""
Static method returns a Records object instantiated with CPS
input data. This works in a analogous way to Records(), which
Expand All @@ -188,7 +188,7 @@ def cps_constructor(data=None,
data = os.path.join(Records.CUR_PATH, 'cps.csv.gz')
return Records(data=data,
exact_calculations=exact_calculations,
gfactors=growfactors,
gfactors=gfactors,
weights=Records.CPS_WEIGHTS_FILENAME,
adjust_ratios=Records.CPS_RATIOS_FILENAME,
start_year=CPSCSV_YEAR)
Expand All @@ -213,7 +213,7 @@ def increment_year(self):
Also, does extrapolation, reweighting, adjusting for new current year.
"""
self._current_year += 1
# apply variable extrapolation growfactors
# apply variable extrapolation grow factors
if self.gfactors is not None:
self._blowup(self.current_year)
# apply variable adjustment ratios
Expand Down
4 changes: 2 additions & 2 deletions taxcalc/taxcalcio.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,11 @@ def init(self, input_data, tax_year, reform, assump,
if aging_input_data:
if self.cps_input_data:
recs = Records.cps_constructor(
growfactors=gfactors_ref,
gfactors=gfactors_ref,
exact_calculations=exact_calculations
)
recs_clp = Records.cps_constructor(
growfactors=gfactors_clp,
gfactors=gfactors_clp,
exact_calculations=exact_calculations
)
else: # if not cps_input_data
Expand Down
4 changes: 4 additions & 0 deletions taxcalc/tbi/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from taxcalc.tbi.tbi import (run_nth_year_tax_calc_model,
run_nth_year_gdp_elast_model,
create_dict_table,
reform_warnings_errors)
106 changes: 60 additions & 46 deletions taxcalc/dropq/dropq.py → taxcalc/tbi/tbi.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
"""
The dropq functions are used by TaxBrain to call Tax-Calculator in order
to maintain the privacy of the IRS-SOI PUF data being used by TaxBrain.
This is done by "fuzzing" reform results for several randomly selected
The tbi functions are used by TaxBrain to call Tax-Calculator in order
to do distributed processing of TaxBrain runs and in order to maintain
the privacy of the IRS-SOI PUF data being used by TaxBrain. Maintaining
privacy is done by "fuzzing" reform results for several randomly selected
filing units in each table cell. The filing units randomly selected
differ for each policy reform and the "fuzzing" involves replacing the
post-reform tax results for the selected units with their pre-reform
tax results.
"""
# CODING-STYLE CHECKS:
# pep8 --ignore=E402 dropq.py
# pylint --disable=locally-disabled dropq.py
# pep8 --ignore=E402 tbi.py
# pylint --disable=locally-disabled tbi.py

from __future__ import print_function
import time
import numpy as np
import pandas as pd
from taxcalc.dropq.dropq_utils import (dropq_calculate,
random_seed,
dropq_summary,
AGGR_ROW_NAMES)
from taxcalc.tbi.tbi_utils import (calculate,
random_seed,
summary,
AGGR_ROW_NAMES)
from taxcalc import (results, DIST_TABLE_LABELS,
proportional_change_gdp, Growdiff, Growfactors, Policy)

Expand All @@ -45,7 +46,7 @@
def reform_warnings_errors(user_mods):
"""
The reform_warnings_errors function assumes user_mods is a dictionary
returned by the Calculator.read_json_parameter_files() function.
returned by the Calculator.read_json_param_objects() function.

This function returns a dictionary containing two STR:STR pairs:
{'warnings': '<empty-or-message(s)>', 'errors': '<empty-or-message(s)>'}
Expand Down Expand Up @@ -81,22 +82,27 @@ def reform_warnings_errors(user_mods):


def run_nth_year_tax_calc_model(year_n, start_year,
taxrec_df, user_mods,
return_json=True):
use_puf_not_cps,
use_full_sample,
user_mods,
return_dict=True):
"""
The run_nth_year_tax_calc_model function assumes user_mods is a
dictionary returned by the Calculator.read_json_parameter_files()
function with an extra key:value pair that is specified as
'gdp_elasticity': {'value': <float_value>}.
The run_nth_year_tax_calc_model function assumes user_mods is a dictionary
returned by the Calculator.read_json_param_objects() function.
Setting use_puf_not_cps=True implies use puf.csv input file;
otherwise, use cps.csv input file.
Setting use_full_sample=False implies use sub-sample of input file;
otherwsie, use the complete sample.
"""
# pylint: disable=too-many-locals
# pylint: disable=too-many-arguments,too-many-locals

start_time = time.time()

# create calc1 and calc2 calculated for year_n and mask
(calc1, calc2, mask) = dropq_calculate(year_n, start_year,
taxrec_df, user_mods,
behavior_allowed=True,
mask_computed=True)
(calc1, calc2, mask) = calculate(year_n, start_year,
use_puf_not_cps, use_full_sample,
user_mods,
behavior_allowed=True)

# extract raw results from calc1 and calc2
rawres1 = results(calc1.records)
Expand All @@ -107,11 +113,8 @@ def run_nth_year_tax_calc_model(year_n, start_year,
print('seed={}'.format(seed))
np.random.seed(seed) # pylint: disable=no-member

# construct dropq summary results from raw results
summ = dropq_summary(rawres1, rawres2, mask)

elapsed_time = time.time() - start_time
print('elapsed time for this run: ', elapsed_time)
# construct TaxBrain summary results from raw results
summ = summary(rawres1, rawres2, mask)

def append_year(pdf):
"""
Expand All @@ -121,10 +124,12 @@ def append_year(pdf):
return pdf

# optionally return non-JSON results
if not return_json:
if not return_dict:
res = dict()
for tbl in summ:
res[tbl] = append_year(summ[tbl])
elapsed_time = time.time() - start_time
print('elapsed time for this run: {:.1f}'.format(elapsed_time))
return res

# optionally construct JSON results tables for year n
Expand All @@ -147,41 +152,50 @@ def append_year(pdf):
res = dict()
for tbl in summ:
if 'aggr' in tbl:
res_table = create_json_table(summ[tbl],
res_table = create_dict_table(summ[tbl],
row_names=info[tbl]['row_names'])
res[tbl] = dict((k, v[0]) for k, v in res_table.items())
else:
res[tbl] = create_json_table(summ[tbl],
res[tbl] = create_dict_table(summ[tbl],
row_names=info[tbl]['row_names'],
column_types=info[tbl]['col_types'])
elapsed_time = time.time() - start_time
print('elapsed time for this run: {:.1f}'.format(elapsed_time))
return res


def run_nth_year_gdp_elast_model(year_n, start_year,
taxrec_df, user_mods,
return_json=True):
use_puf_not_cps,
use_full_sample,
user_mods,
gdp_elasticity,
return_dict=True):
"""
The run_nth_year_gdp_elast_model function assumes user_mods is a
dictionary returned by the Calculator.read_json_parameter_files()
function with an extra key:value pair that is specified as
'gdp_elasticity': {'value': <float_value>}.
The run_nth_year_gdp_elast_model function assumes user_mods is a dictionary
returned by the Calculator.read_json_param_objects() function.
Setting use_puf_not_cps=True implies use puf.csv input file;
otherwise, use cps.csv input file.
Setting use_full_sample=False implies use sub-sample of input file;
otherwsie, use the complete sample.
"""
# pylint: disable=too-many-arguments

# create calc1 and calc2 calculated for year_n
(calc1, calc2, _) = dropq_calculate(year_n, start_year,
taxrec_df, user_mods,
behavior_allowed=False,
mask_computed=False)
(calc1, calc2, _) = calculate(year_n, start_year,
use_puf_not_cps,
use_full_sample,
user_mods,
behavior_allowed=False)

# compute GDP effect given assumed gdp elasticity
gdp_elasticity = user_mods['gdp_elasticity']['value']
# compute GDP effect given specified gdp_elasticity
gdp_effect = proportional_change_gdp(calc1, calc2, gdp_elasticity)

# return gdp_effect results
if return_json:
if return_dict:
gdp_df = pd.DataFrame(data=[gdp_effect], columns=['col0'])
gdp_elast_names_n = [x + '_' + str(year_n)
for x in GDP_ELAST_ROW_NAMES]
gdp_elast_total = create_json_table(gdp_df,
gdp_elast_total = create_dict_table(gdp_df,
row_names=gdp_elast_names_n,
num_decimals=5)
gdp_elast_total = dict((k, v[0]) for k, v in gdp_elast_total.items())
Expand All @@ -190,10 +204,10 @@ def run_nth_year_gdp_elast_model(year_n, start_year,
return gdp_effect


def create_json_table(dframe, row_names=None, column_types=None,
def create_dict_table(dframe, row_names=None, column_types=None,
num_decimals=2):
"""
Create and return dictionary with JSON-like contents from specified dframe.
Create and return dictionary with JSON-like content from specified dframe.
"""
# embedded formatted_string function
def formatted_string(val, _type, num_decimals):
Expand All @@ -216,7 +230,7 @@ def formatted_string(val, _type, num_decimals):
except ValueError:
# try making it a string - good luck!
return str(val)
# high-level create_json_table function logic
# high-level create_dict_table function logic
out = dict()
if row_names is None:
row_names = [str(x) for x in list(dframe.index)]
Expand Down
Loading