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()