Skip to content

cosmotron_mcp.tools.systematics_checks

compute_cterm

compute_cterm(session_dir: str, bin_index: int, n_bootstrap: int = 300, jobspec: dict | None = None) -> dict

Additive shear c-term for a spin-2 bin: c_k = ⟨w·e_k⟩/⟨w⟩ vs σ_e.

Weighted means from the bin's standardised FITS; seeded bootstrap errors (deterministic). Gate statistic max(|c1|,|c2|)/σ_e vs cterm_sigma_e_max_frac. Writes results/systematics/cterm_bin_{i:02d}.json. Spin-2 bins only (spin-0 → needs_input).

Parameters:

Name Type Description Default
session_dir str

Session directory.

required
bin_index int

Tomographic bin index (must be spin-2).

required
n_bootstrap int

Number of bootstrap resamples for the error estimate.

300
jobspec dict | None

Optional {"backend": "slurm", "site": "<site>"} — this check reads the full per-bin shear catalogue + bootstraps, so it is catalogue-bound; run it remotely on a large catalogue (async receipt; poll with check_job). Omit for in-process.

None

Returns:

Type Description
dict

The c-term result dict, written to

dict

results/systematics/cterm_bin_{i:02d}.json.

Source code in cosmotron_mcp/server.py
@mcp.tool()
@sync_budget_guard
def compute_cterm(
    session_dir: str, bin_index: int, n_bootstrap: int = 300,
    jobspec: dict | None = None,
) -> dict:
    """Additive shear c-term for a spin-2 bin: c_k = ⟨w·e_k⟩/⟨w⟩ vs σ_e.

    Weighted means from the bin's standardised FITS; seeded bootstrap errors
    (deterministic). Gate statistic `max(|c1|,|c2|)/σ_e` vs `cterm_sigma_e_max_frac`.
    Writes `results/systematics/cterm_bin_{i:02d}.json`. Spin-2 bins only (spin-0 → `needs_input`).

    Args:
        session_dir: Session directory.
        bin_index: Tomographic bin index (must be spin-2).
        n_bootstrap: Number of bootstrap resamples for the error estimate.
        jobspec: Optional ``{"backend": "slurm", "site": "<site>"}`` — this
            check reads the full per-bin shear catalogue + bootstraps, so it
            is catalogue-bound; run it remotely on a large catalogue (async
            receipt; poll with `check_job`). Omit for in-process.

    Returns:
        The c-term result dict, written to
        ``results/systematics/cterm_bin_{i:02d}.json``.
    """
    _require_human_gates(session_dir)
    from cosmotron_mcp.remote.dispatch import maybe_submit_async
    async_receipt = maybe_submit_async(
        "compute_cterm", session_dir,
        {"session_dir": session_dir, "bin_index": bin_index,
         "n_bootstrap": n_bootstrap}, jobspec,
    )
    if async_receipt is not None:
        return async_receipt
    result = _compute_cterm(session_dir, bin_index, n_bootstrap=n_bootstrap)
    _log_tool_call(session_dir, "compute_cterm",
                   {"bin_index": bin_index, "n_bootstrap": n_bootstrap})
    return _compact_result(result)

compute_psf_leakage

compute_psf_leakage(session_dir: str, bin_index: int, jobspec: dict | None = None) -> dict

PSF-ellipticity leakage for a spin-2 bin (Heymans-style; no treecorr).

Catalogue-level weighted regression α per component PLUS a harmonic shear×PSF-ellipticity cross-Cℓ contamination fraction (gate statistic max_ℓ |α·Cℓ^{e,PSF}|/σ(Cℓ) vs template_contamination_max_frac). Builds the PSF Q/U map from the same catalogue and reuses compute_systematics_cls. Missing PSF_E1/PSF_E2 → status SKIPPED (not FAIL). Writes results/systematics/psf_leakage_bin_{i:02d}.json. Spin-2 bins only.

Parameters:

Name Type Description Default
session_dir str

Session directory.

required
bin_index int

Tomographic bin index (must be spin-2).

required
jobspec dict | None

Optional {"backend": "slurm", "site": "<site>"} — catalogue-bound; run remotely on a large catalogue (async receipt; poll with check_job). Omit for in-process.

None

Returns:

Type Description
dict

The PSF-leakage result dict, written to

dict

results/systematics/psf_leakage_bin_{i:02d}.json.

