File size: 5,915 Bytes
f3f4d58 bc1f545 f3f4d58 bc1f545 712a4b7 bc1f545 712a4b7 bc1f545 712a4b7 bc1f545 f3f4d58 bc1f545 f3f4d58 bc1f545 712a4b7 bc1f545 712a4b7 bc1f545 712a4b7 f3f4d58 bc1f545 f3f4d58 bc1f545 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
import os
import io
import gradio as gr
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime
def plot_ketones(file):
"""
Process uploaded file and create a ketone levels plot over time.
Args:
file: Uploaded file object (CSV or Excel)
Returns:
matplotlib figure as PIL Image
"""
try:
# Read the file
if file is None:
return None, "Please upload a file"
# Get file extension
filename = file.name if hasattr(file, 'name') else 'uploaded_file'
# Read the file based on extension
if filename.endswith('.xlsx') or filename.endswith('.xls'):
df = pd.read_excel(file, engine='openpyxl')
elif filename.endswith('.csv'):
df = pd.read_csv(file)
else:
return None, "Please upload a CSV or Excel file"
# Display column names for debugging
print(f"Columns found: {df.columns.tolist()}")
print(f"First few rows:\n{df.head()}")
# Try to identify date and ketone columns (case-insensitive)
date_col = None
ketone_col = None
for col in df.columns:
col_lower = str(col).lower()
if 'date' in col_lower or 'time' in col_lower:
date_col = col
if 'ketone' in col_lower or 'level' in col_lower or 'value' in col_lower or 'reading' in col_lower or 'sensor' in col_lower:
ketone_col = col
# If not found by name, assume first column is date and second is ketone level
if date_col is None:
date_col = df.columns[0]
if ketone_col is None:
ketone_col = df.columns[1] if len(df.columns) > 1 else df.columns[0]
print(f"Using date column: {date_col}")
print(f"Using ketone column: {ketone_col}")
# Convert date column to datetime
df[date_col] = pd.to_datetime(df[date_col], errors='coerce')
# Remove rows with invalid dates or ketone values
df = df.dropna(subset=[date_col, ketone_col])
# Convert ketone values to numeric
df[ketone_col] = pd.to_numeric(df[ketone_col], errors='coerce')
df = df.dropna(subset=[ketone_col])
# Sort by date
df = df.sort_values(date_col)
if len(df) == 0:
return None, "No valid data found in the file. Please check your data format."
# Create the plot
fig, ax = plt.subplots(figsize=(12, 6))
ax.plot(df[date_col], df[ketone_col], marker='o', linestyle='-',
linewidth=2, markersize=6, color='#FF6B6B', label='Ketone Levels')
# Formatting
ax.set_xlabel('Date', fontsize=12, fontweight='bold')
ax.set_ylabel('Ketone Level (mmol/L)', fontsize=12, fontweight='bold')
ax.set_title('Ketone Levels Over Time', fontsize=14, fontweight='bold', pad=20)
ax.grid(True, alpha=0.3, linestyle='--')
ax.legend(loc='best')
# Format x-axis dates
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax.xaxis.set_major_locator(mdates.AutoDateLocator())
plt.xticks(rotation=45, ha='right')
# Add some padding
plt.tight_layout()
# Save to bytes buffer
buf = io.BytesIO()
plt.savefig(buf, format='png', dpi=150, bbox_inches='tight')
buf.seek(0)
plt.close(fig)
# Create summary stats
summary = f"""
**Data Summary:**
- Total measurements: {len(df)}
- Date range: {df[date_col].min().strftime('%Y-%m-%d')} to {df[date_col].max().strftime('%Y-%m-%d')}
- Average ketone level: {df[ketone_col].mean():.2f} mmol/L
- Min ketone level: {df[ketone_col].min():.2f} mmol/L
- Max ketone level: {df[ketone_col].max():.2f} mmol/L
"""
return buf, summary
except Exception as e:
error_msg = f"Error processing file: {str(e)}\n\nPlease ensure your file has:\n- A date/time column\n- A ketone level column\n- Valid numeric values"
print(f"Error details: {e}")
import traceback
traceback.print_exc()
return None, error_msg
# Create Gradio interface
with gr.Blocks(title="Ketone Level Plotter") as demo:
gr.Markdown("""
# 🔬 Ketone Level Plotter
Upload a CSV or Excel file containing your ketone measurements to visualize trends over time.
**Expected file format:**
- First column: Date/Time (any common date format)
- Second column: Ketone levels (numeric values in mmol/L)
Or use column names containing 'date', 'time' for dates and 'ketone', 'level', or 'value' for measurements.
""")
with gr.Row():
with gr.Column(scale=1):
file_input = gr.File(
label="Upload CSV or Excel file",
file_types=[".csv", ".xlsx", ".xls"],
type="filepath"
)
plot_button = gr.Button("Generate Plot", variant="primary", size="lg")
with gr.Column(scale=2):
image_output = gr.Image(label="Ketone Levels Plot", type="filepath")
summary_output = gr.Markdown(label="Summary Statistics")
gr.Markdown("""
---
### Tips:
- Your file can be either CSV (.csv) or Excel (.xlsx, .xls)
- The app will automatically detect date and ketone columns
- Make sure dates are in a recognizable format (YYYY-MM-DD, MM/DD/YYYY, etc.)
- Ketone levels should be numeric values
""")
# Connect the button to the function
plot_button.click(
fn=plot_ketones,
inputs=[file_input],
outputs=[image_output, summary_output]
)
# Also allow submission by uploading file
file_input.upload(
fn=plot_ketones,
inputs=[file_input],
outputs=[image_output, summary_output]
)
if __name__ == "__main__":
demo.launch()
|