Skip to content

Commit

Permalink
Merge pull request #71 from jdebacker/fix_calib_run
Browse files Browse the repository at this point in the history
Merging
  • Loading branch information
rickecon committed Aug 5, 2024
2 parents 516df70 + fce9545 commit 6e576ae
Show file tree
Hide file tree
Showing 9 changed files with 101,689 additions and 207 deletions.
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
include ogzaf/ogzaf_default_parameters.json
include ogzaf/ogzaf_default_parameters_multisector.json
56 changes: 19 additions & 37 deletions examples/run_og_zaf.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,18 @@
import json
import time
import copy
import importlib.resources
import matplotlib.pyplot as plt
from ogzaf.calibrate import Calibration
from ogcore.parameters import Specifications
from ogcore import output_tables as ot
from ogcore import output_plots as op
from ogcore.execute import runner
from ogcore.utils import safe_read_pickle, param_dump_json
from ogcore.utils import safe_read_pickle
from ogzaf.utils import is_connected

# Use a custom matplotlib style file for plots
style_file_url = (
"https://raw.githubusercontent.com/PSLmodels/OG-Core/"
+ "master/ogcore/OGcorePlots.mplstyle"
)
plt.style.use(style_file_url)
plt.style.use("ogcore.OGcorePlots")


def main():
Expand All @@ -30,8 +28,9 @@ def main():

# Directories to save data
CUR_DIR = os.path.dirname(os.path.realpath(__file__))
base_dir = os.path.join(CUR_DIR, "OG-ZAF-Example", "OUTPUT_BASELINE")
reform_dir = os.path.join(CUR_DIR, "OG-ZAF-Example", "OUTPUT_REFORM")
save_dir = os.path.join(CUR_DIR, "OG-ZAF-Example")
base_dir = os.path.join(save_dir, "OUTPUT_BASELINE")
reform_dir = os.path.join(save_dir, "OUTPUT_REFORM")

"""
---------------------------------------------------------------------------
Expand All @@ -46,33 +45,16 @@ def main():
output_base=base_dir,
)
# Update parameters for baseline from default json file
p.update_specifications(
json.load(
open(
os.path.join(
CUR_DIR, "..", "ogzaf", "ogzaf_default_parameters.json"
)
)
)
)
with importlib.resources.open_text(
"ogzaf", "ogzaf_default_parameters.json"
) as file:
defaults = json.load(file)
p.update_specifications(defaults)
# Update parameters from calibrate.py Calibration class
c = Calibration(p)
updated_params = c.get_dict()
p.tax_func_type = "linear"
p.age_specific = False
p.update_specifications(updated_params)
# set underlying growth rate to zero, as value from data is negative
p.g_y = 0.0
# set tax rates
p.update_specifications(
{
"cit_rate": [[0.27]],
"etr_params": [[[0.22]]],
"mtrx_params": [[[0.31]]],
"mtry_params": [[[0.25]]],
"tau_c": [[0.15]],
}
)
if is_connected(): # only update if connected to internet
c = Calibration(p)
updated_params = c.get_dict()
p.update_specifications(updated_params)

# Run model
start_time = time.time()
Expand All @@ -90,7 +72,7 @@ def main():
p2.baseline = False
p2.output_base = reform_dir

# additional parameters to change
# Parameter change for the reform run
updated_params_ref = {
"cit_rate": [[0.30]],
}
Expand Down Expand Up @@ -128,12 +110,12 @@ def main():

# create plots of output
op.plot_all(
base_dir, reform_dir, os.path.join(CUR_DIR, "OG-ZAF_example_plots")
base_dir, reform_dir, os.path.join(save_dir, "OG-ZAF_example_plots")
)

print("Percentage changes in aggregates:", ans)
# save percentage change output to csv file
ans.to_csv("ogzaf_example_output.csv")
ans.to_csv(os.path.join(save_dir, "OG-ZAF_example_output.csv"))


if __name__ == "__main__":
Expand Down
63 changes: 24 additions & 39 deletions examples/run_og_zaf_multiple_industry.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,29 @@
import json
import time
import copy
import numpy as np

# from taxcalc import Calculator
from ogzaf.calibrate import Calibration
import importlib.resources
import matplotlib.pyplot as plt
from ogcore.parameters import Specifications
from ogcore import output_tables as ot
from ogcore import output_plots as op
from ogcore.execute import runner
from ogcore.utils import safe_read_pickle, param_dump_json

# Use a custom matplotlib style file for plots
plt.style.use("ogcore.OGcorePlots")


def main():
# Define parameters to use for multiprocessing
client = Client()
num_workers = min(multiprocessing.cpu_count(), 7)
client = Client(n_workers=num_workers, threads_per_worker=1)
print("Number of workers = ", num_workers)

# Directories to save data
CUR_DIR = os.path.dirname(os.path.realpath(__file__))
base_dir = os.path.join(CUR_DIR, "OG-ZAF-CIT_Example", "OUTPUT_BASELINE")
reform_dir = os.path.join(CUR_DIR, "OG-ZAF-CIT_Example", "OUTPUT_REFORM")
save_dir = os.path.join(CUR_DIR, "OG-ZAF-MultipleIndustry-example")
base_dir = os.path.join(save_dir, "OUTPUT_BASELINE")
reform_dir = os.path.join(save_dir, "OUTPUT_REFORM")

"""
---------------------------------------------------------------------------
Expand All @@ -41,32 +43,11 @@ def main():
output_base=base_dir,
)
# Update parameters for baseline from default json file
p.update_specifications(
json.load(
open(
os.path.join(
CUR_DIR, "..", "ogzaf", "ogzaf_default_parameters.json"
)
)
)
)
# Update parameters from calibrate.py Calibration class
p.M = 4
p.I = 5
c = Calibration(p)
updated_params_tax = {
# order of industries is primary, energy, tertiary, secondary ex energy
"Z": [[0.5, 0.4, 1.7, 1.0]],
"epsilon": [1.0, 1.0, 1.0, 1.0],
"gamma": [0.67, 0.50, 0.45, 0.53],
"gamma_g": [0.0, 0.0, 0.0, 0.0],
"alpha_c": c.alpha_c,
"io_matrix": c.io_matrix,
}
p.update_specifications(updated_params_tax)

