from pandas import DataFrame from plotly.subplots import make_subplots from plotly.graph_objects import Figure, Pie, Bar, Scatter def draw_report_figure(df: DataFrame) -> Figure: figure_specs = [ [{"type": "xy"}, {"type": "xy"}], [{"type": "domain"}, None], ] fig = make_subplots( rows=2, cols=2, specs=figure_specs, subplot_titles=( "Carbon Emission by Category", "Cumulative Emission %", "Emission Distribution", ), ) # Pie chart settings pie_pull = [0.15 if x == min(df["Value"]) else 0.0 for x in df["Value"]] fig.add_trace( Pie( values=df["Value"], labels=df["Category"], hole=0.3, pull=pie_pull, name="Emission Distribution", marker={"colors": ["#6DA34D", "#81C3D7", "#FFC857"]}, ), row=2, col=1, ) # Bar chart for emissions by category fig.add_trace( Bar( x=df["Category"], y=df["Value"], name="Carbon Emission (kgCO2)", marker_color=["#6DA34D", "#81C3D7", "#FFC857"], ), row=1, col=1, ) # Annotation for highest emission fig.add_annotation( x=df["Category"][df["Value"].idxmax()], y=df["Value"].max(), text="Highest Emission", showarrow=True, arrowhead=1, ax=0, ay=-40, row=1, col=1, ) # Cumulative line chart cumulative_percentage = (df["Value"].cumsum() / df["Value"].sum()) * 100 fig.add_trace( Scatter( x=df["Category"], y=cumulative_percentage, name="Cumulative %", mode="lines+markers", line=dict(color="#333333", dash="dash"), ), row=1, col=2, ) # Update layout for axes and overall layout fig.update_layout( title_text=f"Carbon Footprint of {df['Name'][0]}", plot_bgcolor="white", legend_title_text="Breakdown", xaxis_title="Emission Category", yaxis_title="Carbon Emission (kgCO2)", yaxis=dict( linecolor="black", showline=True, ticks="outside", mirror=True, gridcolor="lightgrey", ), yaxis2=dict( title="Cumulative Percentage", side="right", showgrid=False, ), legend=dict( x=1, # Horizontal position (1 for right) y=0, # Vertical position (0 for bottom) xanchor="right", yanchor="bottom", orientation="h", # Horizontal layout for compactness ), ) fig.update_xaxes( linecolor="black", ticks="outside", showline=True, mirror=True, ) fig.update_yaxes( linecolor="black", showline=True, ticks="outside", mirror=True, gridcolor="lightgrey", ) return fig def draw_historic_figure(df: DataFrame) -> Figure: # Create subplots with 2 rows and 2 columns fig = make_subplots( rows=2, cols=2, subplot_titles=( "Energy Usage by Company", "Waste Generated by Company", "Business Travel by Company", "Total Carbon Footprint by Company", ), ) # Add gradient-filled area traces for each metric fig.add_trace( Scatter( x=df["Name"], y=df["Energy Usage"], mode="lines", fill="tozeroy", line=dict(color="blue"), fillcolor="rgba(31, 119, 180, 0.5)", # Gradient fill for blue name="Energy Usage", ), row=1, col=1, ) fig.add_trace( Scatter( x=df["Name"], y=df["Waste Generated"], mode="lines", fill="tozeroy", line=dict(color="orange"), fillcolor="rgba(255, 127, 14, 0.5)", # Gradient fill for orange name="Waste Generated", ), row=1, col=2, ) fig.add_trace( Scatter( x=df["Name"], y=df["Business Travel"], mode="lines", fill="tozeroy", line=dict(color="green"), fillcolor="rgba(44, 160, 44, 0.5)", # Gradient fill for green name="Business Travel", ), row=2, col=1, ) # Calculate each company's total carbon footprint as the sum of the three metrics df["Carbon Footprint"] = ( df["Energy Usage"] + df["Waste Generated"] + df["Business Travel"] ) # Add a line trace for the total sum of each metric fig.add_trace( Scatter( x=df["Name"], y=df["Carbon Footprint"], mode="lines+markers", line=dict(color="black", dash="dash"), name="Total Carbon Footprint", ), row=2, col=2, ) # Update layout for titles, legends, and aesthetics fig.update_layout( title="Company Metrics with Total Carbon Footprint", barmode="group", # Group bars by category template="plotly_white", showlegend=True, height=600, width=1000, legend=dict(x=1.05, y=1), # Adjust legend position outside plot for clarity ) # Add axis labels to each subplot fig.update_xaxes(title_text="Company", row=1, col=1) fig.update_yaxes(title_text="Energy Usage", row=1, col=1) fig.update_xaxes(title_text="Company", row=1, col=2) fig.update_yaxes(title_text="Waste Generated", row=1, col=2) fig.update_xaxes(title_text="Company", row=2, col=1) fig.update_yaxes(title_text="Business Travel", row=2, col=1) fig.update_xaxes(title_text="Company", row=2, col=2) fig.update_yaxes(title_text="Carbon Footprint (total)", row=2, col=2) return fig def make_dataframe( company_name: str, avg_electric_bill: float, avg_gas_bill: float, avg_transport_bill: float, monthly_waste_generated: float, recycled_waste_percent: float, annual_travel_kms: float, fuel_efficiency: float, ) -> DataFrame: energy_usage = ( (avg_electric_bill * 12 * 5e-4) + (avg_gas_bill * 12 * 5.3e-3) + (avg_transport_bill * 12 * 2.32) ) waste_generated = monthly_waste_generated * 12 * 0.57 - recycled_waste_percent business_travel = annual_travel_kms * 1 / fuel_efficiency * 2.31 return DataFrame( { "Name": company_name, "Category": ["Energy Usage", "Waste Generated", "Business Travel"], "Value": [energy_usage, waste_generated, business_travel], } ) def dataframe_to_dict(df: DataFrame) -> dict: return { "Name": df["Name"][0], "Energy Usage": df["Value"][0], "Waste Generated": df["Value"][1], "Business Travel": df["Value"][2], }