Commit 3a9af7ac authored by Gaetano Scandariato's avatar Gaetano Scandariato
Browse files

Refactor report generation to handle per-instrument residual correlation and improve error logging

parent 66bbc4af
Loading
Loading
Loading
Loading
Loading
+8 −1
Changes for PyAETNA/planet_phys.py: 8 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -2064,11 +2064,18 @@ def _render_corner_groups(pdf, corner_groups, plModel, num_chains, log_func, der
                    valid_params.append(p)
                else:
                    # It's fixed, add to notes
                    # Handle case where arr might be a scalar (float) instead of array
                    if hasattr(arr, 'flatten'):
                        val = arr.flatten()[0] if np.size(arr) > 0 else 0.0
                    else:
                        val = float(arr) if np.size(arr) > 0 else 0.0
                    fixed_notes.append(f"{p} = {val:.4g}")
            
            # Filter samples to only include valid parameters (with variation)
            valid_samples_dict = {p: samples_dict[p] for p in valid_params if p in samples_dict}
            
            fig = plot_corner(
                group['samples'], group['params'],
                valid_samples_dict, valid_params,
                truths=group['truths'],
                title=group['title'],
                plModel=plModel,
+24 −19
Changes for PyAETNA/reporting/pdf_report.py: 24 added lines, 19 removed lines.
Original line number Diff line number Diff line
@@ -647,25 +647,6 @@ def generate_report(pickle_path, output_pdf, log_file=None, config_file=None):
                                pdf.savefig(fig)
                                plt.close(fig)

            # ── 1b. Per-instrument residual correlation (all visits combined, colored by visit) ─
            # After showing individual per-visit correlation plots, add one page showing
            # all visits for this instrument with colors distinguishing each visit.
            inst_mask_full = instrument_full == inst_id
            if _do_per_visit and np.sum(inst_mask_full) >= 10:
                inst_visits = [v for v in visits_to_plot
                               if np.any((visit_arr == v) & (instrument_arr == inst_id))]
                # Only show this combined plot if the instrument has multiple visits with data
                if len(inst_visits) > 1:
                    if hasattr(plData, 'dBasis') and len(plData.dBasis) > 0:
                        _log(f"  - Per-instrument residual correlation (all {len(inst_visits)} visits): {inst_name}")
                        fig = plot_residuals_vs_dbasis(plData, residuals_full_unsorted, plModel=plModel,
                                                      visit_to_plot=None,
                                                      instrument_to_plot=inst_id,
                                                      title=f'Residuals vs. dBasis Variables (All Visits) - {inst_name}')
                        if fig is not None:
                            pdf.savefig(fig)
                            plt.close(fig)

            # ── 2. Per-instrument best-fit model (all visits combined) ───
            try:
                _log(f"  - Per-instrument best-fit {data_type_label}: {inst_name}")
@@ -678,6 +659,9 @@ def generate_report(pickle_path, output_pdf, log_file=None, config_file=None):
                    plt.close(fig)
            except Exception as e:
                _log(f"WARNING: failed to generate per-instrument plot for {inst_name}: {e}")
                import traceback
                for line in traceback.format_exc().split('\n'):
                    _log(f"  {line}")
                fig = plot_models(plData, plModel, best_params, param_config,
                                  samples_dict=samples,
                                  instrument_to_plot=inst_id, show_gp=True, log_func=_log,
@@ -706,6 +690,27 @@ def generate_report(pickle_path, output_pdf, log_file=None, config_file=None):
                pdf.savefig(fig)
                plt.close(fig)

            # ── 1b. Per-instrument residual correlation (all visits combined, colored by visit) ─
            # After showing individual per-visit correlation plots, add one page showing
            # all visits for this instrument with colors distinguishing each visit.
            inst_mask_full = instrument_full == inst_id
            print(_do_per_visit)
            print(np.sum(inst_mask_full))
            if _do_per_visit and np.sum(inst_mask_full) >= 10:
                inst_visits = [v for v in visits_to_plot
                               if np.any((visit_arr == v) & (instrument_arr == inst_id))]
                # Only show this combined plot if the instrument has multiple visits with data
                if len(inst_visits) > 1:
                    if hasattr(plData, 'dBasis') and len(plData.dBasis) > 0:
                        _log(f"  - Per-instrument residual correlation (all {len(inst_visits)} visits): {inst_name}")
                        fig = plot_residuals_vs_dbasis(plData, residuals_full_unsorted, plModel=plModel,
                                                      visit_to_plot=None,
                                                      instrument_to_plot=inst_id,
                                                      title=f'Residuals vs. dBasis Variables (All Visits) - {inst_name}')
                        if fig is not None:
                            pdf.savefig(fig)
                            plt.close(fig)

        # Noise budget summary: per-instrument (and per-visit when jitter scope is per_visit).
        # Shows median σ_orig, median jitter contribution, and residuals RMS side by side
        # so the reader can see at a glance how much of the noise floor comes from the
+1 −0
Changes for PyAETNA/reporting/periodogram_plots.py: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ def _log(msg, level='INFO'):
    logger._log(msg, level=level)

from .plot_model_helpers import _compute_planet_model_for_plotting
from .corner_plot import _get_distinct_colors


def plot_residuals_histogram(residuals, dy, title='Residuals Distribution', figsize=(8, 5)):