"""OPE coefficients of the 3D Ising CFT -- numberdb.org/T474.

Reproduce the published scalar coefficients, without rerunning the bootstrap.
With SageMath and the numberdb package installed:

    sage -python generate.py --check     # offline numerical and source checks
    sage -python generate.py             # check all stored entries
    sage -python generate.py --fill      # write entries to an authorized table

For a draft, set NUMBERDB_API_KEY for reading as well as writing. --fill calls
Generator.publish(), which writes entries, not the table's publication state.
This script never offers a draft for review or makes it public.

Source: Chang et al., JHEP 03 (2025) 136, arXiv:2411.15300v2, Table 1.
The two values are 1.05185373(11) and 1.53244304(58), in the order below.
The positive sign of epsilon is fixed by lambda_sigma_sigma_epsilon > 0.
Two-point functions have coefficient one. Permutation-equivalent triples
are stored once, ordered by increasing scaling dimension. Only the two
symmetry-allowed triples of the leading spin and energy scalar primaries
are included. The stated errors are estimates from the sampled bootstrap
region, not rigorous enclosures or statistical standard deviations.

No precision escalation can improve a transcription of these estimates.
Six significant digits is a conservative precision floor for both error
intervals. The literal centres and radii retain all published source digits.
The independent checks compare to Hasenbusch's Monte Carlo estimates and to
Kos et al.'s earlier bootstrap determination. They do not reproduce either
large numerical calculation.
"""
import os
import sys
import numberdb.sage as numberdb


class IsingOPE(numberdb.Generator):
    table = 'T474'
    parameters = ('operator1', 'operator2', 'operator3')
    type = 'R'
    digits = 6
    rigour = 'measured'
    files = ('generate.py', 'checks.py', 'check.py', 'source-evidence.json')

    def enumerate(self):
        yield dict(zip(self.parameters, ('sigma', 'sigma', 'epsilon')))
        yield dict(zip(self.parameters, ('epsilon', 'epsilon', 'epsilon')))

    def value(self, params, digits):
        key = tuple(params[name] for name in self.parameters)
        values = {
            ('sigma', 'sigma', 'epsilon'): {
                'number': '1.05185373 +/- 0.00000011',
                'comment': r'The spin-spin-energy coefficient, Table 1 of CITE{Chang2025}.'},
            ('epsilon', 'epsilon', 'epsilon'): {
                'number': '1.53244304 +/- 0.00000058',
                'comment': r'The energy three-point coefficient, Table 1 of CITE{Chang2025}.'},
        }
        return values[key].copy()


def values():
    generator = IsingOPE()
    return {tuple(params[k] for k in generator.parameters):
            generator.value(params, generator.digits)
            for params in generator.enumerate()}


if __name__ == '__main__':
    if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
        numberdb.configure(api_key=sys.stdin.read().strip())
    if '--check' in sys.argv:
        import json
        from checks import run_checks
        print(json.dumps(run_checks(values()), indent=2))
    elif '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
        from checks import run_checks
        run_checks(values())
        print(IsingOPE().publish(message='Transcribe the two leading scalar OPE coefficients with source uncertainties'))
    else:
        report = IsingOPE().verify(sample=None)
        print(report)
        sys.exit(0 if report.ok else 1)
