hvac_fable / OUTPUT_GENERATOR_GUI_GUIDE.md
Rachel7's picture
Deploy Fable B-test analyzer
dac3297 verified
|
Raw
History Blame Contribute Delete
26.1 kB

HVAC Blueprint Analyzer - Output Generator & GUI Guide

Date: June 19, 2026
Component: Output Generation & User Interface


πŸ“Š OUTPUT GENERATOR OVERVIEW

Purpose

Convert analyzed HVAC data into multiple formats:

  • CSV files for spreadsheet analysis
  • PDF reports with visual summaries
  • JSON for API consumption
  • HTML reports for web viewing
  • Excel workbooks with multiple sheets

🎯 PHASE A: CSV OUTPUT GENERATION

CSV Output 1: Floor & Units Summary

File: hvac_analysis_floors_units.csv

Floor,Unit_ID,Unit_Type,Quantity,Capacity_BTU,Capacity_kW,Status,Notes
1,AC-A,Ceiling Concealed Ducted,1,36000,10.5,Detected,Located near kitchen
1,AC-B,Wall Mounted,1,24000,7.0,Detected,Bedroom unit
2,AC-C,Ceiling Concealed Ducted,1,36000,10.5,Detected,Master bedroom
2,AC-D,Wall Mounted,2,12000,3.5,Detected,Living areas
3,AC-E,Ceiling Concealed Ducted,1,48000,14.0,Detected,Commercial zone
3,AC-F,Wall Mounted,1,24000,7.0,Detected,Office area

Columns to Include:

  • Floor number (1, 2, 3, B for basement)
  • Unit ID/Tag (AC-A, AC-B, etc.)
  • Unit Type (Ceiling Concealed Ducted, Wall Mounted, Ductless, etc.)
  • Quantity (number of units)
  • Capacity in BTU
  • Capacity in kW
  • Detection Status (Detected, Manual Entry, Inferred)
  • Notes/Comments
  • Location within floor (optional)
  • Equipment Schedule reference (optional)

Implementation:

def export_floors_units_csv(analysis_data, output_path):
    """
    Export floor-by-floor unit breakdown to CSV
    
    Args:
        analysis_data: Dict with floors and units
        output_path: Path to save CSV
    
    Returns:
        Path to saved CSV file
    """
    import pandas as pd
    
    rows = []
    for floor in analysis_data['floors']:
        floor_num = floor['number']
        for unit in floor['units']:
            rows.append({
                'Floor': floor_num,
                'Unit_ID': unit['tag'],
                'Unit_Type': unit['type'],
                'Quantity': unit['quantity'],
                'Capacity_BTU': unit.get('capacity_btu', ''),
                'Capacity_kW': unit.get('capacity_kw', ''),
                'Status': unit.get('detection_status', 'Detected'),
                'Notes': unit.get('notes', ''),
                'Location': unit.get('location', ''),
            })
    
    df = pd.DataFrame(rows)
    df.to_csv(output_path, index=False)
    return output_path

CSV Output 2: Equipment Schedule

File: hvac_equipment_schedule.csv

Equipment_ID,Manufacturer,Model,Type,Capacity_BTU,Voltage,Phase,Frequency_Hz,Quantity,Floor,Unit_Tag,Remarks
1,Carrier,25HNE024A03,Ceiling Cassette,24000,208-230,1,60,1,2,AC-B,Installed Jan 2023
2,Daikin,FCAG71B,Ceiling Concealed,36000,208-230,3,60,2,1,AC-A,New equipment
3,LG,ASNQ48LNZA0,Wall Mounted,48000,208-230,1,60,1,3,AC-E,High efficiency model

Columns to Include:

  • Equipment ID (from schedule)
  • Manufacturer
  • Model number
  • Equipment Type
  • Capacity (BTU)
  • Voltage
  • Phase (1 or 3)
  • Frequency (Hz)
  • Quantity
  • Floor number
  • Associated Unit Tag (AC-A, AC-B, etc.)
  • Remarks/Notes

CSV Output 3: Reconciliation Report

File: hvac_reconciliation_report.csv

Issue_Type,Severity,Floor,Unit_ID,Detected_in_Plan,Found_in_Schedule,Details,Recommended_Action
Missing_Unit,High,2,AC-B,No,Yes,Unit found in schedule but not detected in floor plan,Review floor plan markup
Extra_Unit,Medium,1,AC-A,Yes,No,Unit detected in plan but not listed in schedule,Add to equipment schedule
Capacity_Mismatch,Medium,3,AC-E,36000,48000,Plan shows 36kBTU but schedule lists 48kBTU,Verify actual installed capacity
Floor_Mismatch,High,NULL,AC-C,3,2,Unit AC-C listed on floor 2 but appears in floor 3 plan,Correct schedule or floor plan

Columns to Include:

  • Issue Type (Missing Unit, Extra Unit, Capacity Mismatch, Floor Mismatch, etc.)
  • Severity (Low, Medium, High)
  • Floor number
  • Unit ID
  • Detected in floor plan (Yes/No)
  • Found in schedule (Yes/No)
  • Details/Description
  • Recommended Action
  • Confidence Score (0-100%)

πŸ–₯️ PHASE B: GUI - USER INTERFACE

Technology Stack (Recommended)

  • Frontend Framework: Streamlit (easiest for quick demo) OR React
  • Styling: Tailwind CSS (if React) OR Streamlit theme
  • Charting: Plotly or Chart.js (for visualizations)
  • Forms: Built-in Streamlit components OR React Hook Form

GUI Features Checklist

1. File Upload Section

# Streamlit example
import streamlit as st

st.title("🏒 HVAC Blueprint Analyzer")

uploaded_file = st.file_uploader("Upload Mechanical Blueprint (PDF)", type="pdf")

if uploaded_file:
    st.info(f"πŸ“„ File: {uploaded_file.name} ({uploaded_file.size / 1024:.2f} KB)")
    
    col1, col2 = st.columns(2)
    with col1:
        model_choice = st.radio("Choose AI Model:", ["Gemini", "OpenAI"])
    with col2:
        schedule_mode = st.radio("Schedule Mode:", 
                                ["Auto-Detect", "Upload Schedule"])
    
    if st.button("πŸš€ Analyze Blueprint"):
        with st.spinner("Analyzing..."):
            results = analyze_blueprint(uploaded_file, model_choice, schedule_mode)
        st.success("Analysis complete!")

Checklist:

  • PDF upload widget
  • File validation (size, format)
  • Progress indicator during upload
  • File preview/info display
  • Multiple file upload support (batch processing)
  • Drag-and-drop file upload

2. Configuration Section

  • Model selection (Gemini vs OpenAI toggle)
  • Schedule mode selection (Auto vs Manual)
  • Output format selection (CSV, PDF, JSON)
  • Advanced options (OCR threshold, confidence limits)
  • Cost calculator (estimate before processing)

3. Analysis Results Display

Tab 1: Floors & Units Summary

st.header("πŸ“Š Analysis Results")

tab1, tab2, tab3, tab4 = st.tabs([
    "Floors & Units", 
    "Equipment Schedule", 
    "Reconciliation",
    "Downloads"
])

with tab1:
    st.subheader("HVAC Units by Floor")
    
    # Interactive table
    st.dataframe(
        floors_units_df,
        use_container_width=True,
        column_config={
            "Floor": st.column_config.TextColumn("Floor"),
            "Unit_ID": st.column_config.TextColumn("Unit ID", width="medium"),
            "Unit_Type": st.column_config.TextColumn("Type", width="medium"),
            "Quantity": st.column_config.NumberColumn("Qty"),
            "Capacity_BTU": st.column_config.NumberColumn("BTU"),
        }
    )
    
    # Summary statistics
    col1, col2, col3, col4 = st.columns(4)
    with col1:
        st.metric("Total Floors", len(analysis_data['floors']))
    with col2:
        st.metric("Total Units", sum([u['quantity'] for f in analysis_data['floors'] for u in f['units']]))
    with col3:
        st.metric("Total Capacity", f"{total_btu:,.0f} BTU")
    with col4:
        st.metric("Cost (Gemini)", f"${cost:.2f}")

Tab 2: Equipment Schedule Table

  • Sortable table with equipment details
  • Filter by floor, manufacturer, type
  • Search functionality
  • Edit capability (for manual corrections)
  • Export to CSV

Tab 3: Reconciliation Report

  • Visual summary of issues (count by severity)
  • Detailed issue list
  • Severity indicators (color-coded)
  • Recommended actions
  • Mark issues as resolved

Tab 4: Downloads

  • Download CSV files (Floors & Units, Schedule, Reconciliation)
  • Download PDF report
  • Download JSON data
  • Zip all outputs together

4. Visualization Components

Floor Plan Overview

