|
import streamlit as st |
|
import pandas as pd |
|
import plotly.express as px |
|
import os |
|
from groq import Groq |
|
|
|
|
|
def add_background(): |
|
background_url = "https://huggingface.co/spaces/ZainMalik0925/GreenLensAI_LCA/resolve/main/BCK2.jpg" |
|
css = f""" |
|
<style> |
|
.stApp {{ |
|
background-image: url("{background_url}"); |
|
background-size: cover; |
|
background-position: center; |
|
background-attachment: fixed; |
|
}} |
|
.highlight {{ |
|
background-color: rgba(27, 27, 27, 0.7); /* 70% opaque black */ |
|
padding: 10px; |
|
border-radius: 5px; |
|
margin-bottom: 15px; |
|
color: white; |
|
}} |
|
</style> |
|
""" |
|
st.markdown(css, unsafe_allow_html=True) |
|
|
|
|
|
st.set_page_config(page_title="GreenLens AI", layout="wide") |
|
|
|
|
|
add_background() |
|
|
|
|
|
st.markdown("<h1 style='text-align: center; color: white;'>GreenLens AI</h1>", unsafe_allow_html=True) |
|
st.markdown( |
|
""" |
|
<p style='text-align: center; color: white; font-size: 18px;'> |
|
A Comprehensive Tool for Assessing Water, Energy, and Carbon Footprints of Textile Products π |
|
</p> |
|
""", |
|
unsafe_allow_html=True, |
|
) |
|
|
|
|
|
DATASET_URL = "https://huggingface.co/spaces/ZainMalik0925/GreenLensAI_LCA/resolve/main/DataSet01.xlsx" |
|
|
|
|
|
@st.cache_data |
|
def process_dataset(url): |
|
try: |
|
excel_content = pd.ExcelFile(url) |
|
fiber_data = pd.read_excel(excel_content, sheet_name="Fiber Impact Data") |
|
transport_data = pd.read_excel(excel_content, sheet_name="Transport Impact Data") |
|
washing_data = pd.read_excel(excel_content, sheet_name="Washing Data") |
|
|
|
|
|
fiber_impact_data = fiber_data.set_index("Fiber Type")[["Water (L/kg)", "Energy (MJ/kg)", "Carbon (kg CO2e/kg)"]].to_dict(orient="index") |
|
transport_impact_data = transport_data.set_index("Transport Mode")["CFP (kg CO2e/km)"].to_dict() |
|
washing_impact_data = washing_data.set_index("Washing Temperature")[["Water (L/kg)", "Energy Use (MJ/wash)", "Carbon (kg CO2e/wash)", "Dryer CFP (kg CO2e/cycle)"]].to_dict(orient="index") |
|
return fiber_impact_data, transport_impact_data, washing_impact_data |
|
except Exception as e: |
|
st.error(f"Error loading dataset: {e}") |
|
return None, None, None |
|
|
|
|
|
def calculate_footprints(weight, composition, lifecycle_inputs): |
|
water_fp, energy_fp, carbon_fp = 0, 0, 0 |
|
for fiber, percentage in composition.items(): |
|
if fiber in fiber_impact_data: |
|
data = fiber_impact_data[fiber] |
|
fraction = percentage / 100 |
|
water_fp += data["Water (L/kg)"] * weight * fraction |
|
energy_fp += data["Energy (MJ/kg)"] * weight * fraction |
|
carbon_fp += data["Carbon (kg CO2e/kg)"] * weight * fraction |
|
|
|
|
|
if lifecycle_inputs["transport_mode"] in transport_impact_data: |
|
carbon_fp += transport_impact_data[lifecycle_inputs["transport_mode"]] * lifecycle_inputs["transport_distance"] * weight |
|
|
|
|
|
if lifecycle_inputs["washing_temperature"] in washing_impact_data: |
|
washing_data = washing_impact_data[lifecycle_inputs["washing_temperature"]] |
|
washing_water = washing_data["Water (L/kg)"] * lifecycle_inputs["washing_cycles"] |
|
washing_energy = washing_data["Energy Use (MJ/wash)"] * lifecycle_inputs["washing_cycles"] |
|
washing_carbon = washing_data["Carbon (kg CO2e/wash)"] * lifecycle_inputs["washing_cycles"] |
|
dryer_carbon = washing_data["Dryer CFP (kg CO2e/cycle)"] if lifecycle_inputs["use_dryer"] else 0 |
|
water_fp += washing_water |
|
energy_fp += washing_energy |
|
carbon_fp += washing_carbon + (dryer_carbon * lifecycle_inputs["washing_cycles"]) |
|
|
|
|
|
water_fp /= 1000 |
|
return water_fp, energy_fp, carbon_fp |
|
|
|
|
|
def get_inputs(prefix): |
|
weight = st.sidebar.number_input(f"{prefix} Product Weight (kg)", min_value=0.0, value=0.0, step=0.01, key=f"{prefix}_weight") |
|
st.sidebar.markdown(f"<h3 style='color: white;'>{prefix} Material Composition (%)</h3>", unsafe_allow_html=True) |
|
cotton = st.sidebar.number_input("Conventional Cotton (%)", 0, 100, 0, step=1, key=f"{prefix}_cotton") |
|
polyester = st.sidebar.number_input("Polyester (%)", 0, 100, 0, step=1, key=f"{prefix}_polyester") |
|
nylon = st.sidebar.number_input("Nylon 6 (%)", 0, 100, 0, step=1, key=f"{prefix}_nylon") |
|
acrylic = st.sidebar.number_input("Acrylic (%)", 0, 100, 0, step=1, key=f"{prefix}_acrylic") |
|
viscose = st.sidebar.number_input("Viscose (%)", 0, 100, 0, step=1, key=f"{prefix}_viscose") |
|
|
|
if cotton + polyester + nylon + acrylic + viscose != 100: |
|
st.sidebar.error("Fiber composition must sum to 100%!") |
|
|
|
st.sidebar.markdown(f"<h3 style='color: white;'>{prefix} Transport Inputs</h3>", unsafe_allow_html=True) |
|
transport_mode = st.sidebar.selectbox(f"{prefix} Transport Mode", list(transport_impact_data.keys()), key=f"{prefix}_transport_mode") |
|
transport_distance = st.sidebar.number_input(f"{prefix} Transport Distance (km)", min_value=0, value=0, step=10, key=f"{prefix}_transport_distance") |
|
|
|
lifecycle_inputs = { |
|
"washing_cycles": st.sidebar.number_input(f"{prefix} Washing Cycles", min_value=0, value=0, key=f"{prefix}_wash_cycles"), |
|
"washing_temperature": st.sidebar.selectbox(f"{prefix} Washing Temperature", list(washing_impact_data.keys()), key=f"{prefix}_wash_temp"), |
|
"use_dryer": st.sidebar.checkbox(f"{prefix} Use Dryer?", key=f"{prefix}_use_dryer"), |
|
"transport_mode": transport_mode, |
|
"transport_distance": transport_distance, |
|
} |
|
|
|
composition = { |
|
"Conventional Cotton": cotton, |
|
"Polyester": polyester, |
|
"Nylon 6": nylon, |
|
"Acrylic": acrylic, |
|
"Viscose": viscose, |
|
} |
|
return weight, composition, lifecycle_inputs |
|
|
|
|
|
def style_figure(fig): |
|
fig.update_layout( |
|
plot_bgcolor="rgba(27, 27, 27, 0.8)", |
|
paper_bgcolor="rgba(27, 27, 27, 0.8)", |
|
font=dict(color="white"), |
|
title_font=dict(size=18, color="white"), |
|
xaxis=dict(title_font=dict(color="white"), tickfont=dict(color="white")), |
|
yaxis=dict(title_font=dict(color="white"), tickfont=dict(color="white")), |
|
) |
|
fig.update_traces(marker=dict(color="white", line=dict(color="gray", width=1))) |
|
return fig |
|
|
|
|
|
def generate_recommendations(water, energy, carbon): |
|
try: |
|
client = Groq(api_key=os.environ.get("GROQ_API_KEY")) |
|
prompt = ( |
|
f"The environmental impact values for a textile product are as follows:\n" |
|
f"Water Footprint: {water:.2f} kL\n" |
|
f"Energy Footprint: {energy:.2f} MJ\n" |
|
f"Carbon Footprint: {carbon:.2f} kg CO2e\n" |
|
f"Provide recommendations to lower these impacts." |
|
) |
|
|
|
response = client.chat.completions.create( |
|
messages=[{"role": "user", "content": prompt}], |
|
model="llama-3.3-70b-versatile", |
|
) |
|
|
|
return response.choices[0].message.content |
|
except Exception as e: |
|
return f"Error generating recommendations: {e}" |
|
|
|
|
|
fiber_impact_data, transport_impact_data, washing_impact_data = process_dataset(DATASET_URL) |
|
|
|
if fiber_impact_data and transport_impact_data and washing_impact_data: |
|
comparison_mode = st.sidebar.checkbox("Enable Comparison Mode") |
|
|
|
if comparison_mode: |
|
|
|
col1, col2 = st.columns(2) |
|
with col1: |
|
weight1, composition1, lifecycle1 = get_inputs("Assessment 1") |
|
with col2: |
|
weight2, composition2, lifecycle2 = get_inputs("Assessment 2") |
|
|
|
|
|
water1, energy1, carbon1 = calculate_footprints(weight1, composition1, lifecycle1) |
|
water2, energy2, carbon2 = calculate_footprints(weight2, composition2, lifecycle2) |
|
|
|
|
|
st.markdown(f""" |
|
<div class="highlight"> |
|
<h2>Numerical Comparison</h2> |
|
<p>Assessment 1: Water: {water1:.2f} kL, Energy: {energy1:.2f} MJ, Carbon: {carbon1:.2f} kg CO2e</p> |
|
<p>Assessment 2: Water: {water2:.2f} kL, Energy: {energy2:.2f} MJ, Carbon: {carbon2:.2f} kg CO2e</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
comparison_data = pd.DataFrame({ |
|
"Footprint Type": ["Water (kL)", "Energy (MJ)", "Carbon (kg CO2e)"], |
|
"Assessment 1": [water1, energy1, carbon1], |
|
"Assessment 2": [water2, energy2, carbon2], |
|
}) |
|
fig = px.bar( |
|
comparison_data.melt(id_vars="Footprint Type", var_name="Assessment", value_name="Value"), |
|
x="Footprint Type", |
|
y="Value", |
|
color="Assessment", |
|
title="Comparison of Assessments" |
|
) |
|
st.plotly_chart(style_figure(fig)) |
|
else: |
|
|
|
weight, composition, lifecycle = get_inputs("Single") |
|
water, energy, carbon = calculate_footprints(weight, composition, lifecycle) |
|
|
|
|
|
st.markdown(f""" |
|
<div class="highlight"> |
|
<h2>Single Assessment Results</h2> |
|
<p>Water Footprint: {water:.2f} kL</p> |
|
<p>Energy Footprint: {energy:.2f} MJ</p> |
|
<p>Carbon Footprint: {carbon:.2f} kg CO2e</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
result_data = pd.DataFrame({ |
|
"Footprint Type": ["Water (kL)", "Energy (MJ)", "Carbon (kg CO2e)"], |
|
"Value": [water, energy, carbon] |
|
}) |
|
fig = px.bar(result_data, x="Footprint Type", y="Value", title="Single Assessment Footprint Breakdown") |
|
st.plotly_chart(style_figure(fig)) |
|
|
|
|
|
if water > 0 or energy > 0 or carbon > 0: |
|
recommendations = generate_recommendations(water, energy, carbon) |
|
st.markdown(f""" |
|
<div class="highlight"> |
|
<h2>Recommendations to Lower Environmental Impacts</h2> |
|
<p>{recommendations}</p> |
|
</div> |
|
""", unsafe_allow_html=True) |
|
else: |
|
st.error("Failed to load dataset.") |
|
|