Sharan Thakur commited on
Commit
4eafb07
·
1 Parent(s): 31e6c7f

Initial commit

Browse files
README.md CHANGED
@@ -11,4 +11,25 @@ license: mit
11
  short_description: This project is a Carbon Footprint Calculator and Visualizer
12
  ---
13
 
14
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  short_description: This project is a Carbon Footprint Calculator and Visualizer
12
  ---
13
 
14
+ # Carbon Footprint Visualizer 🌍
15
+
16
+ ## Overview
17
+
18
+ A Python-based web application that helps organizations calculate, visualize, and analyze their carbon footprint through an intuitive Gradio interface.
19
+
20
+ ## 🚀 Features
21
+
22
+ - **Comprehensive Carbon Emission Calculation**
23
+ - Analyze emissions across multiple dimensions:
24
+ - Electricity consumption
25
+ - Gas usage
26
+ - Transportation
27
+ - Waste management
28
+ - **Interactive Visualization**
29
+ - Generate detailed pie and bar charts
30
+ - Visualize carbon impact across different categories
31
+ - **Personalized Reporting**
32
+ - Export customized PDF reports
33
+ - Downloadable carbon footprint analysis
34
+ - **Company Data Visualization**
35
+ - See all companies' emissions ranges
reports/historic_data.csv ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ Name,Energy Usage,Waste Generated,Business Travel
2
+ Company 1,1024699.9871999999,49929.88,44083.78333333334
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ plotly
2
+ "ipywidgets>=7.6"
3
+ "jupyterlab>=3"
4
+ notebook
5
+ gradio
6
+ kaleido
7
+ chart_studio
8
+ pandas
src/app.py ADDED
@@ -0,0 +1,277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+
3
+ from csv import DictWriter
4
+ import os.path as os_path
5
+
6
+ from plotly.graph_objects import Figure
7
+ import gradio as gr
8
+ from pandas import read_csv, DataFrame
9
+ import emission_calculator.calculator as ec
10
+
11
+ DATA_PATH = "./reports/historic_data.csv"
12
+
13
+
14
+ def compute_history() -> Figure:
15
+ if not os_path.exists(DATA_PATH):
16
+ f = open(DATA_PATH, "xt")
17
+ f.write("Name,Energy Usage,Waste Generated,Business Travel")
18
+ f.close()
19
+ df = DataFrame.from_dict({})
20
+ else:
21
+ df = read_csv(DATA_PATH)
22
+ return ec.draw_historic_figure(df)
23
+
24
+
25
+ def validate_input(
26
+ company_name: str,
27
+ avg_electric_bill: float,
28
+ avg_gas_bill: float,
29
+ avg_transport_cost: float,
30
+ monthly_waste_generated: float,
31
+ recycled_waste_percent: float,
32
+ annual_travel_kms: float,
33
+ fuel_efficiency: float,
34
+ ) -> None:
35
+ """
36
+ Comprehensive validation for input parameters with non-zero requirements
37
+ """
38
+ # Company Name Validation
39
+ if not company_name or company_name.isspace():
40
+ raise gr.Error("Company name cannot be empty or just whitespace!")
41
+
42
+ if len(company_name) > 100:
43
+ raise gr.Error("Company name is too long (maximum 100 characters)!")
44
+
45
+ # Non-Zero Input Validation
46
+ non_zero_fields = [
47
+ ("Electricity Bill", avg_electric_bill),
48
+ ("Gas Bill", avg_gas_bill),
49
+ ("Transport Cost", avg_transport_cost),
50
+ ("Monthly Waste", monthly_waste_generated),
51
+ ("Annual Travel Distance", annual_travel_kms),
52
+ ("Fuel Efficiency", fuel_efficiency),
53
+ ]
54
+
55
+ for name, value in non_zero_fields:
56
+ try:
57
+ float_val = float(value)
58
+ except (TypeError, ValueError):
59
+ raise gr.Error(f"{name} must be a valid number!")
60
+
61
+ if float_val <= 0:
62
+ raise gr.Error(f"{name} must be a positive number greater than zero!")
63
+
64
+ # Additional realistic range checks
65
+ if name == "Electricity Bill" and float_val > 10000:
66
+ raise gr.Error(
67
+ "Electricity bill seems unrealistically high. Please check the amount!"
68
+ )
69
+
70
+ if name == "Monthly Waste" and float_val > 1000:
71
+ raise gr.Error(
72
+ "Monthly waste generation seems extremely high. Please verify!"
73
+ )
74
+
75
+ # Percentage-specific validation
76
+ try:
77
+ recycled_percent = float(recycled_waste_percent)
78
+ except (TypeError, ValueError):
79
+ raise gr.Error("Recycled waste percentage must be a valid number!")
80
+
81
+ if recycled_percent < 0 or recycled_percent > 100:
82
+ raise gr.Error("Recycled waste percentage must be between 0 and 100!")
83
+
84
+
85
+ def compute(
86
+ company_name: str,
87
+ avg_electric_bill: float,
88
+ avg_gas_bill: float,
89
+ avg_transport_cost: float,
90
+ monthly_waste_generated: float,
91
+ recycled_waste_percent: float,
92
+ annual_travel_kms: float,
93
+ fuel_efficiency: float,
94
+ ) -> tuple[str, gr.Button]:
95
+ """
96
+ Compute carbon footprint with comprehensive input validation
97
+ Returns:
98
+ result (tuple)
99
+ of summary HTML (str)
100
+ and download_report button (Button)
101
+ """
102
+ # Validate inputs first
103
+ validate_input(
104
+ company_name,
105
+ avg_electric_bill,
106
+ avg_gas_bill,
107
+ avg_transport_cost,
108
+ monthly_waste_generated,
109
+ recycled_waste_percent,
110
+ annual_travel_kms,
111
+ fuel_efficiency,
112
+ )
113
+
114
+ # Proceed with calculation if validation passes
115
+ df = ec.make_dataframe(
116
+ company_name=company_name,
117
+ avg_electric_bill=avg_electric_bill,
118
+ avg_gas_bill=avg_gas_bill,
119
+ avg_transport_bill=avg_transport_cost,
120
+ monthly_waste_generated=monthly_waste_generated,
121
+ recycled_waste_percent=recycled_waste_percent,
122
+ annual_travel_kms=annual_travel_kms,
123
+ fuel_efficiency=fuel_efficiency,
124
+ )
125
+
126
+ try:
127
+ df_dump = ec.dataframe_to_dict(df=df)
128
+ with open(DATA_PATH, mode="a") as f:
129
+ w = DictWriter(f, fieldnames=df_dump.keys())
130
+ if not os_path.exists(DATA_PATH):
131
+ w.writeheader()
132
+ w.writerow(df_dump)
133
+ print("Saving is successful")
134
+ except Exception as e:
135
+ print(e)
136
+
137
+ plot = ec.draw_report_figure(df)
138
+
139
+ # Convert plot to base64 image
140
+ img_data = base64.b64encode(
141
+ plot.to_image(width=1400, height=800, format="png")
142
+ ).decode("utf-8")
143
+
144
+ # convert plot to pdf for downloading report
145
+ file_path = f"./reports/{company_name.lower().replace(' ', '_')[:10]}_report.pdf"
146
+ plot.write_image(file_path, width=1400, height=800)
147
+
148
+ # Generate a summary HTML with embedded image
149
+ summary = f"""
150
+ <div style="max-width: 1400px; margin: 0 auto; font-family: Arial, sans-serif;">
151
+ <h3 style="color: #ffffff;"> Carbon Footprint Summary for {company_name} </h3>
152
+ <ul style="color: #666;">
153
+ <li>🏭 <strong>Total Carbon Impact</strong>: Calculated based on your inputs</li>
154
+ <li>💡 <strong>Energy Consumption</strong>: €{avg_electric_bill + avg_gas_bill:.2f}</li>
155
+ <li>🚗 <strong>Transportation Emissions</strong>: {annual_travel_kms} km</li>
156
+ <li>🗑️ <strong>Waste Management</strong>: {monthly_waste_generated} kg (Recycled: {recycled_waste_percent}%)</li>
157
+ </ul>
158
+ <img src="data:image/png;base64,{img_data}" style="max-width: 100%; height: auto;" alt="Carbon Footprint Report"/>
159
+ </div>
160
+ """
161
+ download_button = gr.DownloadButton(
162
+ "Download Report", variant="secondary", visible=True, value=file_path
163
+ )
164
+ return summary, download_button
165
+
166
+
167
+ def create_carbon_footprint_app() -> gr.Blocks:
168
+ with gr.Blocks(theme="soft") as demo:
169
+ with gr.Tab("Calculator 📱"):
170
+ gr.Markdown("# 🌍 Carbon Footprint Calculator")
171
+
172
+ # Hidden image download button
173
+ download_button = gr.File(
174
+ label="Download Carbon Footprint Report", type="binary", visible=False
175
+ )
176
+
177
+ with gr.Column():
178
+ with gr.Column(scale=2):
179
+ with gr.Column(variant="compact"):
180
+ company_name = gr.Textbox(
181
+ label="Company Name",
182
+ placeholder="Enter your company name",
183
+ info="Required: Full legal company name",
184
+ )
185
+ with gr.Row():
186
+ with gr.Column(variant="compact"):
187
+ avg_electric_bill = gr.Number(
188
+ value=1.0,
189
+ label="Average Electricity Bill (€)",
190
+ minimum=0.01,
191
+ info="Monthly electricity expenses",
192
+ )
193
+ avg_gas_bill = gr.Number(
194
+ value=1.0,
195
+ label="Average Gas Bill (€)",
196
+ minimum=0.01,
197
+ info="Monthly natural gas expenses",
198
+ )
199
+ avg_transport_cost = gr.Number(
200
+ value=1.0,
201
+ label="Average Transport Cost (€)",
202
+ info="Monthly Fuel bill for transport",
203
+ )
204
+
205
+ with gr.Column(variant="compact"):
206
+ annual_travel_kms = gr.Number(
207
+ value=1.0,
208
+ label="Annual Business Travel (km)",
209
+ minimum=0.01,
210
+ info="Total kilometers traveled by employees",
211
+ )
212
+ fuel_efficiency = gr.Number(
213
+ value=1.0,
214
+ label="Vehicle Fuel Efficiency (L/100 km)",
215
+ minimum=0.01,
216
+ info="Average fleet fuel consumption",
217
+ )
218
+
219
+ with gr.Column(variant="compact"):
220
+ monthly_waste_generated = gr.Number(
221
+ value=1.0,
222
+ label="Monthly Waste Generated (kg)",
223
+ minimum=0.01,
224
+ info="Total waste produced monthly",
225
+ )
226
+ recycled_waste_percent = gr.Number(
227
+ value=0.0,
228
+ label="Recycled Waste (%)",
229
+ minimum=0.0,
230
+ maximum=100.0,
231
+ info="Percentage of waste recycled",
232
+ )
233
+
234
+ with gr.Column(scale=1):
235
+ output_plot = gr.HTML(label="Carbon Footprint Report")
236
+ # Create a row for buttons
237
+ with gr.Row():
238
+ submit_button = gr.Button("Generate Report", variant="primary")
239
+ download_button = gr.DownloadButton(
240
+ "Download Report", variant="secondary", visible=False
241
+ )
242
+
243
+ submit_button.click(
244
+ fn=compute,
245
+ inputs=[
246
+ company_name,
247
+ avg_electric_bill,
248
+ avg_gas_bill,
249
+ avg_transport_cost,
250
+ monthly_waste_generated,
251
+ recycled_waste_percent,
252
+ annual_travel_kms,
253
+ fuel_efficiency,
254
+ ],
255
+ outputs=[output_plot, download_button],
256
+ )
257
+
258
+ with gr.Tab("History 📊") as historic_tab:
259
+ gr.Markdown("# Historic Company Data")
260
+
261
+ plot = gr.Plot(value=compute_history(), label="Historic Data")
262
+ refresh = gr.Button("Refresh", variant="secondary")
263
+ refresh.click(
264
+ fn=compute_history,
265
+ outputs=[plot],
266
+ )
267
+ # auto-reload
268
+ historic_tab.select(
269
+ fn=compute_history,
270
+ outputs=[plot],
271
+ )
272
+
273
+ return demo
274
+
275
+
276
+ if __name__ == "__main__":
277
+ create_carbon_footprint_app().launch()
src/emission_calculator/calculator.py ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pandas import DataFrame
2
+
3
+ from plotly.subplots import make_subplots
4
+ from plotly.graph_objects import Figure, Pie, Bar, Scatter
5
+
6
+
7
+ def draw_report_figure(df: DataFrame) -> Figure:
8
+ figure_specs = [
9
+ [{"type": "xy"}, {"type": "xy"}],
10
+ [{"type": "domain"}, None],
11
+ ]
12
+
13
+ fig = make_subplots(
14
+ rows=2,
15
+ cols=2,
16
+ specs=figure_specs,
17
+ subplot_titles=(
18
+ "Carbon Emission by Category",
19
+ "Cumulative Emission %",
20
+ "Emission Distribution",
21
+ ),
22
+ )
23
+
24
+ # Pie chart settings
25
+ pie_pull = [0.15 if x == min(df["Value"]) else 0.0 for x in df["Value"]]
26
+ fig.add_trace(
27
+ Pie(
28
+ values=df["Value"],
29
+ labels=df["Category"],
30
+ hole=0.3,
31
+ pull=pie_pull,
32
+ name="Emission Distribution",
33
+ marker={"colors": ["#6DA34D", "#81C3D7", "#FFC857"]},
34
+ ),
35
+ row=2,
36
+ col=1,
37
+ )
38
+
39
+ # Bar chart for emissions by category
40
+ fig.add_trace(
41
+ Bar(
42
+ x=df["Category"],
43
+ y=df["Value"],
44
+ name="Carbon Emission (kgCO2)",
45
+ marker_color=["#6DA34D", "#81C3D7", "#FFC857"],
46
+ ),
47
+ row=1,
48
+ col=1,
49
+ )
50
+
51
+ # Annotation for highest emission
52
+ fig.add_annotation(
53
+ x=df["Category"][df["Value"].idxmax()],
54
+ y=df["Value"].max(),
55
+ text="Highest Emission",
56
+ showarrow=True,
57
+ arrowhead=1,
58
+ ax=0,
59
+ ay=-40,
60
+ row=1,
61
+ col=1,
62
+ )
63
+
64
+ # Cumulative line chart
65
+ cumulative_percentage = (df["Value"].cumsum() / df["Value"].sum()) * 100
66
+ fig.add_trace(
67
+ Scatter(
68
+ x=df["Category"],
69
+ y=cumulative_percentage,
70
+ name="Cumulative %",
71
+ mode="lines+markers",
72
+ line=dict(color="#333333", dash="dash"),
73
+ ),
74
+ row=1,
75
+ col=2,
76
+ )
77
+
78
+ # Update layout for axes and overall layout
79
+ fig.update_layout(
80
+ title_text=f"Carbon Footprint of {df['Name'][0]}",
81
+ plot_bgcolor="white",
82
+ legend_title_text="Breakdown",
83
+ xaxis_title="Emission Category",
84
+ yaxis_title="Carbon Emission (kgCO2)",
85
+ yaxis=dict(
86
+ linecolor="black",
87
+ showline=True,
88
+ ticks="outside",
89
+ mirror=True,
90
+ gridcolor="lightgrey",
91
+ ),
92
+ yaxis2=dict(
93
+ title="Cumulative Percentage",
94
+ side="right",
95
+ showgrid=False,
96
+ ),
97
+ legend=dict(
98
+ x=1, # Horizontal position (1 for right)
99
+ y=0, # Vertical position (0 for bottom)
100
+ xanchor="right",
101
+ yanchor="bottom",
102
+ orientation="h", # Horizontal layout for compactness
103
+ ),
104
+ )
105
+
106
+ fig.update_xaxes(
107
+ linecolor="black",
108
+ ticks="outside",
109
+ showline=True,
110
+ mirror=True,
111
+ )
112
+ fig.update_yaxes(
113
+ linecolor="black",
114
+ showline=True,
115
+ ticks="outside",
116
+ mirror=True,
117
+ gridcolor="lightgrey",
118
+ )
119
+
120
+ return fig
121
+
122
+
123
+ def draw_historic_figure(df: DataFrame) -> Figure:
124
+ # Create subplots with 2 rows and 2 columns
125
+ fig = make_subplots(
126
+ rows=2,
127
+ cols=2,
128
+ subplot_titles=(
129
+ "Energy Usage by Company",
130
+ "Waste Generated by Company",
131
+ "Business Travel by Company",
132
+ "Total Carbon Footprint by Company",
133
+ ),
134
+ )
135
+
136
+ # Add gradient-filled area traces for each metric
137
+ fig.add_trace(
138
+ Scatter(
139
+ x=df["Name"],
140
+ y=df["Energy Usage"],
141
+ mode="lines",
142
+ fill="tozeroy",
143
+ line=dict(color="blue"),
144
+ fillcolor="rgba(31, 119, 180, 0.5)", # Gradient fill for blue
145
+ name="Energy Usage",
146
+ ),
147
+ row=1,
148
+ col=1,
149
+ )
150
+
151
+ fig.add_trace(
152
+ Scatter(
153
+ x=df["Name"],
154
+ y=df["Waste Generated"],
155
+ mode="lines",
156
+ fill="tozeroy",
157
+ line=dict(color="orange"),
158
+ fillcolor="rgba(255, 127, 14, 0.5)", # Gradient fill for orange
159
+ name="Waste Generated",
160
+ ),
161
+ row=1,
162
+ col=2,
163
+ )
164
+
165
+ fig.add_trace(
166
+ Scatter(
167
+ x=df["Name"],
168
+ y=df["Business Travel"],
169
+ mode="lines",
170
+ fill="tozeroy",
171
+ line=dict(color="green"),
172
+ fillcolor="rgba(44, 160, 44, 0.5)", # Gradient fill for green
173
+ name="Business Travel",
174
+ ),
175
+ row=2,
176
+ col=1,
177
+ )
178
+
179
+ # Calculate each company's total carbon footprint as the sum of the three metrics
180
+ df["Carbon Footprint"] = (
181
+ df["Energy Usage"] + df["Waste Generated"] + df["Business Travel"]
182
+ )
183
+
184
+ # Add a line trace for the total sum of each metric
185
+ fig.add_trace(
186
+ Scatter(
187
+ x=df["Name"],
188
+ y=df["Carbon Footprint"],
189
+ mode="lines+markers",
190
+ line=dict(color="black", dash="dash"),
191
+ name="Total Carbon Footprint",
192
+ ),
193
+ row=2,
194
+ col=2,
195
+ )
196
+
197
+ # Update layout for titles, legends, and aesthetics
198
+ fig.update_layout(
199
+ title="Company Metrics with Total Carbon Footprint",
200
+ barmode="group", # Group bars by category
201
+ template="plotly_white",
202
+ showlegend=True,
203
+ height=600,
204
+ width=1000,
205
+ legend=dict(x=1.05, y=1), # Adjust legend position outside plot for clarity
206
+ )
207
+
208
+ # Add axis labels to each subplot
209
+ fig.update_xaxes(title_text="Company", row=1, col=1)
210
+ fig.update_yaxes(title_text="Energy Usage", row=1, col=1)
211
+
212
+ fig.update_xaxes(title_text="Company", row=1, col=2)
213
+ fig.update_yaxes(title_text="Waste Generated", row=1, col=2)
214
+
215
+ fig.update_xaxes(title_text="Company", row=2, col=1)
216
+ fig.update_yaxes(title_text="Business Travel", row=2, col=1)
217
+
218
+ fig.update_xaxes(title_text="Company", row=2, col=2)
219
+ fig.update_yaxes(title_text="Carbon Footprint (total)", row=2, col=2)
220
+
221
+ return fig
222
+
223
+
224
+ def make_dataframe(
225
+ company_name: str,
226
+ avg_electric_bill: float,
227
+ avg_gas_bill: float,
228
+ avg_transport_bill: float,
229
+ monthly_waste_generated: float,
230
+ recycled_waste_percent: float,
231
+ annual_travel_kms: float,
232
+ fuel_efficiency: float,
233
+ ) -> DataFrame:
234
+ energy_usage = (
235
+ (avg_electric_bill * 12 * 5e-4)
236
+ + (avg_gas_bill * 12 * 5.3e-3)
237
+ + (avg_transport_bill * 12 * 2.32)
238
+ )
239
+ waste_generated = monthly_waste_generated * 12 * 0.57 - recycled_waste_percent
240
+ business_travel = annual_travel_kms * 1 / fuel_efficiency * 2.31
241
+
242
+ return DataFrame(
243
+ {
244
+ "Name": company_name,
245
+ "Category": ["Energy Usage", "Waste Generated", "Business Travel"],
246
+ "Value": [energy_usage, waste_generated, business_travel],
247
+ }
248
+ )
249
+
250
+
251
+ def dataframe_to_dict(df: DataFrame) -> dict:
252
+ return {
253
+ "Name": df["Name"][0],
254
+ "Energy Usage": df["Value"][0],
255
+ "Waste Generated": df["Value"][1],
256
+ "Business Travel": df["Value"][2],
257
+ }
src/rep ADDED
File without changes