Changes for .kilo/cluster_plotting_plan.md: 0 added lines, 65 removed lines.
Original line number
Diff line number
Diff line
# Plan: Autodetect Data Clusters for Time-Series Plotting
## Objective
Modify the plotting logic in `plot_models.py` to automatically detect data clusters and create a "zoomed-in" view of these clusters. This applies **only** for per-instrument plots. This will eliminate uninformative gaps in the time-series plots while maintaining the overall figure structure and the 6:1 ratio between the left (time-series) and right (diagnostics/KDE) columns.
## Requirements
1.**Cluster Detection**: Use `detect_data_clusters` from `model_math.py` to identify contiguous blocks of data.
2.**Layout Preservation**:
- Keep the 6:1 ratio between the left and right columns.
- The right column (KDE/diagnostics) remains a single panel per row.
- Each row of the left column must be split into subpanels, one per detected cluster.
3.**Proportional Widths**: The width of each subpanel must be proportional to the timespan of the corresponding data cluster.
4.**Zoom-in Effect**:
- Iterate the current plotting procedure over these subpanels.
- Set `xlim` for each subpanel to the timespan of its corresponding cluster, adding a buffer of 5% of the cluster's timespan to the left and right.
5.**Shared Y-Axis**: Subpanels within the same row must share the same y-axis.
6.**No Logic Modification**: The actual plotting commands (errorbars, lines, fills) must remain unchanged; only the axes they are plotted on and their limits are modified.
## Implementation Plan
At the end of each step, run `/dati/pyaetnaEnv/bin/python /dati/software/pyLib/PyAETNA/runPyAETNA.py` and do not proceed until all bugs are fixed.
### 1. Integration of Cluster Detection
#### Status: COMPLETE
- Import `detect_data_clusters` into `plot_models.py`.
- In `plot_models()`, after sorting the data by time (`t`), call `detect_data_clusters(t)` to get the list of cluster boundaries.
- Calculate the total timespan of all clusters to determine the proportional widths.
-*Note: While clusters are detected for any selection, the zoomed-in layout will be applied only when plotting per-instrument data (where gaps are most prevalent).*
### 2. Modification of Figure Layout
#### Status: COMPLETE
- The current `create_figure_layout` likely creates a grid of axes. This needs to be updated or wrapped.
- Instead of a single `axes[i]` for the left column, we will need a list of sub-axes for each row `i`.
- Use `matplotlib.gridspec.GridSpec` or `subplot_mosaic` to create a layout where:
- The right column is a fixed width.
- The left column is divided into $N$ sub-columns (where $N$ is the number of clusters), with widths proportional to the cluster durations.
### 3. Refactoring the Plotting Loop
#### Status: COMPLETE
- Wrap the existing plotting logic for each panel (Panel 0, Panel 1, Panel 2) in a loop over the detected clusters.
- This looping logic must be applied regardless of the number of clusters (including when only one cluster is detected) to ensure consistent code paths.
- For each cluster $C_j$:
- Select the sub-axis $Ax_{i,j}$ corresponding to row $i$ and cluster $j$.
- Execute the existing plotting code on $Ax_{i,j}$.
- Set `Ax_{i,j}.set_xlim(C_j.start, C_j.end)`.
- Ensure `sharey` is enabled across $Ax_{i,j}$ for all $j$ in row $i$.
### 4. Handling Specific Panels
#### Status: COMPLETE
-**Panel 0 (Raw Data)**: Apply the same cluster-splitting logic if it is visible.
-**Panel 1 (Detrended)**: Split into subpanels per cluster.
-**Panel 2 (Residuals)**: Split into subpanels per cluster.
-**KDE/Right Column**: Remains as a single panel per row, as it does not depend on the time-axis.
### 5. Axis Formatting
- Update `format_plot_axes` to handle the new multi-axis structure.
- Ensure x-axis labels and tickmarks are only shown on the bottom-most row of subpanels.
- Ensure y-axis labels and tickmarks are only shown on the left-most column of subpanels.
- Ensure the the y ranges are shared only per-row, not all over the subpanels
- Remove redundant y-axis labels for internal subpanels.
- Promote the title of the [0,0] panel to the title of the whole page
## Technical Details
-**Cluster Widths**: If clusters are $[(t_{0,start}, t_{0,end}), \dots, (t_{N,start}, t_{N,end})]$, the width ratio for `GridSpec` will be $[(t_{0,end}-t_{0,start}), \dots, (t_{N,end}-t_{N,start})]$.
-**Y-Axis Sharing**: Use `sharey=axes[i, 0]` when creating sub-axes for row $i$.
Changes for .kilo/legend_relocation_plan.md: 0 added lines, 27 removed lines.
Original line number
Diff line number
Diff line
# Plan: Relocate Legends for Overlay and Detrended Rows
## Motivation
Currently, legends for the model overlay and detrended rows are placed within the first subpanel (leftmost column). In multi-cluster/multi-instrument plots, this can clutter the data visualization in the first panel while leaving the right side of the figure underutilized.
To maintain consistency with the residual row—which uses a dedicated KDE inset axis on the right—the legends for the upper rows should be moved to a similar dedicated space. This improves visual balance and ensures that data in the first subpanel is not obscured by the legend.
## Objectives
1.**Modify Figure Layout**: Update `FigureLayoutManager` to expand the `GridSpec` by one column. This new rightmost column will be dedicated to legends for the `overlay` and `detrended` rows.
2.**Implement Legend Axes**: Create `legend_ax` for the overlay and detrended rows in the new column, ensuring `axis('off')` is called to keep them borderless.
3.**Update Overlay Rendering**: Modify `_render_rv_overlay` and `_render_lc_overlay` in `panel_overlay.py` to:
* Remove labels from the primary subpanels (set all to `_nolegend_`).
* Use the new dedicated `legend_ax` to render the legend, using `bbox_to_anchor` for precise centering.
4.**Update Detrended Rendering**: Apply similar logic to the detrended row rendering.
5.**Verification**: Ensure that the shift in `GridSpec` does not cause overlap between the new legends and the dynamically positioned KDE insets.