saraht14 commited on
Commit
f5e2323
·
verified ·
1 Parent(s): 829b2a9

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +502 -0
app.py ADDED
@@ -0,0 +1,502 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # change the eval ftn to take a list of lists
2
+ import gradio as gr
3
+ import pandas as pd
4
+ import time
5
+ import torch
6
+ import os
7
+ import torchvision.transforms as transforms
8
+ from torchvision import datasets
9
+ import torch.nn.functional as F
10
+ from torch.utils.data import DataLoader
11
+ import subprocess
12
+ # from dummy_eval import foo
13
+ import zipfile
14
+ import shutil
15
+ import numpy as np
16
+ import importlib.util
17
+ import inspect
18
+ from huggingface_hub import HfApi
19
+ from datasets import load_dataset, Dataset
20
+ from huggingface_hub import login
21
+ import requests
22
+ import matplotlib
23
+ matplotlib.use("Agg")
24
+
25
+ def fetch_required_files(exp_config):
26
+ # os.makedirs("temp_data", exist_ok=True)
27
+ for key in exp_config:
28
+ file_path = exp_config[key]['file']
29
+ url = f"https://saraht14-server.hf.space/file/{file_path}.txt"
30
+
31
+ filename_only = os.path.basename(file_path) + ".txt"
32
+ local_path = os.path.join("./", filename_only)
33
+
34
+ downloaded = download_file(url, local_path)
35
+ if not downloaded:
36
+ raise Exception(f"Could not download file: {file_path}")
37
+
38
+ exp_config[key]["local_file"] = local_path
39
+
40
+ return exp_config
41
+
42
+
43
+ def call_flask_server(username):
44
+ url = "https://saraht14-server.hf.space/"
45
+
46
+ try:
47
+ response = requests.get(url)
48
+ result = response.json()
49
+ print("Flask response:", result)
50
+ return result.get("result", "No result")
51
+ except Exception as e:
52
+ print("Failed to contact Flask server:", e)
53
+ return f"Error contacting server: {e}"
54
+ call_flask_server("sarah")
55
+ def download_file(url, local_path):
56
+ try:
57
+ r = requests.get(url, headers={"Authorization": f"Bearer {HF_TOKEN}"})
58
+ r.raise_for_status()
59
+ with open(local_path, 'wb') as f:
60
+ f.write(r.content)
61
+ return local_path
62
+ except Exception as e:
63
+ print(f"Error downloading file from {url}: {e}")
64
+ return None
65
+ # def log_submission_request(username, zip_file):
66
+ # try:
67
+ # requests_ds = load_dataset("IndoorOutdoor/requests", split="train")
68
+ # except Exception as e:
69
+ # print("Could not load requests dataset, creating a new one.", e)
70
+ # requests_ds = Dataset.from_dict({"username": [], "timestamp": [], "zip_filename": []})
71
+
72
+ # new_entry = {"username": username,
73
+ # "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
74
+ # "zip_filename": os.path.basename(zip_file.name)}
75
+
76
+ # updated_requests = requests_ds.add_item(new_entry)
77
+
78
+ # updated_requests.push_to_hub("IndoorOutdoor/requests", token=HF_TOKEN)
79
+ # print("Logged submission request to the requests dataset.")
80
+ # def update_results_dataset(leaderboard_df):
81
+ repo_id = "saraht14/responses"
82
+ def update_results_dataset(new_row_df):
83
+ repo_id = "saraht14/responses"
84
+
85
+ try:
86
+ leaderboard_dataset = load_dataset(repo_id, split="train", token=HF_TOKEN)
87
+ leaderboard_df = leaderboard_dataset.to_pandas()
88
+ updated_df = pd.concat([leaderboard_df, new_row_df], ignore_index=True)
89
+ updated_dataset = Dataset.from_pandas(updated_df)
90
+ updated_dataset.push_to_hub(repo_id, token=HF_TOKEN)
91
+ print("New row(s) added to existing leaderboard dataset.")
92
+ return updated_dataset
93
+ except Exception as e:
94
+ print("Dataset not found or failed to load, creating a new one.")
95
+ try:
96
+ new_dataset = Dataset.from_pandas(new_row_df)
97
+ new_dataset.push_to_hub(repo_id, token=HF_TOKEN)
98
+ return new_dataset
99
+ print("New leaderboard dataset created and uploaded.")
100
+ except Exception as inner_e:
101
+ print("Failed to create and push new leaderboard dataset:", inner_e)
102
+
103
+
104
+
105
+ # Info to change for your repository
106
+ # ----------------------------------
107
+ HF_TOKEN = os.environ.get("HF_TOKEN") # A read/write token for your org
108
+ print(f"{HF_TOKEN}")
109
+ OWNER = "IndoorOutdoor" # Change to your org - don't forget to create a results and request dataset, with the correct format!
110
+ # ----------------------------------
111
+
112
+ REPO_ID = f"{OWNER}/leaderboard"
113
+ QUEUE_REPO = f"{OWNER}/requests"
114
+ RESULTS_REPO = f"{OWNER}/results"
115
+ global_error_message = "Ready for submission!"
116
+ # def set_error_message(message):
117
+ # global global_error_message
118
+ # global_error_message = message
119
+ # print("ERROR UPDATED:", global_error_message) # Debugging
120
+
121
+ def get_error_message():
122
+ return global_error_message
123
+
124
+ def install_requirements(file_path):
125
+ try:
126
+ with open(file_path, "r") as file:
127
+ requirements = file.readlines()
128
+
129
+ for req in requirements:
130
+ package = req.strip()
131
+ if package:
132
+ subprocess.run(["pip", "install", package], check=True)
133
+ print(f"Installed: {package}")
134
+
135
+ print("All requirements installed successfully.")
136
+
137
+ except FileNotFoundError:
138
+ print(f"Error: {file_path} not found.")
139
+ except subprocess.CalledProcessError as e:
140
+ print(f"Installation failed: {e}")
141
+ HEADERS = ["Username", "Execution Time (s)", "Accuracy", "TP", "FP", "FN", "TN", "Status"]
142
+ BASE = {'ottawa':(45.30326753851309,-75.93640391349997),
143
+ 'ali_home':(37.88560412289598,-122.30218612514359),
144
+ 'josh_home':(37.8697406, -122.30218612514359),
145
+ 'cory':(37.8697406,-122.281570)}
146
+
147
+ def get_base(filename):
148
+ if "home" in filename:
149
+ return BASE["ali_home"]
150
+ elif "ottawa" in filename:
151
+ return BASE["ottawa"]
152
+ elif "josh" in filename:
153
+ return BASE["josh_home"]
154
+ else:
155
+ return BASE["cory"]
156
+
157
+ metadata_path = "metadata.csv"
158
+ dir = ""
159
+ df = pd.read_csv(metadata_path)
160
+
161
+ print(df.head())
162
+ def fetch_lb():
163
+ try:
164
+ leaderboard_dataset = load_dataset("saraht14/responses", split="train", token=HF_TOKEN)
165
+ leaderboard_data = leaderboard_dataset.to_pandas()
166
+ leaderboard_data = leaderboard_data[HEADERS] # keep it ordered
167
+ leaderboard_data = leaderboard_data.sort_values(by=["Accuracy", "Execution Time (s)"], ascending=[False, True])
168
+ except Exception as e:
169
+ print(f"Error loading leaderboard:", e)
170
+ leaderboard_data = pd.DataFrame(columns=HEADERS)
171
+
172
+ print(f"THIS IS THE LEADERBOARD:\n{leaderboard_data}")
173
+ return leaderboard_data
174
+
175
+
176
+ leaderboard_data = fetch_lb()
177
+
178
+ def compute_stats_sector(sectors_model, sector_gt):
179
+ TP = FP = FN = TN = 0
180
+ ignored = 0
181
+ for i in range(len(sector_gt)):
182
+ if sector_gt[i] == 1:
183
+ if sectors_model[i] > 0 or sectors_model[(i+1) % 8] > 0 or sectors_model[(i-1) % 8] > 0 :
184
+ TP += 1
185
+ else:
186
+ FN += 1
187
+ else:
188
+ if sectors_model[i] > 0:
189
+ if sector_gt[(i-1) % 8] > 0 or sector_gt[(i+1) % 8] > 0:
190
+ TP += 1
191
+ continue
192
+ FP += 1
193
+ else:
194
+ TN += 1
195
+ NUM_SECTORS = 8 - ignored
196
+ return [TP / NUM_SECTORS, FP / NUM_SECTORS, FN / NUM_SECTORS, TN / NUM_SECTORS]
197
+
198
+ #Compare the model output with ground truth
199
+ #return TP, FP, FN, TN
200
+ #This fuction compute stats when the model is binary i.e., outputs only indoor vs outdoor
201
+ def compute_stats_in_out(sectors_model, indoor_gt):
202
+ if indoor_gt: #if groundtruth is indoor
203
+ for i in range(len(sectors_model)):
204
+ if sectors_model[i]:
205
+ return [0,1,0,0]
206
+ return [0,0,0,1]
207
+ else: #if outdoor
208
+ for i in range(len(sectors_model)):
209
+ if sectors_model[i]:
210
+ return [1,0,0,0]
211
+ return [0,0,1,0]
212
+
213
+ def read_configuration(filename):
214
+ print("read config")
215
+ with open(filename, 'r') as file:
216
+ data = file.read().split('\n')
217
+ data = data[1:] #ignore the header
218
+ print("head", data)
219
+ exp = {}
220
+ for line in data:
221
+ if len(line) == 0:
222
+ continue
223
+ tokens =line.split(',')
224
+ file = tokens[0]
225
+ scenario = tokens[1]
226
+ indoor = True if tokens[2] == "TRUE" else 0
227
+
228
+ exp[scenario] = {'sectors':[1 if x == "TRUE" else 0 for x in tokens[3:]], 'indoor':indoor, "file":file}
229
+ return exp
230
+
231
+
232
+
233
+
234
+ def evaluate_model(username, file):
235
+ print("evaluating...")
236
+ global leaderboard_data
237
+
238
+ username = username.strip()
239
+ if not username:
240
+ return leaderboard_data.values.tolist()
241
+
242
+ script_path = f"submissions/{username}.py"
243
+ os.makedirs("submissions", exist_ok=True)
244
+
245
+ # # Get the file path from the NamedString object
246
+ # file_path = file.name # Get the actual file path
247
+ # print("file_path:", file_path)
248
+ # with open(script_path, "wb") as f:
249
+ # with open(file_path, "rb") as uploaded_file:
250
+ # f.write(uploaded_file.read())
251
+
252
+
253
+
254
+ # script_path = f"submissions/{username}.py"
255
+ # os.makedirs("submissions", exist_ok=True)
256
+ # with open(script_path, "wb") as f:
257
+ # f.write(file.read())
258
+
259
+ try:
260
+
261
+ exp = read_configuration("metadata.csv")
262
+ print(f"FIRST: {len(exp)}")
263
+ exp = fetch_required_files(exp)
264
+ print(f"SECOND: {len(exp)}")
265
+
266
+ start_time = time.time()
267
+ stats_model_sectors = []
268
+ stats_model_in_out = []
269
+
270
+ for key in exp:
271
+ filename = exp[key]['file']
272
+ indoor_gt = exp[key]['indoor']
273
+ sectors_gt = exp[key]["sectors"]
274
+
275
+ # file_path = os.path.join(dataset_directory, filename)
276
+ # print(file_path)
277
+ filename = filename + ".txt"
278
+ print("FILE TO PROCESS:", filename)
279
+ # filename_url = f"https://saraht14-server.hf.space/file/{filename}"
280
+ # local_txt_path = f"./{filename}.txt"
281
+ # os.makedirs("temp_data", exist_ok=True)
282
+ local_file_path = exp[key]["local_file"]
283
+ # downloaded = download_file(filename_url, local_txt_path)
284
+
285
+ # if not downloaded:
286
+ # raise Exception("Failed to fetch remote file.")
287
+ # sectors_model = subprocess.run(["python", script_path,filename], capture_output=True, text=True, timeout=300)
288
+ # hello = foo()
289
+ # print(f"HELLO: {hello}")
290
+ # import
291
+ sectors_model = import_and_run_function(file, "evaluate", local_file_path)
292
+ try:
293
+ os.remove(local_file_path)
294
+ except Exception as e:
295
+ print(f"Warning: Couldn't delete {local_file_path} — {e}")
296
+ # print(status)
297
+ print(f"TYPE: {type(sectors_model), {type(sectors_model[0])}}")
298
+
299
+
300
+ print("SECTORS MODEL: ", sectors_model)
301
+ # sectors_model = eval(filename)
302
+ # print(sectors_model)
303
+ # sectors_model = model_based_clustering(dataset_directory, filename)
304
+
305
+ stats_model_sectors.append(compute_stats_sector(sectors_model, sectors_gt))
306
+ stats_model_in_out.append(compute_stats_in_out(sectors_model, indoor_gt))
307
+
308
+ execution_time = round(time.time() - start_time, 4)
309
+ print("calculating summary stats")
310
+ TP = np.mean([x[0] for x in stats_model_sectors])
311
+ FP = np.mean([x[1] for x in stats_model_sectors])
312
+ FN = np.mean([x[2] for x in stats_model_sectors])
313
+ TN = np.mean([x[3] for x in stats_model_sectors])
314
+ print("calculating exec stats")
315
+
316
+ accuracy = round((TP + TN) / (TP + TN + FP + FN), 2)
317
+
318
+ status = "Success" if accuracy > 0 else "Incorrect Model"
319
+ # ["Username", "Execution Time (s)", "Accuracy", "True Positive", "False Positive", "False Negative", "False Positive", "Status"]
320
+ except Exception as e:
321
+ leaderboard_data = pd.concat([leaderboard_data, pd.DataFrame([[username, float("inf"), 0,-1,-1,-1,-1, f"Model Error: {str(e)}"]],
322
+ columns=HEADERS)], ignore_index=True)
323
+ return leaderboard_data.values.tolist()
324
+ print("calculating new entry")
325
+
326
+ new_entry = pd.DataFrame([[username, execution_time, accuracy, TP, FP, FN, TN, status]],
327
+ columns=HEADERS)
328
+ print("updating new entry")
329
+ leaderboard_data = update_results_dataset(new_entry)
330
+ # leaderboard_data = pd.concat([leaderboard_data, new_entry], ignore_index=True)
331
+ leaderboard_data = leaderboard_data.to_pandas() if leaderboard_data is not None else None
332
+ if leaderboard_data is not None:
333
+ leaderboard_data = leaderboard_data.sort_values(by=["Accuracy", "Execution Time (s)"], ascending=[False, True]).reset_index(drop=True)
334
+ print(f"DATA: {leaderboard_data}")
335
+ return leaderboard_data.values.tolist()
336
+
337
+
338
+ def import_and_run_function(script_path, function_name, filename):
339
+
340
+
341
+ if not os.path.exists(script_path):
342
+ set_error_message(f"Error: {script_path} not found.")
343
+ return None
344
+
345
+
346
+ if not script_path.endswith(".py"):
347
+ set_error_message("Error: Provided file is not a Python script.")
348
+ return None
349
+
350
+ module_name = os.path.splitext(os.path.basename(script_path))[0]
351
+
352
+ try:
353
+ spec = importlib.util.spec_from_file_location(module_name, script_path)
354
+ module = importlib.util.module_from_spec(spec)
355
+ spec.loader.exec_module(module)
356
+ except SyntaxError as e:
357
+ set_error_message(f"Error: Syntax error in the script - {e}")
358
+ return None
359
+ except ImportError as e:
360
+ set_error_message(f"Error: Import issue in the script - {e}")
361
+ return None
362
+ except Exception as e:
363
+ set_error_message(f"Error: Failed to import script - {e}")
364
+ return None
365
+
366
+
367
+ if not hasattr(module, function_name):
368
+ set_error_message(f"Error: Function '{function_name}' not found in '{script_path}'.")
369
+ return None
370
+
371
+ function_to_run = getattr(module, function_name)
372
+
373
+ try:
374
+ sig = inspect.signature(function_to_run)
375
+ params = list(sig.parameters.values())
376
+ if len(params) != 1 or params[0].kind not in [inspect.Parameter.POSITIONAL_OR_KEYWORD]:
377
+ set_error_message(f"Error: Function '{function_name}' must have exactly one parameter (filepath).")
378
+ return None
379
+ except Exception as e:
380
+ set_error_message(f"Error: Unable to inspect function signature - {e}")
381
+ return None
382
+
383
+ try:
384
+ result = function_to_run(filename)
385
+ print(f"TYPE: {type(result), {type(result[0])}}, RESULT: {result}")
386
+ except Exception as e:
387
+ set_error_message(f"Error: Function '{function_name}' raised an error during execution - {e}")
388
+ return None
389
+
390
+ if not isinstance(result, list):
391
+ set_error_message(f"Error: Function '{function_name}' must return a list.")
392
+ return None
393
+
394
+ if len(result) != 8:
395
+ set_error_message(f"Error: Function '{function_name}' must return a list of exactly 8 elements.")
396
+ return None
397
+
398
+ if not all(isinstance(x, int) and x in [0, 1] for x in result):
399
+ return f"Error: Function '{function_name}' must return a list of 8 integers, each 0 or 1.", None
400
+
401
+ print(f"Function '{function_name}' executed successfully. Output: {result}")
402
+ # set_error_message(f"Function '{function_name}' executed successfully.")
403
+ return result
404
+
405
+
406
+
407
+
408
+ def update_leaderboard(username, zip_file):
409
+ if not zip_file:
410
+ set_error_message("No file uploaded.")
411
+ return get_error_message(), None
412
+
413
+ zip_path = zip_file.name
414
+ extract_path = os.path.join("", username)
415
+ # if not os.path.exists(extract_path):
416
+ # os.makedirs(extract_path)
417
+
418
+ try:
419
+ if not os.path.exists(extract_path):
420
+ os.makedirs(extract_path)
421
+
422
+ except OSError:
423
+ set_error_message("Error creating directory for extraction.")
424
+ return get_error_message(), None
425
+
426
+ try:
427
+ with zipfile.ZipFile(zip_path, "r") as zip_ref:
428
+ zip_ref.extractall(extract_path)
429
+ except zipfile.BadZipFile:
430
+ return "Invalid ZIP file.", None
431
+
432
+ except Exception as e:
433
+ return f"Error extracting ZIP file: {str(e)}", None
434
+
435
+
436
+ extracted_files = os.listdir(extract_path)
437
+ print("EXTRACTED FILES:", extracted_files)
438
+
439
+ req_file = os.path.join(extract_path, "user_reqs.txt")
440
+
441
+ if "user_reqs.txt" not in extracted_files:
442
+ return "Missing user_reqs.txt in ZIP file.", None
443
+ try:
444
+ install_requirements(req_file)
445
+ except Exception as e:
446
+ return f"Error installing dependencies: {str(e)}", None
447
+
448
+
449
+
450
+ # for file in os.listdir(extract_path):
451
+ # if file.endswith(".py"):
452
+ # python_script = os.path.join(extract_path, file)
453
+ # break
454
+ python_script = os.path.join(extract_path, "main.py")
455
+
456
+ if "main.py" not in extracted_files:
457
+ return "No Python script (main.py) found in ZIP.", None
458
+
459
+
460
+ # if not python_script:
461
+ # return "No Python script found in ZIP."
462
+
463
+ if "main.py" not in extracted_files:
464
+ return "No Python script (main.py) found in ZIP.", None
465
+
466
+ try:
467
+ updated_leaderboard = evaluate_model(username, python_script)
468
+ except Exception as e:
469
+ print("Error in eval mode:", str(e))
470
+ return f"Error evaluating model: {str(e)}", None
471
+
472
+ # log_submission_request(username, zip_file)
473
+ return "Submission successful!", updated_leaderboard
474
+
475
+
476
+
477
+ with gr.Blocks() as demo:
478
+
479
+ gr.Markdown("# 🚀 Model Submission & Leaderboard (Hugging Face Spaces)")
480
+
481
+ with gr.Row():
482
+ username_input = gr.Textbox(label="Username")
483
+ file_input = gr.File(label="Upload Zip File")
484
+ submit_button = gr.Button("Submit File")
485
+
486
+ status_output = gr.Textbox(label="Status", interactive=False)
487
+
488
+ with gr.Row():
489
+ leaderboard_display = gr.Dataframe(
490
+ headers=HEADERS,
491
+ value=fetch_lb,
492
+ label="Leaderboard"
493
+ )
494
+
495
+
496
+ submit_button.click(fn=update_leaderboard,
497
+ inputs=[username_input, file_input],
498
+ outputs=[status_output, leaderboard_display])
499
+
500
+ status_output.change(fn=get_error_message, inputs=[], outputs=status_output)
501
+
502
+ demo.launch()