Exploring the Output

In the former tutorial we computed an evolution operator, but we didn’t use it. In this one, we’ll then explore the content a structure of a computed operator.

[1]:
import eko

We can access the operator, by using the open method (similar to python’s open):

[2]:
with eko.EKO.read("./myeko.tar") as evolution_operator:
    print(type(evolution_operator))
<class 'eko.io.struct.EKO'>

Now, let’s inspect the content of the operator: e.g. you can extract the theory and operator card

[3]:
with eko.EKO.read("./myeko.tar") as evolution_operator:
    # obtain theory card
    print(evolution_operator.theory_card)
    # or operator card
    print(evolution_operator.operator_card)
TheoryCard(order=(1, 0), couplings=CouplingsInfo(alphas=0.118, alphaem=0.007496252, scale=91.2, max_num_flavs=6, num_flavs_ref=5, em_running=False), heavy=HeavyInfo(num_flavs_init=4, num_flavs_max_pdf=6, intrinsic_flavors=[4, 5, 6], masses=[[2.0, nan], [4.5, nan], [173.07, nan]], masses_scheme=<QuarkMassScheme.POLE: 'pole'>, matching_ratios=[1.0, 1.0, 1.0]), xif=1.0, n3lo_ad_variation=(0, 0, 0, 0))
OperatorCard(mu0=1.65, mugrid=[(100.0, 5)], xgrid=<eko.interpolation.XGrid object at 0x7f21152a83a0>, configs=Configs(evolution_method=<EvolutionMethod.ITERATE_EXACT: 'iterate-exact'>, ev_op_max_order=(10, 0), ev_op_iterations=10, scvar_method=None, inversion_method=None, interpolation_polynomial_degree=4, interpolation_is_log=True, polarized=False, time_like=False, n_integration_cores=0), debug=Debug(skip_singlet=False, skip_non_singlet=False), eko_version='0.0.0')

So an EKO object has some internal parameters, related to the interpolation used for the calculation, and then some external attributes, related to the final operator delivered. But actually, we have not accessed yet the actual operator - let’s first find out again which final scales we computed:

[4]:
with eko.EKO.read("./myeko.tar") as evolution_operator:
    print(evolution_operator.evolgrid)
[(10000.0, 5)]

Remember that the unique starting scale is \(Q_0^2\). In the present case there is a unique final scale, but in the general one there might be many. Now, let’s use this operator! The recommended way to load an operator is by using again a context manager:

[5]:
with eko.EKO.read("./myeko.tar") as evolution_operator:
    with evolution_operator.operator((10000.,5)) as op:
        print(f"operator: {op.operator.shape}")
        print(f"error: {op.error.shape}")
operator: (14, 5, 14, 5)
error: (14, 5, 14, 5)

This is the final product we expected from the beginning: the evolution operator, delivered as a numerical array. It is actually composed by two elements:

  • the operator itself, whose dimensions are (flavor_out, x_out, flavor_in, x_in)

  • the error on each operator element, propagated from the integration error on the numerical Mellin inversion (no other source is taken into account)

How to use this object is now completely up to the user, but a few helpers are included in another package: ekobox!

This package will be explored in a separate tutorial.