import plotly.graph_objects as go

fig = go.Figure()

# Add floor layers
for floor in analysis_data['floors']:
    fig.add_trace(go.Scatter(
        x=floor['units_x'],
        y=floor['units_y'],
        mode='markers+text',
        text=floor['units_tags'],
        marker=dict(size=15, color='blue'),
        name=f"Floor {floor['number']}"
    ))

st.plotly_chart(fig, use_container_width=True)

Capacity Distribution Chart

  • Stacked bar chart showing capacity by floor
  • Unit type distribution pie chart
  • Comparison chart (Detected vs Schedule)

Cost Breakdown

  • API cost per model comparison
  • Cost per unit analyzed
  • Total project cost estimate

5. Schedule Upload Section (if auto-detect fails)

with st.expander("πŸ“‹ Manual Schedule Upload"):
    schedule_source = st.radio(
        "How would you like to provide the schedule?",
        ["Upload CSV", "Upload Excel", "Paste Data", "Use Previous Schedule"]
    )
    
    if schedule_source == "Upload CSV":
        schedule_file = st.file_uploader("Upload CSV with schedule", type="csv")
        if schedule_file:
            schedule_df = pd.read_csv(schedule_file)
            st.dataframe(schedule_df)
    
    elif schedule_source == "Paste Data":
        schedule_text = st.text_area("Paste schedule data (CSV format)")
        if schedule_text:
            schedule_df = pd.read_csv(StringIO(schedule_text))
            st.dataframe(schedule_df)

Checklist:

  • CSV upload
  • Excel upload (.xlsx, .xls)
  • Copy/paste data
  • Data validation
  • Preview of uploaded data
  • Confirm & save schedule

6. A/B Testing Comparison View

col1, col2 = st.columns(2)

with col1:
    st.subheader("πŸ”΅ Gemini Results")
    st.write(f"Time: {gemini_time:.2f}s")
    st.write(f"Cost: ${gemini_cost:.4f}")
    st.write(f"Units Found: {gemini_units}")
    st.dataframe(gemini_results)

with col2:
    st.subheader("🟠 OpenAI Results")
    st.write(f"Time: {openai_time:.2f}s")
    st.write(f"Cost: ${openai_cost:.4f}")
    st.write(f"Units Found: {openai_units}")
    st.dataframe(openai_results)

# Comparison metrics
st.subheader("πŸ“Š Comparison")
comparison_data = {
    'Metric': ['Speed (seconds)', 'Cost ($)', 'Units Detected', 'Accuracy (%)'],
    'Gemini': [gemini_time, gemini_cost, gemini_units, gemini_accuracy],
    'OpenAI': [openai_time, openai_cost, openai_units, openai_accuracy]
}
comparison_df = pd.DataFrame(comparison_data)
st.dataframe(comparison_df, use_container_width=True)

πŸ“ PHASE C: PDF REPORT GENERATION

Report Sections

  • Cover Page

    • Project name
    • Analysis date
    • Number of blueprints analyzed
    • Model used (Gemini/OpenAI)
  • Executive Summary

    • Total units found
    • Total capacity
    • Number of floors
    • Key findings
  • Floor-by-Floor Summary

    • Table of units per floor
    • Visual breakdown
  • Equipment Schedule

    • Full equipment table
    • Specifications
  • Reconciliation Issues

    • List of discrepancies
    • Severity indicators
    • Recommended actions
  • Appendix

    • Analysis parameters
    • Processing time
    • Cost breakdown

PDF Generation Library

from reportlab.lib.pagesizes import letter, A4
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph
import pandas as pd

def generate_pdf_report(analysis_data, output_path):
    """Generate comprehensive PDF report"""
    
    from reportlab.lib import colors
    from reportlab.lib.units import inch
    
    doc = SimpleDocTemplate(output_path, pagesize=letter)
    elements = []
    
    # Title
    title = Paragraph(
        "<font size=24><b>HVAC Blueprint Analysis Report</b></font>",
        style=ParagraphStyle(alignment=1)  # Center aligned
    )
    elements.append(title)
    elements.append(Spacer(1, 0.5*inch))
    
    # Summary table
    summary_data = [
        ['Total Floors', str(len(analysis_data['floors']))],
        ['Total Units', str(sum_units(analysis_data))],
        ['Total Capacity', f"{total_btu(analysis_data):,} BTU"],
    ]
    
    summary_table = Table(summary_data)
    summary_table.setStyle(TableStyle([
        ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
        ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
        ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
        ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
        ('FONTSIZE', (0, 0), (-1, 0), 14),
        ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
        ('GRID', (0, 0), (-1, -1), 1, colors.black)
    ]))
    elements.append(summary_table)
    
    # Build PDF
    doc.build(elements)
    return output_path

