|
import gradio as gr |
|
import plotly.graph_objects as go |
|
from huggingface_hub import hf_hub_download |
|
from datasets import load_dataset |
|
import pathlib |
|
import json |
|
import pandas as pd |
|
from evaluation import load_boundary, load_boundaries |
|
from constellaration import forward_model, initial_guess |
|
from constellaration.boozer import boozer |
|
from constellaration.utils import ( |
|
file_exporter, |
|
visualization, |
|
visualization_utils, |
|
) |
|
|
|
|
|
organization = 'proxima-fusion' |
|
results_repo = f'{organization}/constellaration-bench-results' |
|
|
|
def read_result_from_hub(filename): |
|
local_path = hf_hub_download( |
|
repo_id=results_repo, |
|
repo_type="dataset", |
|
filename=filename, |
|
) |
|
return local_path |
|
|
|
def make_boundary_plot(boundary): |
|
boundary_ax = visualization.plot_boundary(boundary) |
|
boundary_plot = boundary_ax.get_figure() |
|
return boundary_plot |
|
|
|
def make_interactive_plot(boundary): |
|
interactive_plot = visualization.plot_surface(boundary) |
|
return interactive_plot |
|
|
|
def make_boozer_plot(boundary): |
|
settings = forward_model.ConstellarationSettings.default_high_fidelity_skip_qi() |
|
boundary_metrics, boundary_equilibrium = forward_model.forward_model( |
|
boundary, settings=settings |
|
) |
|
boozer_settings = boozer.BoozerSettings(normalized_toroidal_flux=[0.0, 0.25, 1]) |
|
boozer_plot = visualization.plot_boozer_surfaces( |
|
boundary_equilibrium, settings=boozer_settings |
|
) |
|
return |
|
|
|
def make_flux_surface_plot(boundary): |
|
settings = forward_model.ConstellarationSettings.default_high_fidelity_skip_qi() |
|
boundary_metrics, boundary_equilibrium = forward_model.forward_model( |
|
boundary, settings=settings |
|
) |
|
flux_surface_plot = visualization.plot_flux_surfaces( |
|
boundary_equilibrium, boundary |
|
) |
|
return flux_surface_plot |
|
|
|
def gradio_interface() -> gr.Blocks: |
|
with gr.Blocks() as demo: |
|
gr.Markdown(""" |
|
# Welcome to the ConStellaration Boundary Explorer! |
|
|
|
### Here, you can visualize submissions to the ConStellaration Leaderboard, generate and visualize new random boundaries, or upload and visualize your own! |
|
|
|
If you want to explore additional visualizations, like Boozer plots and flux surface plots, check out the `constellaration` library's [visualization tools](https://github.com/proximafusion/constellaration/blob/main/notebooks/boundary_explorer.ipynb). |
|
""") |
|
|
|
ds = load_dataset(results_repo, split='train') |
|
full_df = pd.DataFrame(ds) |
|
filenames = full_df['result_filename'].to_list() |
|
|
|
boundary = gr.State() |
|
|
|
mode_selector = gr.Radio(choices=["Generate", "Leaderboard", "Upload"], |
|
label="Select input method:", |
|
value="Leaderboard") |
|
|
|
|
|
with gr.Row(): |
|
with gr.Column(visible=False) as generate_ui: |
|
aspect_ratio = gr.Number(label="Aspect Ratio", value=3) |
|
elongation = gr.Number(label="Elongation", value=0.5) |
|
rotational_transform = gr.Number(label="Rotational Transform", value=0.4) |
|
n_field_periods = gr.Number(label="Number of Period Fields", value=3) |
|
generate_btn = gr.Button(value="Generate") |
|
|
|
with gr.Column(visible=True) as leaderboard_ui: |
|
dropdown = gr.Dropdown(choices=filenames, label="Choose a leaderboard entry", value=filenames[0]) |
|
rld_btn = gr.Button(value="Reload") |
|
|
|
with gr.Column(visible=False) as upload_ui: |
|
upload_box = gr.File(file_types=[".json"], label="Upload your boundary file") |
|
|
|
|
|
with gr.Column(visible=True): |
|
interactive_plot = gr.Plot() |
|
boundary_plot = gr.Plot() |
|
|
|
|
|
|
|
def update_ui(mode): |
|
return ( |
|
gr.update(visible=(mode == "Generate")), |
|
gr.update(visible=(mode == "Leaderboard")), |
|
gr.update(visible=(mode == "Upload")), |
|
) |
|
|
|
mode_selector.change(update_ui, inputs=[mode_selector], outputs=[generate_ui, leaderboard_ui, upload_ui]) |
|
|
|
def get_boundary_from_leaderboard(selected_file): |
|
row = full_df[full_df['result_filename'] == selected_file].iloc[0] |
|
if row['problem_type'] == 'mhd_stable': |
|
raise gr.Error("Sorry this isn't implemented for files with multiple boundaries yet!") |
|
else: |
|
boundary = load_boundary(row['boundary_json']) |
|
|
|
return boundary |
|
|
|
|
|
rld_btn.click(get_boundary_from_leaderboard, dropdown, boundary) \ |
|
.then(make_interactive_plot, boundary, interactive_plot) \ |
|
.then(make_boundary_plot, boundary, boundary_plot) \ |
|
|
|
|
|
|
|
|
|
def get_boundary_vis_from_upload(uploaded_file): |
|
if uploaded_file is None: |
|
raise gr.Error("Please upload a file.") |
|
with open(uploaded_file.name, 'r') as f: |
|
data = f.read() |
|
boundary = load_boundary(data) |
|
return boundary |
|
|
|
upload_box.change(get_boundary_vis_from_upload, inputs=[upload_box], outputs=boundary) \ |
|
.then(make_interactive_plot, boundary, interactive_plot) \ |
|
.then(make_boundary_plot, boundary, boundary_plot) \ |
|
|
|
|
|
|
|
def generate_random_boundary(aspect_ratio, elongation, rotational_transform, n_field_periods): |
|
boundary = initial_guess.generate_rotating_ellipse( |
|
aspect_ratio=aspect_ratio, elongation=elongation, rotational_transform=rotational_transform, n_field_periods=n_field_periods |
|
) |
|
return boundary |
|
|
|
generate_btn.click(generate_random_boundary, [aspect_ratio, elongation, rotational_transform, n_field_periods], boundary) \ |
|
.then(make_interactive_plot, boundary, interactive_plot) \ |
|
.then(make_boundary_plot, boundary, boundary_plot) \ |
|
|
|
|
|
|
|
return demo |
|
|
|
|
|
if __name__ == "__main__": |
|
gradio_interface().launch() |
|
|