Source code in cosmotron_mcp/server.py
@mcp.tool()
@sync_budget_guard
def compute_psf_leakage(session_dir: str, bin_index: int,
                        jobspec: dict | None = None) -> dict:
    """PSF-ellipticity leakage for a spin-2 bin (Heymans-style; no treecorr).

    Catalogue-level weighted regression α per component PLUS a harmonic
    shear×PSF-ellipticity cross-Cℓ contamination fraction (gate statistic
    `max_ℓ |α·Cℓ^{e,PSF}|/σ(Cℓ)` vs `template_contamination_max_frac`). Builds the
    PSF Q/U map from the same catalogue and reuses `compute_systematics_cls`.
    Missing `PSF_E1/PSF_E2` → status `SKIPPED` (not FAIL). Writes
    `results/systematics/psf_leakage_bin_{i:02d}.json`. Spin-2 bins only.

    Args:
        session_dir: Session directory.
        bin_index: Tomographic bin index (must be spin-2).
        jobspec: Optional ``{"backend": "slurm", "site": "<site>"}`` —
            catalogue-bound; run remotely on a large catalogue (async
            receipt; poll with `check_job`). Omit for in-process.

    Returns:
        The PSF-leakage result dict, written to
        ``results/systematics/psf_leakage_bin_{i:02d}.json``.
    """
    _require_human_gates(session_dir)
    from cosmotron_mcp.remote.dispatch import maybe_submit_async
    async_receipt = maybe_submit_async(
        "compute_psf_leakage", session_dir,
        {"session_dir": session_dir, "bin_index": bin_index}, jobspec,
    )
    if async_receipt is not None:
        return async_receipt
    result = _compute_psf_leakage(session_dir, bin_index)
    _log_tool_call(session_dir, "compute_psf_leakage", {"bin_index": bin_index})
    return _compact_result(result)

run_systematics_check_job

run_systematics_check_job(session_dir: str, bin_index: int, check: str = 'cterm', n_bootstrap: int = 300, jobspec: dict | None = None) -> dict

Submit compute_cterm/compute_psf_leakage as a non-blocking background job.

Use this instead of calling compute_cterm/compute_psf_leakage directly when the bin's catalogue is large (tens of millions of objects) — the in-process call can run long enough to exceed the client's request timeout, which kills the WHOLE MCP connection (every cosmotron tool), not just that one call. NON-BLOCKING — returns a job_id immediately; poll with check_job(session_dir, job_id). Once done, re-call compute_cterm/compute_psf_leakage/build_systematics_evidence — they load the JSON this job already wrote instead of recomputing.

Parameters:

Name Type Description Default
session_dir str

Session directory.

required
bin_index int

Tomographic bin index.

required
check str

"cterm" or "psf_leakage".

'cterm'
n_bootstrap int

Forwarded to compute_cterm when check="cterm".

300
jobspec dict | None

Optional resource dict, forwarded to submit_job.

None

Returns:

Type Description
dict

{job_id, status, run_dir, backend}.

Source code in cosmotron_mcp/server.py
@mcp.tool()
@sync_budget_guard
def run_systematics_check_job(
    session_dir: str, bin_index: int, check: str = "cterm",
    n_bootstrap: int = 300, jobspec: dict | None = None,
) -> dict:
    """Submit `compute_cterm`/`compute_psf_leakage` as a non-blocking background job.

    Use this instead of calling `compute_cterm`/`compute_psf_leakage` directly
    when the bin's catalogue is large (tens of millions of objects) — the
    in-process call can run long enough to exceed the client's request
    timeout, which kills the WHOLE MCP connection (every cosmotron tool),
    not just that one call. NON-BLOCKING — returns a `job_id` immediately;
    poll with `check_job(session_dir, job_id)`. Once `done`, re-call
    `compute_cterm`/`compute_psf_leakage`/`build_systematics_evidence` — they
    load the JSON this job already wrote instead of recomputing.

    Args:
        session_dir: Session directory.
        bin_index: Tomographic bin index.
        check: ``"cterm"`` or ``"psf_leakage"``.
        n_bootstrap: Forwarded to `compute_cterm` when ``check="cterm"``.
        jobspec: Optional resource dict, forwarded to `submit_job`.

    Returns:
        ``{job_id, status, run_dir, backend}``.
    """
    _require_human_gates(session_dir)
    result = _run_systematics_check_job(
        session_dir, bin_index, check=check, n_bootstrap=n_bootstrap, jobspec=jobspec,
    )
    _log_tool_call(session_dir, "run_systematics_check_job",
                   {"bin_index": bin_index, "check": check, "n_bootstrap": n_bootstrap})
    return result