Spaces:
Sleeping
Sleeping
DariusGiannoli
refactor: tab-based routing with two pipelines (Stereo+Depth & Generalisation)
a51a1a7 | """Generalisation Feature Lab β Stage 2 of the Generalisation pipeline.""" | |
| import streamlit as st | |
| import cv2 | |
| import numpy as np | |
| import plotly.graph_objects as go | |
| from src.detectors.rce.features import REGISTRY | |
| from src.models import BACKBONES | |
| def render(): | |
| pipe = st.session_state.get("gen_pipeline") | |
| if not pipe or "crop" not in pipe: | |
| st.error("Please complete the **Data Lab** first!") | |
| st.stop() | |
| obj = pipe.get("crop_aug", pipe.get("crop")) | |
| if obj is None: | |
| st.error("No crop found. Go back to Data Lab and define a ROI.") | |
| st.stop() | |
| gray = cv2.cvtColor(obj, cv2.COLOR_BGR2GRAY) | |
| st.title("π¬ Feature Lab: Physical Module Selection") | |
| col_rce, col_cnn = st.columns([3, 2]) | |
| with col_rce: | |
| st.header("𧬠RCE: Modular Physics Engine") | |
| st.subheader("Select Active Modules") | |
| active = {} | |
| items = list(REGISTRY.items()) | |
| for row_start in range(0, len(items), 4): | |
| row_items = items[row_start:row_start + 4] | |
| m_cols = st.columns(4) | |
| for col, (key, meta) in zip(m_cols, row_items): | |
| active[key] = col.checkbox(meta["label"], | |
| value=(key in ("intensity", "sobel", "spectral")), | |
| key=f"gen_fl_{key}") | |
| final_vector = [] | |
| viz_images = [] | |
| for key, meta in REGISTRY.items(): | |
| if active[key]: | |
| vec, viz = meta["fn"](gray) | |
| final_vector.extend(vec) | |
| viz_images.append((meta["viz_title"], viz)) | |
| st.divider() | |
| if viz_images: | |
| for row_start in range(0, len(viz_images), 3): | |
| row = viz_images[row_start:row_start + 3] | |
| v_cols = st.columns(3) | |
| for col, (title, img) in zip(v_cols, row): | |
| col.image(img, caption=title, use_container_width=True) | |
| else: | |
| st.warning("No modules selected β vector is empty.") | |
| st.write(f"### Current DNA Vector Size: **{len(final_vector)}**") | |
| fig_vec = go.Figure(data=[go.Bar(y=final_vector, marker_color="#00d4ff")]) | |
| fig_vec.update_layout(title="Active Feature Vector (RCE Input)", | |
| template="plotly_dark", height=300) | |
| st.plotly_chart(fig_vec, use_container_width=True) | |
| with col_cnn: | |
| st.header("π§ CNN: Static Architecture") | |
| selected_cnn = st.selectbox("Compare against Model", list(BACKBONES.keys()), | |
| key="gen_fl_cnn") | |
| st.info("CNN features are fixed by pre-trained weights.") | |
| with st.spinner(f"Loading {selected_cnn} and extracting activations..."): | |
| try: | |
| bmeta = BACKBONES[selected_cnn] | |
| backbone = bmeta["loader"]() | |
| layer_name = bmeta["hook_layer"] | |
| act_maps = backbone.get_activation_maps(obj, n_maps=6) | |
| st.caption(f"Hooked layer: `{layer_name}` β showing 6 of " | |
| f"{len(act_maps)} channels") | |
| act_cols = st.columns(3) | |
| for i, amap in enumerate(act_maps): | |
| act_cols[i % 3].image(amap, caption=f"Channel {i}", | |
| use_container_width=True) | |
| except Exception as e: | |
| st.error(f"Could not load model: {e}") | |
| st.divider() | |
| st.markdown(f""" | |
| **Analysis:** | |
| - **Modularity:** RCE is **High** | CNN is **Zero** | |
| - **Explainability:** RCE is **High** | CNN is **Low** | |
| - **Compute Cost:** {len(final_vector)} floats | 512+ floats | |
| """) | |
| if st.button("π Lock Modular Configuration", key="gen_fl_lock"): | |
| if not final_vector: | |
| st.error("Please select at least one module!") | |
| else: | |
| pipe["final_vector"] = np.array(final_vector) | |
| pipe["active_modules"] = {k: v for k, v in active.items()} | |
| st.session_state["gen_pipeline"] = pipe | |
| st.success("Modular DNA Locked! Ready for Model Tuning.") | |