diff --git a/app.py b/app.py
index 65c2d13..50a25ab 100644
--- a/app.py
+++ b/app.py
@@ -366,10 +366,6 @@
f"症例 {cid}" + (" ✓" if cid in st.session_state.annotated_cases else "")
for cid in st.session_state.case_ids
]
-
- # 症例選択のコールバック
- def on_case_change():
- pass
selected_idx = st.selectbox(
"症例リスト",
@@ -414,24 +410,36 @@
if st.session_state.zoom_percent not in zoom_levels:
st.session_state.zoom_percent = 80
- current_idx = zoom_levels.index(st.session_state.zoom_percent)
+ current_zoom_idx = zoom_levels.index(st.session_state.zoom_percent)
+
+ # Zoom変更用コールバック関数
+ def change_zoom(amount: int):
+ new_idx = current_zoom_idx + amount
+ if 0 <= new_idx < len(zoom_levels):
+ st.session_state.zoom_percent = zoom_levels[new_idx]
col_z1, col_z2, col_z3 = st.columns([1, 2, 1])
with col_z1:
- if st.button("-", key="zoom_out", use_container_width=True):
- if current_idx > 0:
- st.session_state.zoom_percent = zoom_levels[current_idx - 1]
- st.rerun()
+ st.button(
+ "-",
+ key="zoom_out",
+ use_container_width=True,
+ on_click=change_zoom,
+ args=(-1,)
+ )
with col_z2:
st.markdown(f"
{st.session_state.zoom_percent} %
", unsafe_allow_html=True)
with col_z3:
- if st.button("+", key="zoom_in", use_container_width=True):
- if current_idx < len(zoom_levels) - 1:
- st.session_state.zoom_percent = zoom_levels[current_idx + 1]
- st.rerun()
+ st.button(
+ "+",
+ key="zoom_in",
+ use_container_width=True,
+ on_click=change_zoom,
+ args=(1,)
+ )
def render_image_viewer(case_id: Union[int, float], container):
@@ -534,7 +542,8 @@
PREDICTION_OPTIONS,
key=f"prediction_{case_id}",
horizontal=True, # 変更: 横並びにして省スペース化
- label_visibility="collapsed"
+ label_visibility="collapsed",
+ index=1 # デフォルトは「なし」
)
# Q2: Confidence (横並び)
@@ -542,7 +551,7 @@
confidence = container.radio(
"確信度",
CONFIDENCE_OPTIONS,
- index=2, # 50%
+ index=3, # 50%
format_func=lambda x: f"{x}%",
key=f"confidence_{case_id}",
label_visibility="collapsed",
@@ -575,6 +584,23 @@
}
+def render_complete_screen():
+ """全てのアノテーションが完了した際に表示する終了画面"""
+ st.balloons() # 完了のお祝いエフェクト
+
+ st.markdown("""
+
+
🎉 アノテーション完了 🎉
+ 全症例の判定が終了しました。ご協力ありがとうございました!
+
+ """, unsafe_allow_html=True)
+
+ st.success(f"データは以下の場所に保存されました:")
+ st.code(st.session_state.csv_path, language=None)
+
+ st.info("ブラウザのタブを閉じて終了してください。")
+
+
def validate_annotation(annotation_data: dict) -> tuple[bool, str]:
"""
保存前にアノテーションデータを検証。
@@ -610,6 +636,14 @@
# Get ground truth label for this case (may be None)
ground_truth = st.session_state.ground_truth_labels.get(case_id, None)
+ # 見つからず,CaseIDに小数点を含む場合
+ if ground_truth is None:
+ try:
+ int_case_id = int(case_id)
+ ground_truth = st.session_state.ground_truth_labels.get(int_case_id, None)
+ except:
+ pass
+
save_annotation(
csv_path=st.session_state.csv_path,
case_id=case_id,
@@ -642,7 +676,7 @@
st.session_state.current_case_idx = next_idx
st.rerun()
else:
- container.info("全症例のアノテーションが完了しました! 🎉")
+ st.rerun()
except Exception as e:
container.error(f"保存エラー: {e}")
@@ -665,6 +699,14 @@
render_sidebar_ui()
+ # 完了判定ロジック
+ total_cases = len(st.session_state.case_ids)
+ annotated_count = len(st.session_state.annotated_cases)
+
+ if total_cases > 0 and annotated_count >= total_cases:
+ render_complete_screen()
+ return
+
current_case_id = get_current_case_id()
if current_case_id is None: