File size: 5,618 Bytes
c2d0da9
 
 
 
 
 
 
 
 
 
 
 
8d3f1a3
 
c2d0da9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8d3f1a3
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
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)