# dump params to json
param_dump_json(p, os.path.join(base_dir, "model_params.json"))
with importlib.resources.open_text(
"ogzaf", "ogzaf_default_parameters_multisector.json"
) as file:
defaults = json.load(file)
p.update_specifications(defaults)

# Run model
start_time = time.time()
Expand All @@ -84,12 +65,14 @@ def main():
p2.baseline = False
p2.output_base = reform_dir

# additional parameters to change
# Example reform is a corp tax rate cut (phased in) for all
# industries EXCEPT for secondary ex energy, which has a one point
# increae in the CIT rate
updated_params_ref = {
"cit_rate": [
[0.28, 0.28, 0.28, 0.28],
[0.28, 0.28, 0.28, 0.28],
[0.27, 0.27, 0.27, 0.27],
[0.27, 0.27, 0.27, 0.28],
[0.26, 0.26, 0.26, 0.28],
[0.25, 0.25, 0.25, 0.28],
],
"baseline_spending": True,
}
Expand Down Expand Up @@ -129,12 +112,14 @@ def main():
op.plot_all(
base_dir,
reform_dir,
os.path.join(CUR_DIR, "OG-ZAF_CIT_multi_industry_plots"),
os.path.join(save_dir, "OG-ZAF-MultipleIndustry-example_plots"),
)

print("Percentage changes in aggregates:", ans)
# save percentage change output to csv file
ans.to_csv("ogzaf_CIT_multi_industry_output.csv")
ans.to_csv(
os.path.join(save_dir, "OG-ZAF-MultipleIndustry-example_output.csv")
)


if __name__ == "__main__":
Expand Down
16 changes: 6 additions & 10 deletions ogzaf/calibrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from ogzaf import input_output as io
import os
import numpy as np
import datetime
from ogcore import demographics


Expand All @@ -11,8 +12,8 @@ class Calibration:
def __init__(
self,
p,
estimate_tax_functions=False,
estimate_chi_n=False,
macro_data_start_year=datetime.datetime(1947, 1, 1),
macro_data_end_year=datetime.date.today(),
demographic_data_path=None,
output_path=None,
):
Expand All @@ -21,9 +22,6 @@ def __init__(
Args:
p (OG-Core Specifications object): model parameters
estimate_tax_functions (bool): whether to estimate tax
function parameters
estimate_chi_n (bool): whether to estimate chi_n
demographic_data_path (str): path to save demographic data
output_path (str): path to save output to
Expand All @@ -35,11 +33,11 @@ def __init__(
if output_path is not None:
if not os.path.exists(output_path):
os.makedirs(output_path)
self.estimate_tax_functions = estimate_tax_functions
self.estimate_chi_n = estimate_chi_n

# Macro estimation
self.macro_params = macro_params.get_macro_params()
self.macro_params = macro_params.get_macro_params(
macro_data_start_year, macro_data_end_year
)

# io matrix and alpha_c
if p.I > 1: # no need if just one consumption good
Expand Down Expand Up @@ -96,8 +94,6 @@ def __init__(
# method to return all newly calibrated parameters in a dictionary
def get_dict(self):
dict = {}
# if self.estimate_chi_n:
# dict["chi_n"] = self.chi_n
dict.update(self.macro_params)
dict["e"] = self.e
dict["alpha_c"] = self.alpha_c
Expand Down
2 changes: 1 addition & 1 deletion ogzaf/income.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ def get_e_interp(S, age_wgts, age_wgts_80, abil_wgts, plot_path=None):


def get_e_orig(age_wgts, abil_wgts, plot_path=None):
"""
r"""
This function generates the 80 x 7 matrix of lifetime earnings
ability profiles, corresponding to annual ages from 21 to 100 and to
paths based on income percentiles 0-25, 25-50, 50-70, 70-80, 80-90,
Expand Down
18 changes: 11 additions & 7 deletions ogzaf/input_output.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pandas as pd
import numpy as np
from ogzaf.utils import is_connected
from ogzaf.constants import CONS_DICT, PROD_DICT

"""
Expand All @@ -8,13 +9,16 @@
# Read in SAM file
storage_options = {"User-Agent": "Mozilla/5.0"}
SAM_path = "https://www.wider.unu.edu/sites/default/files/Data/SASAM-2015-Data-Resource.xlsx"
SAM = pd.read_excel(
SAM_path,
sheet_name="Micro SAM 2015",
skiprows=6,
index_col=0,
storage_options=storage_options,
)
if is_connected():
SAM = pd.read_excel(
SAM_path,
sheet_name="Micro SAM 2015",
skiprows=6,
index_col=0,
storage_options=storage_options,
)
else:
SAM = None


def get_alpha_c(sam=SAM, cons_dict=CONS_DICT):
Expand Down
Loading

0 comments on commit 6e576ae

Please sign in to comment.