Spatial convergence test

Spatial convergence test#

import json
import numpy as np
from collections import defaultdict
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import requests

pd.options.display.max_columns = 5
headers = {
    "Accept": "application/vnd.github+json",
    "X-GitHub-Api-Version": "2022-11-28",
}
print("Get existing data from gist")
response = requests.get(
    "https://api.github.com/gists/73fa6531f28da2b3633a7ddaca38a7cd",
    headers=headers,
)
data = json.loads(response.json()["files"]["convergence_test.json"]["content"])
Get existing data from gist
runs = set()
all_results = defaultdict(list)
spatial_convergence = []
for git_hash, d in data.items():
    runs |= set(d.keys())
    if "dx0.1_dt0.05" not in d:
        # We have not spatial convergence data
        continue

    for key1, d1 in d.items():
        if "dt0.05" not in key1:
            continue  # Only select data with "dt0.05"
        for key, value in d1.items():
            all_results[key].append(value)

N = max(len(v) for v in all_results.values())
results = {}
for k, v in all_results.items():
    print(k, len(v))
    if len(v) == N:
        results[k] = v

df = pd.DataFrame(results)
df["timestamp"] = pd.to_datetime(df["timestamp"])
df
import_time 39
timestamp 39
simcardems_version 39
dt 39
dx 39
sha 39
coupling_type 21
num_cells_mechanics 39
num_vertices_mechanics 39
num_cells_ep 39
num_vertices_ep 39
create_runner_time 39
solve_time 39
APD40 39
APD50 39
APD90 39
triangulation 39
Vpeak 39
Vmin 39
dvdt_max 21
maxCa 39
ampCa 39
CaTD50 39
CaTD80 39
maxTa 39
ampTa 39
ttp_Ta 39
rt50_Ta 39
rt95_Ta 39
maxlmbda 39
minlmbda 39
ttplmbda 39
lmbdaD50 39
lmbdaD80 39
lmbdaD90 39
rt50_lmbda 39
rt95_lmbda 39
max_displacement_norm 39
min_displacement_norm 21
time_to_max_displacement_norm 39
time_to_min_displacement_norm 21
max_displacement_x 39
min_displacement_x 21
time_to_max_displacement_x 39
time_to_min_displacement_x 21
max_displacement_y 39
min_displacement_y 21
time_to_max_displacement_y 39
time_to_min_displacement_y 21
max_displacement_z 39
min_displacement_z 21
time_to_max_displacement_z 39
time_to_min_displacement_z 21
dvdt 18
CaTD90 18
rel_max_displacement_norm 18
max_displacement_perc_norm 18
rel_max_displacement_perc_norm 18
rel_max_displacement_x 18
max_displacement_perc_x 18
rel_max_displacement_perc_x 18
rel_max_displacement_y 18
max_displacement_perc_y 18
rel_max_displacement_perc_y 18
rel_max_displacement_z 18
max_displacement_perc_z 18
rel_max_displacement_perc_z 18
import_time timestamp ... max_displacement_z time_to_max_displacement_z
0 1.062000e-06 2025-02-14 17:45:23.568211 ... 0.104098 138.05
1 5.910000e-07 2025-02-14 17:45:23.848380 ... 0.104101 138.05
2 5.710000e-07 2025-02-14 17:45:22.740188 ... 0.104108 139.05
3 1.000000e-06 2023-10-26 09:55:43.116594 ... 0.104235 137.05
4 7.000000e-07 2023-10-26 09:55:25.319508 ... 0.104234 136.05
5 7.600000e-06 2023-10-26 09:55:49.558780 ... 0.104241 137.05
6 8.000000e-07 2023-09-24 20:53:35.963792 ... 0.097217 138.05
7 1.000000e-06 2023-09-24 20:53:48.833177 ... 0.097159 138.05
8 9.000000e-07 2023-09-24 20:54:02.914676 ... 0.096905 139.05
9 9.000000e-07 2023-09-11 12:49:33.990384 ... 0.097217 138.05
10 9.000000e-07 2023-09-11 12:49:36.888188 ... 0.097159 138.05
11 9.000000e-07 2023-09-11 12:49:33.033569 ... 0.096905 139.05
12 8.000000e-07 2023-06-27 12:42:45.253835 ... 0.097159 138.05
13 1.100000e-06 2023-06-27 12:42:49.266930 ... 0.097217 138.05
14 1.100000e-06 2023-06-27 12:42:43.474076 ... 0.096905 139.05
15 1.600000e-06 2023-06-05 10:35:21.889433 ... 0.096905 139.05
16 1.000000e-06 2023-06-05 10:34:58.182515 ... 0.097159 138.05
17 8.000000e-07 2023-06-05 10:34:56.082409 ... 0.097217 138.05
18 1.000000e-06 2023-05-23 19:54:03.785756 ... 0.097159 138.05
19 1.000000e-06 2023-05-23 19:54:26.746227 ... 0.097217 138.05
20 1.700000e-06 2023-05-23 19:54:21.676974 ... 0.096905 139.05
21 1.200000e-06 2023-05-22 18:51:32.688650 ... 0.097159 0.05
22 7.000000e-07 2023-05-22 18:51:29.002098 ... 0.097217 0.05
23 1.000000e-06 2023-05-22 18:51:20.047152 ... 0.096905 0.05
24 1.300000e-06 2023-05-16 08:33:54.547115 ... 0.097159 0.05
25 1.000000e-06 2023-05-16 08:34:13.875302 ... 0.097217 0.05
26 1.000000e-06 2023-05-16 08:33:56.392320 ... 0.096905 0.05
27 1.200000e-06 2023-05-10 07:52:46.302512 ... 0.096905 0.05
28 1.000000e-06 2023-05-10 07:52:54.342434 ... 0.097159 0.05
29 9.000000e-07 2023-05-10 07:52:36.195420 ... 0.097217 0.05
30 9.000000e-07 2023-04-12 20:33:25.203391 ... 0.096905 0.05
31 1.001000e-06 2023-04-12 20:33:25.502552 ... 0.097217 0.05
32 1.000000e-06 2023-04-12 20:33:32.537703 ... 0.097159 0.05
33 1.100000e-06 2023-04-12 17:17:24.396818 ... 0.096905 0.05
34 1.000000e-06 2023-04-12 17:17:24.948740 ... 0.097217 0.05
35 1.000000e-06 2023-04-12 17:17:26.820219 ... 0.097159 0.05
36 1.300000e-06 2023-04-12 09:53:34.139318 ... 0.096905 0.05
37 8.000000e-07 2023-04-12 09:53:30.436212 ... 0.097217 0.05
38 1.000000e-06 2023-04-12 09:53:31.010237 ... 0.097159 0.05

