# ============================================
# Interactive Three-step Tsurukame Visualization
# Matplotlib + ipywidgets (Google Colab)
# ============================================
!pip install ipywidgets
from ipywidgets import interact, FloatSlider, IntSlider, Button, HBox, VBox, Output
from IPython.display import display, clear_output
import matplotlib.pyplot as plt
import numpy as np
# --------------------------------------------------
# Output area for plot
# --------------------------------------------------
plot_out = Output()
# --------------------------------------------------
# Draw function
# --------------------------------------------------
def draw_tsurukame(point_base, point_std, point_app,
num_base, num_std, num_app,
baseline):
with plot_out:
clear_output(wait=True)
# Derived values
remain_base = point_base - baseline
remain_std = point_std - baseline
remain_app = point_app - baseline
avg_remain = (remain_base + remain_std) / 2
diff_app = remain_app - avg_remain
total_score = point_base*num_base + point_std*num_std + point_app*num_app
remain_total = remain_base*num_base + remain_std*num_std + remain_app*num_app
# Prepare figure
fig = plt.figure(figsize=(16,10))
plt.suptitle("Three-step Tsurukame Visualization (Interactive)", fontsize=20)
xs = [1, 5, 9]
widths = [num_base, num_std, num_app]
labels = [f"Base ({num_base})", f"Standard ({num_std})", f"Applied ({num_app})"]
# --------------------------------------------------
# 1. Triple Tower
# --------------------------------------------------
ax1 = plt.subplot(2,2,1)
ax1.set_title("① Triple Tower (Original Situation)")
heights = [point_base, point_std, point_app]
colors = ["#4A90E2", "#7ED321", "#D0021B"]
for i in range(3):
ax1.bar(xs[i], heights[i], width=widths[i], color=colors[i])
ax1.text(xs[i], heights[i] + 0.4, f"{heights[i]} pt", ha="center", fontsize=11)
ax1.set_xlim(0, 12)
ax1.set_ylim(0, max(heights)+2)
ax1.set_xticks(xs)
ax1.set_xticklabels(labels)
ax1.text(0.5, max(heights), f"Total Score = {total_score}", fontsize=11)
# --------------------------------------------------
# 2. Baseline removal
# --------------------------------------------------
ax2 = plt.subplot(2,2,2)
ax2.set_title("② Remove Baseline")
# baseline parts
for i in range(3):
ax2.bar(xs[i], baseline, width=widths[i], color="#DDDDDD")
# remain parts
ax2.bar(xs[0], remain_base, bottom=baseline, width=widths[0], color="#4A90E2")
ax2.bar(xs[1], remain_std, bottom=baseline, width=widths[1], color="#7ED321")
ax2.bar(xs[2], remain_app, bottom=baseline, width=widths[2], color="#D0021B")
ax2.axhline(baseline, linestyle="--", color="black")
ax2.text(0.5, baseline+remain_app+1.5,
f"Remaining Score = {remain_total}", fontsize=11)
ax2.set_xlim(0, 12)
ax2.set_ylim(0, baseline+remain_app+3)
ax2.set_xticks(xs)
ax2.set_xticklabels(labels)
# --------------------------------------------------
# 3. Averaging (Base+Standard merged)
# --------------------------------------------------
ax3 = plt.subplot(2,2,3)
ax3.set_title("③ Average Merge (Base + Standard)")
ax3.bar(3, avg_remain, width=num_base+num_std, color="#8888FF")
ax3.text(3, avg_remain+0.4,
f"Avg Remain = {avg_remain:.2f} pt", ha="center")
ax3.bar(10, remain_app, width=num_app, color="#D0021B")
ax3.text(10, remain_app+0.4,
f"{remain_app} pt", ha="center")
ax3.axhline(avg_remain, linestyle="--", color="black")
ax3.set_xlim(0, 14)
ax3.set_ylim(0, remain_app+3)
ax3.set_xticks([3,10])
ax3.set_xticklabels([f"Base+Std ({num_base+num_std})",
f"Applied ({num_app})"])
# --------------------------------------------------
# 4. Twin Tower (hypothesis method)
# --------------------------------------------------
ax4 = plt.subplot(2,2,4)
ax4.set_title("④ Twin Tower (Hypothesis Method)")
# average tower
ax4.bar(3, avg_remain, width=num_base+num_std, color="#8888FF")
# applied tower: base + difference
ax4.bar(10, avg_remain, width=num_app, color="#FFAAAA")
ax4.bar(10, diff_app, width=num_app, bottom=avg_remain, color="#FF4444")
ax4.axhline(avg_remain, linestyle="--", color="black")
total_diff = diff_app * num_app
ax4.text(0.5, diff_app + avg_remain + 1.2,
f"Total difference = {total_diff:.2f} pt", fontsize=12)
ax4.text(0.5, diff_app + avg_remain + 0.2,
f"{total_diff:.2f} ÷ {diff_app:.2f} = {num_app}",
fontsize=14, fontweight="bold")
ax4.set_xlim(0, 14)
ax4.set_ylim(0, diff_app + avg_remain + 3)
ax4.set_xticks([3,10])
ax4.set_xticklabels([f"Average ({num_base+num_std})",
f"Applied ({num_app})"])
plt.tight_layout(rect=[0, 0, 1, 0.94])
plt.show()
# --------------------------------------------------
# Interactive sliders
# --------------------------------------------------
sl_point_base = IntSlider(value=5, min=1, max=20, description="Base pt")
sl_point_std = IntSlider(value=10, min=1, max=20, description="Std pt")
sl_point_app = IntSlider(value=12, min=1, max=20, description="App pt")
sl_num_base = IntSlider(value=3, min=1, max=10, description="Base n")
sl_num_std = IntSlider(value=3, min=1, max=10, description="Std n")
sl_num_app = IntSlider(value=2, min=1, max=10, description="App n")
sl_baseline = IntSlider(value=5, min=0, max=20, description="Baseline")
# --------------------------------------------------
# Buttons for Reset / Save
# --------------------------------------------------
btn_reset = Button(description="Reset", button_style="warning")
btn_save_png = Button(description="Save PNG", button_style="success")
btn_save_pdf = Button(description="Save PDF", button_style="primary")
def on_reset_clicked(b):
sl_point_base.value = 5
sl_point_std.value = 10
sl_point_app.value = 12
sl_num_base.value = 3
sl_num_std.value = 3
sl_num_app.value = 2
sl_baseline.value = 5
def on_save_png_clicked(b):
plt.savefig("/content/tsurukame_plot.png", dpi=200)
print("Saved PNG → /content/tsurukame_plot.png")
def on_save_pdf_clicked(b):
plt.savefig("/content/tsurukame_plot.pdf")
print("Saved PDF → /content/tsurukame_plot.pdf")
btn_reset.on_click(on_reset_clicked)
btn_save_png.on_click(on_save_png_clicked)
btn_save_pdf.on_click(on_save_pdf_clicked)
# --------------------------------------------------
# Display UI
# --------------------------------------------------
ui = VBox([
HBox([sl_point_base, sl_point_std, sl_point_app]),
HBox([sl_num_base, sl_num_std, sl_num_app]),
HBox([sl_baseline]),
HBox([btn_reset, btn_save_png, btn_save_pdf])
])
display(ui)
display(plot_out)
# --------------------------------------------------
# Connect interactive plotting
# --------------------------------------------------
interact(
draw_tsurukame,
point_base=sl_point_base,
point_std=sl_point_std,
point_app=sl_point_app,
num_base=sl_num_base,
num_std=sl_num_std,
num_app=sl_num_app,
baseline=sl_baseline
);
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme