JSON Workflow¶
OpenPyTEA supports a fully declarative, JSON-based workflow that makes studies
reproducible, shareable, and easy to version-control.
The openpytea.io module handles loading configuration files and
exporting results.
Three high-level functions drive the workflow:
run_equipment()— reads an equipment configuration file and returns a list ofEquipmentobjects with all costs estimated, writing the results to an output JSON file.run_plant()— reads a plant configuration file, combines it with the equipment list, runs all calculations, and writes the plant results to an output JSON file.run_tea()— executes the full TEA pipeline (cost breakdowns, sensitivity analysis, Monte Carlo simulation) from three input files, writing results and optional plots to an output directory.
To see all examples below in action, refer to the walkthrough notebook and the case study JSON notebook.
from openpytea import run_equipment, run_plant, run_tea, load_results
File structure¶
A complete TEA study uses three JSON input files:
project/
├── equipment.json # List of equipment items
├── plant.json # Plant configuration and financial assumptions
└── analysis.json # Analysis settings and output options
equipment.json¶
Each entry requires name, process_type, category, and either
param (size/capacity parameter) or purchased_cost (manual override).
All other fields are optional.
{
"equipment": [
{
"name": "COMP-1",
"param": 945,
"process_type": "Fluids",
"category": "Compressors, fans, & blowers",
"type": "Compressor, centrifugal",
"material": "Carbon steel"
},
{
"name": "HX-1",
"param": 31.87,
"process_type": "Fluids",
"category": "Heat Exchangers",
"type": "U-tube shell & tube",
"material": "Carbon steel"
}
]
}
plant.json¶
The plant object mirrors the configuration dict accepted by
Plant. Monte Carlo uncertainty fields (std,
min, max) can be embedded directly in variable_opex_inputs,
plant_products, and operator_hourly_rate — they are ignored when
running plant-only calculations and activated automatically when
run_tea() executes a Monte Carlo block.
{
"plant": {
"plant_name": "Steam Reforming",
"process_type": "Fluids",
"country": "United States",
"region": "Gulf Coast",
"interest_rate": 0.09,
"project_lifetime": 30,
"plant_utilization": 0.95,
"operator_hourly_rate": {
"rate": 38.11,
"std": 10,
"min": 25,
"max": 50
},
"plant_products": {
"hydrogen": {
"production": 50000,
"price": 5.5
}
},
"variable_opex_inputs": {
"electricity": {
"consumption": 38293.44,
"price": 0.05,
"std": 0.03,
"min": 0.01,
"max": 3
},
"methane_feed": {
"consumption": 219936,
"price": 0.4,
"std": 0.25,
"min": 0,
"max": 5
}
}
}
}
analysis.json¶
The analysis block contains one sub-object per analysis type. Each must
have "run": true to be executed, plus an "args" dict that is passed
directly to the corresponding Python function. The output block controls
whether results and plots are saved, and in what format.
{
"analysis": {
"direct_costs": { "run": true, "args": { "pct": false } },
"fixed_capital": { "run": true, "args": { "additional_capex": false, "pct": false } },
"fixed_opex": { "run": true, "args": { "pct": true } },
"variable_opex": { "run": true, "args": { "pct": false } },
"sensitivity": {
"run": true,
"cases": [
{
"name": "methane_feed_lcop",
"args": { "parameter": "methane_feed", "plus_minus_value": 1.0, "metric": "LCOP" }
},
{
"name": "electricity_npv",
"args": { "parameter": "electricity", "plus_minus_value": 0.5, "metric": "NPV" }
}
]
},
"tornado": {
"run": true,
"args": { "plus_minus_value": 0.5, "metric": "NPV" }
},
"monte_carlo": {
"run": true,
"args": { "num_samples": 1000000, "batch_size": 10000 },
"metric": ["LCOP", "NPV"]
}
},
"output": {
"save_json": true,
"save_plots": true,
"plot_format": "pdf",
"dpi": 600
}
}
The "metric" list under monte_carlo controls which metrics are
rendered as histogram plots when save_plots is true. The args
dict maps directly to monte_carlo() keyword
arguments.
Running a study¶
Equipment I/O¶
run_equipment() reads the equipment file, builds the
Equipment objects, and writes a results JSON:
equipment_list = run_equipment(
input_path="project/equipment.json",
output_path="outputs/equipment_results.json",
)
print(equipment_list[0]) # inspect a single Equipment object
Plant I/O¶
run_plant() loads the plant configuration, attaches the
equipment, runs all calculations, and writes a plant results JSON:
plant = run_plant(
plant_input_path="project/plant.json",
plant_output_path="outputs/plant_results.json",
equipment_input_path="project/equipment.json",
)
If you already have an equipment_list from a previous run_equipment
call, pass it directly instead:
plant = run_plant(
plant_input_path="project/plant.json",
plant_output_path="outputs/plant_results.json",
equipment_list=equipment_list,
)
Full TEA pipeline¶
run_tea() orchestrates the complete workflow from the
three input files and writes all results and plots to output_dir:
results = run_tea(
equipment_input_path="project/equipment.json",
plant_input_path="project/plant.json",
analysis_input_path="project/analysis.json",
output_dir="outputs/tea_results",
)
The function returns a dict with keys for each analysis that was run:
results["direct_costs"] # equipment-level cost breakdown
results["fixed_capital"] # CAPEX breakdown
results["fixed_opex"] # fixed OPEX breakdown
results["variable_opex"] # variable OPEX breakdown
results["sensitivity"] # dict of sensitivity cases
results["tornado"] # tornado data
results["monte_carlo"] # Monte Carlo results
Loading saved results¶
Use load_results() to reload a previously saved analysis
results file for further analysis or visualization. The output file is named
{plant_name}_analysis_results.json inside output_dir:
results = load_results(
filepath="outputs/tea_results/Steam Reforming_analysis_results.json"
)
mc = results["monte_carlo"]
from openpytea.plotting import plot_monte_carlo
plot_monte_carlo(mc, metric="LCOP", bins=30)
Comparing multiple scenarios¶
Run run_tea() for each scenario and reload the Monte Carlo results to
compare them on the same figure:
run_tea(
equipment_input_path="project/smr_equipment.json",
plant_input_path="project/smr_plant.json",
analysis_input_path="project/analysis.json",
output_dir="outputs/smr_results",
)
run_tea(
equipment_input_path="project/aec_equipment.json",
plant_input_path="project/aec_plant.json",
analysis_input_path="project/analysis.json",
output_dir="outputs/aec_results",
)
smr_mc = load_results("outputs/smr_results/Steam Reforming_analysis_results.json")["monte_carlo"]
aec_mc = load_results("outputs/aec_results/Electrolysis_analysis_results.json")["monte_carlo"]
from openpytea.plotting import plot_multiple_monte_carlo
plot_multiple_monte_carlo(data_list=[smr_mc, aec_mc], metric="LCOP", bins=30)
See also¶
openpytea.io— full API referenceAnalysis — analysis functions used inside
run_tea()Plotting — visualization functions for loaded results
Walkthrough notebook — end-to-end worked example