Skip to content

Iterate on Python program

A natural language prompt asking for edits to a Streamlit program/utility.

Contains both V1 and requested edits dictated by voice.

The use case is testing out the ability of the LLM to output a sufficiently long output to output the whole updated script without breaks.

Please fix the formatting in the Streamlit app. The problem is that I want the EBITDA and EBITDA minus total emissions to have the exact same presentation format. They should both firstly be denominated in dollars, firstly in billions, correct to two decimal places. Then on a separate line, in millions, correct to two decimal places. That number is preceded by dollars as well. Additionally, in the generated csv data row, nothing should have more than two decimal places

Return an updated V2 in full.

Here's V1:

import streamlit as st
import csv
from io import StringIO

# Initialize session state variables
if 'data' not in st.session_state:
    st.session_state.data = {}

if 'config' not in st.session_state:
    st.session_state.config = {'csv_path': 'emissions_data.csv'}

def calculate_values():
    try:
        scope1 = float(st.session_state.scope_one_input)
        scope2 = float(st.session_state.scope_two_input)
        scope3 = float(st.session_state.scope_three_input)
        ebitda = float(st.session_state.ebitda_input)
        ebitda_unit = st.session_state.ebitda_unit_combo

        total_emissions = scope1 + scope2 + scope3
        total_scope12_emissions = scope1 + scope2
        monetized_scope12 = total_scope12_emissions * 236 * 1_000_000
        monetized_total_emissions = total_emissions * 236 * 1_000_000

        if ebitda_unit == "BN":
            ebitda *= 1_000_000_000
        elif ebitda_unit == "MN":
            ebitda *= 1_000_000

        ebitda_minus_emissions = ebitda - monetized_total_emissions
        emissions_intensity_ratio = monetized_total_emissions / ebitda if ebitda != 0 else 0
        emissions_intensity_percentage = emissions_intensity_ratio * 100

        # Format monetized values for display
        monetized_scope12_display = format_monetized_value(monetized_scope12)
        monetized_total_emissions_display = format_monetized_value(monetized_total_emissions)
        ebitda_display = format_ebitda_value(ebitda, ebitda_unit)
        ebitda_minus_emissions_display = format_ebitda_value(ebitda_minus_emissions, ebitda_unit)
        monetized_scope12_display_full = format_monetized_value_with_full(monetized_scope12)
        monetized_total_emissions_display_full = format_monetized_value_with_full(monetized_total_emissions)

        st.session_state.total_emissions_value = f"{total_emissions:.2f} million tons of CO2e"
        st.session_state.total_scope12_emissions_value = f"{total_scope12_emissions:.2f} million tons of CO2e"
        st.session_state.monetized_scope12_value = f"${monetized_scope12_display} ({monetized_scope12:,.2f})"
        st.session_state.monetized_total_emissions_value = f"${monetized_total_emissions_display} ({monetized_total_emissions:,.2f})"
        st.session_state.ebitda_value = ebitda_display
        st.session_state.ebitda_minus_emissions_value = ebitda_minus_emissions_display
        st.session_state.emissions_intensity_value = f"{emissions_intensity_ratio:.2f}"
        st.session_state.emissions_intensity_percentage_value = f"{emissions_intensity_percentage:.2f}%"

        st.session_state.data = {
            'Company Name': st.session_state.company_name_input,
            'Emissions Reporting Year': st.session_state.reporting_year_input,
            'Emissions Report URL': st.session_state.emissions_report_url_input,
            'EBITDA Report URL': st.session_state.ebitda_report_url_input,
            'Scope One Emissions': scope1,
            'Scope Two Emissions': scope2,
            'Scope Three Emissions': scope3,
            'Total Emissions': total_emissions,
            'Total Scope 1 & 2 Emissions': total_scope12_emissions,
            'Monetized Scope 1 & 2 Emissions': monetized_scope12,
            'Monetized Total Emissions': monetized_total_emissions,
            'EBITDA': ebitda,
            'EBITDA Minus Total Monetized Emissions': ebitda_minus_emissions,
            'Emissions Intensity Ratio': emissions_intensity_ratio,
            'Emissions Intensity Percentage': emissions_intensity_percentage
        }
    except ValueError:
        st.error("Please enter valid numeric values for emissions and EBITDA.")

def format_monetized_value(value):
    if value >= 1_000_000_000:
        return f"{value / 1_000_000_000:.2f} B"
    else:
        return f"{value / 1_000_000:.2f} M"

def format_monetized_value_with_full(value):
    if value >= 1_000_000_000:
        short_value = f"{value / 1_000_000_000:.2f} B"
        full_value = f"{value / 1_000_000:.2f} M"
    else:
        short_value = f"{value / 1_000_000:.2f} M"
        full_value = f"{value:,.2f}"
    return f"{short_value}\n({full_value})"

def format_ebitda_value(ebitda, ebitda_unit):
    if ebitda >= 1_000_000_000:
        short_value = f"{ebitda / 1_000_000_000:.2f} B"
        full_value = f"{ebitda / 1_000_000:.2f} M"
    else:
        short_value = f"{ebitda / 1_000_000:.2f} M"
        full_value = f"{ebitda:,.2f}"
    return f"${short_value}\n(${full_value})"

