From 27d9dbee5bd618a0e1c6eeb2d4391cc7bc112c0f Mon Sep 17 00:00:00 2001 From: Antoine Date: Fri, 30 Jan 2026 00:03:38 +0000 Subject: [PATCH] fix(psd): auto-scale x-axis to data range, improve plot layout - X-axis now auto-ranges from data (was going to 10^21) - Band annotations clamped to actual data extent - Legend moved to upper-right (was overlapping data) - Thicker lines (2.5px), larger axis labels - dtick=1 for clean log-scale tick marks --- tools/generate_optical_report.py | 51 ++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/tools/generate_optical_report.py b/tools/generate_optical_report.py index 5aa8c43a..6f3e65e2 100644 --- a/tools/generate_optical_report.py +++ b/tools/generate_optical_report.py @@ -381,36 +381,55 @@ def make_psd_plot(psd_data_dict, title="Power Spectral Density"): '90° (Abs)': '#16a34a', '20° (Abs)': '#64748b'} fig = go.Figure() + # Determine axis range from data + all_freqs = [] + all_psd = [] for label, (freqs, psd) in psd_data_dict.items(): valid = psd > 0 + f_valid, p_valid = freqs[valid], psd[valid] + all_freqs.extend(f_valid.tolist()) + all_psd.extend(p_valid.tolist()) fig.add_trace(go.Scatter( - x=freqs[valid], y=psd[valid], + x=f_valid, y=p_valid, mode='lines', name=label, - line=dict(color=colors.get(label, '#6366f1'), width=2), + line=dict(color=colors.get(label, '#6366f1'), width=2.5), hovertemplate="%{x:.1f} cyc/apt: %{y:.2e}" + label + "", )) - # Band annotations - fig.add_vrect(x0=0.1, x1=2.0, fillcolor='rgba(59,130,246,0.08)', line_width=0, layer='below', + # Compute axis limits from actual data + if all_freqs: + f_min = max(0.05, min(all_freqs) * 0.5) + f_max = max(all_freqs) * 2.0 + else: + f_min, f_max = 0.05, 200.0 + + # Band annotations — clamped to data range + band_max = min(f_max, 200.0) + fig.add_vrect(x0=0.1, x1=2.0, fillcolor='rgba(59,130,246,0.07)', line_width=0, layer='below', annotation_text="Gravity", annotation_position="top left", - annotation=dict(font=dict(size=10, color='#3b82f6'))) - fig.add_vrect(x0=2.0, x1=20.0, fillcolor='rgba(245,158,11,0.08)', line_width=0, layer='below', + annotation=dict(font=dict(size=11, color='#3b82f6'))) + fig.add_vrect(x0=2.0, x1=20.0, fillcolor='rgba(245,158,11,0.07)', line_width=0, layer='below', annotation_text="Support", annotation_position="top left", - annotation=dict(font=dict(size=10, color='#f59e0b'))) - fig.add_vrect(x0=20.0, x1=200.0, fillcolor='rgba(239,68,68,0.06)', line_width=0, layer='below', - annotation_text="High Freq", annotation_position="top left", - annotation=dict(font=dict(size=10, color='#ef4444'))) + annotation=dict(font=dict(size=11, color='#f59e0b'))) + if band_max > 20: + fig.add_vrect(x0=20.0, x1=band_max, fillcolor='rgba(239,68,68,0.05)', line_width=0, layer='below', + annotation_text="High Freq", annotation_position="top left", + annotation=dict(font=dict(size=11, color='#ef4444'))) fig.update_layout( height=500, width=1100, margin=dict(t=30, b=60, l=80, r=30), **_PLOTLY_LIGHT_LAYOUT, - xaxis=dict(type='log', title=dict(text="Spatial Frequency [cycles/aperture]", font=dict(color='#1e293b')), - gridcolor='#e2e8f0', tickfont=dict(color='#475569')), - yaxis=dict(type='log', title=dict(text="PSD [nm²·mm²]", font=dict(color='#1e293b')), - gridcolor='#e2e8f0', tickfont=dict(color='#475569')), - legend=dict(x=0.01, y=0.99, bgcolor='rgba(255,255,255,0.9)', - bordercolor='#e2e8f0', borderwidth=1, font=dict(size=11, color='#1e293b')), + xaxis=dict(type='log', + title=dict(text="Spatial Frequency [cycles/aperture]", font=dict(color='#1e293b', size=13)), + range=[np.log10(f_min), np.log10(f_max)], + gridcolor='#e2e8f0', tickfont=dict(color='#475569', size=11), + dtick=1), + yaxis=dict(type='log', + title=dict(text="PSD [nm\u00b2\u00b7mm\u00b2]", font=dict(color='#1e293b', size=13)), + gridcolor='#e2e8f0', tickfont=dict(color='#475569', size=11)), + legend=dict(x=0.70, y=0.98, bgcolor='rgba(255,255,255,0.92)', + bordercolor='#e2e8f0', borderwidth=1, font=dict(size=12, color='#1e293b')), ) return fig.to_html(include_plotlyjs=False, full_html=False, div_id="psd_plot")