Checklist:

  • ReportLab setup
  • Cover page generation
  • Table formatting
  • Chart embedding
  • Multi-page support
  • Table of contents
  • Page numbering

πŸ“Š PHASE D: JSON OUTPUT

JSON Structure

{
  "metadata": {
    "analysis_date": "2026-06-19T10:30:00Z",
    "blueprint_file": "353_E_86th_St.pdf",
    "model_used": "gemini-2.5-pro",
    "processing_time_seconds": 25.3,
    "cost_usd": 0.08
  },
  "summary": {
    "total_floors": 3,
    "total_units": 8,
    "total_capacity_btu": 256000,
    "total_capacity_kw": 75.0
  },
  "floors": [
    {
      "floor_number": 1,
      "floor_type": "residential",
      "units": [
        {
          "id": "AC-A",
          "type": "Ceiling Concealed Ducted",
          "quantity": 1,
          "capacity_btu": 36000,
          "capacity_kw": 10.5,
          "manufacturer": "Carrier",
          "model": "25HNE024A03",
          "location": "Living area",
          "detection_confidence": 0.95
        }
      ]
    }
  ],
  "equipment_schedule": [
    {
      "id": 1,
      "manufacturer": "Carrier",
      "model": "25HNE024A03",
      "type": "Ceiling Cassette",
      "capacity_btu": 24000,
      "voltage": "208-230V",
      "phase": 1,
      "frequency_hz": 60,
      "quantity": 1,
      "floor": 2,
      "unit_tag": "AC-B"
    }
  ],
  "reconciliation": {
    "issues_found": 2,
    "high_severity": 0,
    "medium_severity": 2,
    "low_severity": 0,
    "issues": [
      {
        "type": "capacity_mismatch",
        "floor": 3,
        "unit_id": "AC-E",
        "plan_capacity": 36000,
        "schedule_capacity": 48000,
        "severity": "medium",
        "recommendation": "Verify actual installed capacity"
      }
    ]
  }
}

Checklist:

  • Metadata section
  • Summary statistics
  • Detailed floor data
  • Equipment schedule
  • Reconciliation issues
  • Confidence scores
  • Timestamps

πŸ–₯️ PHASE E: GUI IMPLEMENTATION OPTIONS

Option 1: Streamlit (Recommended for Quick Demo)

Pros:

  • Fastest to build
  • No frontend experience needed
  • Built-in data visualization
  • Free hosting on Streamlit Cloud

Cons:

  • Limited customization
  • Not suitable for production UIs
  • Slower for large datasets

Setup:

pip install streamlit plotly pandas openpyxl
streamlit run app.py

Option 2: React + FastAPI

Pros:

  • Full customization
  • Production-quality UI
  • Better performance
  • Responsive design

Cons:

  • Takes longer to build
  • Requires frontend/backend skills
  • More complex deployment

Setup:

# Backend
pip install fastapi uvicorn pydantic

# Frontend
npm create vite@latest hvac-ui -- --template react
npm install axios react-query

Option 3: Simple HTML + jQuery

Pros:

  • Minimal dependencies
  • Fast to build
  • Easy to deploy
  • No build step needed

Cons:

  • Limited functionality
  • Not modern
  • Harder to maintain

πŸ“‹ CSV EXPORT IMPLEMENTATION CHECKLIST

Code Structure

# outputs/csv_exporter.py
import pandas as pd
from typing import Dict, List
from pathlib import Path