def generate_csv():
    if not st.session_state.data:
        st.error("Please calculate values first.")
        return

    headers = st.session_state.data.keys()
    output = StringIO()
    writer = csv.DictWriter(output, fieldnames=headers)
    writer.writeheader()
    writer.writerow(st.session_state.data)
    csv_data = output.getvalue()

    st.session_state.csv_header_row = ','.join(headers)
    st.session_state.csv_data_row = csv_data.split('\n')[1]

def clear_fields():
    for key in st.session_state.keys():
        if key.endswith('_input') or key.endswith('_value'):
            st.session_state[key] = ''

def copy_to_clipboard(text):
    js_code = f"""
    navigator.clipboard.writeText(`{text}`);
    alert("Copied to clipboard: {text}");
    """
    st.components.v1.html(f"<button onclick='{js_code}'>Copy to Clipboard</button>", height=32)

# Title and Description
st.title("Monetized GHG Emissions Calculator")
st.text("""
This utility takes GHG emissions as reported by companies and converts them into monetary terms 
at the rate of $236 per ton of carbon dioxide equivalents proposed by the International Foundation 
for Valuing Units. Please ensure that the input fields are denominated in this unit only and select 
the correct reporting unit for EBITDA (Earnings Before Interest, Tax, Depreciation, and Amortization). 
The calculator will calculate the emissions intensity ratio which is the monetized emissions divided 
by the EBITDA and it will express it as a percentage as well. To copy the data out of this utility, 
use the CSV data row which is generated below the data table.
""")

# Layout with two columns
col1, col2 = st.columns([1, 1.2])

# Left Column - Input Fields
with col1:
    st.subheader("Input Fields")
    st.text_input("Company Name:", key='company_name_input')
    st.text_input("Emissions Reporting Year:", key='reporting_year_input')
    st.text_input("Emissions Report URL:", key='emissions_report_url_input')
    st.text_input("EBITDA Report URL:", key='ebitda_report_url_input')
    st.text_input("Scope One Emissions (in millions of tons of CO2e):", key='scope_one_input')
    st.text_input("Scope Two Emissions (in millions of tons of CO2e):", key='scope_two_input')
    st.text_input("Scope Three Emissions (in millions of tons of CO2e):", key='scope_three_input')
    st.text_input("EBITDA:", key='ebitda_input')
    st.selectbox("EBITDA Unit:", options=["BN", "MN"], key='ebitda_unit_combo')
    st.button("Calculate", on_click=calculate_values)
    st.button("Generate CSV", on_click=generate_csv)
    st.button("Clear", on_click=clear_fields)

# Vertical Divider
st.markdown("<style>.stVerticalBlock {display: flex; align-items: stretch; gap: 20px;}</style>", unsafe_allow_html=True)
st.markdown("<div style='width: 2px; background-color: #ccc;'></div>", unsafe_allow_html=True)

# Right Column - Calculated Values
with col2:
    st.subheader("Calculated Values")

    st.markdown(f"**Total Emissions (Scope 1 + 2 + 3):**")
    st.markdown(f"{st.session_state.get('total_emissions_value', '')}")

    st.markdown(f"**Total Scope 1 & 2 Emissions:**")
    st.markdown(f"{st.session_state.get('total_scope12_emissions_value', '')}")

    st.markdown(f"**Monetized Scope 1 & 2 Emissions ($):**")
    st.markdown(f"{st.session_state.get('monetized_scope12_value', '')}")
    st.markdown(f"{st.session_state.get('monetized_scope12_display_full', '')}")

    st.markdown(f"**Monetized Total Emissions ($):**")
    st.markdown(f"{st.session_state.get('monetized_total_emissions_value', '')}")
    st.markdown(f"{st.session_state.get('monetized_total_emissions_display_full', '')}")

    st.markdown(f"**EBITDA:**")
    st.markdown(f"{st.session_state.get('ebitda_value', '')}")

    st.markdown(f"**EBITDA - Total Monetized Emissions ($):**")
    st.markdown(f"{st.session_state.get('ebitda_minus_emissions_value', '')}")

    st.markdown(f"**Emissions Intensity Ratio:**")
    st.markdown(f"{st.session_state.get('emissions_intensity_value', '')}")

    st.markdown(f"**Emissions Intensity Percentage (%):**")
    st.markdown(f"{st.session_state.get('emissions_intensity_percentage_value', '')}")

# CSV Output
st.subheader("CSV Output")
csv_header_row = st.session_state.get('csv_header_row', '')
csv_data_row = st.session_state.get('csv_data_row', '')

col3, col4 = st.columns(2)

with col3:
    st.text_area("CSV Header Row:", value=csv_header_row, key='csv_header_row', disabled=True, height=100)
    copy_to_clipboard(csv_header_row)

with col4:
    st.text_area("CSV Data Row:", value=csv_data_row, key='csv_data_row', disabled=True, height=100)
    copy_to_clipboard(csv_data_row)