Commit
·
ee733e1
1
Parent(s):
d19b092
updated
Browse files- app-versions/v6.py +284 -0
- calculator-app/app.py +7 -4
app-versions/v6.py
ADDED
@@ -0,0 +1,284 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import pandas as pd
|
3 |
+
import plotly.express as px
|
4 |
+
import requests # Import the requests library
|
5 |
+
|
6 |
+
|
7 |
+
# Path to the data file relative to the app.py file
|
8 |
+
DATA_PATH = "https://huggingface.co/spaces/danielrosehill/Monetised-GHG-Emissions-Calculator/raw/main/calculator-app/data.csv"
|
9 |
+
INSTRUCTIONS_PATH = "https://huggingface.co/spaces/danielrosehill/Monetised-GHG-Emissions-Calculator/raw/main/calculator-app/instructions.md"
|
10 |
+
|
11 |
+
GITHUB_LINK = "https://github.com/danielrosehill/Emissions-Monetisation-Calculator"
|
12 |
+
|
13 |
+
|
14 |
+
def load_data():
|
15 |
+
try:
|
16 |
+
df = pd.read_csv(DATA_PATH)
|
17 |
+
return df
|
18 |
+
except FileNotFoundError:
|
19 |
+
st.error(
|
20 |
+
f"Error: Could not find the data file at {DATA_PATH}. Please ensure the file exists."
|
21 |
+
)
|
22 |
+
return None
|
23 |
+
|
24 |
+
|
25 |
+
def load_instructions():
|
26 |
+
try:
|
27 |
+
response = requests.get(INSTRUCTIONS_PATH) # Fetch the content of the URL
|
28 |
+
response.raise_for_status() # Raise an error for bad status codes
|
29 |
+
return response.text # return the text of the response
|
30 |
+
except requests.exceptions.RequestException as e:
|
31 |
+
return f"Error: Could not fetch instructions file: {e}"
|
32 |
+
|
33 |
+
|
34 |
+
def format_currency(value, display_unit):
|
35 |
+
if display_unit == "Millions":
|
36 |
+
formatted_value = f"${value / 1_000_000:.2f} MN"
|
37 |
+
elif display_unit == "Billions":
|
38 |
+
formatted_value = f"${value / 1_000_000_000:.2f} BN"
|
39 |
+
return formatted_value
|
40 |
+
|
41 |
+
|
42 |
+
def main():
|
43 |
+
st.set_page_config(layout="wide")
|
44 |
+
st.markdown("""
|
45 |
+
<style>
|
46 |
+
[data-testid="stHorizontalBlock"] {
|
47 |
+
border: 1px solid #e6e6e6;
|
48 |
+
border-radius: 5px;
|
49 |
+
padding: 1em;
|
50 |
+
margin-bottom: 1em;
|
51 |
+
}
|
52 |
+
</style>
|
53 |
+
""", unsafe_allow_html=True)
|
54 |
+
|
55 |
+
st.title("GHG Emissions Monetization Calculator")
|
56 |
+
st.markdown(
|
57 |
+
"This tool explores the potential financial implications of proposed greenhouse gas emissions costs. It accompanies a repository on Github and Hugging Face that aggregates proposals for the social cost of carbon."
|
58 |
+
)
|
59 |
+
st.markdown(
|
60 |
+
"The social cost of carbon represents the economic damages associated with emitting one additional ton of carbon dioxide into the atmosphere."
|
61 |
+
)
|
62 |
+
st.markdown(
|
63 |
+
"Detailed notes and instructions about the use of this calculator can be found in the Instructions tab."
|
64 |
+
)
|
65 |
+
st.markdown(
|
66 |
+
"This calculator was developed by Daniel Rosehill in December 2024 (danielrosehill.com)."
|
67 |
+
)
|
68 |
+
|
69 |
+
|
70 |
+
# Load the data and instructions
|
71 |
+
df = load_data()
|
72 |
+
instructions = load_instructions()
|
73 |
+
if df is None:
|
74 |
+
return # Don't proceed if data can't be loaded
|
75 |
+
|
76 |
+
# Tabs for calculator, instructions and SCC proposals
|
77 |
+
tabs = st.tabs(["Calculator", "Instructions", "SCC Chart", "SCC Details", "Data"])
|
78 |
+
|
79 |
+
with tabs[0]: # Calculator tab
|
80 |
+
with st.container():
|
81 |
+
st.markdown("### Input your emissions and proposal of interest")
|
82 |
+
left, right = st.columns(2)
|
83 |
+
|
84 |
+
with left:
|
85 |
+
st.subheader("Input Values")
|
86 |
+
st.markdown("Enter your company's greenhouse gas emissions:")
|
87 |
+
scope1_emissions = st.number_input("Scope 1 Emissions", value=0.0)
|
88 |
+
st.markdown("*(Direct emissions from owned or controlled sources)*")
|
89 |
+
scope2_emissions = st.number_input("Scope 2 Emissions", value=0.0)
|
90 |
+
st.markdown("*(Indirect emissions from the generation of purchased energy)*")
|
91 |
+
scope3_emissions = st.number_input("Scope 3 Emissions", value=0.0)
|
92 |
+
st.markdown("*(All other indirect emissions that occur in a company's value chain)*")
|
93 |
+
unit_of_reporting = st.selectbox("Unit of Reporting", ["TCO2E", "MTCO2E"])
|
94 |
+
proposal_names = df['proposal_with_date'].tolist()
|
95 |
+
selected_proposal = st.selectbox("Social cost of carbon proposal", proposal_names)
|
96 |
+
calculate_button = st.button("Calculate Monetized Emissions")
|
97 |
+
|
98 |
+
with right:
|
99 |
+
st.subheader("Calculated Values")
|
100 |
+
if calculate_button:
|
101 |
+
# Calculated emissions
|
102 |
+
scope1_2_emissions = scope1_emissions + scope2_emissions
|
103 |
+
all_scopes_emissions = (
|
104 |
+
scope1_emissions + scope2_emissions + scope3_emissions
|
105 |
+
)
|
106 |
+
st.markdown(
|
107 |
+
f"Scope 1 and 2 Emissions: {scope1_2_emissions:.2f} {unit_of_reporting}"
|
108 |
+
)
|
109 |
+
st.markdown(
|
110 |
+
f"All Scopes Emissions: {all_scopes_emissions:.2f} {unit_of_reporting}"
|
111 |
+
)
|
112 |
+
|
113 |
+
# Find the value in USD per ton
|
114 |
+
selected_row = df[df['proposal_with_date'] == selected_proposal].iloc[0]
|
115 |
+
multiplier = selected_row['usd_proposed_value']
|
116 |
+
|
117 |
+
st.subheader("Monetized Emissions")
|
118 |
+
display_unit = st.radio("Display units", ["Millions", "Billions"])
|
119 |
+
|
120 |
+
if unit_of_reporting == "MTCO2E":
|
121 |
+
scope1_emissions = scope1_emissions * 1_000_000
|
122 |
+
scope2_emissions = scope2_emissions * 1_000_000
|
123 |
+
scope3_emissions = scope3_emissions * 1_000_000
|
124 |
+
all_scopes_emissions = all_scopes_emissions * 1_000_000
|
125 |
+
|
126 |
+
# Monetization calculations
|
127 |
+
monetized_scope1 = scope1_emissions * multiplier
|
128 |
+
monetized_scope2 = scope2_emissions * multiplier
|
129 |
+
monetized_scope3 = scope3_emissions * multiplier
|
130 |
+
monetized_all_scopes = all_scopes_emissions * multiplier
|
131 |
+
|
132 |
+
st.markdown(f"Scope 1: {format_currency(monetized_scope1, display_unit)}")
|
133 |
+
st.markdown(f"Scope 2: {format_currency(monetized_scope2, display_unit)}")
|
134 |
+
st.markdown(f"Scope 3: {format_currency(monetized_scope3, display_unit)}")
|
135 |
+
st.markdown(
|
136 |
+
f"All Scopes: {format_currency(monetized_all_scopes, display_unit)}"
|
137 |
+
)
|
138 |
+
|
139 |
+
with tabs[1]: # Instructions tab
|
140 |
+
st.markdown(instructions)
|
141 |
+
|
142 |
+
with tabs[2]: # SCC Chart tab
|
143 |
+
st.subheader("Social Cost of Carbon Proposals")
|
144 |
+
|
145 |
+
# Convert the 'date' column to datetime objects for proper sorting
|
146 |
+
df['date'] = pd.to_datetime(df['date'])
|
147 |
+
# Sort by value
|
148 |
+
df_sorted = df.sort_values(by='usd_proposed_value', ascending=True)
|
149 |
+
|
150 |
+
# Create horizontal bar chart
|
151 |
+
bar_fig = px.bar(
|
152 |
+
df_sorted,
|
153 |
+
x="usd_proposed_value",
|
154 |
+
y="proposal_with_date",
|
155 |
+
title="Social Cost of Carbon Proposals",
|
156 |
+
labels={
|
157 |
+
"usd_proposed_value": "USD Proposed Value",
|
158 |
+
"proposal_with_date": "Proposal",
|
159 |
+
},
|
160 |
+
orientation='h', # Set orientation to horizontal
|
161 |
+
hover_data={
|
162 |
+
"usd_proposed_value": True,
|
163 |
+
}
|
164 |
+
)
|
165 |
+
bar_fig.update_traces(texttemplate='%{x:.2f}', textposition='outside')
|
166 |
+
st.plotly_chart(bar_fig)
|
167 |
+
|
168 |
+
# Organization filter
|
169 |
+
organizations = df['organization_name'].unique().tolist()
|
170 |
+
selected_org = st.selectbox("Filter by organization", ["All"] + organizations)
|
171 |
+
|
172 |
+
# Filter data
|
173 |
+
if selected_org != "All":
|
174 |
+
filtered_df = df[df['organization_name'] == selected_org]
|
175 |
+
else:
|
176 |
+
filtered_df = df
|
177 |
+
|
178 |
+
# Sort the data by date before creating the line chart
|
179 |
+
filtered_df = filtered_df.sort_values(by='date')
|
180 |
+
|
181 |
+
# Create line chart with data points and custom hover text
|
182 |
+
show_points = st.checkbox("Display Data Points", value=True)
|
183 |
+
line_fig = px.line(
|
184 |
+
filtered_df,
|
185 |
+
x="date",
|
186 |
+
y="usd_proposed_value",
|
187 |
+
title="Trend of Social Cost of Carbon Proposals Over Time",
|
188 |
+
labels={
|
189 |
+
"usd_proposed_value": "USD Proposed Value",
|
190 |
+
"date": "Date",
|
191 |
+
},
|
192 |
+
hover_data={
|
193 |
+
"usd_proposed_value": True,
|
194 |
+
"proposal_with_date": True,
|
195 |
+
"organization_name": True,
|
196 |
+
},
|
197 |
+
)
|
198 |
+
|
199 |
+
line_fig.update_traces(
|
200 |
+
mode="lines+markers" if show_points else "lines",
|
201 |
+
hovertemplate="USD Value: %{y:.2f}<br>Proposal: %{customdata[0]}<br>Organization: %{customdata[1]}",
|
202 |
+
text=filtered_df["proposal_with_date"],
|
203 |
+
marker=dict(size=6),
|
204 |
+
customdata=filtered_df[["proposal_with_date","organization_name"]]
|
205 |
+
)
|
206 |
+
|
207 |
+
st.plotly_chart(line_fig)
|
208 |
+
|
209 |
+
|
210 |
+
with tabs[3]: # SCC Details tab
|
211 |
+
st.subheader("Social Cost of Carbon Proposal Details")
|
212 |
+
proposal_names = df["proposal_with_date"].tolist()
|
213 |
+
selected_proposal = st.selectbox("Select a proposal", proposal_names)
|
214 |
+
|
215 |
+
if selected_proposal:
|
216 |
+
selected_row = df[df["proposal_with_date"] == selected_proposal].iloc[0]
|
217 |
+
|
218 |
+
# Prepare data for the table
|
219 |
+
col1, col2 = st.columns(2)
|
220 |
+
with col1:
|
221 |
+
st.markdown(" **Organization Name:**")
|
222 |
+
st.markdown(" **Organization Description:**")
|
223 |
+
st.markdown(" **Date:**")
|
224 |
+
st.markdown(" **Country:**")
|
225 |
+
st.markdown(" **ISO3:**")
|
226 |
+
st.markdown(" **ISO2:**")
|
227 |
+
st.markdown(" **HDI Value:**")
|
228 |
+
st.markdown(" **HDI Category:**")
|
229 |
+
st.markdown(" **Details:**")
|
230 |
+
with col2:
|
231 |
+
st.markdown(selected_row["organization_name"])
|
232 |
+
st.markdown(selected_row["organization_description"])
|
233 |
+
st.markdown(selected_row["date"].strftime('%Y-%m-%d'))
|
234 |
+
st.markdown(selected_row["country"])
|
235 |
+
st.markdown(selected_row["iso3"])
|
236 |
+
st.markdown(selected_row["iso2"])
|
237 |
+
st.markdown(str(selected_row["hdi_value"]))
|
238 |
+
st.markdown(selected_row["hdi_category"])
|
239 |
+
st.markdown(selected_row["details"])
|
240 |
+
|
241 |
+
col3, col4 = st.columns(2)
|
242 |
+
with col3:
|
243 |
+
st.markdown(" **Original Proposed Value:**")
|
244 |
+
st.markdown(" **Average Value:**")
|
245 |
+
st.markdown(" **USD Proposed Value:**")
|
246 |
+
st.markdown(" **USD Proposed Value (Empty CO2e):**")
|
247 |
+
st.markdown(" **USD Conversion Date:**")
|
248 |
+
st.markdown(" **Value Units:**")
|
249 |
+
st.markdown(" **Environmental Units:**")
|
250 |
+
st.markdown(" **Methodologies Used:**")
|
251 |
+
st.markdown(" **Calculation Scope:**")
|
252 |
+
st.markdown(" **Is Range:**")
|
253 |
+
with col4:
|
254 |
+
st.markdown(f"{selected_row['original_proposed_value']} {selected_row['original_currency_name']}")
|
255 |
+
st.markdown(str(selected_row["average_value"]))
|
256 |
+
st.markdown(str(selected_row["usd_proposed_value"]))
|
257 |
+
st.markdown(str(selected_row['use_proposed_value_mtco2e']))
|
258 |
+
st.markdown(str(selected_row["usd_conversion_date"]))
|
259 |
+
st.markdown(selected_row["value_units"])
|
260 |
+
st.markdown(selected_row["environmental_units"])
|
261 |
+
st.markdown(selected_row["methodologies_used"])
|
262 |
+
st.markdown(selected_row["calculation_scope"])
|
263 |
+
st.markdown(str(selected_row["is_range"]))
|
264 |
+
|
265 |
+
with tabs[4]: # Data Tab
|
266 |
+
st.subheader("Data")
|
267 |
+
st.dataframe(df)
|
268 |
+
st.markdown("#### Download Data")
|
269 |
+
|
270 |
+
def convert_df(df):
|
271 |
+
return df.to_csv().encode('utf-8')
|
272 |
+
|
273 |
+
csv = convert_df(df)
|
274 |
+
st.download_button(
|
275 |
+
label="Download data as CSV",
|
276 |
+
data=csv,
|
277 |
+
file_name='scc_data.csv',
|
278 |
+
mime='text/csv',
|
279 |
+
)
|
280 |
+
|
281 |
+
st.markdown(f'<a href="{GITHUB_LINK}"><img src="https://img.shields.io/badge/View%20on%20GitHub-blue?logo=github"></a>', unsafe_allow_html=True)
|
282 |
+
|
283 |
+
if __name__ == "__main__":
|
284 |
+
main()
|
calculator-app/app.py
CHANGED
@@ -1,6 +1,8 @@
|
|
1 |
import streamlit as st
|
2 |
import pandas as pd
|
3 |
import plotly.express as px
|
|
|
|
|
4 |
|
5 |
# Path to the data file relative to the app.py file
|
6 |
DATA_PATH = "https://huggingface.co/spaces/danielrosehill/Monetised-GHG-Emissions-Calculator/raw/main/calculator-app/data.csv"
|
@@ -22,10 +24,11 @@ def load_data():
|
|
22 |
|
23 |
def load_instructions():
|
24 |
try:
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
|
|
29 |
|
30 |
|
31 |
def format_currency(value, display_unit):
|
|
|
1 |
import streamlit as st
|
2 |
import pandas as pd
|
3 |
import plotly.express as px
|
4 |
+
import requests # Import the requests library
|
5 |
+
|
6 |
|
7 |
# Path to the data file relative to the app.py file
|
8 |
DATA_PATH = "https://huggingface.co/spaces/danielrosehill/Monetised-GHG-Emissions-Calculator/raw/main/calculator-app/data.csv"
|
|
|
24 |
|
25 |
def load_instructions():
|
26 |
try:
|
27 |
+
response = requests.get(INSTRUCTIONS_PATH) # Fetch the content of the URL
|
28 |
+
response.raise_for_status() # Raise an error for bad status codes
|
29 |
+
return response.text # return the text of the response
|
30 |
+
except requests.exceptions.RequestException as e:
|
31 |
+
return f"Error: Could not fetch instructions file: {e}"
|
32 |
|
33 |
|
34 |
def format_currency(value, display_unit):
|