forked from PolicyEngine/policyengine-taxsim
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request PolicyEngine#26 from MaxGhenis/MaxGhenis/issue24
Create package
- Loading branch information
Showing
25 changed files
with
908 additions
and
415 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
name: Run Tests | ||
|
||
on: | ||
push: | ||
branches: [main] | ||
pull_request: | ||
branches: [main] | ||
|
||
jobs: | ||
test: | ||
runs-on: ${{ matrix.os }} | ||
strategy: | ||
matrix: | ||
os: [ubuntu-latest, macos-latest, windows-latest] | ||
python-version: [3.9, "3.10", 3.11, 3.12] | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- name: Set up Python ${{ matrix.python-version }} | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
|
||
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install -e . | ||
pip install pytest | ||
- name: Make TAXSIM executables executable (Unix) | ||
if: runner.os != 'Windows' | ||
run: chmod +x resources/taxsim35/taxsim35-*.exe | ||
|
||
- name: Run tests | ||
run: pytest tests/ |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Copyright 2024 PolicyEngine | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
taxsimid,year,state,mstat,page,sage,fiitax,siitax,fica | ||
1,2021,3,1,40,0,[2775.],[1008.87],[3748.5] | ||
1,2021,3,1,40,0,[2535.],[942.07],[3595.5] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
taxsimid,year,state,fiitax,siitax,fica,frate,srate,ficar,tfica,credits,v10,v11,v12,v13,v14,v15,v16,v17,v18,v19,v20, v21,v22,v23,v24,v25,v26,v27,v28,v29,v30,v31,v32,v33,v34, v35,v36,v37,v38,v39,v40,v41,staxbc,v42,v43,v44,v45 | ||
1.,2021,3,2775.00,1008.87,7497.00,12.00,3.34,15.30,3748.50,.00,49000.00,.00,.00,12550.00,.00,.00,.00,.00,36450.00,4175.00,.00,.00,.00,.00,.00,.00,49000.00,.00,4175.00,7497.00,49000.01,.00,49000.01,.00,12550.00,1008.87,36450.01,.00,.00,.00,.00,3.34,.00,.00,.00,.00,1400.00 | ||
1.,2021,3,2535.00,942.07,7191.00,12.00,3.34,15.30,3595.50,.00,47000.00,.00,.00,12550.00,.00,.00,.00,.00,34450.00,3935.00,.00,.00,.00,.00,.00,.00,47000.00,.00,3935.00,7191.00,47001.01,.00,47000.01,.00,12550.00,942.07,34450.01,.00,.00,.00,.00,3.34,.00,.00,.00,.00,1400.00 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from .core.input_mapper import import_single_household | ||
from .core.output_mapper import export_single_household | ||
from .cli import main as cli | ||
|
||
__all__ = ["import_single_household", "export_single_household", "cli"] | ||
|
||
__version__ = "0.1.0" # Make sure this matches the version in pyproject.toml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import click | ||
import pandas as pd | ||
from pathlib import Path | ||
from policyengine_taxsim.core.input_mapper import import_single_household | ||
from policyengine_taxsim.core.output_mapper import export_single_household | ||
|
||
|
||
@click.command() | ||
@click.argument("input_file", type=click.Path(exists=True)) | ||
@click.option( | ||
"--output", | ||
"-o", | ||
type=click.Path(), | ||
default="output.csv", | ||
help="Output file path", | ||
) | ||
def main(input_file, output): | ||
""" | ||
Process TAXSIM input file and generate PolicyEngine-compatible output. | ||
""" | ||
try: | ||
# Read input file | ||
df = pd.read_csv(input_file) | ||
|
||
# Process each row | ||
results = [] | ||
for _, row in df.iterrows(): | ||
taxsim_input = row.to_dict() | ||
pe_situation = import_single_household(taxsim_input) | ||
taxsim_output = export_single_household(pe_situation) | ||
results.append(taxsim_output) | ||
|
||
# Create output dataframe and save to csv | ||
output_df = pd.DataFrame(results) | ||
output_path = Path(output) | ||
output_path.parent.mkdir(parents=True, exist_ok=True) | ||
output_df.to_csv(output_path, index=False) | ||
click.echo(f"Output saved to {output}") | ||
except Exception as e: | ||
click.echo(f"Error processing input: {str(e)}", err=True) | ||
raise | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
taxsim_to_policyengine: | ||
year: get_year | ||
state: get_state_code | ||
fiitax: income_tax | ||
siitax: state_income_tax | ||
fica: get_fica | ||
frate: federal_mtr | ||
srate: state_mtr | ||
ficar: placeholder | ||
tfica: taxsim_tfica | ||
v10: adjusted_gross_income | ||
v11: tax_unit_taxable_unemployment_compensation | ||
v12: tax_unit_taxable_social_security | ||
v13: basic_standard_deduction | ||
v14: exemptions | ||
v15: placeholder | ||
v16: placeholder | ||
v17: taxable_income_deductions | ||
v18: taxable_income | ||
v19: income_tax | ||
v20: placeholder | ||
v21: placeholder | ||
v22: ctc | ||
v23: refundable_ctc | ||
v24: cdcc | ||
v25: eitc | ||
v26: amt_income | ||
v27: alternative_minimum_tax | ||
v28: income_tax_before_refundable_credits | ||
v29: placeholder | ||
v30: household_net_income | ||
v31: placeholder | ||
v32: state_agi | ||
v33: placeholder | ||
v34: state_standard_deduction | ||
v35: state_itemized_deductions | ||
v36: state_taxable_income | ||
v37: property_tax_credit | ||
v38: child_care_credit | ||
v39: placeholder | ||
v40: placeholder | ||
v41: placeholder | ||
v42: self_employment_income | ||
v43: net_investment_income_tax | ||
v44: employee_medicare_tax | ||
v45: rrc_cares | ||
|
||
policyengine_to_taxsim: | ||
# This section would be the inverse of the above mapping | ||
# It's left empty for brevity, but you should populate it | ||
# with the inverse relationships for bidirectional conversion |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
from policyengine_taxsim.core.utils import ( | ||
load_variable_mappings, | ||
get_state_code, | ||
) | ||
|
||
|
||
def import_single_household(taxsim_vars): | ||
""" | ||
Convert TAXSIM input variables to a PolicyEngine situation. | ||
Args: | ||
taxsim_vars (dict): Dictionary of TAXSIM input variables | ||
Returns: | ||
dict: PolicyEngine situation dictionary | ||
""" | ||
mappings = load_variable_mappings()["taxsim_to_policyengine"] | ||
|
||
year = str(int(taxsim_vars["year"])) # Ensure year is an integer string | ||
state = get_state_code(taxsim_vars["state"]) | ||
|
||
situation = { | ||
"people": { | ||
"you": { | ||
"age": {year: int(taxsim_vars.get("page", 40))}, | ||
"employment_income": {year: int(taxsim_vars.get("pwages", 0))}, | ||
} | ||
}, | ||
"households": { | ||
"your household": {"members": ["you"], "state_name": {year: state}} | ||
}, | ||
"tax_units": {"your tax unit": {"members": ["you"]}}, | ||
} | ||
|
||
return situation |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
from policyengine_taxsim.core.utils import ( | ||
load_variable_mappings, | ||
get_state_number, | ||
) | ||
from policyengine_us import Simulation | ||
|
||
|
||
def export_single_household(policyengine_situation): | ||
""" | ||
Convert a PolicyEngine situation to TAXSIM output variables. | ||
Args: | ||
policyengine_situation (dict): PolicyEngine situation dictionary | ||
Returns: | ||
dict: Dictionary of TAXSIM output variables | ||
""" | ||
mappings = load_variable_mappings()["policyengine_to_taxsim"] | ||
|
||
simulation = Simulation(situation=policyengine_situation) | ||
|
||
year = list( | ||
policyengine_situation["households"]["your household"][ | ||
"state_name" | ||
].keys() | ||
)[0] | ||
state_name = policyengine_situation["households"]["your household"][ | ||
"state_name" | ||
][year] | ||
|
||
taxsim_output = { | ||
"taxsimid": policyengine_situation.get("taxsimid", 1), | ||
"year": int(year), | ||
"state": get_state_number(state_name), | ||
"mstat": policyengine_situation["tax_units"]["your tax unit"] | ||
.get("marital_status", {}) | ||
.get(year, 1), | ||
"page": policyengine_situation["people"]["you"]["age"][year], | ||
"sage": policyengine_situation["people"] | ||
.get("your spouse", {}) | ||
.get("age", {}) | ||
.get(year, 0), | ||
"fiitax": simulation.calculate("income_tax", period=year), | ||
"siitax": simulation.calculate("state_income_tax", period=year), | ||
"fica": simulation.calculate( | ||
"employee_social_security_tax", period=year | ||
) | ||
+ simulation.calculate("employee_medicare_tax", period=year), | ||
} | ||
|
||
# Add more variables as needed to match TAXSIM output | ||
|
||
return taxsim_output |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import yaml | ||
from pathlib import Path | ||
|
||
|
||
def load_variable_mappings(): | ||
"""Load variable mappings from YAML file.""" | ||
config_path = ( | ||
Path(__file__).parent.parent / "config" / "variable_mappings.yaml" | ||
) | ||
with open(config_path, "r") as f: | ||
return yaml.safe_load(f) | ||
|
||
|
||
STATE_MAPPING = { | ||
1: "AL", | ||
2: "AK", | ||
3: "AZ", | ||
4: "AR", | ||
5: "CA", | ||
6: "CO", | ||
7: "CT", | ||
8: "DE", | ||
9: "DC", | ||
10: "FL", | ||
11: "GA", | ||
12: "HI", | ||
13: "ID", | ||
14: "IL", | ||
15: "IN", | ||
16: "IA", | ||
17: "KS", | ||
18: "KY", | ||
19: "LA", | ||
20: "ME", | ||
21: "MD", | ||
22: "MA", | ||
23: "MI", | ||
24: "MN", | ||
25: "MS", | ||
26: "MO", | ||
27: "MT", | ||
28: "NE", | ||
29: "NV", | ||
30: "NH", | ||
31: "NJ", | ||
32: "NM", | ||
33: "NY", | ||
34: "NC", | ||
35: "ND", | ||
36: "OH", | ||
37: "OK", | ||
38: "OR", | ||
39: "PA", | ||
40: "RI", | ||
41: "SC", | ||
42: "SD", | ||
43: "TN", | ||
44: "TX", | ||
45: "UT", | ||
46: "VT", | ||
47: "VA", | ||
48: "WA", | ||
49: "WV", | ||
50: "WI", | ||
51: "WY", | ||
} | ||
|
||
|
||
def get_state_code(state_number): | ||
"""Convert state number to state code.""" | ||
return STATE_MAPPING.get(state_number, "Invalid state number") | ||
|
||
|
||
def get_state_number(state_code): | ||
"""Convert state code to state number.""" | ||
state_mapping_reverse = {v: k for k, v in STATE_MAPPING.items()} | ||
return state_mapping_reverse.get( | ||
state_code, 0 | ||
) # Return 0 for invalid state codes | ||
|
||
|
||
def is_date(string): | ||
"""Check if a string represents a valid year.""" | ||
try: | ||
year = int(string) | ||
return ( | ||
1900 <= year <= 2100 | ||
) # Assuming years between 1900 and 2100 are valid | ||
except ValueError: | ||
return False |
Oops, something went wrong.