Getting Started
Installation
In order to start using yadism, one first needs to install it and some of its extra-dependencies. The easiest way to install the latest stable version of yadism is via pip using the following command:
pip install 'yadism[mark, box]'
In addition to installing the main yadism package, the above command also installs yadmark and yadbox. yadmark is package that provides APIs to perform the benchmark of yadism to other DIS codes (e.g. APFEL, APFEL++, QCDNUM). yadbox instead provides an interface to PineAPPL to store predictions in the form of fast-interpolation grids.
In order to check that yadism was installed properly, one can check the version:
[1]:
import yadism
yadism.__version__
[1]:
'0.0.0'
Preparing the run cards
Yadism takes as inputs two runcards whose representations are given in terms of python dictionaries. That is, one needs: - an observable card which contains the details on the observable to be computed - a theory card which contains the various theory settings to compute the observable in question
Below is an example of an observable card in which the meaning of each key is also specified:
[2]:
observable_card = {
# Process type: "EM", "NC", "CC"
"prDIS": "NC",
# Projectile: "electron", "positron", "neutrino", "antineutrino"
"ProjectileDIS": "electron",
# Scattering target: "proton", "neutron", "isoscalar", "lead", "iron", "neon" or "marble"
"TargetDIS": "proton",
# Interpolation: if True use log interpolation
"interpolation_is_log": True,
# Interpolation: polynomial degree, 1 = linear, ...
"interpolation_polynomial_degree": 4,
# Interpolation: xgrid values
# Note: for illustrative purposes the grid is chosen very small here
"interpolation_xgrid": [1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1.0],
# Observables configurations
"observables": {
"XSHERANCAVG_charm": [
{
"y": 0.8240707777909629,
"x": 3e-05,
"Q2": 2.5,
},
{
"y": 0.3531731904818413,
"x": 7e-05,
"Q2": 2.5,
},
# Add here the kinematics of other datapoints
],
# Potentially include observables other than XSHERANCAVG_charm,
# each of them has to be: TYPE_heaviness, where heaviness can take:
# "charm", "bottom", "top", "total" or "light".
},
# Projectile polarization faction, float from 0 to 1.
"PolarizationDIS": 0.0,
# Exchanged boson propagator correction
"PropagatorCorrection": 0.0,
# Restrict boson coupling to a single parton ? Monte Carlo PID or None for all partons
"NCPositivityCharge": None,
}
The observables key in the observable_card (which is also a dictionary) can contain multiple elements whose keys must represent structure functions or cross-sections. For the list of available observables, refer to the following part of the documentation.
Similarly, below is an example of a theory card defining the theory parameters:
[3]:
theory_card = {
# QCD perturbative order
"PTO": 2, # perturbative order in alpha_s: 0 = LO (alpha_s^0), 1 = NLO (alpha_s^1) ...
# SM parameters and masses
"CKM": "0.97428 0.22530 0.003470 0.22520 0.97345 0.041000 0.00862 0.04030 0.999152", # CKM matrix elements
"GF": 1.1663787e-05, # [GeV^-2] Fermi coupling constant
"MP": 0.938, # [GeV] proton mass
"MW": 80.398, # [GeV] W boson mass
"MZ": 91.1876, # [GeV] Z boson mass
"alphaqed": 0.007496252, # alpha_em value
"kcThr": 1.0, # ratio of the charm matching scale over the charm mass
"kbThr": 1.0, # ratio of the bottom matching scale over the bottom mass
"ktThr": 1.0, # ratio of the top matching scale over the top mass
"mc": 1.51, # [GeV] charm mass
"mb": 4.92, # [GeV] bottom mass
"mt": 172.5, # [GeV] top mass
# Flavor number scheme settings
"FNS": "FFNS", # Flavour Number Scheme, options: "FFNS", "FFN0", "ZM-VFNS"
"NfFF": 4, # (fixed) number of running flavors, only for FFNS or FFN0 schemes
"Q0": 1.65, # [GeV] reference scale for the flavor patch determination
"nf0": 4, # number of active flavors at the Q0 reference scale
# Alphas settings and boundary conditions
"Qref": 91.2, # [GeV] reference scale for the alphas value
"nfref": 5, # number of active flavors at the reference scale Qref
"alphas": 0.118, # alphas value at the reference scale
"MaxNfAs": 5, # maximum number of flavors in running of strong coupling
"QED": 0, # QED correction to running of strong coupling: 0 = disabled, 1 = allowed
# Scale Variations
"XIF": 1.0, # ratio of factorization scale over the hard scattering scale
"XIR": 1.0, # ratio of renormalization scale over the hard scattering scale
# Other settings
"IC": 1, # 0 = perturbative charm only, 1 = intrinsic charm allowed
"TMC": 1, # include target mass corrections: 0 = disabled, 1 = leading twist, 2 = higher twist approximated, 3 = higher twist exact
"n3lo_cf_variation": 0, # N3LO coefficient functions variation: -1 = lower bound, 0 = central , 1 = upper bound
# Other EKO settings, not relevant for Yadism
"HQ": "POLE", # heavy quark mass scheme (not yet implemented in yadism)
"MaxNfPdf": 5, # maximum number of flavors in running of PDFs (ignored by yadism)
"ModEv": "EXA", # evolution solver for PDFs (ignored by yadism)
}
Note that a template observable card is provided by yadmark and contains the default yadism values. One can thus start from the default card and overwrite the values.
[4]:
import json # just used for pretty-printing
from yadmark.data.observables import default_card # imports the default yadism observable card
print(json.dumps(default_card, sort_keys=False, indent=4))
{
"NCPositivityCharge": null,
"PolarizationDIS": 0,
"ProjectileDIS": "electron",
"PropagatorCorrection": 0,
"TargetDIS": "proton",
"interpolation_is_log": true,
"interpolation_polynomial_degree": 4,
"interpolation_xgrid": [
1e-07,
1.6102620275609392e-07,
2.592943797404667e-07,
4.1753189365604003e-07,
6.723357536499335e-07,
1.0826367338740541e-06,
1.7433288221999873e-06,
2.8072162039411756e-06,
4.520353656360241e-06,
7.2789538439831465e-06,
1.1721022975334793e-05,
1.8873918221350995e-05,
3.039195382313195e-05,
4.893900918477499e-05,
7.880462815669905e-05,
0.0001268961003167922,
0.00020433597178569417,
0.00032903445623126676,
0.0005298316906283707,
0.0008531678524172806,
0.0013738237958832637,
0.00221221629107045,
0.003562247890262444,
0.005736152510448681,
0.009236708571873866,
0.014873521072935119,
0.02395026619987486,
0.03856620421163472,
0.06210169418915616,
0.1,
0.1473684210526316,
0.19473684210526315,
0.24210526315789474,
0.2894736842105263,
0.33684210526315794,
0.38421052631578945,
0.43157894736842106,
0.4789473684210527,
0.5263157894736842,
0.5736842105263158,
0.6210526315789474,
0.6684210526315789,
0.7157894736842105,
0.7631578947368421,
0.8105263157894737,
0.8578947368421053,
0.9052631578947369,
0.9526315789473684,
1.0
],
"observables": {},
"prDIS": "EM"
}
Computing predictions
Now that we have defined our observable and theory, we can now compute the corresponding preditions. This can be easily done by running the following:
[5]:
import warnings
with warnings.catch_warnings():
warnings.simplefilter("ignore") # skip noisy warnings
out = yadism.run_yadism(theory_card, observable_card)
┌────────────────────────────────────┐ │ │ │ __ __ _ _ │ │ \ \ / / | (_) │ │ \ \_/ /_ _ __| |_ ___ _ __ ___ │ │ \ / _` |/ _` | / __| '_ ` _ \ │ │ | | (_| | (_| | \__ \ | | | | | │ │ |_|\__,_|\__,_|_|___/_| |_| |_| │ │ │ └────────────────────────────────────┘
Plan
• XSHERANCAVG_charm at 2 pts
Calculation
yadism took off! please stay tuned ...
[?25h
took 0.36 s
out is an object of type yadism.output.Output from which one can perform various operations. In our example, we are interested in convoluting it with a PDF set in the LHAPDF format.
To do so, first we need to import the lhapdf package. For this example, we will use the NNLO NNPDF4.0 set: NNPDF40_nnlo_as_01180.
[6]:
import lhapdf
# load the PDF set
pdf = lhapdf.mkPDF("NNPDF40_nnlo_as_01180")
LHAPDF 6.5.0 loading /home/tanjona/miniconda3/envs/yadism/share/LHAPDF/NNPDF40_nnlo_as_01180/NNPDF40_nnlo_as_01180_0000.dat
NNPDF40_nnlo_as_01180 PDF set, member #0, version 1; LHAPDF ID = 331100
The convolution can simply be performed as follow:
[7]:
values = out.apply_pdf(pdf)
[13:09:24] INFO Atlas [0.00e+00 - 2.28e+00 - 2.42e+01 - 2.98e+04 - inf], ref=8317.44 @ 5 matchings.py:69
INFO Strong Coupling: a_s(µ_R^2=8317.440000)^(nf=5)=0.009390=0.118000/(4π) couplings.py:458
INFO Atlas [0.00e+00 - 2.28e+00 - 2.42e+01 - 2.98e+04 - inf], ref=8317.44 @ 5 matchings.py:69
[8]:
print(json.dumps(values, sort_keys=False, indent=4))
{
"XSHERANCAVG_charm": [
{
"x": 3e-05,
"Q2": 2.5,
"result": -0.9959496128078331,
"error": 1.281070214968848e-08,
"y": 0.8240707777909629
},
{
"x": 7e-05,
"Q2": 2.5,
"result": -0.7710853256052412,
"error": 2.3298246570353407e-08,
"y": 0.3531731904818413
}
]
}
We can see that values is a dictionary containing one element whose key is the name of the observable (as we defined above). If we had defined two observables in the observable_card, values would also contain two elements.
Dumping predictions into fast-interpolation grids
We learned from the previous sections how to compute an observable using yadism and now we’ll see how to tabulate the output of yadism.run_yadism into a fast-interpolation table. This has the convenient advantage that one can re-use the same computations without the need to re-run yadism (to convolve with different PDF sets for example).
One of the main advantage of yadism is its interface with PineAPPL - a library providing fast interpolation into a unique format suitable for various HEP-related softwares.
Each observable defined in observable_card can be dumped into its own fast-interpolation grid. The steps are as follow:
[9]:
# import function that dumps the predictions into a Pineappl format
from yadbox.export import dump_pineappl_to_file
# Extract the names of the different observables (in case there are many)
list_observables = observable_card['observables'].keys()
# Dump each observable into a PineAPPL grid
for obs in list_observables:
dump_pineappl_to_file(out, f"outputgrid_{obs}.pineappl.lz4", f"{obs}")
Our PineAPPL grid has now been written on the disk. Note that the extension has to be pineappl.lz4.
[10]:
!ls outputgrid_*
outputgrid_XSHERANCAVG_charm.pineappl.lz4
To load the pre-computed predictions, we need to import the pineappl package. Given that pineappl is a dependency of yadism it was already installed so we don’t have to install it again.
[11]:
# imports the pineappl package
import pineappl
# Read the pineappl grid saved earlier
grid = pineappl.grid.Grid.read("./outputgrid_XSHERANCAVG_charm.pineappl.lz4")
# Convolve the grid with the same PDF as above, 2212 is the PID of the proton
results = grid.convolve_with_one(2212, pdf.xfxQ2, pdf.alphasQ2)
[12]:
print(results)
[-0.98699882 -0.7640712 ]
As we can see, we get similar results to what we got before. Now, the results is just an array of two dimension corresponding to the different kinematic values.