class HVACCSVExporter:
    """Export HVAC analysis data to CSV formats"""
    
    def __init__(self, output_dir: str = "./outputs"):
        self.output_dir = Path(output_dir)
        self.output_dir.mkdir(exist_ok=True)
    
    def export_all(self, analysis_data: Dict) -> Dict[str, Path]:
        """Export all CSV files and return paths"""
        return {
            'floors_units': self.export_floors_units(analysis_data),
            'equipment_schedule': self.export_equipment_schedule(analysis_data),
            'reconciliation': self.export_reconciliation(analysis_data),
            'summary': self.export_summary(analysis_data),
        }
    
    def export_floors_units(self, data: Dict) -> Path:
        """Export floor and unit breakdown"""
        rows = []
        for floor in data['floors']:
            for unit in floor['units']:
                rows.append({
                    'Floor': floor['number'],
                    'Unit_ID': unit['tag'],
                    'Unit_Type': unit['type'],
                    'Quantity': unit['quantity'],
                    'Capacity_BTU': unit.get('capacity_btu'),
                    'Capacity_kW': unit.get('capacity_kw'),
                    'Status': unit.get('detection_status', 'Detected'),
                    'Location': unit.get('location', ''),
                    'Notes': unit.get('notes', ''),
                })
        
        df = pd.DataFrame(rows)
        path = self.output_dir / "hvac_floors_units.csv"
        df.to_csv(path, index=False)
        return path
    
    def export_equipment_schedule(self, data: Dict) -> Path:
        """Export equipment schedule"""
        df = pd.DataFrame(data.get('equipment_schedule', []))
        path = self.output_dir / "hvac_equipment_schedule.csv"
        df.to_csv(path, index=False)
        return path
    
    def export_reconciliation(self, data: Dict) -> Path:
        """Export reconciliation report"""
        issues = data.get('reconciliation', {}).get('issues', [])
        df = pd.DataFrame(issues)
        path = self.output_dir / "hvac_reconciliation.csv"
        df.to_csv(path, index=False)
        return path
    
    def export_summary(self, data: Dict) -> Path:
        """Export summary statistics"""
        summary = data.get('summary', {})
        summary_df = pd.DataFrame([summary])
        path = self.output_dir / "hvac_summary.csv"
        summary_df.to_csv(path, index=False)
        return path

# Usage
exporter = HVACCSVExporter()
csv_files = exporter.export_all(analysis_data)
print(f"Exported to: {csv_files}")

Checklist:

  • CSV exporter class created
  • floors_units.csv export working
  • equipment_schedule.csv export working
  • reconciliation.csv export working
  • summary.csv export working
  • Error handling for missing data
  • File encoding (UTF-8)
  • Column ordering consistent

🎨 GUI MOCKUP LAYOUT

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  🏒 HVAC Blueprint Analyzer                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                 β”‚
β”‚  πŸ“€ Upload Blueprint                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ Drag & drop PDF here or click to browse β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                 β”‚
β”‚  βš™οΈ Configuration                               β”‚
β”‚  Model: [Gemini ●] [OpenAI β—‹]                  β”‚
β”‚  Schedule: [Auto-Detect ●] [Upload β—‹]          β”‚
β”‚  Output Format: [CSV βœ“] [PDF βœ“] [JSON βœ“]      β”‚
β”‚                                                 β”‚
β”‚  [πŸš€ Analyze Blueprint]        [πŸ’Ύ Save Config]β”‚
β”‚                                                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ πŸ“Š Results (Tabs)                               β”‚
β”‚ [Floors & Units] [Equipment] [Reconciliation] [Downloads] β”‚
β”‚                                                 β”‚
β”‚ β”Œβ”€ Floors & Units ──────────────────────────┐  β”‚
β”‚ β”‚                                            β”‚  β”‚
β”‚ β”‚ Summary Statistics:                        β”‚  β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β” β”‚  β”‚
β”‚ β”‚ β”‚  Floors  β”‚  Units   β”‚ Capacity β”‚ Cost β”‚ β”‚  β”‚
β”‚ β”‚ β”‚    3     β”‚    8     β”‚256kBTU   β”‚$0.08 β”‚ β”‚  β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”˜ β”‚  β”‚
β”‚ β”‚                                            β”‚  β”‚
β”‚ β”‚ Detailed Table:                            β”‚  β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚  β”‚
β”‚ β”‚ β”‚Floorβ”‚Unit IDβ”‚Type         β”‚Qtyβ”‚BTU     β”‚β”‚  β”‚
β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”‚  β”‚
β”‚ β”‚ β”‚  1  β”‚ AC-A  β”‚Ceiling Duct β”‚ 1 β”‚36000   β”‚β”‚  β”‚
β”‚ β”‚ β”‚  1  β”‚ AC-B  β”‚Wall Mount   β”‚ 1 β”‚24000   β”‚β”‚  β”‚
β”‚ β”‚ β”‚  2  β”‚ AC-C  β”‚Ceiling Duct β”‚ 1 β”‚36000   β”‚β”‚  β”‚
β”‚ β”‚ β”‚  2  β”‚ AC-D  β”‚Wall Mount   β”‚ 2 β”‚24000   β”‚β”‚  β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚  β”‚
β”‚ β”‚                                            β”‚  β”‚
β”‚ β”‚ [πŸ“Š Chart View] [πŸ“‹ Table View] [πŸ”„ Refresh]β”‚  β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                 β”‚
β”‚ β”Œβ”€ Downloads ────────────────────────────────┐  β”‚
β”‚ β”‚                                            β”‚  β”‚
β”‚ β”‚ Available Outputs:                         β”‚  β”‚
β”‚ β”‚ β˜‘ Floors & Units (CSV)     [⬇ Download]  β”‚  β”‚
β”‚ β”‚ β˜‘ Equipment Schedule (CSV)  [⬇ Download]  β”‚  β”‚
β”‚ β”‚ β˜‘ Reconciliation (CSV)      [⬇ Download]  β”‚  β”‚
β”‚ β”‚ β˜‘ Analysis Report (PDF)     [⬇ Download]  β”‚  β”‚
β”‚ β”‚                                            β”‚  β”‚
β”‚ β”‚ [πŸ“¦ Download All as ZIP]                   β”‚  β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸš€ IMPLEMENTATION ORDER

