Skip to content

Commit

Permalink
bug fix: load_scenario accepts dict
Browse files Browse the repository at this point in the history
factory.load_scenario will work with a correct AdvancedControls, but those are hard to construct because they depend on the solution's VMAs.  So now accept a dict and create the AC internally.
  • Loading branch information
denised committed Aug 30, 2021
1 parent 449c00f commit 325abfd
Show file tree
Hide file tree
Showing 3 changed files with 210 additions and 10 deletions.
19 changes: 12 additions & 7 deletions model/advanced_controls.py
Original file line number Diff line number Diff line change
Expand Up @@ -971,7 +971,8 @@ def __hash__(self):
def write_to_json_file(self):
jsfilenew = self.jsfile + '.new'
d = dataclasses.asdict(self)
for rem in ['vmas', 'js', 'jsfile']:
#for rem in ['vmas', 'js', 'jsfile']:
for rem in ['vmas', 'jsfile']:
del d[rem]
with open(jsfilenew, 'w') as f:
json.dump(d, f)
Expand Down Expand Up @@ -1005,15 +1006,19 @@ def load_scenarios_from_json(directory, vmas):
result = {}
for filename in glob.glob(str(directory.joinpath('*.json'))):
with open(filename, 'r') as fid:
j = json.loads(fid.read())
js = j.copy()
js['vmas'] = vmas
js['js'] = j
js['jsfile'] = str(filename)
a = AdvancedControls(**js)
jd = json.loads(fid.read())
a = ac_from_dict(jd, vmas, filename)
result[a.name] = a
return result

def ac_from_dict(data: dict, vmas, filename="") -> AdvancedControls:
"""Create an AdvancedControls object from a dictionary of values, as retrieved from a scenario json file."""
d = data.copy()
d['vmas'] = vmas
d['jsfile'] = str(filename)
return AdvancedControls(**d)


def get_vma_for_param(param):
for field in dataclasses.fields(AdvancedControls):
if field.name == param:
Expand Down
9 changes: 7 additions & 2 deletions solution/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import importlib
from pathlib import Path
from functools import lru_cache
from model import advanced_controls as ac