39 rows × 43 columns

df["timestamp"]
df.keys()
df["dx"].unique()
array([0.4, 0.2, 0.1])
def get_ylim(values):
    if np.isclose(values, 1).all():
        return (0.99, 1.01)
    y_max = np.max(values)
    y_min = np.min(values)
    d_max = y_max - 1
    d_min = 1 - y_min

    d = max(d_min, d_max) + 0.025
    return (1 - d, 1 + d)
dxs = df["dx"].unique()
DX = np.median(dxs)  # Choose the dx in the middle as the one to compare with
dxs
array([0.4, 0.2, 0.1])
columns = [c for c in df.columns if c not in ["timestamp", "simcardems_version", "sha", "dx", "dt"]]
git_hash = df["sha"]
versions = df["simcardems_version"]
dxs = df["dx"].unique()
dates = [t.date() for t in df["timestamp"]]

df_DX = df[df["dx"] == DX]
df_DX.sort_values(by="timestamp")

fig = make_subplots(
    rows=len(columns),
    cols=1,
    subplot_titles=columns,
    y_title="Percentage deviation from median case",
    shared_xaxes=True,
)

yranges = []
colors = ["red", "green", "blue"]
for color, dx in zip(colors, sorted(dxs)):
    df_dx = df[df["dx"] == dx]
    df_dx.sort_values(by="timestamp")

    git_hash = df_dx["sha"]
    versions = df_dx["simcardems_version"]
    dates = [t.date() for t in df_dx["timestamp"]]

    text = []
    for h, v, t in zip(git_hash, versions, dates):
        text.append(
            "\n".join(
                [
                    f"<br>Git Hash: {h}</br>",
                    f"<br>Version: {v}</br>",
                    f"<br>Timestamp {t}</br>",
                ]
            )
        )

    for i, c in enumerate(columns):
        y = df_dx[c].to_numpy() / df_DX[c].to_numpy()

        row = i + 1
        col = 1
        showlegend = i == 0
        fig.add_trace(
            go.Scatter(
                x=df_dx["timestamp"],
                y=y,
                text=text,
                hovertemplate="%{text}",
                name=f"dx={dx}",
                legendgroup=str(dx),
                showlegend=i == 0,
                marker_color=color,
            ),
            row=row,
            col=col,
        )
        fig.update_yaxes(range=get_ylim(y), row=row, col=col)

fig.update_layout(height=5000, showlegend=True)
fig.show()