File size: 5,135 Bytes
281711d
 
 
 
2982a51
281711d
 
8efd41a
b20af37
281711d
 
51aaefc
 
281711d
 
51aaefc
fb695b7
51aaefc
b20af37
956b725
281711d
8efd41a
281711d
 
 
8efd41a
281711d
 
 
 
 
 
 
 
 
0c144dc
281711d
 
0c144dc
 
8efd41a
 
f3c8f85
8efd41a
956b725
8efd41a
 
f3c8f85
b20af37
8efd41a
0c144dc
 
 
 
 
2a0354e
0c144dc
8efd41a
b20af37
8efd41a
 
 
0c144dc
8efd41a
0c144dc
b20af37
 
281711d
b20af37
956b725
281711d
 
 
 
0c144dc
281711d
 
 
b20af37
 
 
 
 
 
 
 
956b725
 
 
2982a51
 
956b725
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2982a51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
281711d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8efd41a
281711d
 
 
2982a51
 
 
 
 
 
 
 
 
 
 
 
281711d
 
 
 
 
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
import pathlib
import tempfile
from typing import BinaryIO, Literal
import json
import pandas as pd

import gradio as gr
from datasets import load_dataset, Dataset
from huggingface_hub import upload_file, hf_hub_download
from evaluation import evaluate_problem
from datetime import datetime
import os
from huggingface_hub import HfApi

PROBLEM_TYPES = ["geometrical", "simple_to_build", "mhd_stable"]
TOKEN = os.environ.get("HF_TOKEN")
CACHE_PATH=os.getenv("HF_HOME", ".")
API = HfApi(token=TOKEN)
submissions_repo = "cgeorgiaw/constellaration-submissions"
results_repo = "cgeorgiaw/constellaration-results"

def submit_boundary(
    problem_type: Literal["geometrical", "simple_to_build", "mhd_stable"],
    boundary_file: BinaryIO,
) -> str:
    
    file_path = boundary_file.name
    if not file_path:
        return "Error: Uploaded file object does not have a valid file path."
    
    path_obj = pathlib.Path(file_path)
    timestamp = datetime.utcnow().isoformat()

    with (
        path_obj.open("rb") as f_in,
        tempfile.NamedTemporaryFile(delete=False, suffix=".json") as tmp_boundary,
    ):
        file_content = f_in.read()
        tmp_boundary.write(file_content)
        tmp_boundary_path = pathlib.Path(tmp_boundary.name)

        # write to dataset
        filename = f"{problem_type}/{timestamp.replace(':', '-')}_{problem_type}.json"
        record = {
            "submission_filename": filename,
            "submission_time": timestamp,
            "problem_type": problem_type,
            "boundary_json": file_content.decode("utf-8"),
            "evaluated": False,
        }
        with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as tmp:
            json.dump(record, tmp, indent=2)
            tmp.flush()
            tmp_name = tmp.name

        API.upload_file(
            path_or_fileobj=tmp_name, 
            path_in_repo=filename,
            repo_id=submissions_repo,
            repo_type="dataset",
            commit_message=f"Add submission for {problem_type} at {timestamp}"
        )
        pathlib.Path(tmp_name).unlink()

    # then do eval
    local_path = read_boundary(filename)

    try:
        result = evaluate_problem(problem_type, local_path)
        write_results(record, result)
        output = str(result)
    except Exception as e:
        output = f"Error during evaluation:\n{e}"
    finally:
        tmp_boundary_path.unlink()

    return output

def read_boundary(filename):
    local_path = hf_hub_download(
        repo_id=submissions_repo,
        repo_type="dataset",
        filename=filename,
    )
    return local_path

def write_results(record, result):
    record.update(result)
    record['result_filename'] = record['submission_filename'].strip('.json') + '_results.json'
    record['evaluated'] = True

    with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as tmp:
        json.dump(record, tmp, indent=2)
        tmp.flush()
        tmp_name = tmp.name
    
    API.upload_file(
            path_or_fileobj=tmp_name, 
            path_in_repo=record['result_filename'],
            repo_id=results_repo,
            repo_type="dataset",
            commit_message=f"Add result data for {record['result_filename']}"
        )
    
    pathlib.Path(tmp_name).unlink()
    return


def get_leaderboard(problem_type: str):
    ds = load_dataset(results_repo, split=problem_type)

    filtered = ds.filter(lambda x: x["evaluated"])

    if len(filtered) == 0:
        return pd.DataFrame(columns=["submission_time", "problem_type", "score"])

    df = pd.DataFrame(filtered)
    score_field = "score" if "score" in df.columns else "objective"  # fallback

    df = df.sort_values(by=score_field, ascending=True)
    leaderboard = df[["submission_time", "problem_type", score_field]].reset_index(drop=True)
    return leaderboard

def gradio_interface() -> gr.Blocks:
    with gr.Blocks() as demo:
        gr.Markdown(
            """
        # Plasma Boundary Evaluation App
        Upload your plasma boundary JSON and select the problem type to get your score.
        """
        )
        with gr.Row():
            problem_type = gr.Dropdown(
                PROBLEM_TYPES, label="Problem Type", value="geometrical"
            )
            boundary_file = gr.File(label="Boundary JSON File (.json)")

        boundary_file
        output = gr.Textbox(label="Evaluation Result", lines=10)
        submit_btn = gr.Button("Evaluate")
        submit_btn.click(
            submit_boundary,
            inputs=[problem_type, boundary_file],
            outputs=output,
        )

        with gr.Row():
            leaderboard_type = gr.Dropdown(PROBLEM_TYPES, label="Leaderboard Problem Type", value="geometrical")
            leaderboard_btn = gr.Button("Load Leaderboard")

        leaderboard_df = gr.Dataframe(label="Leaderboard")

        leaderboard_btn.click(
            lambda pt: get_leaderboard(pt).to_dict(orient="records"),
            inputs=[leaderboard_type],
            outputs=[leaderboard_df]
        )
    return demo


if __name__ == "__main__":
    gradio_interface().launch()