def growmodel_analysis(input_data, tax_year, baseline, reform, assump, aging_input_data, exact_calculations, writing_output_file=False, output_tables=False, output_graphs=False, dump_varset=None, output_dump=False, output_sqldb=False): """ High-level logic for dynamic analysis using GrowModel class. Parameters ---------- First five parameters are same as the first five parameters of the TaxCalcIO.init method. Last seven parameters are same as the first seven parameters of the TaxCalcIO.analyze method. Returns ------- Nothing """ # pylint: disable=too-many-arguments,too-many-locals progress = 'STARTING ANALYSIS FOR YEAR {}' gdiff_dict = {Policy.JSON_START_YEAR: {}} for year in range(Policy.JSON_START_YEAR, tax_year + 1): print(progress.format(year)) # specify growdiff_growmodel using gdiff_dict growdiff_growmodel = GrowDiff() growdiff_growmodel.update_growdiff(gdiff_dict) gd_dict = TaxCalcIO.annual_analysis(input_data, tax_year, baseline, reform, assump, aging_input_data, exact_calculations, growdiff_growmodel, year, writing_output_file, output_tables, output_graphs, dump_varset, output_dump, output_sqldb) gdiff_dict[year + 1] = gd_dict
def with_suffix(gdict, growdiff_baseline_dict, growdiff_response_dict): """ Return param_base:year dictionary having only suffix parameters. """ if bool(growdiff_baseline_dict) or bool(growdiff_response_dict): gdiff_baseline = GrowDiff() gdiff_baseline.update_growdiff(growdiff_baseline_dict) gdiff_response = GrowDiff() gdiff_response.update_growdiff(growdiff_response_dict) growfactors = GrowFactors() gdiff_baseline.apply_to(growfactors) gdiff_response.apply_to(growfactors) else: gdiff_baseline = None gdiff_response = None growfactors = None pol = Policy(gfactors=growfactors) pol.ignore_reform_errors() odict = dict() for param in gdict.keys(): odict[param] = dict() for year in sorted(gdict[param].keys()): odict[param][year] = dict() for suffix in gdict[param][year].keys(): plist = getattr(pol, param).tolist() dvals = plist[int(year) - Policy.JSON_START_YEAR] odict[param][year] = [dvals] idx = Policy.JSON_REFORM_SUFFIXES[suffix] odict[param][year][0][idx] = gdict[param][year][suffix] udict = {int(year): {param: odict[param][year]}} pol.implement_reform(udict, print_warnings=False, raise_errors=False) del gdiff_baseline del gdiff_response del growfactors del pol return odict
def test_json_file_contents(tests_path, fname): """ Check contents of JSON parameter files in Tax-Calculator/taxcalc directory. """ first_year = Policy.JSON_START_YEAR last_known_year = Policy.LAST_KNOWN_YEAR # for indexed parameter values known_years = set(range(first_year, last_known_year + 1)) long_params = [ 'II_brk1', 'II_brk2', 'II_brk3', 'II_brk4', 'II_brk5', 'II_brk6', 'II_brk7', 'PT_brk1', 'PT_brk2', 'PT_brk3', 'PT_brk4', 'PT_brk5', 'PT_brk6', 'PT_brk7', 'PT_qbid_taxinc_thd', 'ALD_BusinessLosses_c', 'STD', 'II_em', 'II_em_ps', 'AMT_em', 'AMT_em_ps', 'AMT_em_pe', 'ID_ps', 'ID_AllTaxes_c' ] # for TCJA-reverting long_params long_known_years = set(range(first_year, last_known_year + 1)) long_known_years.add(2026) # check elements in each parameter sub-dictionary failures = '' with open(os.path.join(tests_path, "..", fname)) as f: allparams = json.loads(f.read()) for pname in allparams: if pname == "schema": continue # check that param contains required keys param = allparams[pname] # check that indexable and indexed are False in many files if fname != 'policy_current_law.json': assert param.get('indexable', False) is False assert param.get('indexed', False) is False # check that indexable is True when indexed is True if param.get('indexed', False) and not param.get('indexable', False): msg = 'param:<{}>; indexed={}; indexable={}' fail = msg.format(pname, param.get('indexed', False), param.get('indexable', False)) failures += fail + '\n' # check that indexable param has value_type float if param.get('indexable', False) and param['type'] != 'float': msg = 'param:<{}>; type={}; indexable={}' fail = msg.format(pname, param['type'], param.get('indexable', False)) failures += fail + '\n' # ensure that indexable is False when value_type is not real if param.get('indexable', False) and param['type'] != 'float': msg = 'param:<{}>; indexable={}; type={}' fail = msg.format(pname, param.get('indexable', False), param['value_type']) failures += fail + '\n' if fname == "consumption.json": o = Consumption() elif fname == "policy_current_law.json": o = Policy() elif fname == "growdiff.json": o = GrowDiff() param_list = [] for k in o: if k[0].isupper(): # find parameters by case of first letter param_list.append(k) for param in param_list: for y in known_years: o.set_year(y) if np.isnan(getattr(o, param)).any(): msg = 'param:<{}>; not found in year={}' fail = msg.format(param, y) failures += fail + '\n' if failures: raise ValueError(failures)
def init(self, input_data, tax_year, baseline, reform, assump, growdiff_growmodel, aging_input_data, exact_calculations): """ TaxCalcIO class post-constructor method that completes initialization. Parameters ---------- First five are same as the first five of the TaxCalcIO constructor: input_data, tax_year, baseline, reform, assump. growdiff_growmodel: GrowDiff object or None growdiff_growmodel GrowDiff object is used only in the TaxCalcIO.growmodel_analysis method. aging_input_data: boolean whether or not to extrapolate Records data from data year to tax_year. exact_calculations: boolean specifies whether or not exact tax calculations are done without any smoothing of "stair-step" provisions in the tax law. """ # pylint: disable=too-many-arguments,too-many-locals # pylint: disable=too-many-statements,too-many-branches self.errmsg = '' # get policy parameter dictionary from --baseline file basedict = Calculator.read_json_param_objects(baseline, None) # get assumption sub-dictionaries paramdict = Calculator.read_json_param_objects(None, assump) # get policy parameter dictionaries from --reform file(s) policydicts = list() if self.specified_reform: reforms = reform.split('+') for ref in reforms: pdict = Calculator.read_json_param_objects(ref, None) policydicts.append(pdict['policy']) paramdict['policy'] = policydicts[0] # remember parameters for reform documentation self.param_dict = paramdict self.policy_dicts = policydicts # create Behavior object beh = Behavior() try: beh.update_behavior(paramdict['behavior']) except ValueError as valerr_msg: self.errmsg += valerr_msg.__str__() self.behavior_has_any_response = beh.has_any_response() # create gdiff_baseline object gdiff_baseline = GrowDiff() try: gdiff_baseline.update_growdiff(paramdict['growdiff_baseline']) except ValueError as valerr_msg: self.errmsg += valerr_msg.__str__() # create GrowFactors base object that incorporates gdiff_baseline gfactors_base = GrowFactors() gdiff_baseline.apply_to(gfactors_base) # specify gdiff_response object gdiff_response = GrowDiff() try: gdiff_response.update_growdiff(paramdict['growdiff_response']) except ValueError as valerr_msg: self.errmsg += valerr_msg.__str__() # create GrowFactors ref object that has all gdiff objects applied gfactors_ref = GrowFactors() gdiff_baseline.apply_to(gfactors_ref) gdiff_response.apply_to(gfactors_ref) if growdiff_growmodel: growdiff_growmodel.apply_to(gfactors_ref) # create Policy objects: # ... the baseline Policy object base = Policy(gfactors=gfactors_base) try: base.implement_reform(basedict['policy'], print_warnings=False, raise_errors=False) self.errmsg += base.parameter_errors except ValueError as valerr_msg: self.errmsg += valerr_msg.__str__() # ... the reform Policy object if self.specified_reform: pol = Policy(gfactors=gfactors_ref) for poldict in policydicts: try: pol.implement_reform(poldict, print_warnings=False, raise_errors=False) self.errmsg += pol.parameter_errors except ValueError as valerr_msg: self.errmsg += valerr_msg.__str__() else: pol = Policy(gfactors=gfactors_base) # create Consumption object con = Consumption() try: con.update_consumption(paramdict['consumption']) except ValueError as valerr_msg: self.errmsg += valerr_msg.__str__() # create GrowModel object self.growmodel = GrowModel() try: self.growmodel.update_growmodel(paramdict['growmodel']) except ValueError as valerr_msg: self.errmsg += valerr_msg.__str__() # check for valid tax_year value if tax_year < pol.start_year: msg = 'tax_year {} less than policy.start_year {}' msg = msg.format(tax_year, pol.start_year) self.errmsg += 'ERROR: {}\n'.format(msg) if tax_year > pol.end_year: msg = 'tax_year {} greater than policy.end_year {}' msg = msg.format(tax_year, pol.end_year) self.errmsg += 'ERROR: {}\n'.format(msg) # any errors imply cannot proceed with calculations if self.errmsg: return # set policy to tax_year pol.set_year(tax_year) base.set_year(tax_year) # read input file contents into Records objects if aging_input_data: if self.cps_input_data: recs = Records.cps_constructor( gfactors=gfactors_ref, exact_calculations=exact_calculations) recs_base = Records.cps_constructor( gfactors=gfactors_base, exact_calculations=exact_calculations) else: # if not cps_input_data but aging_input_data recs = Records(data=input_data, gfactors=gfactors_ref, exact_calculations=exact_calculations) recs_base = Records(data=input_data, gfactors=gfactors_base, exact_calculations=exact_calculations) else: # input_data are raw data that are not being aged recs = Records(data=input_data, gfactors=None, exact_calculations=exact_calculations, weights=None, adjust_ratios=None, start_year=tax_year) recs_base = copy.deepcopy(recs) if tax_year < recs.data_year: msg = 'tax_year {} less than records.data_year {}' msg = msg.format(tax_year, recs.data_year) self.errmsg += 'ERROR: {}\n'.format(msg) # create Calculator objects self.calc = Calculator(policy=pol, records=recs, verbose=True, consumption=con, behavior=beh, sync_years=aging_input_data) self.calc_base = Calculator(policy=base, records=recs_base, verbose=False, consumption=con, sync_years=aging_input_data)
def init(self, input_data, tax_year, baseline, reform, assump, aging_input_data, exact_calculations): """ TaxCalcIO class post-constructor method that completes initialization. Parameters ---------- First five are same as the first five of the TaxCalcIO constructor: input_data, tax_year, baseline, reform, assump. aging_input_data: boolean whether or not to extrapolate Records data from data year to tax_year. exact_calculations: boolean specifies whether or not exact tax calculations are done without any smoothing of "stair-step" provisions in the tax law. """ # pylint: disable=too-many-arguments,too-many-locals # pylint: disable=too-many-statements,too-many-branches self.errmsg = '' # get policy parameter dictionary from --baseline file basedict = Calculator.read_json_param_objects(baseline, None) # get assumption sub-dictionaries paramdict = Calculator.read_json_param_objects(None, assump) # get policy parameter dictionaries from --reform file(s) policydicts = list() if self.specified_reform: reforms = reform.split('+') for ref in reforms: pdict = Calculator.read_json_param_objects(ref, None) policydicts.append(pdict['policy']) paramdict['policy'] = policydicts[0] # remember parameters for reform documentation self.param_dict = paramdict self.policy_dicts = policydicts # create gdiff_baseline object gdiff_baseline = GrowDiff() try: gdiff_baseline.update_growdiff(paramdict['growdiff_baseline']) except ValueError as valerr_msg: self.errmsg += valerr_msg.__str__() # create GrowFactors base object that incorporates gdiff_baseline gfactors_base = GrowFactors() gdiff_baseline.apply_to(gfactors_base) # specify gdiff_response object gdiff_response = GrowDiff() try: gdiff_response.update_growdiff(paramdict['growdiff_response']) except ValueError as valerr_msg: self.errmsg += valerr_msg.__str__() # create GrowFactors ref object that has all gdiff objects applied gfactors_ref = GrowFactors() gdiff_baseline.apply_to(gfactors_ref) gdiff_response.apply_to(gfactors_ref) # create Policy objects: # ... the baseline Policy object base = Policy(gfactors=gfactors_base) try: base.implement_reform(basedict['policy'], print_warnings=False, raise_errors=False) self.errmsg += base.parameter_errors except ValueError as valerr_msg: self.errmsg += valerr_msg.__str__() # ... the reform Policy object if self.specified_reform: pol = Policy(gfactors=gfactors_ref) for poldict in policydicts: try: pol.implement_reform(poldict, print_warnings=False, raise_errors=False) self.errmsg += pol.parameter_errors except ValueError as valerr_msg: self.errmsg += valerr_msg.__str__() else: pol = Policy(gfactors=gfactors_base) # create Consumption object con = Consumption() try: con.update_consumption(paramdict['consumption']) except ValueError as valerr_msg: self.errmsg += valerr_msg.__str__() # check for valid tax_year value if tax_year < pol.start_year: msg = 'tax_year {} less than policy.start_year {}' msg = msg.format(tax_year, pol.start_year) self.errmsg += 'ERROR: {}\n'.format(msg) if tax_year > pol.end_year: msg = 'tax_year {} greater than policy.end_year {}' msg = msg.format(tax_year, pol.end_year) self.errmsg += 'ERROR: {}\n'.format(msg) # any errors imply cannot proceed with calculations if self.errmsg: return # set policy to tax_year pol.set_year(tax_year) base.set_year(tax_year) # read input file contents into Records objects if aging_input_data: if self.cps_input_data: recs = Records.cps_constructor( gfactors=gfactors_ref, exact_calculations=exact_calculations ) recs_base = Records.cps_constructor( gfactors=gfactors_base, exact_calculations=exact_calculations ) else: # if not cps_input_data but aging_input_data recs = Records( data=input_data, gfactors=gfactors_ref, exact_calculations=exact_calculations ) recs_base = Records( data=input_data, gfactors=gfactors_base, exact_calculations=exact_calculations ) else: # input_data are raw data that are not being aged recs = Records(data=input_data, gfactors=None, exact_calculations=exact_calculations, weights=None, adjust_ratios=None, start_year=tax_year) recs_base = copy.deepcopy(recs) if tax_year < recs.data_year: msg = 'tax_year {} less than records.data_year {}' msg = msg.format(tax_year, recs.data_year) self.errmsg += 'ERROR: {}\n'.format(msg) # create Calculator objects self.calc = Calculator(policy=pol, records=recs, verbose=True, consumption=con, sync_years=aging_input_data) self.calc_base = Calculator(policy=base, records=recs_base, verbose=False, consumption=con, sync_years=aging_input_data)