Amol Kaushik commited on
Commit
1656b45
·
1 Parent(s): 505ce90

updated main app for hf

Browse files
Files changed (1) hide show
  1. app.py +229 -7
app.py CHANGED
@@ -1,12 +1,234 @@
1
  import gradio as gr
 
 
 
 
2
 
3
- similar_app = "https://huggingface.co/spaces/sems/pose-think"
 
 
4
 
5
- def greet(name):
6
- return "Hello " + name + "!!"
 
7
 
8
- description_string = """
9
- Simple Demo app that should be developed into a Movement Assessment similar to the [posture analysis](https://huggingface.co/spaces/sems/pose-think).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  """
11
- iface = gr.Interface(fn=greet, inputs="text", outputs="text", description=description_string)
12
- iface.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ import pandas as pd
3
+ import numpy as np
4
+ import pickle
5
+ import os
6
 
7
+ # Paths for HuggingFace deployment (running from root folder)
8
+ MODEL_PATH = "A2/models/champion_model_final.pkl"
9
+ DATA_PATH = "A2/A2_dataset.csv"
10
 
11
+ model = None
12
+ FEATURE_NAMES = None
13
+ MODEL_METRICS = None
14
 
15
+
16
+ def load_champion_model():
17
+ global model, FEATURE_NAMES, MODEL_METRICS
18
+
19
+ possible_paths = [
20
+ MODEL_PATH,
21
+ "A2/models/champion_model_final.pkl",
22
+ "../A2/models/champion_model_final.pkl",
23
+ ]
24
+
25
+ for path in possible_paths:
26
+ if os.path.exists(path):
27
+ print(f"Loading champion model from {path}")
28
+ with open(path, "rb") as f:
29
+ artifact = pickle.load(f)
30
+
31
+ model = artifact["model"]
32
+ FEATURE_NAMES = artifact["feature_columns"]
33
+ MODEL_METRICS = artifact.get("test_metrics", {})
34
+
35
+ print(f"model loaded successfully")
36
+ print(f"Features: {len(FEATURE_NAMES)} columns")
37
+ print(f"Test R2: {MODEL_METRICS.get('r2', 'N/A')}")
38
+ return True
39
+
40
+ print("champion model not found")
41
+ return False
42
+
43
+
44
+ load_champion_model()
45
+
46
+
47
+ # prediction function
48
+ def predict_score(*feature_values):
49
+ if model is None:
50
+ return "Error", "Model not loaded"
51
+
52
+ # Convert inputs to dataframe with correct feature names
53
+ features_df = pd.DataFrame([feature_values], columns=FEATURE_NAMES)
54
+
55
+ raw_score = model.predict(features_df)[0]
56
+
57
+ # score to valid range and change to %
58
+ score = max(0, min(1, raw_score)) * 100
59
+
60
+ if score >= 80:
61
+ interpretation = "Excellent, great squat form"
62
+ elif score >= 60:
63
+ interpretation = "Good, minor improvements needed"
64
+ elif score >= 40:
65
+ interpretation = "Average, a lot of areas to work on"
66
+ else:
67
+ interpretation = "Needs work, focus on proper form"
68
+
69
+ # Create output
70
+ r2 = MODEL_METRICS.get('r2', 'N/A')
71
+ correlation = MODEL_METRICS.get('correlation', 'N/A')
72
+
73
+ # Format metrics
74
+ r2_str = f"{r2:.4f}" if isinstance(r2, (int, float)) else str(r2)
75
+ corr_str = f"{correlation:.4f}" if isinstance(correlation, (int, float)) else str(correlation)
76
+
77
+ details = f"""
78
+ ### Prediction Details
79
+ - **Raw Model Output:** {raw_score:.4f}
80
+ - **Normalized Score:** {score:.1f}%
81
+ - **Assessment:** {interpretation}
82
+
83
+ ### Model Performance
84
+ - **Test R-squared:** {r2_str}
85
+ - **Test Correlation:** {corr_str}
86
+
87
+ *Lower deviation values = better form*
88
+ """
89
+
90
+ return f"{score:.1f}%", interpretation, details
91
+
92
+
93
+ # load example for tesitng
94
+ def load_example():
95
+ if FEATURE_NAMES is None:
96
+ return [0.5] * 35
97
+
98
+ try:
99
+ possible_paths = [
100
+ DATA_PATH,
101
+ "A2/A2_dataset.csv",
102
+ "../A2/A2_dataset.csv",
103
+ "../Datasets_all/A2_dataset_80.csv",
104
+ ]
105
+
106
+ df = None
107
+ for path in possible_paths:
108
+ if os.path.exists(path):
109
+ df = pd.read_csv(path)
110
+ break
111
+
112
+ # Get a random row with only the features we need
113
+ available_features = [f for f in FEATURE_NAMES if f in df.columns]
114
+ sample = df[available_features].sample(1).values[0]
115
+ # Convert to float list to ensure proper types for Gradio sliders
116
+ return [float(x) for x in sample]
117
+ except Exception as e:
118
+ print(f"Error loading example: {e}")
119
+ return [0.5] * len(FEATURE_NAMES)
120
+
121
+
122
+ # create gradio interface
123
+ def create_interface():
124
+ if FEATURE_NAMES is None:
125
+ return gr.Interface(
126
+ fn=lambda: "Model not loaded",
127
+ inputs=[],
128
+ outputs="text",
129
+ title="Error: Model not loaded"
130
+ )
131
+
132
+ # Create input sliders for features
133
+ inputs = []
134
+ for name in FEATURE_NAMES:
135
+ slider = gr.Slider(
136
+ minimum=0,
137
+ maximum=1,
138
+ value=0.5,
139
+ step=0.01,
140
+ label=name.replace("_", " "),
141
+ )
142
+ inputs.append(slider)
143
+
144
+ # Build the interface
145
+ description = """
146
+ ## Deep Squat Movement Assessment
147
+
148
+ **How to use:**
149
+ 1. Adjust the sliders to input deviation values (0 = no deviation, 1 = maximum deviation)
150
+ 2. Click "Submit" to get your predicted score
151
+ 3. Or click "Load Random Example" to test with real data
152
+
153
+ **Score Interpretation:**
154
+ - 80-100%: Excellent form
155
+ - 60-79%: Good form
156
+ - 40-59%: Average form
157
+ - 0-39%: Needs improvement
158
  """
