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`
```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**:
```python
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`
```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`
```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**
```python
# 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**
```python
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**
```python
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)
```python
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**
```python
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
```python
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
```json
{
"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:**
```bash
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:**
```bash
# 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
```python
# 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
5. [ ] Add charts and visualizations
6. [ ] Implement tabs (Floors, Schedule, Reconciliation)
7. [ ] Add schedule upload functionality
8. [ ] Create downloads section
### Week 3: Polish & Deployment
9. [ ] PDF report generation
10. [ ] A/B testing comparison view
11. [ ] Error handling and validation
12. [ ] 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
```python
# 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