def all_solutions():
# Find all the directories containing an __init__.py
Expand All @@ -24,9 +25,13 @@ def load_scenario(solution, scenario=None):
* None (the default): return the PDS2 scenario for this solution
* `PDS`, `PDS2` or `PDS3`: get the most recent scenario of the requested type
* a scenario name: load the scenario with that name
* an Advanced_Controls object: load a completely custom scenario based on the data in the object"""
* an AdvancedControl object: load a scenario with completely custom values
* a json dictionary representing an AdvancedControl object: load a completely custom scenario based on the data in the object
* the format should be the same as the sceanrios stored with the solution."""
m = _load_module(solution)
if scenario in ['PDS1','PDS2','PDS3']:
if isinstance(scenario, dict):
scenario = ac.ac_from_dict(scenario, m.VMAs)
elif scenario in ['PDS1','PDS2','PDS3']:
md = {'PDS1': m.PDS1, 'PDS2': m.PDS2, 'PDS3': m.PDS3}
scenario = md[scenario]
return m.Scenario(scenario)
Expand Down
192 changes: 191 additions & 1 deletion solution/test_factory.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Test solution classes."""
import dataclasses
import json
from . import factory
from model import scenario
from model import advanced_controls as ac
Expand All @@ -22,7 +23,7 @@ def test_load_named_scenario():
result = factory.load_scenario('geothermal', scenarios[0])
assert result and isinstance(result, scenario.Scenario)

def test_load_custom_scenario():
def test_load_custom_scenario_by_copying():
onescenario = factory.load_scenario('hybridcars')

# Make a new Advanced Controls by dumping one and tweaking it
Expand All @@ -32,3 +33,192 @@ def test_load_custom_scenario():

result = factory.load_scenario('hybridcars',twoac)
assert result.scenario == "Change the Name"


def test_load_custom_scenario_from_dict():
adict = json.loads(biochar_scenario_json)
result = factory.load_scenario("biochar",adict)
assert result.ac.conv_fuel_emissions_factor == 0
assert result.tm.ref_tam_per_region() is not None

biochar_scenario_json="""
{
"name": "PDS-8p2050-Plausible-CustomPDS-Avg-Jan2020",
"solution_category": "reduction",
"vmas": "VMAs",
"description": "This is updated results with new data.",
"report_start_year": 2020,
"report_end_year": 2050,
"conv_2014_cost": {
"value": 0.0,
"statistic": ""
},
"conv_first_cost_efficiency_rate": 0.0,
"conv_lifetime_capacity": {
"value": 1.0,
"statistic": ""
},
"conv_avg_annual_use": {
"value": 1.0,
"statistic": ""
},
"conv_var_oper_cost_per_funit": {
"value": 0.0,
"statistic": ""
},
"conv_fixed_oper_cost_per_iunit": {
"value": 0.0,
"statistic": ""
},
"conv_fuel_cost_per_funit": 0.0,
"pds_2014_cost": {
"value": 21639272.7272727,
"statistic": "mean"
},
"ref_2014_cost": {
"value": 21639272.7272727,
"statistic": "mean"
},
"soln_first_cost_efficiency_rate": 0.0,
"soln_first_cost_below_conv": true,
"soln_lifetime_capacity": {
"value": 410116.363636364,
"statistic": "mean"
},
"soln_avg_annual_use": {
"value": 20505.8181818182,
"statistic": "mean"
},
"soln_var_oper_cost_per_funit": {
"value": 193.920714285714,
"statistic": "mean"
},
"soln_fixed_oper_cost_per_iunit": {
"value": 0.0,
"statistic": ""
},
"soln_fuel_cost_per_funit": 0.0,
"npv_discount_rate": 0.02,
"conv_annual_energy_used": {
"value": 0.0,
"statistic": ""
},
"soln_energy_efficiency_factor": {
"value": 0.0,
"statistic": ""
},
"soln_annual_energy_used": {
"value": 0.0,
"statistic": ""
},
"conv_fuel_consumed_per_funit": {
"value": 0.0,
"statistic": ""
},
"soln_fuel_efficiency_factor": {
"value": 0.0,
"statistic": ""
},
"conv_fuel_emissions_factor": {
"value": 0.0,
"statistic": ""
},
"soln_fuel_emissions_factor": {
"value": 0.0,
"statistic": ""
},
"conv_emissions_per_funit": {
"value": 0.0,
"statistic": ""
},
"soln_emissions_per_funit": {
"value": -0.958331730769231,
"statistic": "mean"
},
"conv_indirect_co2_per_unit": {
"value": 0.0,
"statistic": ""
},
"soln_indirect_co2_per_iunit": {
"value": 0.0,
"statistic": ""
},
"conv_indirect_co2_is_iunits": true,
"ch4_co2_per_funit": {
"value": 0.0,
"statistic": ""
},
"ch4_is_co2eq": false,
"n2o_co2_per_funit": {
"value": 0.0,
"statistic": ""
},
"n2o_is_co2eq": false,
"co2eq_conversion_source": "AR5 with feedback",
"emissions_use_co2eq": true,
"emissions_grid_source": "Meta-Analysis",
"emissions_grid_range": "Mean",
"source_until_2014": "ALL SOURCES",
"ref_source_post_2014": "ALL SOURCES",
"pds_source_post_2014": "ALL SOURCES",
"ref_base_adoption": {
"World": 7457.0,
"OECD90": 0.0,
"Eastern Europe": 0.0,
"Asia (Sans Japan)": 0.0,
"Middle East and Africa": 0.0,
"Latin America": 0.0,
"China": 0.0,
"India": 0.0,
"EU": 0.0,
"USA": 0.0
},
"soln_pds_adoption_basis": "Fully Customized PDS",
"soln_pds_adoption_regional_data": false,
"pds_adoption_final_percentage": [
[
"World",
0.0
],
[
"OECD90",
0.0
],
[
"Eastern Europe",
0.0
],
[
"Asia (Sans Japan)",
0.0
],
[
"Middle East and Africa",
0.0
],
[
"Latin America",
0.0
],
[
"China",
0.0
],
[
"India",
0.0
],
[
"EU",
0.0
],
[
"USA",
0.0
]
],
"soln_pds_adoption_custom_name": "Average of All Custom PDS Scenarios",
"soln_ref_adoption_basis": "Custom",
"soln_ref_adoption_custom_name": "Average of All Custom REF Scenarios",
"soln_ref_adoption_regional_data": false
}"""

0 comments on commit 325abfd

Please sign in to comment.