159
+
160
+ # features into categories
161
+ angle_features = [n for n in FEATURE_NAMES if "Angle" in n]
162
+ nasm_features = [n for n in FEATURE_NAMES if "NASM" in n]
163
+ time_features = [n for n in FEATURE_NAMES if "Time" in n]
164
+
165
+ # Get indices for each category
166
+ angle_indices = [FEATURE_NAMES.index(f) for f in angle_features]
167
+ nasm_indices = [FEATURE_NAMES.index(f) for f in nasm_features]
168
+ time_indices = [FEATURE_NAMES.index(f) for f in time_features]
169
+
170
+ # Create the main interface
171
+ with gr.Blocks(title="Deep Squat Assessment") as demo:
172
+ gr.Markdown("# Deep Squat Movement Assessment")
173
+ gr.Markdown(description)
174
+
175
+ with gr.Row():
176
+ with gr.Column(scale=2):
177
+ gr.Markdown("### Input Features")
178
+ gr.Markdown(f"*{len(FEATURE_NAMES)} features loaded from champion model*")
179
+ gr.Markdown("*Deviation values: 0 = perfect, 1 = maximum deviation*")
180
+
181
+ with gr.Tabs():
182
+ with gr.TabItem(f"Angle Deviations ({len(angle_indices)})"):
183
+ for idx in angle_indices:
184
+ inputs[idx].render()
185
+
186
+ with gr.TabItem(f"NASM Deviations ({len(nasm_indices)})"):
187
+ for idx in nasm_indices:
188
+ inputs[idx].render()
189
+
190
+ with gr.TabItem(f"Time Deviations ({len(time_indices)})"):
191
+ for idx in time_indices:
192
+ inputs[idx].render()
193
+
194
+ with gr.Column(scale=1):
195
+ gr.Markdown("### Results")
196
+ score_output = gr.Textbox(label="Predicted Score")
197
+ interp_output = gr.Textbox(label="Assessment")
198
+ details_output = gr.Markdown(label="Details")
199
+
200
+ with gr.Row():
201
+ submit_btn = gr.Button("Submit", variant="primary")
202
+ example_btn = gr.Button("Load Random Example")
203
+ clear_btn = gr.Button("Clear")
204
+
205
+ submit_btn.click(
206
+ fn=predict_score,
207
+ inputs=inputs,
208
+ outputs=[score_output, interp_output, details_output],
209
+ )
210
+
211
+ example_btn.click(
212
+ fn=load_example,
213
+ inputs=[],
214
+ outputs=inputs
215
+ )
216
+
217
+ clear_btn.click(
218
+ fn=lambda: [0.5] * len(FEATURE_NAMES) + ["", "", ""],
219
+ inputs=[],
220
+ outputs=inputs + [score_output, interp_output, details_output],
221
+ )
222
+
223
+ return demo
224
+
225
+
226
+ # Create the interface
227
+ demo = create_interface()
228
+
229
+ if __name__ == "__main__":
230
+ demo.launch(
231
+ share=False,
232
+ server_name="0.0.0.0",
233
+ server_port=7860,
234
+ )