Week 1: CSV Output & Basic GUI

  1. Create CSV exporter (all 3 CSV types)
  2. Test CSV output with sample data
  3. Build basic Streamlit app with file upload
  4. Add results display table

Week 2: Full GUI & Visualizations

  1. Add charts and visualizations
  2. Implement tabs (Floors, Schedule, Reconciliation)
  3. Add schedule upload functionality
  4. Create downloads section

Week 3: Polish & Deployment

  1. PDF report generation
  2. A/B testing comparison view
  3. Error handling and validation
  4. Deploy to Streamlit Cloud or cloud provider

πŸ“‹ SUCCESS CRITERIA

CSV Output:

  • βœ… All three CSVs generated successfully
  • βœ… Data is accurate and complete
  • βœ… Columns are properly labeled
  • βœ… No missing values (or clearly marked)

GUI:

  • βœ… File upload works smoothly
  • βœ… Results display in <2 seconds
  • βœ… All tabs functional
  • βœ… Download buttons work
  • βœ… Mobile-responsive (if web)

Integration:

  • βœ… FastAPI endpoint returns CSVs
  • βœ… GUI calls API correctly
  • βœ… Error messages are clear
  • βœ… No hardcoded paths

πŸ”— INTEGRATION WITH FASTAPI

# main.py - FastAPI app with CSV export
from fastapi import FastAPI, UploadFile, File
from fastapi.responses import FileResponse, StreamingResponse
from outputs.csv_exporter import HVACCSVExporter
import zipfile
from io import BytesIO

app = FastAPI()
exporter = HVACCSVExporter()

@app.post("/analyze")
async def analyze_blueprint(file: UploadFile = File(...)):
    """Analyze blueprint and return results"""
    analysis_data = await process_blueprint(file)
    
    # Generate CSVs
    csv_files = exporter.export_all(analysis_data)
    
    return {
        "status": "success",
        "analysis": analysis_data,
        "csv_files": {name: str(path) for name, path in csv_files.items()}
    }

@app.get("/download/csv/{csv_type}")
async def download_csv(csv_type: str, task_id: str):
    """Download specific CSV file"""
    file_path = f"./outputs/{task_id}_{csv_type}.csv"
    return FileResponse(file_path, filename=f"hvac_{csv_type}.csv")

@app.get("/download/all/{task_id}")
async def download_all(task_id: str):
    """Download all outputs as ZIP"""
    zip_buffer = BytesIO()
    with zipfile.ZipFile(zip_buffer, 'w') as zf:
        zf.write(f"./outputs/{task_id}_floors_units.csv")
        zf.write(f"./outputs/{task_id}_equipment_schedule.csv")
        zf.write(f"./outputs/{task_id}_reconciliation.csv")
        zf.write(f"./outputs/{task_id}_report.pdf")
    
    zip_buffer.seek(0)
    return StreamingResponse(
        iter([zip_buffer.getvalue()]),
        media_type="application/zip",
        headers={"Content-Disposition": "attachment; filename=hvac_analysis.zip"}
    )

Checklist:

  • /analyze endpoint returns CSV file paths
  • /download/csv/{type} serves files
  • /download/all/{task_id} creates ZIP
  • Content-Type headers correct
  • Filenames are descriptive
  • Error handling for missing files