diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index fd3b19549..ca8023037 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -26,7 +26,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.10", "3.11"] + python-version: ["3.11", "3.12"] steps: - name: Checkout diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml index 56889fde8..aa35afc26 100644 --- a/.github/workflows/deploy_docs.yml +++ b/.github/workflows/deploy_docs.yml @@ -27,7 +27,7 @@ jobs: miniforge-variant: Mambaforge activate-environment: ogcore-dev environment-file: environment.yml - python-version: "3.11" + python-version: "3.12" auto-activate-base: false - name: Build # Build Jupyter Book diff --git a/.github/workflows/docs_check.yml b/.github/workflows/docs_check.yml index 4e0ce22c5..35714b60b 100644 --- a/.github/workflows/docs_check.yml +++ b/.github/workflows/docs_check.yml @@ -25,7 +25,7 @@ jobs: miniforge-variant: Mambaforge activate-environment: ogcore-dev environment-file: environment.yml - python-version: "3.11" + python-version: "3.12" auto-activate-base: false - name: Build # Build Jupyter Book diff --git a/.github/workflows/publish_to_pypi.yml b/.github/workflows/publish_to_pypi.yml index 8f54f3093..ea1acb773 100644 --- a/.github/workflows/publish_to_pypi.yml +++ b/.github/workflows/publish_to_pypi.yml @@ -16,7 +16,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: "3.12" - name: Build package run: make pip-package - name: Publish a Python distribution to PyPI diff --git a/CHANGELOG.md b/CHANGELOG.md index a09429d72..ccfcf653d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.12.0] - 2024-08-20 12:00:00 + +### Added + +- Support for Python 3.12 + +## [0.11.17] - 2024-08-18 12:00:00 + +### Added + +- Description of `alpha_I` in docs +- Updates valid range of the nominal UBI parameters + +### Bug Fix + +- Extrapolate `alpha_I` in `parameters.py` +- Ensure `alpha_I` shape conforms in `TPI.py` +- Fix formatting of labels in `constants.py` ## [0.11.16] - 2024-08-10 12:00:00 @@ -290,7 +308,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Version [0.7.0] on August 30, 2021 was the first time that the OG-USA repository was detached from all of the core model logic, which was named OG-Core. Before this version, OG-USA was part of what is now the [`OG-Core`](https://github.com/PSLmodels/OG-Core) repository. In the next version of OG-USA, we adjusted the version numbering to begin with 0.1.0. This initial version of 0.7.0, was sequential from what OG-USA used to be when the OG-Core project was called OG-USA. - Any earlier versions of OG-USA can be found in the [`OG-Core`](https://github.com/PSLmodels/OG-Core) repository [release history](https://github.com/PSLmodels/OG-Core/releases) from [v.0.6.4](https://github.com/PSLmodels/OG-Core/releases/tag/v0.6.4) (Jul. 20, 2021) or earlier. - +[0.12.0]: https://github.com/PSLmodels/OG-Core/compare/v0.11.17...v0.12.0 +[0.11.17]: https://github.com/PSLmodels/OG-Core/compare/v0.11.16...v0.11.17 [0.11.16]: https://github.com/PSLmodels/OG-Core/compare/v0.11.15...v0.11.16 [0.11.15]: https://github.com/PSLmodels/OG-Core/compare/v0.11.14...v0.11.15 [0.11.14]: https://github.com/PSLmodels/OG-Core/compare/v0.11.13...v0.11.14 diff --git a/Makefile b/Makefile index 42cc6b320..a32fd53c5 100644 --- a/Makefile +++ b/Makefile @@ -70,6 +70,11 @@ git-pr: build-docs: @cd ./docs ; python make_params.py; jb build ./book +format: + black . -l 79 + linecheck . --fix + pip-package: pip install wheel + pip install setuptools python setup.py sdist bdist_wheel diff --git a/environment.yml b/environment.yml index a33d4f754..68fadd400 100644 --- a/environment.yml +++ b/environment.yml @@ -2,7 +2,7 @@ name: ogcore-dev channels: - conda-forge dependencies: -- python>=3.7.7, <3.12 +- python>=3.7.7, <3.13 - numpy - ipython - setuptools diff --git a/ogcore/TPI.py b/ogcore/TPI.py index 15016fcd0..52765667b 100644 --- a/ogcore/TPI.py +++ b/ogcore/TPI.py @@ -593,7 +593,7 @@ def run_TPI(p, client=None): if p.baseline_spending: I_g[: p.T] = Ig_baseline[: p.T] else: - I_g = fiscal.get_I_g(Y, p.alpha_I) + I_g = fiscal.get_I_g(Y[: p.T], p.alpha_I[: p.T]) if p.baseline: K_g0 = p.initial_Kg_ratio * Y[0] else: @@ -945,7 +945,7 @@ def run_TPI(p, client=None): B[: p.T], K_demand_open_vec.sum(-1), D_d[: p.T], p.zeta_K[: p.T] ) if not p.baseline_spending: - I_g = fiscal.get_I_g(Y, p.alpha_I) + I_g = fiscal.get_I_g(Y[: p.T], p.alpha_I[: p.T]) if p.baseline: K_g0 = p.initial_Kg_ratio * Y[0] K_g = fiscal.get_K_g(K_g0, I_g, p, "TPI") diff --git a/ogcore/__init__.py b/ogcore/__init__.py index 18ff55530..a11acad60 100644 --- a/ogcore/__init__.py +++ b/ogcore/__init__.py @@ -20,4 +20,4 @@ from ogcore.txfunc import * from ogcore.utils import * -__version__ = "0.11.16" +__version__ = "0.12.0" diff --git a/ogcore/default_parameters.json b/ogcore/default_parameters.json index 23e4018b5..c464129ca 100644 --- a/ogcore/default_parameters.json +++ b/ogcore/default_parameters.json @@ -730,7 +730,7 @@ }, "alpha_I": { "title": "Exogenous fraction of GDP that goes towards government investment in infrastructure (public capital)", - "description": "", + "description": "Exogenous fraction of GDP that goes towards government investment in infrastructure (public capital)", "section_1": "Fiscal Policy Parameters", "section_2": "Spending", "notes": "", @@ -1254,7 +1254,7 @@ "description": "Dollar (nominal) amount of universal basic income (UBI) per child age 0 through 17.", "section_1": "Fiscal Policy Parameters", "section_2": "Spending", - "notes": "The universal basic income (UBI) per child ages 0 through 17 can range from $0 per year to $7,200 per year (max $600 per month).", + "notes": "The universal basic income (UBI) per child ages 0 through 17 can take positive or negative values (e.g., a negative value may be used to implement a head tax).", "type": "float", "value": [ { @@ -1263,8 +1263,8 @@ ], "validators": { "range": { - "min": 0.0, - "max": 7200.0 + "min": -99e9, + "max": 99e9 } } }, @@ -1273,7 +1273,7 @@ "description": "Dollar (nominal) amount of universal basic income (UBI) per adult age 18 to 64.", "section_1": "Fiscal Policy Parameters", "section_2": "Spending", - "notes": "The universal basic income (UBI) per adult age 18 through 64 can range from $0 per year to $18,000 per year ($1,500 per month).", + "notes": "The universal basic income (UBI) per adult age 18 through 64 can take positive or negative values (e.g., a negative value may be used to implement a head tax).", "type": "float", "value": [ { @@ -1282,8 +1282,8 @@ ], "validators": { "range": { - "min": 0.0, - "max": 18000.0 + "min": -99e9, + "max": 99e9 } } }, @@ -1292,7 +1292,7 @@ "description": "Dollar (nominal) amount of universal basic income (UBI) per adult age 65 and over.", "section_1": "Fiscal Policy Parameters", "section_2": "Spending", - "notes": "The universal basic income (UBI) per adult age 65 and over can range from $0 per year to $12,000 per year ($1,000 per month).", + "notes": "The universal basic income (UBI) per adult age 65 can take positive or negative values (e.g., a negative value may be used to implement a head tax).", "type": "float", "value": [ { @@ -1301,8 +1301,8 @@ ], "validators": { "range": { - "min": 0.0, - "max": 12000.0 + "min": -99e9, + "max": 99e9 } } }, diff --git a/ogcore/parameters.py b/ogcore/parameters.py index f900d5bd9..fd653da1b 100644 --- a/ogcore/parameters.py +++ b/ogcore/parameters.py @@ -158,6 +158,7 @@ def compute_default_params(self): tp_param_list = [ "alpha_G", "alpha_T", + "alpha_I", "world_int_rate_annual", "adjustment_factor_for_cit_receipts", "tau_bq", diff --git a/setup.py b/setup.py index f430ca8d7..47bd7f8d8 100755 --- a/setup.py +++ b/setup.py @@ -5,10 +5,10 @@ setuptools.setup( name="ogcore", - version="0.11.16", + version="0.12.0", author="Jason DeBacker and Richard W. Evans", license="CC0 1.0 Universal (CC0 1.0) Public Domain Dedication", - description="A general equilibribum overlapping generations model for fiscal policy analysis", + description="A general equilibrium overlapping generations model for fiscal policy analysis", long_description_content_type="text/markdown", long_description=longdesc, url="https://github.com/PSLmodels/OG-Core/", @@ -21,7 +21,7 @@ "ogcore": ["default_parameters.json", "OGcorePlots.mplstyle"] }, include_packages=True, - python_requires=">=3.7.7, <3.12", + python_requires=">=3.7.7, <3.13", install_requires=[ "numpy", "scipy>=1.7.1", diff --git a/tests/test_io_data/model_params_baseline_v312.pkl b/tests/test_io_data/model_params_baseline_v312.pkl new file mode 100644 index 000000000..d9e0c1bd9 Binary files /dev/null and b/tests/test_io_data/model_params_baseline_v312.pkl differ diff --git a/tests/test_output_plots.py b/tests/test_output_plots.py index 0aa78fcc2..de4425061 100644 --- a/tests/test_output_plots.py +++ b/tests/test_output_plots.py @@ -22,12 +22,18 @@ base_params = utils.safe_read_pickle( os.path.join(CUR_PATH, "test_io_data", "model_params_baseline.pkl") ) -else: +elif sys.version_info[1] == 11: base_params = utils.safe_read_pickle( os.path.join( CUR_PATH, "test_io_data", "model_params_baseline_v311.pkl" ) ) +else: + base_params = utils.safe_read_pickle( + os.path.join( + CUR_PATH, "test_io_data", "model_params_baseline_v312.pkl" + ) + ) reform_ss = utils.safe_read_pickle( os.path.join(CUR_PATH, "test_io_data", "SS_vars_reform.pkl") ) @@ -38,10 +44,16 @@ reform_params = utils.safe_read_pickle( os.path.join(CUR_PATH, "test_io_data", "model_params_reform.pkl") ) -else: +elif sys.version_info[1] == 11: reform_params = utils.safe_read_pickle( os.path.join(CUR_PATH, "test_io_data", "model_params_reform_v311.pkl") ) +else: + reform_params = utils.safe_read_pickle( + os.path.join( + CUR_PATH, "test_io_data", "model_params_baseline_v312.pkl" + ) + ) reform_taxfunctions = utils.safe_read_pickle( os.path.join(CUR_PATH, "test_io_data", "TxFuncEst_reform.pkl") ) @@ -147,7 +159,7 @@ def test_plot_aggregates( plot_type=plot_type, stationarized=stationarized, num_years_to_plot=20, - start_year=2023, + start_year=int(base_params.start_year), forecast_data=np.ones(20), forecast_units="ones", vertical_line_years=vertical_line_years, @@ -198,7 +210,7 @@ def test_plot_industry_aggregates( var_list=["Y_vec"], plot_type=plot_type, num_years_to_plot=20, - start_year=2023, + start_year=int(base_params.start_year), forecast_data=np.ones(20), forecast_units="ones", vertical_line_years=vertical_line_years, @@ -218,7 +230,11 @@ def test_plot_industry_aggregates( def test_plot_aggregates_save_fig(tmpdir): path = os.path.join(tmpdir, "test_plot.png") output_plots.plot_aggregates( - base_tpi, base_params, start_year=2023, plot_type="levels", path=path + base_tpi, + base_params, + start_year=int(base_params.start_year), + plot_type="levels", + path=path, ) img = mpimg.imread(path) @@ -228,7 +244,10 @@ def test_plot_aggregates_save_fig(tmpdir): def test_plot_aggregates_not_a_type(tmpdir): with pytest.raises(AssertionError): output_plots.plot_aggregates( - base_tpi, base_params, start_year=2023, plot_type="levels2" + base_tpi, + base_params, + start_year=int(base_params.start_year), + plot_type="levels2", ) @@ -275,7 +294,7 @@ def test_plot_gdp_ratio( base_params, reform_tpi=reform_tpi, reform_params=reform_params, - start_year=2023, + start_year=int(base_params.start_year), plot_type=plot_type, vertical_line_years=vertical_line_years, plot_title=plot_title, @@ -289,7 +308,7 @@ def test_plot_gdp_ratio_save_fig(tmpdir): base_tpi, base_params, reform_tpi=reform_tpi, - start_year=2023, + start_year=int(base_params.start_year), reform_params=reform_params, path=path, ) @@ -304,7 +323,7 @@ def test_ability_bar(): base_params, reform_tpi, reform_params, - start_year=2023, + start_year=int(base_params.start_year), plot_title=" Test Plot Title", ) assert fig @@ -317,7 +336,7 @@ def test_ability_bar_save_fig(tmpdir): base_params, reform_tpi, reform_params, - start_year=2023, + start_year=int(base_params.start_year), path=path, ) img = mpimg.imread(path) @@ -374,7 +393,7 @@ def test_tpi_profiles(by_j): base_params, reform_tpi, reform_params, - start_year=2023, + start_year=int(base_params.start_year), by_j=by_j, plot_title=" Test Plot Title", ) @@ -404,7 +423,7 @@ def test_tpi_profiles_save_fig(tmpdir): base_params, reform_tpi, reform_params, - start_year=2023, + start_year=int(base_params.start_year), path=path, ) img = mpimg.imread(path) @@ -515,7 +534,7 @@ def test_inequality_plot( base_params, reform_tpi=reform_tpi, reform_params=reform_params, - start_year=2023, + start_year=int(base_params.start_year), ineq_measure=ineq_measure, pctiles=pctiles, plot_type=plot_type, @@ -530,7 +549,7 @@ def test_inequality_plot_save_fig(tmpdir): base_params, reform_tpi=reform_tpi, reform_params=reform_params, - start_year=2023, + start_year=int(base_params.start_year), path=path, ) img = mpimg.imread(path) diff --git a/tests/test_output_tables.py b/tests/test_output_tables.py index aa8521938..c915cee68 100644 --- a/tests/test_output_tables.py +++ b/tests/test_output_tables.py @@ -22,12 +22,18 @@ base_params = utils.safe_read_pickle( os.path.join(CUR_PATH, "test_io_data", "model_params_baseline.pkl") ) -else: +elif sys.version_info[1] == 11: base_params = utils.safe_read_pickle( os.path.join( CUR_PATH, "test_io_data", "model_params_baseline_v311.pkl" ) ) +else: + base_params = utils.safe_read_pickle( + os.path.join( + CUR_PATH, "test_io_data", "model_params_baseline_v312.pkl" + ) + ) reform_ss = utils.safe_read_pickle( os.path.join(CUR_PATH, "test_io_data", "SS_vars_reform.pkl") ) @@ -38,10 +44,16 @@ reform_params = utils.safe_read_pickle( os.path.join(CUR_PATH, "test_io_data", "model_params_reform.pkl") ) -else: +elif sys.version_info[1] == 11: reform_params = utils.safe_read_pickle( os.path.join(CUR_PATH, "test_io_data", "model_params_reform_v311.pkl") ) +else: + reform_params = utils.safe_read_pickle( + os.path.join( + CUR_PATH, "test_io_data", "model_params_baseline_v312.pkl" + ) + ) # add investment tax credit parameter that not in cached parameters base_params.inv_tax_credit = np.zeros( (base_params.T + base_params.S, base_params.M) @@ -76,7 +88,7 @@ def test_macro_table( base_params, reform_tpi=reform_tpi, reform_params=reform_params, - start_year=2023, + start_year=int(base_params.start_year), output_type=output_type, stationarized=stationarized, include_SS=True, @@ -176,7 +188,7 @@ def test_dynamic_revenue_decomposition(include_business_tax, full_break_out): reform_params, reform_tpi, reform_ss, - start_year=2023, + start_year=int(base_params.start_year), include_business_tax=include_business_tax, full_break_out=full_break_out, ) diff --git a/tests/test_parameter_plots.py b/tests/test_parameter_plots.py index 14a4fc387..c5b1b51cf 100644 --- a/tests/test_parameter_plots.py +++ b/tests/test_parameter_plots.py @@ -17,12 +17,18 @@ base_params = utils.safe_read_pickle( os.path.join(CUR_PATH, "test_io_data", "model_params_baseline.pkl") ) -else: +elif sys.version_info[1] == 11: base_params = utils.safe_read_pickle( os.path.join( CUR_PATH, "test_io_data", "model_params_baseline_v311.pkl" ) ) +else: + base_params = utils.safe_read_pickle( + os.path.join( + CUR_PATH, "test_io_data", "model_params_baseline_v312.pkl" + ) + ) base_taxfunctions = utils.safe_read_pickle( os.path.join(CUR_PATH, "test_io_data", "TxFuncEst_baseline.pkl") ) @@ -36,10 +42,11 @@ micro_data = utils.safe_read_pickle( os.path.join(CUR_PATH, "test_io_data", "micro_data_dict_for_tests.pkl") ) -base_params.rho = np.tile( - base_params.rho.reshape(1, base_params.S), - (base_params.T + base_params.S, 1), -) +if base_params.rho.ndim == 1: + base_params.rho = np.tile( + base_params.rho.reshape(1, base_params.S), + (base_params.T + base_params.S, 1), + ) def test_plot_imm_rates(): @@ -94,13 +101,15 @@ def test_plot_surv_rates_save_fig(tmpdir): def test_plot_pop_growth(): fig = parameter_plots.plot_pop_growth( - base_params, start_year=2023, include_title=True + base_params, start_year=int(base_params.start_year), include_title=True ) assert fig def test_plot_pop_growth_rates_save_fig(tmpdir): - parameter_plots.plot_pop_growth(base_params, start_year=2023, path=tmpdir) + parameter_plots.plot_pop_growth( + base_params, start_year=int(base_params.start_year), path=tmpdir + ) img = mpimg.imread(os.path.join(tmpdir, "pop_growth_rates.png")) assert isinstance(img, np.ndarray) diff --git a/tests/test_parameter_tables.py b/tests/test_parameter_tables.py index d579a8049..30a4f6543 100644 --- a/tests/test_parameter_tables.py +++ b/tests/test_parameter_tables.py @@ -16,12 +16,18 @@ base_params = utils.safe_read_pickle( os.path.join(CUR_PATH, "test_io_data", "model_params_baseline.pkl") ) -else: +elif sys.version_info[1] == 11: base_params = utils.safe_read_pickle( os.path.join( CUR_PATH, "test_io_data", "model_params_baseline_v311.pkl" ) ) +else: + base_params = utils.safe_read_pickle( + os.path.join( + CUR_PATH, "test_io_data", "model_params_baseline_v312.pkl" + ) + ) base_taxfunctions = utils.safe_read_pickle( os.path.join(CUR_PATH, "test_io_data", "TxFuncEst_baseline.pkl") )