File size: 3,600 Bytes
f05cf29
1f42a63
5d06efa
 
f05cf29
dadeab2
f05cf29
1f42a63
 
f05cf29
53bb559
 
 
 
 
 
a3a298d
53bb559
e90b2d6
0f0bbc4
044def1
24553c5
 
 
 
 
0f0bbc4
3202282
0f0bbc4
ff37873
282e7b3
ff37873
 
 
 
 
 
0f0bbc4
6bab7ba
d7637a3
 
3538c07
6bab7ba
 
c15f07f
 
6bab7ba
0a586d6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ce04373
 
 
72cba90
 
0a586d6
ce04373
 
 
 
 
 
 
 
 
 
 
9ac02cf
 
ce04373
 
 
9ac02cf
ce04373
 
 
 
 
 
 
0a586d6
ce04373
 
 
0a586d6
ce04373
 
 
0a586d6
 
ce04373
 
 
0a586d6
9ac02cf
ce04373
 
 
 
 
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
import streamlit as st
import pandas as pd
import numpy as np
import plotly.graph_objects as go

st.set_page_config(layout="wide")

st.title("TwinTrack")
st.subheader("Observed vs Simulated Interaction Dynamics")

DATA_DIR = "/app/src/"

FILES = {
    "Human": f"{DATA_DIR}/BigFlame_turns.csv",
    "Minimalist": f"{DATA_DIR}/minimalist_turns.csv",
    "Cheerleader": f"{DATA_DIR}/cheerleader_turns.csv",
    "Poet": f"{DATA_DIR}/poet_turns.csv"
}

@st.cache_data
def load_data():
    human = pd.read_csv(FILES['Human'])
    minimalist = pd.read_csv(FILES['Minimalist'])
    cheerleader = pd.read_csv(FILES['Cheerleader'])
    poet = pd.read_csv(FILES['Poet'])
    return human, minimalist, cheerleader, poet

df_human, df_minimlist, df_cheerleader, df_poet = load_data()

def normalize_time(df):
    df["t_norm"] = df.index / (len(df) - 1)
    return df

df_human = normalize_time(df_human)
df_minimlist = normalize_time(df_minimlist)
df_cheerleader = normalize_time(df_cheerleader)
df_poet = normalize_time(df_poet)

synth_map = {
    "minimalist": df_minimlist,
    "cheerleader": df_cheerleader,
    "poet": df_poet
}

choice = st.selectbox("Select Synthetic Persona", synth_map.keys())
df_synth = synth_map[choice]

WINDOW = 0.05  # 5% of conversation

def add_rolling_variance(df, col="tokens_est"):
    window_size = int(len(df) * WINDOW)
    df = df.copy()
    df["roll_var"] = (
        df[col]
        .rolling(window=window_size, center=True)
        .std()
        .fillna(0)
    )
    return df

df_human = add_rolling_variance(df_human)
df_synth = add_rolling_variance(df_synth)

combined_max = max(
    df_human["roll_var"].max(),
    df_synth["roll_var"].max()
)

df_human["roll_var_norm"] = df_human["roll_var"] / combined_max
df_synth["roll_var_norm"] = df_synth["roll_var"] / combined_max

def make_band(df, thickness=20):
    z = [df["roll_var_norm"].values] * thickness
    return z

human_band = make_band(df_human)
synth_band = make_band(df_synth)

# --- REPLACEMENT STARTS HERE ---
from plotly.subplots import make_subplots

COMMON_LEN = 500
t_common = np.linspace(0, 1, COMMON_LEN)

# Interpolate to smooth the data
human_interp = np.interp(t_common, df_human["t_norm"].values, df_human["roll_var_norm"])
synth_interp = np.interp(t_common, df_synth["t_norm"].values, df_synth["roll_var_norm"])

# Create a subplot with 2 rows. 
# "vertical_spacing" is the magic number for your gap! (0.1 = 10% gap)
fig = make_subplots(
    rows=2, cols=1, 
    shared_xaxes=True, 
    vertical_spacing=0.15,  # <--- ADJUST THIS to make the gap bigger/smaller
    subplot_titles=("Human: Big Flame", f"Synthetic: {choice.title()}")
)

# Helper to make the bands "thick" so they look like strips, not thin lines
def make_thick_band(data_row, thickness=10):
    return [data_row] * thickness

# Add Human Trace (Top)
fig.add_trace(go.Heatmap(
    z=make_thick_band(human_interp),
    colorscale="Plasma",
    showscale=False,
    zmin=0, zmax=1  # Lock colors so they are comparable
), row=1, col=1)

# Add Synthetic Trace (Bottom)
fig.add_trace(go.Heatmap(
    z=make_thick_band(synth_interp),
    colorscale="Plasma",
    showscale=False,
    zmin=0, zmax=1
), row=2, col=1)

fig.update_layout(
    height=350,  # Made it slightly taller to accommodate the gap
    margin=dict(l=10, r=10, t=50, b=10),
    xaxis2_title="Normalized Interaction Time", # Label only the bottom axis
)

# Hide the y-axis ticks for a cleaner look
fig.update_yaxes(showticklabels=False, showgrid=False, zeroline=False)
fig.update_xaxes(showgrid=False, zeroline=False)

st.plotly_chart(fig, use_container_width=True)