Dashboard API
Dash dashboard modules, data loaders, schema helpers, and plotting utilities.
Dashboard App
GONet Dashboard Application Entrypoint
This module defines the public entry point used to launch the GONet interactive dashboard within the unified GONet Wizard UI runtime.
Unlike earlier standalone implementations, the dashboard is now launched through
the centralized Dash orchestration layer provided by
GONet_Wizard.ui.dash_runner. This enables:
Reuse of a single Dash server per (app_key, port)
Consistent startup semantics across CLI and GUI invocations
Integration with the unified Flask + pywebview UI runtime
Clean separation between what the dashboard does and how it is launched
The core responsibility of this module is to assemble a
DashLaunchSpec describing how to configure,
lay out, and run the dashboard, and to delegate execution to
ensure_dash_running().
Functions
ensure_dashboard_running()Public entry point used by CLI and GUI commands to launch (or reuse) the dashboard Dash server.
- GONet_Wizard.GONet_dashboard.src.app.ensure_dashboard_running(input_files, debug, port=8050)[source]
Ensure the GONet dashboard Dash server is running and return its URL.
This function is safe to call repeatedly. If a dashboard instance is already running for the given
port, it is reused. Otherwise, a new Dash server is started in a background thread using the centralized Dash runner.- Parameters:
- Return type:
- Returns:
str– The local dashboard URL (e.g."http://127.0.0.1:8050").
Defines the Flask server and Dash app instance for the GONet Dashboard.
This module initializes:
a
flask.Flaskserver namedGONet_dashboard,a Dash app instance that uses this server as its backend.
These objects are imported by the rest of the dashboard system, including the main entry point
(GONet_Wizard.GONet_dashboard.src.app) and the callback definitions in callbacks.
- GONet_Wizard.GONet_dashboard.src.server.app = <dash.dash.Dash object>
The Dash app instance.
GONet Wizard Dashboard Layout Definition.
This module defines the full layout of the GONet Wizard web dashboard using Dash components. It includes UI elements for plotting, filtering, exporting, and inspecting data. It also defines placeholder figures used before user interaction or data loading.
Layout Overview
Top Section:
Title and logo
Graph container for the main scatter plot
Dropdowns and switches to select channels, axes, and fold settings
Export button to download current filtered data
Bottom Section:
Filter controls for custom and selection-based filters
Upload/Save status buttons to persist or restore UI state
GONet image preview section for pixel-level inspection
Placeholders
Variables
layoutdash.development.base_component.ComponentThe full layout tree of the Dash app, including all Divs, Graphs, Dropdowns, Stores, Uploads, Buttons, and custom components.
Notes
The layout dynamically interacts with callbacks registered in
GONet_Wizard.GONet_dashboard.src.callbacks.Styling and visibility are managed primarily through CSS classes and Dash DAQ components.
- GONet_Wizard.GONet_dashboard.src.layout.layout(all_columns)[source]
Construct the full Dash app layout.
- Parameters:
all_columns (list) – List of all available columns for dropdown selections.
- Return type:
Loading- Returns:
layout (dict) – The complete layout tree for the Dash app.
Callbacks for the GONet Dashboard.
This module defines all Dash callback functions that power the interactivity of the GONet Wizard dashboard. The callbacks handle core responsibilities such as:
Loading and parsing the GONet data archive
Applying and managing user-defined filters
Generating interactive plots and statistics
Managing UI state, selections, and saved configurations
Exporting data and application state to JSON
Callback Registration Decorators
Most callbacks in this module use the custom utils.gonet_callback() decorator, which extends
Dash’s default callback mechanism to include:
Automatic alert handling (via the alert-container)
Inline warning and exception capture
Debug logging (including the triggering input and source line)
This greatly simplifies development and debugging, especially for callbacks that modify user-facing components like figures and tables.
⚠️ Important Exception: MATCH/ALL Pattern-Matching Callbacks
Dash requires all Outputs in a callback to use the same wildcard keys when using pattern-matching IDs
(MATCH, ALL, etc.). Since utils.gonet_callback() automatically adds static alert outputs,
it cannot be used with callbacks that include pattern-matching outputs.
For these cases, such as:
Output({"type": "filter-value", "index": MATCH}, "value")
we used instead:
app.callback()directlyDecorate the callback with
utils.debug_print()for logging
This ensures compatibility with Dash’s output constraints and avoids runtime errors.
Functions
update_main_plot(): Update the main plot based on the selected axes, filters, and other plot parameters.add_filter(): Add a new empty filter block to the filter container in the UI.add_or_filter(): Add an additional (OR-based) condition to an existing filter block.update_main_filters_value(): Automatically update the value of the main filter when a filter label is selected.update_secondary_filters_value(): Automatically update the value of the secondary (OR) filter when a label is selected.update_filters(): Assemble and update the active filters list based on user-defined filter inputs.export_data(): Export filtered data from the plot to a downloadable JSON file.save_status(): Save the current dashboard state, including axis selections and filter configurations.load_status(): Load a previously saved dashboard state from a base64-encoded JSON file.update_filter_selection_state(): Enable or disable the “Add Selection Filter” button based on current selection in the plot.add_selection_filter(): Create and add a new filter based on the current selection region in the plot.exit_app(): Exit the entire application when the “Exit” button is clicked.
- GONet_Wizard.GONet_dashboard.src.callbacks.update_main_plot(x_label, y_label, active_filters, channels, show_filtered_points, clickdata, fig, gonet_fig, info_table)[source]
Update the main plot, statistics table, image preview, and info panel in response to user interaction.
This is the central callback for GONet dashboard interactivity. It responds to any change that affects how data should be visualized or interpreted, and coordinates all downstream updates accordingly. It ensures that the displayed figure remains synchronized with the current filter set, axis choices, selected channels, and clicked data point.
Triggers that activate this callback include:
Changing the selected x- or y-axis quantity
Adding, removing, or modifying any active filters
Toggling the visibility of filtered-out points
Enabling or disabling channels in the channel selector
Clicking a data point on the plot
This function manages the following visual components:
The main scatter plot (created or updated using
FigureWrapper)The statistics summary table (mean ± std for x and y values)
The GONet image heatmap of the selected “big point” (if applicable)
The information table containing metadata for the selected data point
Depending on the triggering input, the function will:
Rebuild the entire figure from scratch (on axis change)
Reapply filters and update trace visibility (on filter change)
Show or hide filtered-out points (on toggle)
Add or remove traces corresponding to visible channels (on channel change)
Highlight and load image + metadata for the selected point (on click)
- Parameters:
x_label (
str) – Selected label for the x-axis (e.g., ‘sky_brightness’).y_label (
str) – Selected label for the y-axis (e.g., ‘temperature’).active_filters (
listofdict) – User-defined filters to apply to the dataset. Each filter includes a label, operator, and value.channels (
listofstr) – List of active channels to display (e.g., [‘red’, ‘green’, ‘blue’]).show_filtered_points (
bool) – Whether to display data points that fail the filter criteria with reduced opacity.clickdata (
dictorNone) – Plotly clickData object containing information about the clicked point (if any).fig (
dict) – Current Plotly figure, passed in from the Dash state.gonet_fig (
dict) – Current heatmap image figure, passed in from the Dash state.info_table (
list) – Current info table rows, passed in from the Dash state.all_data (
dict) – Complete flattened dataset returned byload_data_from_json().
- Returns:
dict– Updated Plotly figure reflecting current filters, axes, and channels.list– Updated statistics table rows with mean and standard deviation summaries.dictordash.no_update– Updated heatmap figure ordash.no_updateif no change is needed.list– Updated rows of the data point information table.
- GONet_Wizard.GONet_dashboard.src.callbacks.add_filter(_, filter_div, labels)[source]
Add a new empty filter block to the filter container in the UI.
- GONet_Wizard.GONet_dashboard.src.callbacks.add_or_filter(_, id, labels)[source]
Add an additional (OR-based) condition to an existing filter block.
- Parameters:
- Returns:
new_filter (dash component) – A new filter component to be added to the filter block.
- GONet_Wizard.GONet_dashboard.src.callbacks.remove_filter(n_clicks, filter_children, remove_ids)[source]
Remove an entire filter block when its trash button is clicked.
- GONet_Wizard.GONet_dashboard.src.callbacks.update_main_filters_value(label)[source]
Automatically update the value of the main filter when a filter label is selected.
- Parameters:
label (
str) – The selected label from the main filter dropdown.- Returns:
value (
AnyorNone) – Default value corresponding to the label, or None if not found.
- GONet_Wizard.GONet_dashboard.src.callbacks.update_secondary_filters_value(label)[source]
Automatically update the value of the secondary (OR) filter when a label is selected.
- Parameters:
label (
str) – The selected label from the secondary filter dropdown.- Returns:
value (
AnyorNone) – Default value corresponding to the label, or None if not found.
- GONet_Wizard.GONet_dashboard.src.callbacks.update_filters(_, switches, ops, values, selections, second_ops, second_values, switch_ids, label_ids, labels, op_ids, value_ids, selection_ids, second_label_ids, second_labels, second_op_ids, second_value_ids, filters_before)[source]
Assemble and update the active filters list from the current filter UI state.
The dashboard has two filter types:
ordinary value filters, which have a
filter-valuecomponent;selection filters, which store selected
epoch_idxvalues in afilter-selection-datastore and therefore do not have afilter-valuecomponent.
Because those two filter types do not expose the same pattern-matching components, this callback aligns all inputs by their component
indexIDs rather than by list position. That makes mixed value filters and selection filters safe to add, remove, toggle, and combine.
- GONet_Wizard.GONet_dashboard.src.callbacks.export_data(export_request)[source]
Export filtered data from the plot to a downloadable JSON file.
This function retrieves all points currently visible in the main plot that are not filtered or marked as big points. It extracts relevant metadata and fit parameters for each unique index across all channels, organizing the data into a structured JSON format for export.
- Parameters:
export_request (
dict) – Small client-generated request containing the visibleepoch_idxvalues and a monotonically increasing request identifier.- Returns:
dict– Descriptor for the staged JSON payload. The clientside save callback uses the one-time local URL without sending the full export through a Dash store or the pywebview bridge.
- GONet_Wizard.GONet_dashboard.src.callbacks.save_status(_, *args)[source]
Save the current dashboard state, including axis selections and filter configurations.
This function collects the current state of all dashboard controls—such as axis dropdowns, filters, channel selections, and switches—and assembles them into a dictionary suitable for export or persistent storage. It supports both primary and secondary filters.
- Parameters:
_ (
Any) – Unused placeholder for the n_clicks input from the “save status” button.*args (
list) – Interleaved list of (id, value) pairs for all input states. Each id can either be a string (for global components like axis dropdowns and switches) or a dictionary (for indexed filters).
- Returns:
dict– A dictionary representing the current state of the dashboard, including:Axis selection values.
All filters and their properties.
Active channels and switch states.
The structure is compatible with later reloading via the
load_status()function.
- GONet_Wizard.GONet_dashboard.src.callbacks.load_status(contents, filter_div, labels)[source]
Load a previously saved dashboard state from a base64-encoded JSON file.
This function decodes and parses the uploaded status file and restores the application state, including axis selections, active channels, switches, and filters. It dynamically reconstructs each filter (both primary and secondary) and injects them into the dashboard.
- Parameters:
- Returns:
x_axis_value (
str) – Restored value for the x-axis dropdown.y_axis_value (
str) – Restored value for the y-axis dropdown.channels (
list) – Restored list of selected channels.show_filtered (
bool) – Whether to show filtered points, as restored from the saved state.filter_div (
list) – Updated list of filter UI components reflecting the saved configuration.
- GONet_Wizard.GONet_dashboard.src.callbacks.update_filter_selection_state(relayout_data)[source]
Enable or disable the “Add Selection Filter” button based on current selection in the plot.
This function checks whether a valid lasso or box selection exists in the main plot. If such a selection is detected (i.e., a non-empty path is present), the filter button becomes enabled; otherwise, it remains disabled.
- Parameters:
- Returns:
bool– False if a valid selection exists (enabling the button), True otherwise (disabling it).
- GONet_Wizard.GONet_dashboard.src.callbacks.add_selection_filter(_, filter_div, relayout_data, figure)[source]
Create and add a new filter based on the current selection region in the plot.
Plotly stores lasso/box selections as point positions within each trace. The dashboard filters data using
epoch_idxvalues, so this callback converts selected trace positions into the corresponding epoch indices before storing the selection filter.- Parameters:
_ (
Any) – Placeholder for the button click triggering the addition of a selection-based filter.filter_div (
list) – Existing list of filter components displayed in the UI.relayout_data (
dict) – Plotly relayout data containing information about lasso/box selections.figure (
dict) – The current figure dictionary shown in the main plot.
- Returns:
- GONet_Wizard.GONet_dashboard.src.callbacks.exit_app(_)[source]
Callback to request closing the PyWebView window when the “Exit” button is clicked.
This callback sends a JavaScript command to the embedded PyWebView browser, which calls the exposed Python API method
close_window()to close the window.
Reusable JSON save and load helpers for Dash applications.
The save helper uses the native pywebview save dialog in the desktop app and a
browser save picker, when available, in a regular browser. In every code path,
the selected filename is restricted or normalized to the .json extension.
Functions
register_json_download()Register a clientside callback that saves JSON data through a user-visible save dialog.
stage_json_download()Serialize a large JSON payload once and expose a short-lived descriptor.
register_staged_json_download()Register the optimized save flow for staged JSON payloads.
load_json()Decode a base64-encoded JSON data URL.
- GONet_Wizard.GONet_dashboard.src.load_save_callbacks.stage_json_download(data, default_filename='data.json')[source]
Serialize JSON once and stage it behind a short-lived local URL.
Returning a tiny descriptor instead of the full export prevents Dash from serializing a large payload into a browser
dcc.Storeand, in the desktop application, prevents pywebview from marshaling that payload back into Python a second time.
- GONet_Wizard.GONet_dashboard.src.load_save_callbacks.register_staged_json_route(server)[source]
Register the one-time local endpoint serving staged JSON exports.
- Return type:
- GONet_Wizard.GONet_dashboard.src.load_save_callbacks.register_json_download(app, output_component, input_component, default_filename='data.json')[source]
Register a reusable clientside callback for saving JSON data.
In the desktop application, the callback delegates to the exposed
window.pywebview.api.download_jsonmethod, which opens the operating system’s native save dialog. In a regular browser it uses the File System Access API when available, falling back to a filename prompt and standard browser download.- Parameters:
app (dash.Dash) – Dash application on which to register the callback.
output_component (dash.Output) – Dummy output used to satisfy Dash’s callback contract.
input_component (dash.Input) – Component property containing the JSON-serializable data to save.
default_filename (str, optional) – Suggested output filename. Any supplied suffix is replaced by
.jsonbefore the callback is registered.
- GONet_Wizard.GONet_dashboard.src.load_save_callbacks.register_staged_json_download(app, output_component, input_component, default_filename='data.json')[source]
Register a save callback for server-staged JSON payloads.
The input component must contain the descriptor returned by
stage_json_download(). The browser receives only that small descriptor. In pywebview, Python downloads the staged bytes directly from the local Dash server after the user selects a destination. In a regular browser, JavaScript fetches the same one-time URL after the save picker is confirmed.
- GONet_Wizard.GONet_dashboard.src.load_save_callbacks.load_json(contents)[source]
Decode a base64-encoded JSON data URL into a Python dictionary.
- Parameters:
contents (str) – Data URL containing base64-encoded JSON content.
- Return type:
- Returns:
dict – Parsed JSON content.
- Raises:
ValueError – If the data URL cannot be decoded or parsed as JSON.
GONet Dashboard Configuration Environment.
This module defines constants and environment-specific settings shared across the GONet Wizard dashboard. It includes plotting styles, default UI parameters, geolocation metadata, timezone definitions, filtering thresholds, and other common resources used throughout the dashboard and data processing utilities.
Constants
- CHANNELS
listofstr Image channels used in processing and plotting (e.g., ‘red’, ‘green’, ‘blue’).
- CHANNEL_COLORS
listofstr Available color ratios between channels (e.g., ‘green/blue’).
- BG_COLOR
str Background color used across the dashboard and plot components.
- TEXT_COLOR
str Foreground text color used for UI elements and figure labels.
- BASE_COLORS
dict Dictionary mapping each channel to a base RGB color (without alpha). Used to generate RGBA strings via the rgba() function.
- LOC_LAT
Quantity Latitude of the observing location (Adler roof) in degrees.
- LOC_LON
Quantity Longitude of the observing location in degrees.
- LOC_ALT
Quantity Altitude of the observing location in meters.
- LOCAL_TZ
tzinfo Timezone object for local time conversions (America/Chicago).
- DAY_START_LOCAL
datetime.time Local time used as the start of a “night” (used for grouping observations).
- DAY_START_UTC
datetime.time UTC equivalent of DAY_START_LOCAL.
- DEFAULT_FILTER_VALUES
dict - Threshold defaults for interactive filtering components. Includes:
‘sunaltaz’: minimum Sun altitude
‘moonaltaz’: minimum Moon altitude
‘moon_illumination’: maximum Moon illumination
‘condition_code’: maximum weather condition index
- OP
dict Dictionary mapping string-based logical operators to Python equivalents. Supports basic comparison operations for filtering logic.
- DEFAULT_OP
str Default operator to apply during filter initialization (e.g., ‘<=’).
Functions
- rgba(channel, alpha)
Return a valid RGBA string for the given channel color and transparency.
Notes
This module is imported across layout, callbacks, and plotting utilities.
The geolocation constants define the fixed position of the GONet camera system at Adler.
Filtering logic and color styling are centralized here for consistent UI behavior.
- GONet_Wizard.GONet_dashboard.src.env.rgba(channel, alpha)[source]
Return an RGBA string for the given channel name and alpha transparency.
GONet Wizard Utility Functions.
This module provides utility functions and constants for the GONet Wizard dashboard application. It includes debugging decorators, a custom Dash callback decorator with enhanced error handling, date/time parsing utilities, and functions to create dynamic filter UI components.
Dash components from dash and dash_daq are used to construct UI elements dynamically.
Functions
debug_print(): Decorator that logs when a Dash callback is triggered, including the triggering component ID and source line.gonet_callback(): Custom Dash callback decorator that extends the original callback with automatic alert handling, debug logging, and error state protection.parse_date_time(): Parses and converts a date/time value based on the provided label.new_empty_filter(): Create a Dash component representing an empty primary filter block.new_empty_second_filter(): Create a Dash component block representing a secondary (OR) filter.new_selection_filter(): Create a Dash component for a selection-based filter using manually selected points.
- GONet_Wizard.GONet_dashboard.src.utils.debug_print(callback_fn)[source]
Decorator that logs when a Dash callback is triggered, including the triggering component ID and source line.
This decorator is useful for debugging and tracing which callbacks are being executed during development. Logging only occurs when the
WERKZEUG_RUN_MAINenvironment variable is set to “true”, which ensures the message is printed only by the reloader’s main process.- Parameters:
callback_fn (callable) – The Dash callback function to wrap.
- Returns:
callable – The wrapped function that logs on invocation and then calls the original function.
- GONet_Wizard.GONet_dashboard.src.utils.gonet_callback(*args, **kwargs)[source]
Custom Dash callback decorator that extends the original callback with automatic alert handling, debug logging, and error state protection.
This decorator automatically appends three additional outputs for managing an alert container:
alert-container.children (message content)
alert-container.className (CSS class for styling)
alert-container.style (visibility/display logic)
It also adds one hidden State:
alert-container.className (used to suppress execution if an error is already active)
The wrapped callback will: - Suppress execution if the alert container is currently showing an error (“alert-box error”). - Capture and display any warnings issued during execution. - Catch exceptions and display a red alert box with the error message. - Log a message when the callback is triggered, including the triggering component (if WERKZEUG_RUN_MAIN == “true”).
- Parameters:
*args (dash.Output, dash.Input, dash.State) – Positional arguments defining the Dash callback’s outputs, inputs, and states. All initial Output(…) arguments are treated as actual user outputs.
**kwargs (dict) – Additional keyword arguments passed to Dash’s app.callback.
- Returns:
callable – The decorated function registered as a Dash callback.
- GONet_Wizard.GONet_dashboard.src.utils.parse_date_time(label, value)[source]
Parses and converts a date/time value based on the provided label.
This function processes a given date/time value and returns it in a standardized format. Depending on the label, it either converts an ISO datetime string to Unix time or a time string (hours:minutes:seconds) to a fraction of the day. If the label corresponds to ‘date’, the value is converted to Unix time. If the label corresponds to ‘hours’, the value is converted to a fraction of the day, accounting for potential time zone shifts.
- Parameters:
- Returns:
tuple – A tuple containing the processed label and the parsed value:
If the label starts with ‘date’, the value will be the corresponding Unix time as an integer.
If the label starts with ‘hours’, the value will be a float representing the fraction of the day.
If the time is earlier than the defined ‘day start’ (UTC or local), the function will adjust the value to the following day.
- Raises:
ValueError – If the ‘value’ cannot be parsed into a valid datetime or time string, the function will print an error message and return None.
- GONet_Wizard.GONet_dashboard.src.utils.new_empty_filter(idx, labels)[source]
Create a Dash component representing an empty primary filter block.
This function generates a new UI element for a filter container, including: - A toggle switch to activate the filter - Dropdowns for selecting the data field and comparison operator - An input box for entering the comparison value - A button to optionally add a secondary (OR) filter
- Parameters:
- Return type:
Div- Returns:
dash.html.Div– A fully constructed Dash Div component containing the filter UI.
- GONet_Wizard.GONet_dashboard.src.utils.new_empty_second_filter(idx, labels)[source]
Create a Dash component block representing a secondary (OR) filter.
This function returns a list of Dash components corresponding to a secondary filter UI. It includes a label (“OR”), a dropdown for field selection, a dropdown for the operator, and an input field for the value.
- GONet_Wizard.GONet_dashboard.src.utils.new_selection_filter(idx, selected_indexes)[source]
Create a Dash component for a selection-based filter.
Selection filters are created from lasso/box-selected plot points. The stored values are
epoch_idxidentifiers, not Plotly trace point positions.The component IDs intentionally use the same key schema as ordinary value filters:
{"type": ..., "index": <stable-index>}. Keeping the ID keys consistent is important because Dash pattern-matching callbacks only receive components that match the requested ID schema. A previous implementation put an additionaluuidkey on the switch ID, which meant toggling a selection filter did not reliably trigger the sharedupdate_filterscallback.- Return type:
Div
Hood Plotting and Loaders
Dashboard data and plotting backend.
The hood package contains the non-layout logic used by the GONet dashboard:
data loading, schema coercion, derived columns, and Plotly figure construction.
It intentionally sits below the Dash callback layer so that most data-handling
code can be tested without running a Dash application.
Subpackages
loadersFile-format loaders and shared post-processing for dashboard data tables.
Submodules
plotPlotly figure construction and trace-update helpers used by dashboard callbacks.
Plot utilities for interactive visualization of GONet sky monitoring data.
This module provides Plotly-compatible wrappers and helper classes for rendering, filtering, and interacting with GONet dashboard plots in a Dash application. It includes specialized data structures that extend standard Python types (e.g., dict) to support reactive behavior, styling changes, and integration with user inputs like selections and click events.
Classes
Trace:A dictionary-like wrapper for a single Plotly scatter trace with built-in styling logic tied to filter and visibility states. Automatically updates marker opacity and hover behavior when filtered or hidden flags are set.
FigureWrapper:A manager class that encapsulates a complete Plotly figure dictionary and provides high-level methods for trace filtering, channel updates, visibility toggling, point selection, and summary statistics. Designed to maintain JSON-serializability for use in Dash callbacks.
This module is intended to serve as the plotting backend for the GONet dashboard UI.
- class GONet_Wizard.GONet_dashboard.src.hood.plot.Trace(xfield, yfield, channel)[source]
Bases:
dictA specialized dictionary-like object representing a single Plotly scatter trace with automatic styling and visibility behavior. This class is intended to be used in applications like Dash where Plotly figures must remain JSON-serializable, but where it is useful to treat individual traces as stateful, reactive objects.
This wrapper class auto-initializes a full trace structure upon creation, and includes logic to modify the trace’s appearance when certain semantic fields (
filtered,hidden) are updated.Reactive Key Behaviors
- Setting filtered = True:
Reduces marker opacity to 0.2.
- Setting filtered = False:
Restores marker opacity to 1.0.
- Setting hidden = True:
Sets marker opacity to 0 (fully transparent),
Disables hover information,
Sets marker line width to 0 (if applicable).
- Setting hidden = False:
Sets opacity back to 0.2 (like a filtered trace),
Restores hover information and hovertemplate,
Sets marker line width to 2 (if applicable).
Changing the
markerkey will automatically change theunselectedmarker as well.
Notes
This class behaves like a dictionary and can be appended directly to a Plotly figure’s data list.
It is fully JSON-serializable and can be passed to Dash components.
You must use this class instead of a plain dictionary if you want the special reactive behavior described above.
- class GONet_Wizard.GONet_dashboard.src.hood.plot.FigureWrapper(fig, xfield, yfield, all_data)[source]
Bases:
objectA stateful wrapper around a Plotly figure dictionary for interactive visualization in the GONet dashboard.
This class manages trace creation, filtering, visibility toggling, and interactivity for a multi-channel Plotly scatter plot. It provides a high-level API to dynamically update plots in response to user interactions (e.g., selection filters, click events, channel switching) while maintaining JSON-compatibility for use in Dash callbacks.
Key Features
Stores a reference to the full data (all_data) and x/y labels
Tracks currently plotted channels and filter state
Separates traces into normal, filtered, and big-point variants per channel
Automatically updates trace styling and visibility when filters change
Supports reconstruction from serialized figures (from_fig)
Integrates with environment configuration (e.g., colors, filter ops)
Recommended Entry Point
Use
FigureWrapper.build()to initialize a fresh figure and add traces for each channel. Alternatively, usefrom_fig()to restore a figure after a Dash callback round trip.- all_data
Full GONet dataset used for plotting, including x/y values, filters, and channels.
- Type:
- total_filter
Boolean array (same length as data) representing active filtering state.
- Type:
np.ndarray
- show_filtered_points
Whether to display filtered-out points with reduced opacity or hide them entirely.
- Type:
- big_point_idx
Index of the currently selected “big point” for highlighting and image preview.
- Type:
int or None
Notes
Each channel has three associated traces: visible, filtered, and big-point.
Traces are dynamically updated using filter_traces, update_filters, and apply_visibility.
All traces are Plotly- and Dash-compatible (JSON-serializable).
- classmethod build(xfield, yfield, channels, show_filtered_points, all_data)[source]
Construct a new
FigureWrapperwith default layout and one trace per channel.This method initializes a Plotly figure dictionary with a standardized layout and styling settings based on the GONet dashboard environment. It then creates a new
FigureWrapperinstance and populates it with traces for each requested channel.If both xfield and yfield refer to general (non-channel-specific) quantities, only a single trace is created using channel “gen” as a placeholder.
- Parameters:
xfield (
str) – The quantity to be used for the x-axis. This must be a key in all_data.yfield (
str) – The quantity to be used for the y-axis. This must be a key in all_data.channels (
listofstr) – A list of channel names (e.g., [‘red’, ‘green’, ‘blue’]) to generate traces for.show_filtered_points (bool) – Whether to display filtered-out points with reduced opacity or hide them entirely.
all_data (
pd.DataFrame) – The full dataframe used by the dashboard.
- Returns:
FigureWrapper – A new wrapper object containing the initialized figure and all traces.
Notes
Time-based x-labels (starting with ‘hours_’) are formatted as HH:MM.
The method uses app.server.config[“base_columns”] to determine if the selected axes are non-channel-specific.
This is the standard entry point for figure creation at the beginning of a session.
- classmethod from_fig(fig, all_data)[source]
Reconstruct a
FigureWrapperfrom an existing Plotly figure dictionary.This method is used to rehydrate a previously serialized Plotly figure back into a fully functional
FigureWrapperinstance. It restores internal logic such as:Trace interactivity via the
TracewrapperActive channels
Selection state (big_point_idx)
Visibility toggle for filtered points
- Parameters:
fig (
dict) –A Plotly-compatible figure dictionary, typically from a callback. It must include:
’layout’: with axis title strings under xaxis.title.text and yaxis.title.text
’data’: a list of trace dictionaries, each with at least a ‘channel’ field
all_data (
dict) – The full dataset originally used to construct the figure, including the keys referenced by each trace’s ‘x’, ‘y’, and ‘epoch_idx’ attributes. This is needed to restore filtering, indexing, and interactivity.
- Returns:
FigureWrapper – A fully reconstructed FigureWrapper with trace semantics, filter states, and internal configuration restored.
Notes
Each trace in fig[‘data’] is converted into a
Traceobject.Channels are inferred from the ‘channel’ field in each trace.
If a trace is marked as big_point, its associated epoch_idx[0] is stored as big_point_idx.
If any trace is marked as hidden, show_filtered_points is set to False.
This method assumes that all necessary metadata exists in the figure dictionary and that all_data is consistent with what was used to generate the figure.
- add_trace(channel)[source]
Add a new set of traces to the figure for a given channel.
This method creates three separate traces for the specified channel:
A primary trace for visible (unfiltered) points
A secondary trace for filtered (low-opacity) points
A third trace for the currently selected “big point”
The traces are appended in order to the Plotly figure’s data list. Styling and visibility behaviors are configured using the
Traceclass, which responds to keys like filtered, hidden, and big_point.
- filter_traces(channel)[source]
Apply the current filter mask to all traces associated with a specific channel.
This method updates the x, y, and epoch_idx values of traces in the figure based on whether they should be shown as filtered or not, using the self.total_filter boolean mask and the specified data channel.
For “big point” traces, it toggles the filtered attribute depending on whether the corresponding index appears in the active subset. For other traces, it directly updates their data arrays with filtered or excluded values.
- update_visibility(show_filtered_points)[source]
Update the visibility flag for filtered points.
This method sets the internal flag controlling whether traces marked as filtered should be displayed or hidden in the plot. It does not directly modify the figure; you must call apply_visibility() afterward to apply the change.
- apply_visibility()[source]
Apply the current visibility setting to all filtered traces.
This method updates the ‘hidden’ property of each trace based on whether filtered points should be shown or hidden. It uses the internal flag self.show_filtered_points, which can be modified via update_visibility().
Traces with filtered = True will be: :rtype:
NoneShown with reduced opacity if show_filtered_points is True
Fully hidden if show_filtered_points is False
- update_channels(new_channels)[source]
Add or remove traces to match a new list of active channels.
- Parameters:
new_channels (
list) – The updated list of channels to be shown.
Notes
Traces with ‘channel’ not in new_channels are removed.
Traces for new channels are added with default settings and shared data.
- update_filters(active_filters)[source]
Update the global filter mask based on the provided list of active filters.
This method processes each filter definition and updates self.total_filter, a boolean mask indicating which data points should be retained. Filters may be simple threshold-based comparisons or special selection-based filters using image indices.
Each filter is interpreted as either:
A selection filter: matches image indices (label == “Selection …”)
A numeric filter: compares a field against a value using a specified operator from env.OP, with optional secondary filter logic.
- Parameters:
active_filters (
listofdict) –Each filter dict must include:
’label’ :
str— the field name or “Selection …”.’operator’ :
str— key in env.OP for the comparison function.’value’ : comparable — the value to compare against.
Optionally:
’secondary’ :
dict— a nested filter with the same keys (‘label’, ‘operator’, ‘value’).
- Return type:
Notes
All filters are combined using logical AND.
Secondary filters are combined with the primary using logical OR.
The resulting self.total_filter array is used by filter_traces() to control visibility.
About type casting
When filters come from the UI they are often strings (e.g., “3”, “2024-11-22T23:15:11+00:00”). We cast the comparison value to the column’s native type by looking at the first non-null exemplar in that column (via .dropna().iloc[0]) and calling that type on the incoming value. This avoids deprecated patterns like int(series) / float(series) and ensures we compare numbers to numbers and datetimes to datetimes. If the column has only nulls, we fall back to using the incoming value as-is.
- gather_big_point(clickdata)[source]
Update the index of the selected “big point” based on click interaction data.
This method extracts the index of the clicked point from Plotly’s clickData dictionary and stores it in self.big_point_idx. This index is later used for highlighting or retrieving detailed information about the selected point.
- Parameters:
clickdata (
dict) –A dictionary passed from a Dash Plotly clickData callback. It must contain a ‘points’ list with at least one item, each including:
’curveNumber’: int — the index of the clicked trace in fig[‘data’]
’pointIndex’: int — the index of the clicked point within that trace
- Return type:
- plot_big_point()[source]
Update the figure to highlight the currently selected “big point”.
This method sets the data for the special “big point” trace associated with each channel. It updates the trace with the coordinates of the selected point, based on self.big_point_idx and the current x/y axis labels.
The point is only plotted if both its index and channel match a known data entry. Its filtered flag is also updated depending on whether the point passes the current filter.
- Return type:
- Returns:
None – This method updates the figure in-place.
Notes
The “gen” channel is treated as “red” for indexing purposes.
- get_stats()[source]
Compute summary statistics (mean and standard deviation) for plotted x and y values.
This function extracts unfiltered, non-highlighted data from the figure and calculates per-axis statistics. It builds an HTML table as a list of Dash row components to be rendered in the dashboard’s stats panel.
- Returns:
list– A list ofdash.html.Trelements representing the statistics table rows.
- get_data_point_info()[source]
Retrieve detailed metadata for the currently selected “big point”.
This method gathers all relevant information for the data point indexed by self.big_point_idx, combining general metadata and channel-specific fit values into a single dictionary.
General fields (from app.server.config[“base_columns”]) are assumed to be identical across channels and are taken from the first matching index. Channel-specific fields (from app.server.config[“channel_columns”]) are extracted separately for each matching channel and labeled accordingly.
- Return type:
- Returns:
dict – A dictionary containing the values of all general and fit-related fields for the selected “big point”. Fit values are keyed by {label}_{channel}.
- gonet_image(clickdata)[source]
Render the GONet image associated with the clicked dashboard point.
The dashboard expects the loaded extraction products to contain a
filenamefield storing the full path to the extracted GONet image. This method reads that path fromself.all_dataand loads the image directly, without requiring a separate image-directory setting.If the file is missing or cannot be read, a non-breaking placeholder figure is returned instead of raising an exception.
Loaders package
Unified data loading interface for the GONet dashboard.
This package provides a small, extensible framework for turning various
on-disk data products (JSON logs, CSV summaries, etc.) into a single,
tidy pandas.DataFrame suitable for plotting and analysis in the
GONet dashboard.
Design philosophy
The loaders package is built around a few guiding ideas:
Format-agnostic dashboard code The rest of the dashboard should not care whether data comes from JSON, CSV, or any other future format. It calls a single function,
load_data(), and receives a fully prepared DataFrame plus lists of plottable columns.Thin, pluggable file-format loaders Each concrete loader (e.g. JSON, CSV) is responsible only for:
Reading one or more files of a specific format.
Producing a long/tidy DataFrame with one row per (exposure, channel) pair.
Using the shared
DATA_SPECconfiguration and coercion logic where appropriate.
Loaders do not compute derived columns (colors, etc.) and do not assign epoch indices; those are handled centrally.
Centralized post-processing Once all format-specific loaders have done their work, this module:
Concatenates their DataFrames.
Sorts rows by
filenameand assigns an integerepoch_idxso that all rows from the same exposure share the same index.Derives color columns (e.g.
color_rg,color_gb,color_rb) from channel mean counts viacolors.color_from_channels().Builds the lists of plottable environment and channel columns based on
DATA_SPEC.
This keeps the domain logic (how the dashboard wants to see the data) separate from the I/O logic (how the data is stored on disk).
Public API
The main entry point for other parts of the dashboard is:
load_data(files, kind=None)()Given an iterable of file paths, this function:
Determines the appropriate loader for each file (either from the
kindkeyword or by file extension).Delegates to each loader to read and parse its files.
Concatenates the results into a single DataFrame.
Assigns
epoch_idxbased onfilename.Expands the DataFrame with derived color columns and computes the
base_columnsandchannel_columnslists.
Internal helpers
This module also defines one internal helper that is not intended to be used directly by dashboard code:
_expand_dataframe(df)()Adds derived color columns, normalizes dtypes, and computes the plottable base/channel column name lists from the combined DataFrame.
Submodules
The loaders package is organized into a few small, focused modules:
-
Defines the
DataSpecLoaderBasemixin, which pre-builds per-field parsers fromDATA_SPECand exposesparse_field()for use by concrete loaders. It also contains the loader registry andget_loader(), which maps a loader name or file extension to a registered loader instance. -
Houses the coercion and transform functions used to interpret raw values according to
DATA_SPEC(e.g. converting strings to floats, datetimes, or “hours of the day”). Exposescompose_parser(), which builds a per-field parser from the DATA_SPEC configuration. -
Provides
color_from_channels(), a small utility that computes color indices (e.g.2.5 log10(a/b)) from channel mean counts with robust NaN handling. -
Implements
JsonLoader, a concrete loader that reads GONet JSON logs (lists of epoch dictionaries) and produces a long/tidy DataFrame with one row per (epoch, channel). It relies onDataSpecLoaderBasefor field parsing and registers itself with the global loader registry at import time. -
Implements
CsvLoader, a concrete loader for GONet CSV summary files. It interprets per-channel columns of the form<channel>_<field>(e.g.red_mean_counts) and reshapes them into long format (unprefixed field names plus achannelcolumn). LikeJsonLoader, it registers itself with the loader registry when imported.
Additional loaders for new file formats can be added by defining a new
loader class in this package, subclassing DataSpecLoaderBase,
and registering it via register_loader().
- GONet_Wizard.GONet_dashboard.src.hood.loaders.load_data(files, kind=None)[source]
High-level loader entry point.
- Parameters:
files (
collections.abc.Iterable) – Iterable of file paths to load.kind (
str, optional) – Optional loader key (e.g.,"json"or"csv"). If omitted, the loader is inferred separately for each file from its extension.
- Return type:
- Returns:
tuple– A 3-tuple(df, base_columns, channel_columns), where:dfis the combinedpandas.DataFrame.base_columnsis the list of plottable environment columns.channel_columnsis the list of plottable channel columns.
- Raises:
ValueError – If no suitable loader can be found for one or more files, or if the resulting DataFrame has no ‘filename’ column.
Base Loaders Module
Core loader infrastructure for the GONet dashboard.
This module defines the common base class and registry used by all file-format
loaders (JSON, CSV, and future extensions). Concrete loaders inherit from
DataSpecLoaderBase to obtain DATA_SPEC-aware field parsing, and they
register themselves using register_loader() so that the dispatcher
(get_loader()) can locate the appropriate loader for any given file.
Classes
DataSpecLoaderBaseMixin providing DATA_SPEC-driven field parsing for concrete loaders.
Constants
_NAME_REGISTRYDictionary mapping loader names (e.g.
"json","csv") to loader instances._EXT_REGISTRYDictionary mapping file extensions (e.g.
"json","csv") to loader instances.
Functions
register_loader()Register a concrete loader instance using both its
nameand fileextensions.get_loader()Resolve and return a loader instance, either by explicit
kindor by inferring the appropriate loader from a file’s extension.
- class GONet_Wizard.GONet_dashboard.src.hood.loaders.base.DataSpecLoaderBase[source]
Bases:
objectBase mixin providing DATA_SPEC-driven field parsing via the
parse_field()method. Concrete loaders subclass this and implement aload(files)method, as well as definingnameandextensionsattributes to identify themselves.
- GONet_Wizard.GONet_dashboard.src.hood.loaders.base.register_loader(loader)[source]
Register a loader instance under its name and extensions.
- Parameters:
loader (
DataSpecLoaderBase) – The loader instance to register.- Return type:
- Returns:
None– This function does not return a value.
- GONet_Wizard.GONet_dashboard.src.hood.loaders.base.get_loader(kind, sample_path)[source]
Resolve a loader from an optional kind or from the file extension.
- Parameters:
kind (
str, optional) – Loader name (e.g."json"or"csv"). IfNone, the loader is inferred from thesample_pathextension.sample_path (
pathlib.Path) – A representative file path used for extension inference.
- Return type:
- Returns:
DataSpecLoaderBase– The matching loader.- Raises:
ValueError – If no suitable loader can be found.
Schema coercion helpers for dashboard loaders.
Dashboard input files may contain values as strings, native Python objects, or
serialized timestamps depending on the source format. This module provides the
small coercion and transform functions used by concrete loaders to normalize
those values before they are combined into a single pandas.DataFrame.
The functions are intentionally conservative: failed numeric conversions return
None instead of raising, which lets loaders preserve partially valid rows and
lets the dashboard decide how to handle missing values.
Constants
COERCERSMapping from schema names to value coercion functions.
TRANSFORMSMapping from schema names to post-coercion transform functions.
Functions
compose_parser()Build a per-field parser from a
Field.parse_hours_of_the_day()Parse
HH:MM:SSstrings across a configurable day boundary.
- GONet_Wizard.GONet_dashboard.src.hood.loaders.schema.parse_hours_of_the_day(t, start_of_day)[source]
Parse ‘HH:MM:SS’ into a fixed date, split by a day boundary.
- Parameters:
t (
str) – Time string in ‘HH:MM:SS’ format.start_of_day (
datetime.time) – Time object representing the start-of-day boundary (e.g. UTC or local).
- Return type:
- Returns:
datetime.datetime– Datetime object representing the parsed time.
- GONet_Wizard.GONet_dashboard.src.hood.loaders.schema.as_is(x)[source]
Identity coercer: returns the input as-is.
- Parameters:
x (
Any) – Input value.- Return type:
- Returns:
Any– The same input value.
- GONet_Wizard.GONet_dashboard.src.hood.loaders.schema.as_float(x)[source]
Coerce input to float, or return None if conversion fails.
- GONet_Wizard.GONet_dashboard.src.hood.loaders.schema.as_int(x)[source]
Coerce input to int, or return None if conversion fails.
- GONet_Wizard.GONet_dashboard.src.hood.loaders.schema.as_bool(x)[source]
Coerce input to bool, or return None if conversion fails.
- GONet_Wizard.GONet_dashboard.src.hood.loaders.schema.as_str(x)[source]
Coerce input to str, or return None if input is None.
- GONet_Wizard.GONet_dashboard.src.hood.loaders.schema.as_datetime(x)[source]
Coerce input to datetime, or return None if conversion fails.
- GONet_Wizard.GONet_dashboard.src.hood.loaders.schema.compose_parser(field)[source]
Compose a per-field parser from DATA_SPEC.load: value -> coerce(value) -> transform(value, cfg)
CSV loader for the GONet dashboard.
This module defines CsvLoader, a concrete file-format loader for
GONet CSV summary files. Each CSV file is expected to contain one row per
exposure, with:
Base (environment-level) fields stored as regular columns.
Per-channel photometric fields stored using prefixed column names such as
red_mean_counts,green_total_counts, orblue_std.
The loader reshapes these wide-format rows into a long/tidy
pandas.DataFrame, producing one row per (epoch, channel) pair. It:
Parses base fields using DATA_SPEC-aware coercion via
parse_field().Identifies per-channel fields by their
<channel>_prefix.Strips the prefix to produce unprefixed field names that match the JSON loader.
Attaches a
channelcolumn identifying the color band.
Derived quantities (e.g. color indices) and the assignment of epoch_idx are
handled upstream by load_data() after all loaders have produced their
raw long-format DataFrames.
This loader registers itself with the global loader registry at import time
via register_loader().
Classes
CsvLoaderConcrete loader for GONet CSV summary files.
- class GONet_Wizard.GONet_dashboard.src.hood.loaders.csv_loader.CsvLoader[source]
Bases:
DataSpecLoaderBaseLoader for GONet CSV summary files.
The expected format is one where each row is an epoch, with base fields (env-level) as columns, and per-channel fields prefixed by the channel name (e.g. “red_mean_counts”, “green_std_counts”, etc.).
This class inherits from
DataSpecLoaderBaseand implements aload(files)method that returns a long-format DataFrame with parsed base fields, parsed per-channel fields, and achannelcolumn.- load(files)[source]
Load CSV files containing GONet epoch summaries into a long-format DataFrame.
- Parameters:
files (Iterable[str]) – An iterable of file paths to CSV files containing GONet epoch summaries.
- Return type:
DataFrame- Returns:
pd.DataFrame – A long-format DataFrame with parsed base fields, parsed per-channel fields, and a “channel” column.
JSON loader for the GONet dashboard
This module defines the JsonLoader, a concrete file-format loader that
reads GONet JSON data products. Each JSON file is expected to contain a list of
epoch dictionaries, with top-level metadata fields and per-channel subdicts
(e.g. {"red": {...}, "green": {...}, "blue": {...}}). The loader reshapes
these records into a long/tidy pandas.DataFrame where each row
corresponds to a single (epoch, channel) pair.
Field values are parsed using the DATA_SPEC-driven coercion and transformation
logic provided by DataSpecLoaderBase. This loader does not
compute derived quantities (e.g. color indices) and does not assign epoch
indices—those steps are handled at the package level by load_data().
The loader registers itself at import time using
register_loader(), making it discoverable by the loader
dispatcher.
Classes
JsonLoaderLoader for JSON files where each file is a list of epoch dicts.
- class GONet_Wizard.GONet_dashboard.src.hood.loaders.json_loader.JsonLoader[source]
Bases:
DataSpecLoaderBaseConcrete loader for JSON epoch lists. Inherits from
DataSpecLoaderBaseand implements aload(files)method that returns a long-format DataFrame with parsed base fields, parsed per-channel fields, and achannelcolumn.- load(files)[source]
Load JSON files containing lists of epoch dicts into a long-format DataFrame.
- Parameters:
files (Iterable[str]) – An iterable of file paths to JSON files containing lists of epoch dicts.
- Return type:
DataFrame- Returns:
pd.DataFrame – A long-format DataFrame with parsed base fields, parsed per-channel fields, and a “channel” column.
Derived color-column utilities for dashboard data.
The dashboard represents channel ratios as astronomical color-like quantities,
computed as 2.5 * log10(a / b). This module keeps that calculation in one
place so JSON and CSV dashboard inputs produce the same derived color_*
columns after loading.
Functions
color_from_channels()Compute a vectorized color value from two count arrays, returning
NaNwhere either input is non-finite or non-positive.
- GONet_Wizard.GONet_dashboard.src.hood.loaders.colors.color_from_channels(a, b)[source]
Vectorized 2.5 * log10(a / b) with NaN handling.
- Parameters:
a (array-like) – First channel values.
b (array-like) – Second channel values.
- Returns:
out (ndarray) – Array of color values computed as 2.5 * log10(a / b), with NaNs where inputs are invalid (non-finite or non-positive).