app.sections.data_exploration

Data Exploration Interface for Gradio Application.

This module provides interactive visualization tools for exploring the garbage classification dataset. It enables users to view random samples, analyze class distributions, and examine prototype images (mean/median) with optional Otsu binarization for enhanced visualization.

The interface includes:

  • Random sample visualization per class
  • Class distribution analysis
  • Mean prototype images with Otsu thresholding
  • Interactive controls for threshold adjustment
Notes

Prototype arrays (mean/median) are cached to disk in app/sections/cached_data/ to avoid recomputation. The Otsu binarization feature helps visualize the dominant features of each class by thresholding the prototype images.

  1#!/usr/bin/env python3
  2# -*- coding: utf-8 -*-
  3"""
  4Data Exploration Interface for Gradio Application.
  5
  6This module provides interactive visualization tools for exploring the
  7garbage classification dataset. It enables users to view random samples,
  8analyze class distributions, and examine prototype images (mean/median)
  9with optional Otsu binarization for enhanced visualization.
 10
 11The interface includes:
 12- Random sample visualization per class
 13- Class distribution analysis
 14- Mean prototype images with Otsu thresholding
 15- Interactive controls for threshold adjustment
 16
 17Notes
 18-----
 19Prototype arrays (mean/median) are cached to disk in
 20`app/sections/cached_data/` to avoid recomputation.
 21The Otsu binarization feature helps visualize the dominant
 22features of each class by thresholding the prototype images.
 23"""
 24__docformat__ = "numpy"
 25
 26import os
 27import gradio as gr
 28
 29from source.utils.custom_classes.EdaAnalyzer import EdaAnalyzer
 30
 31
 32def data_exploration_tab():
 33    """
 34    Create the Data Exploration UI section.
 35
 36    Builds an interactive Gradio interface for exploring the dataset through
 37    various visualization methods. Includes buttons for different
 38    visualization types and dynamic controls for prototype image processing.
 39
 40    Returns
 41    -------
 42    list of gr.Component
 43        List of all Gradio components created in this tab, including buttons,
 44        plots, checkboxes, and sliders. Returned for potential external
 45        reference or testing purposes.
 46
 47    Notes
 48    -----
 49    The interface workflow:
 50
 51    1. **Random Samples**: Display random images from each class
 52    2. **Class Distribution**: Show bar chart of samples per class
 53    3. **Mean Prototypes**: Display average image per class with optional
 54       Otsu binarization
 55
 56    Otsu Controls:
 57    - Only visible after generating mean prototypes
 58    - Checkbox enables/disables binarization
 59    - Slider adjusts threshold (-1.0 to 1.0) when enabled
 60    - Updates visualization in real-time
 61
 62    The EdaAnalyzer handles dataset loading, metadata management, and
 63    actual visualization generation. This function provides the UI wrapper.
 64
 65    Cache Directory:
 66    All prototype arrays are saved to `app/sections/cached_data/` to enable
 67    fast toggling between normal and Otsu-binarized views.
 68
 69    Examples
 70    --------
 71    >>> with gr.Blocks() as demo:
 72    ...     components = data_exploration_tab()
 73    ...     # components[0] is btn_random
 74    ...     # components[-2] is output_plot
 75    ...     # components[-1] is output_text
 76
 77    See Also
 78    --------
 79    EdaAnalyzer : Core class for dataset analysis and visualization
 80    """
 81
 82    eda = EdaAnalyzer()
 83    eda.ensure_dataset()
 84    eda.load_metadata()
 85
 86    cached_dir = os.path.join(os.getcwd(), "app", "sections", "cached_data")
 87    os.makedirs(cached_dir, exist_ok=True)
 88    mean_arrays_path = os.path.join(cached_dir, "mean_prototypes.npy")
 89
 90    # --- Internal functions ---
 91    def show_random_samples():
 92        """
 93        Display random sample images from each class.
 94
 95        Returns
 96        -------
 97        tuple of (matplotlib.figure.Figure, str, gr.update, gr.update)
 98            - Figure: Plot showing random samples per class
 99            - str: Status message
100            - gr.update: Hide mean Otsu controls
101            - gr.update: Hide median Otsu controls (commented out)
102
103        Notes
104        -----
105        Generates a grid of random images, typically showing 3-5 examples
106        per class to give an overview of dataset variety.
107        """
108        fig = eda.plot_random_examples_per_class()
109        return (
110            fig,
111            "✅ Random samples plotted.",
112            gr.update(visible=False),
113            gr.update(visible=False),
114        )
115
116    def show_class_distribution():
117        """
118        Display bar chart of samples per class.
119
120        Returns
121        -------
122        tuple of (matplotlib.figure.Figure, str, gr.update, gr.update)
123            - Figure: Bar chart showing class distribution
124            - str: Status message
125            - gr.update: Hide mean Otsu controls
126            - gr.update: Hide median Otsu controls (commented out)
127
128        Notes
129        -----
130        Helps identify class imbalance in the dataset. Each bar represents
131        the number of images in a garbage category.
132        """
133        fig = eda.plot_class_distribution()
134        return (
135            fig,
136            "✅ Class distribution plotted.",
137            gr.update(visible=False),
138            gr.update(visible=False),
139        )
140
141    def show_mean_prototypes():
142        """
143        Display mean prototype images for each class.
144
145        Returns
146        -------
147        tuple of (matplotlib.figure.Figure, str, gr.update, gr.update)
148            - Figure: Grid of mean prototype images
149            - str: Status message indicating Otsu controls are available
150            - gr.update: Show mean Otsu controls
151            - gr.update: Hide median Otsu controls (commented out)
152
153        Notes
154        -----
155        Mean prototypes are computed by averaging all images in each class.
156        They reveal the "typical" appearance and dominant features of each
157        category. Cached to disk for fast subsequent access.
158
159        After display, Otsu binarization controls become visible for
160        enhanced visualization of class features.
161        """
162        fig = eda.plot_mean_images_per_class(filename=mean_arrays_path)
163        msg = "✅ Mean prototypes plotted. Enable Otsu binarization if \
164            you want to adjust."
165        return fig, msg, gr.update(visible=True), gr.update(visible=False)
166
167    def toggle_mean_otsu_binarization(use_otsu, threshold):
168        """
169        Toggle between normal and Otsu-binarized mean prototypes.
170
171        Parameters
172        ----------
173        use_otsu : bool
174            If True, apply Otsu binarization; if False, show normal prototypes.
175        threshold : float
176            Adjustment to Otsu threshold in range [-1.0, 1.0].
177
178        Returns
179        -------
180        tuple of (matplotlib.figure.Figure, gr.update)
181            - Figure: Updated plot (normal or binarized)
182            - gr.update: Show/hide threshold slider based on use_otsu
183
184        Notes
185        -----
186        Otsu binarization converts grayscale images to binary (black/white)
187        using an automatic threshold. The threshold parameter allows fine-
188        tuning this threshold to emphasize different features.
189
190        The slider is only visible and interactive when Otsu is enabled.
191        """
192        if use_otsu:
193            fig = eda.plot_mean_images_per_class_with_otsu(
194                threshold=threshold, filename=mean_arrays_path
195            )
196        else:
197            fig = eda.plot_mean_images_per_class(filename=mean_arrays_path)
198        return fig, gr.update(visible=use_otsu, interactive=use_otsu)
199
200    def update_mean_otsu_threshold(threshold):
201        """
202        Update Otsu-binarized plot when threshold slider changes.
203
204        Parameters
205        ----------
206        threshold : float
207            New threshold adjustment value in range [-1.0, 1.0].
208
209        Returns
210        -------
211        matplotlib.figure.Figure
212            Updated plot with new Otsu threshold applied.
213
214        Notes
215        -----
216        This function is only called when Otsu binarization is enabled.
217        It allows real-time adjustment of the threshold to find the optimal
218        visualization for identifying class features.
219
220        Positive thresholds make the image darker (more black pixels),
221        while negative thresholds make it lighter (more white pixels).
222        """
223        fig = eda.plot_mean_images_per_class_with_otsu(
224            threshold=threshold, filename=mean_arrays_path
225        )
226        return fig
227
228    # --- UI Layout ---
229    with gr.Row():
230        gr.Markdown("### 📊 Data Exploration Section")
231        gr.Markdown(
232            "Explore dataset structure, class balance, \
233                and prototype images below."
234        )
235
236    with gr.Row():
237        btn_random = gr.Button("🎲 Show Random Samples")
238        btn_distribution = gr.Button("📈 Show Class Distribution")
239        btn_mean = gr.Button("⚖️ Show Mean Prototypes")
240
241    output_plot = gr.Plot(label="Visualization")
242    output_text = gr.Textbox(label="Status", interactive=False)
243
244    # --- Checkbox to enable/disable Otsu (initially hidden) ---
245    with gr.Row(visible=False) as otsu_mean_controls_row:
246        otsu_mean_checkbox = gr.Checkbox(
247            label="🔲 Apply Otsu binarization to means",
248            value=False,
249            interactive=True,
250        )
251        mean_threshold_slider = gr.Slider(
252            minimum=-1.0,
253            maximum=1.0,
254            value=0.0,
255            step=0.05,
256            label="🔧 Adjust Otsu Threshold",
257            visible=False,
258            interactive=False,
259        )
260
261    # --- Button interactions ---
262    btn_random.click(
263        fn=show_random_samples,
264        outputs=[
265            output_plot,
266            output_text,
267            otsu_mean_controls_row,
268        ],
269    )
270    btn_distribution.click(
271        fn=show_class_distribution,
272        outputs=[
273            output_plot,
274            output_text,
275            otsu_mean_controls_row,
276        ],
277    )
278
279    btn_mean.click(
280        fn=show_mean_prototypes,
281        outputs=[
282            output_plot,
283            output_text,
284            otsu_mean_controls_row,
285        ],
286    )
287
288    otsu_mean_checkbox.change(
289        fn=toggle_mean_otsu_binarization,
290        inputs=[otsu_mean_checkbox, mean_threshold_slider],
291        outputs=[output_plot, mean_threshold_slider],
292    )
293
294    mean_threshold_slider.change(
295        fn=update_mean_otsu_threshold,
296        inputs=mean_threshold_slider,
297        outputs=output_plot,
298    )
299
300    return [
301        btn_random,
302        btn_distribution,
303        btn_mean,
304        otsu_mean_controls_row,
305        otsu_mean_checkbox,
306        mean_threshold_slider,
307        output_plot,
308        output_text,
309    ]
def data_exploration_tab():
 33def data_exploration_tab():
 34    """
 35    Create the Data Exploration UI section.
 36
 37    Builds an interactive Gradio interface for exploring the dataset through
 38    various visualization methods. Includes buttons for different
 39    visualization types and dynamic controls for prototype image processing.
 40
 41    Returns
 42    -------
 43    list of gr.Component
 44        List of all Gradio components created in this tab, including buttons,
 45        plots, checkboxes, and sliders. Returned for potential external
 46        reference or testing purposes.
 47
 48    Notes
 49    -----
 50    The interface workflow:
 51
 52    1. **Random Samples**: Display random images from each class
 53    2. **Class Distribution**: Show bar chart of samples per class
 54    3. **Mean Prototypes**: Display average image per class with optional
 55       Otsu binarization
 56
 57    Otsu Controls:
 58    - Only visible after generating mean prototypes
 59    - Checkbox enables/disables binarization
 60    - Slider adjusts threshold (-1.0 to 1.0) when enabled
 61    - Updates visualization in real-time
 62
 63    The EdaAnalyzer handles dataset loading, metadata management, and
 64    actual visualization generation. This function provides the UI wrapper.
 65
 66    Cache Directory:
 67    All prototype arrays are saved to `app/sections/cached_data/` to enable
 68    fast toggling between normal and Otsu-binarized views.
 69
 70    Examples
 71    --------
 72    >>> with gr.Blocks() as demo:
 73    ...     components = data_exploration_tab()
 74    ...     # components[0] is btn_random
 75    ...     # components[-2] is output_plot
 76    ...     # components[-1] is output_text
 77
 78    See Also
 79    --------
 80    EdaAnalyzer : Core class for dataset analysis and visualization
 81    """
 82
 83    eda = EdaAnalyzer()
 84    eda.ensure_dataset()
 85    eda.load_metadata()
 86
 87    cached_dir = os.path.join(os.getcwd(), "app", "sections", "cached_data")
 88    os.makedirs(cached_dir, exist_ok=True)
 89    mean_arrays_path = os.path.join(cached_dir, "mean_prototypes.npy")
 90
 91    # --- Internal functions ---
 92    def show_random_samples():
 93        """
 94        Display random sample images from each class.
 95
 96        Returns
 97        -------
 98        tuple of (matplotlib.figure.Figure, str, gr.update, gr.update)
 99            - Figure: Plot showing random samples per class
100            - str: Status message
101            - gr.update: Hide mean Otsu controls
102            - gr.update: Hide median Otsu controls (commented out)
103
104        Notes
105        -----
106        Generates a grid of random images, typically showing 3-5 examples
107        per class to give an overview of dataset variety.
108        """
109        fig = eda.plot_random_examples_per_class()
110        return (
111            fig,
112            "✅ Random samples plotted.",
113            gr.update(visible=False),
114            gr.update(visible=False),
115        )
116
117    def show_class_distribution():
118        """
119        Display bar chart of samples per class.
120
121        Returns
122        -------
123        tuple of (matplotlib.figure.Figure, str, gr.update, gr.update)
124            - Figure: Bar chart showing class distribution
125            - str: Status message
126            - gr.update: Hide mean Otsu controls
127            - gr.update: Hide median Otsu controls (commented out)
128
129        Notes
130        -----
131        Helps identify class imbalance in the dataset. Each bar represents
132        the number of images in a garbage category.
133        """
134        fig = eda.plot_class_distribution()
135        return (
136            fig,
137            "✅ Class distribution plotted.",
138            gr.update(visible=False),
139            gr.update(visible=False),
140        )
141
142    def show_mean_prototypes():
143        """
144        Display mean prototype images for each class.
145
146        Returns
147        -------
148        tuple of (matplotlib.figure.Figure, str, gr.update, gr.update)
149            - Figure: Grid of mean prototype images
150            - str: Status message indicating Otsu controls are available
151            - gr.update: Show mean Otsu controls
152            - gr.update: Hide median Otsu controls (commented out)
153
154        Notes
155        -----
156        Mean prototypes are computed by averaging all images in each class.
157        They reveal the "typical" appearance and dominant features of each
158        category. Cached to disk for fast subsequent access.
159
160        After display, Otsu binarization controls become visible for
161        enhanced visualization of class features.
162        """
163        fig = eda.plot_mean_images_per_class(filename=mean_arrays_path)
164        msg = "✅ Mean prototypes plotted. Enable Otsu binarization if \
165            you want to adjust."
166        return fig, msg, gr.update(visible=True), gr.update(visible=False)
167
168    def toggle_mean_otsu_binarization(use_otsu, threshold):
169        """
170        Toggle between normal and Otsu-binarized mean prototypes.
171
172        Parameters
173        ----------
174        use_otsu : bool
175            If True, apply Otsu binarization; if False, show normal prototypes.
176        threshold : float
177            Adjustment to Otsu threshold in range [-1.0, 1.0].
178
179        Returns
180        -------
181        tuple of (matplotlib.figure.Figure, gr.update)
182            - Figure: Updated plot (normal or binarized)
183            - gr.update: Show/hide threshold slider based on use_otsu
184
185        Notes
186        -----
187        Otsu binarization converts grayscale images to binary (black/white)
188        using an automatic threshold. The threshold parameter allows fine-
189        tuning this threshold to emphasize different features.
190
191        The slider is only visible and interactive when Otsu is enabled.
192        """
193        if use_otsu:
194            fig = eda.plot_mean_images_per_class_with_otsu(
195                threshold=threshold, filename=mean_arrays_path
196            )
197        else:
198            fig = eda.plot_mean_images_per_class(filename=mean_arrays_path)
199        return fig, gr.update(visible=use_otsu, interactive=use_otsu)
200
201    def update_mean_otsu_threshold(threshold):
202        """
203        Update Otsu-binarized plot when threshold slider changes.
204
205        Parameters
206        ----------
207        threshold : float
208            New threshold adjustment value in range [-1.0, 1.0].
209
210        Returns
211        -------
212        matplotlib.figure.Figure
213            Updated plot with new Otsu threshold applied.
214
215        Notes
216        -----
217        This function is only called when Otsu binarization is enabled.
218        It allows real-time adjustment of the threshold to find the optimal
219        visualization for identifying class features.
220
221        Positive thresholds make the image darker (more black pixels),
222        while negative thresholds make it lighter (more white pixels).
223        """
224        fig = eda.plot_mean_images_per_class_with_otsu(
225            threshold=threshold, filename=mean_arrays_path
226        )
227        return fig
228
229    # --- UI Layout ---
230    with gr.Row():
231        gr.Markdown("### 📊 Data Exploration Section")
232        gr.Markdown(
233            "Explore dataset structure, class balance, \
234                and prototype images below."
235        )
236
237    with gr.Row():
238        btn_random = gr.Button("🎲 Show Random Samples")
239        btn_distribution = gr.Button("📈 Show Class Distribution")
240        btn_mean = gr.Button("⚖️ Show Mean Prototypes")
241
242    output_plot = gr.Plot(label="Visualization")
243    output_text = gr.Textbox(label="Status", interactive=False)
244
245    # --- Checkbox to enable/disable Otsu (initially hidden) ---
246    with gr.Row(visible=False) as otsu_mean_controls_row:
247        otsu_mean_checkbox = gr.Checkbox(
248            label="🔲 Apply Otsu binarization to means",
249            value=False,
250            interactive=True,
251        )
252        mean_threshold_slider = gr.Slider(
253            minimum=-1.0,
254            maximum=1.0,
255            value=0.0,
256            step=0.05,
257            label="🔧 Adjust Otsu Threshold",
258            visible=False,
259            interactive=False,
260        )
261
262    # --- Button interactions ---
263    btn_random.click(
264        fn=show_random_samples,
265        outputs=[
266            output_plot,
267            output_text,
268            otsu_mean_controls_row,
269        ],
270    )
271    btn_distribution.click(
272        fn=show_class_distribution,
273        outputs=[
274            output_plot,
275            output_text,
276            otsu_mean_controls_row,
277        ],
278    )
279
280    btn_mean.click(
281        fn=show_mean_prototypes,
282        outputs=[
283            output_plot,
284            output_text,
285            otsu_mean_controls_row,
286        ],
287    )
288
289    otsu_mean_checkbox.change(
290        fn=toggle_mean_otsu_binarization,
291        inputs=[otsu_mean_checkbox, mean_threshold_slider],
292        outputs=[output_plot, mean_threshold_slider],
293    )
294
295    mean_threshold_slider.change(
296        fn=update_mean_otsu_threshold,
297        inputs=mean_threshold_slider,
298        outputs=output_plot,
299    )
300
301    return [
302        btn_random,
303        btn_distribution,
304        btn_mean,
305        otsu_mean_controls_row,
306        otsu_mean_checkbox,
307        mean_threshold_slider,
308        output_plot,
309        output_text,
310    ]

Create the Data Exploration UI section.

Builds an interactive Gradio interface for exploring the dataset through various visualization methods. Includes buttons for different visualization types and dynamic controls for prototype image processing.

Returns
  • list of gr.Component: List of all Gradio components created in this tab, including buttons, plots, checkboxes, and sliders. Returned for potential external reference or testing purposes.
Notes

The interface workflow:

  1. Random Samples: Display random images from each class
  2. Class Distribution: Show bar chart of samples per class
  3. Mean Prototypes: Display average image per class with optional Otsu binarization

Otsu Controls:

  • Only visible after generating mean prototypes
  • Checkbox enables/disables binarization
  • Slider adjusts threshold (-1.0 to 1.0) when enabled
  • Updates visualization in real-time

The EdaAnalyzer handles dataset loading, metadata management, and actual visualization generation. This function provides the UI wrapper.

Cache Directory: All prototype arrays are saved to app/sections/cached_data/ to enable fast toggling between normal and Otsu-binarized views.

Examples
>>> with gr.Blocks() as demo:
...     components = data_exploration_tab()
...     # components[0] is btn_random
...     # components[-2] is output_plot
...     # components[-1] is output_text
See Also

EdaAnalyzer: Core class for dataset analysis and visualization