seismic-arena / app.py
porestar's picture
Update app.py, score_db.py, and requirements.txt
c2d0da9
import base64
import io
import random
from io import BytesIO
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import requests
from datasets import load_dataset
import gradio as gr
from score_db import Battle
from score_db import Model as ModelEnum, Winner
def make_plot(seismic, predicted_image):
fig, ax = plt.subplots(1, 1, figsize=(10, 10))
ax.imshow(Image.fromarray(seismic), cmap="gray")
ax.imshow(predicted_image, cmap="Reds", alpha=0.5, vmin=0, vmax=1)
ax.set_axis_off()
fig.canvas.draw()
# Create a bytes buffer to save the plot
buf = io.BytesIO()
plt.savefig(buf, format='png', bbox_inches='tight')
buf.seek(0)
# Open the PNG image from the buffer and convert it to a NumPy array
image = np.array(Image.open(buf))
return image
def call_endpoint(model: ModelEnum, img_array, url: str="https://lukasmosser--seisbase-endpoints-predict.modal.run"):
response = requests.post(url, json={"img": img_array.tolist(), "model": model})
if response:
# Parse the base64-encoded image data
if response.text.startswith("data:image/tiff;base64,"):
img_data_out = base64.b64decode(response.text.split(",")[1])
predicted_image = np.array(Image.open(BytesIO(img_data_out)))
return predicted_image
def select_random_image(dataset):
idx = random.randint(0, len(dataset))
return idx, np.array(dataset[idx]["seismic"])
def select_random_models():
model_a = random.choice(list(ModelEnum))
model_b = random.choice(list(ModelEnum))
return model_a, model_b
# Create a Gradio interface
with gr.Blocks() as evaluation:
gr.Markdown("""
## Seismic Fault Detection Model Evaluation
This application allows you to compare the performance of different seismic fault detection models.
Two models are selected randomly, and their predictions are displayed side by side.
You can choose the better model or mark it as a tie. The results are recorded and used to update the model ratings.
""")
battle = gr.State([])
radio = gr.Radio(choices=["Less than 5 years", "5 to 20 years", "more than 20 years"], label="How much experience do you have in seismic fault interpretation?")
with gr.Row():
output_img1 = gr.Image(label="Model A Image")
output_img2 = gr.Image(label="Model B Image")
def show_images():
dataset = load_dataset("porestar/crossdomainfoundationmodeladaption-deepfault", split="valid")
idx, image_1 = select_random_image(dataset)
model_a, model_b = select_random_models()
fault_probability_1 = call_endpoint(model_a, image_1)
fault_probability_2 = call_endpoint(model_b, image_1)
img_1 = make_plot(image_1, fault_probability_1)
img_2 = make_plot(image_1, fault_probability_2)
experience = 1
if radio.value == "5 to 20 years":
experience = 2
elif radio.value == "more than 20 years":
experience = 3
battle.value.append(Battle(model_a=model_a, model_b=model_b, winner="tie", judge="None", experience=experience, image_idx=idx))
return img_1, img_2
# Define the function to make an API call
def make_api_call(choice: Winner):
api_url = "https://lukasmosser--seisbase-eval-add-battle.modal.run"
battle_out = battle.value
battle_out[-1].winner = choice
experience = 1
if radio.value == "5 to 20 years":
experience = 2
elif radio.value == "more than 20 years":
experience = 3
battle_out[-1].experience = experience
response = requests.post(api_url, json=battle_out[-1].dict())
# Load images on startup
evaluation.load(show_images, inputs=[], outputs=[output_img1, output_img2])
with gr.Row():
btn_winner_a = gr.Button("Winner Model A")
btn_tie = gr.Button("Tie")
btn_winner_b = gr.Button("Winner Model B")
# Define button click events
btn_winner_a.click(lambda: make_api_call(Winner.model_a), inputs=[], outputs=[]).then(show_images, inputs=[], outputs=[output_img1, output_img2])
btn_tie.click(lambda: make_api_call(Winner.tie), inputs=[], outputs=[]).then(show_images, inputs=[], outputs=[output_img1, output_img2])
btn_winner_b.click(lambda: make_api_call(Winner.model_b), inputs=[], outputs=[]).then(show_images, inputs=[], outputs=[output_img1, output_img2])
with gr.Blocks() as leaderboard:
def get_results():
response = requests.get("https://lukasmosser--seisbase-eval-compute-ratings.modal.run")
data = response.json()
models = [entry["model"] for entry in data]
elo_ratings = [entry["elo_rating"] for entry in data]
fig, ax = plt.subplots()
ax.barh(models, elo_ratings, color='skyblue')
ax.set_xlabel('ELO Rating')
ax.set_title('Model ELO Ratings')
plt.tight_layout()
fig.canvas.draw()
# Create a bytes buffer to save the plot
buf = io.BytesIO()
plt.savefig(buf, format='png', bbox_inches='tight')
buf.seek(0)
# Open the PNG image from the buffer and convert it to a NumPy array
image = np.array(Image.open(buf))
return image
with gr.Row():
elo_ratings = gr.Image(label="ELO Ratings")
leaderboard.load(get_results, inputs=[], outputs=[elo_ratings])
demo = gr.TabbedInterface([evaluation, leaderboard], ["Arena", "Leaderboard"])
# Launch the interface
if __name__ == "__main__":
demo.launch(show_error=True)