Quickstart

Run the anomaly finder

The main inputs are one-dimensional arrays of time, flux, and flux error:

import numpy as np

from jacscanomaly import Finder, FinderConfig

data = np.load("example/example_data.npy")
time = data[:, 0]
flux = data[:, 1]
ferr = data[:, 2]

config = FinderConfig(fitter_kind="pspl", gap=50.0)

finder = Finder(config)
result = finder.run(time, flux, ferr)

result.print_summary()

The returned jacscanomaly.AnomalyResult contains the original data, the single-lens fit, residuals, per-season grid summaries, extracted clusters, and the best anomaly candidate.

Use quality criteria

Large dchi2 values can be caused by a single high-weight point. Use jacscanomaly.CandidateCriteria to reject candidates before best candidate selection:

from jacscanomaly import CandidateCriteria, FinderConfig

config = FinderConfig(
    candidate_criteria=CandidateCriteria(
        min_dchi2=20.0,
        min_n_eff=2.0,
    )
)

Here n_eff is the effective number of contributing points. Candidates with n_eff below the threshold are ignored by the best-candidate selection.

Inspect the result

summary = result.summary_dict()
print(summary["best_score"])
print(summary["best_n_eff"])

if result.best is not None:
    best = result.best
    print(best.t0, best.teff, best.dchi2)
    print(best.quality.n_eff, best.quality.peak_frac)

In notebooks:

display(result.summary_table())

Plot the result

The high-level plotting methods use the latest result stored on the finder:

import matplotlib.pyplot as plt

finder.plot_result()
finder.plot_anomaly_window()
plt.show()

The summary plot shows the light curve, residuals, and scan statistic. The window plot focuses on the best anomaly candidate.

Fit only the single-lens model

If you only need the baseline fit:

fit = finder.fit_single_lens(time, flux, ferr)
print(fit.params)
print(fit.chi2)

You can also provide an explicit nonlinear initial guess:

x0 = np.array([2459000.0, 30.0, 0.1])  # t0, tE, u0
fit = finder.fit_single_lens(time, flux, ferr, x0=x0)