Beispiel #1
0
def pdfflow_tester(pdf, members=None):
    """Test several pdfflow features:
    - Check the single/many/all-pid signatures
    - Checks the python and TF signatures
    - Checks the output of the python and TF signatures are the same
    - Checks the expected shape of the signatures is correct
    """
    grid_size = 7
    x = np.random.rand(grid_size)
    q2 = 1000.0 * np.random.rand(grid_size)
    xtf = float_me(x)
    q2tf = float_me(q2)
    # Check I can get just one pid
    for i in range(-1, 2):
        # as int
        res_1 = pdf.py_xfxQ2(i, x, q2)
        # as list
        res_2 = pdf.py_xfxQ2([i], x, q2)
        np.testing.assert_allclose(res_1, res_2)
        # as tf objects
        tfpid = int_me([i])
        res_3 = pdf.xfxQ2(tfpid, xtf, q2tf)
        np.testing.assert_allclose(res_2, res_3)

        # Check shape
        if members is None:
            assert res_1.numpy().shape == (grid_size, )
        else:
            assert res_1.numpy().shape == (
                members,
                grid_size,
            )

    # Check I can get more than one pid
    nfl_size = 6
    fl_scheme = pdf.flavor_scheme.numpy()
    nfl_total = fl_scheme.size
    many_pid = np.random.choice(fl_scheme, nfl_size)

    res_1 = pdf.py_xfxQ2(many_pid, x, q2)
    res_2 = pdf.xfxQ2(int_me(many_pid), xtf, q2tf)
    np.testing.assert_allclose(res_1, res_2)
    # Check shape
    if members is None:
        assert res_1.numpy().shape == (grid_size, nfl_size)
    else:
        assert res_1.numpy().shape == (members, grid_size, nfl_size)

    # Check I can actually get all PID
    res_1 = pdf.py_xfxQ2_allpid(x, q2)
    res_2 = pdf.xfxQ2_allpid(xtf, q2tf)

    np.testing.assert_allclose(res_1, res_2)
    # Check shape
    if members is None:
        assert res_1.numpy().shape == (grid_size, nfl_total)
    else:
        assert res_1.numpy().shape == (members, grid_size, nfl_total)
Beispiel #2
0
def alphas_first_subgrid(
    shape,
    a_q2,
    log_q2min,
    log_q2max,
    padded_q2,
    s_q2,
    actual_padded,
):
    """
    First subgrid interpolation
    Calls
    alphas_interpolate (basic interpolation) (0)

    Parameters
    ----------
        shape: tf.tensor of shape [None]
            final output shape to scatter points into

        For other parameters refer to subgrid.py:alphas_interpolate

    Returns
    ----------
        tf.tensor of shape `shape`
        alphas interpolated values for each query point
    """
    res = tf.zeros(shape, dtype=DTYPE)

    # --------------------------------------------------------------------
    # normal interpolation

    stripe, f_idx = _condition_to_idx(a_q2 >= log_q2min, a_q2 < log_q2max)
    if tf.math.equal(f_idx, 0) is not None:
        in_q2 = tf.boolean_mask(a_q2, stripe)
        ff_f = alphas_interpolate(in_q2, padded_q2, s_q2, actual_padded)
        res = tf.tensor_scatter_nd_update(res, f_idx, ff_f)

    # --------------------------------------------------------------------
    # lowq2

    stripe = a_q2 < log_q2min
    f_idx = int_me(tf.where(stripe))
    if tf.math.equal(f_idx, 0) is not None:
        in_q2 = tf.boolean_mask(a_q2, stripe)
        m = tf.math.log(actual_padded[2]/actual_padded[1])\
            /(padded_q2[2] - padded_q2[1])

        ff_f = actual_padded[1] * tf.math.pow(
            tf.math.exp(in_q2) / tf.math.exp(padded_q2[1]), m)
        res = tf.tensor_scatter_nd_update(res, f_idx, ff_f)

    return res
Beispiel #3
0
    def py_xfxQ2(self, pid, arr_x, arr_q2):
        """
        Python interface for pdfflow
        The input gets converted to the right tensorflow type
        before calling the corresponding function: `xfxQ2`
        returns PDF evaluated in each f(x,q2) for each pid

        The output of the function is of shape
        (members, number_of_points, flavours)
        but note that dimensions of size 1 will be squeezed out.

        Example
        -------
        >>> from pdfflow.pflow import mkPDFs
        >>> from pdfflow.configflow import run_eager, float_me, int_me
        >>> run_eager(True)
        >>> pdf = mkPDFs("NNPDF31_nlo_as_0118", [0, 1, 4])
        >>> pdf.py_xfxQ2(21, [0.4, 0.5], [15625.0, 15625.0])
        <tf.Tensor: shape=(3, 2), dtype=float64, numpy=
        array([[0.02977381, 0.00854525],
            [0.03653673, 0.00929325],
            [0.031387  , 0.00896622]])>
        >>> pdf.py_xfxQ2([1,2], [0.4], [15625.0])
        <tf.Tensor: shape=(3, 2), dtype=float64, numpy=
        array([[0.05569674, 0.19323399],
            [0.05352555, 0.18965438],
            [0.04515956, 0.18704451]])>


        Parameters
        ----------
            pid: list(int)
                list of PID to be computed
            arr_x: np.array
                grid on x where to compute the PDF
            arr_q2: np.array
                grid on q^2 where to compute the PDF
        Returns
        -------
            pdf: tensor
                grid of results ([members], [number of points], [flavour])
        """
        # if pid is None, the mask is set to true everywhere
        if pid is None:
            return self.py_xfxQ2_allpid(arr_x, arr_q2)

        tensor_pid = tf.reshape(int_me(pid), (-1, ))
        a_x = float_me(arr_x)
        a_q2 = float_me(arr_q2)
        return self.xfxQ2(tensor_pid, a_x, a_q2)
Beispiel #4
0
def alphas_last_subgrid(
    shape,
    a_q2,
    log_q2min,
    log_q2max,
    padded_q2,
    s_q2,
    actual_padded,
):
    """
    Last subgrid interpolation.
    Calls
    alphas_interpolate: (0)

    Parameters
    ----------
        shape: tf.tensor of shape [None]
            final output shape to scatter points into

        For other parameters see :py:func:`pdfflow.alphas_region_interpolator.alphas_interpolate`

    Returns
    ----------
        tf.tensor, shape: `shape`
            alphas interpolated values for each query point
    """
    # Generate all conditions for all stripes
    res = tf.zeros(shape, dtype=DTYPE)

    # --------------------------------------------------------------------
    # normal interpolation
    stripe, f_idx = _condition_to_idx(a_q2 >= log_q2min, a_q2 <= log_q2max)
    if tf.math.equal(f_idx, 0) is not None:
        # Check whether there are any points in this region
        # if there are, execute normal_interpolation
        in_q2 = tf.boolean_mask(a_q2, stripe)
        ff_f = alphas_interpolate(in_q2, padded_q2, s_q2, actual_padded)
        res = tf.tensor_scatter_nd_update(res, f_idx, ff_f)

    # --------------------------------------------------------------------
    # high q2
    stripe = a_q2 > log_q2max
    f_idx = int_me(tf.where(stripe))
    if tf.math.equal(f_idx, 0) is not None:
        ff_f = tf.ones_like(f_idx[:, 0], dtype=DTYPE) * actual_padded[-2]
        res = tf.tensor_scatter_nd_update(res, f_idx, ff_f)

    return res
Beispiel #5
0
def _condition_to_idx(cond1, cond2):
    """ Take two boolean masks and returns the indexes in which both are true """
    full_condition = tf.logical_and(cond1, cond2)
    return full_condition, int_me(tf.where(full_condition))
Beispiel #6
0
    def __init__(self,
                 grid,
                 i=0,
                 total=0,
                 compile_functions=True,
                 alpha_s=False):
        name_sg = f"grid_{i}"
        self.alpha_s = alpha_s
        if alpha_s:
            name_sg += "_alpha"
        self.name_sg = name_sg
        super().__init__(name=f"Parent_{name_sg}")
        q2min = min(grid.q2)
        q2max = max(grid.q2)
        self.log_q2min = float_me(np.log(q2min))
        self.log_q2max = float_me(np.log(q2max))

        # Save grid shape information
        self.s_q2 = int_me(grid.q2.size)

        # Insert a padding at the beginning and the end
        log_q2pad = np.pad(np.log(grid.q2), 1, mode="edge")
        log_q2pad[0] *= 0.99
        log_q2pad[-1] *= 1.01

        self.padded_q2 = float_me(log_q2pad)

        # Depending on whether it is an alphs_s grid or a pdf grid
        # we might need to change some options

        compilation_options = OPT.copy()

        if alpha_s:
            # the grid is sized (q.size), pad it with 0s
            self.padded_grid = float_me(np.pad(grid.grid, (1, 1)))

            if i == 0:
                self.fn_interpolation = alphas_first_subgrid
            elif i == (total - 1):
                self.fn_interpolation = alphas_last_subgrid
            else:
                self.fn_interpolation = alphas_inner_subgrid

            # Change the function signature to that of alpha_s
            compilation_options[
                "input_signature"] = ALPHAS_GRID_FUNCTION_SIGNATURE
        else:
            # If this is a pdf grid, save also the x information
            xmin = min(grid.x)
            xmax = max(grid.x)
            self.log_xmin = float_me(np.log(xmin))
            self.log_xmax = float_me(np.log(xmax))

            self.s_x = int_me(grid.x.size)

            log_xpad = np.pad(np.log(grid.x), 1, mode="edge")
            log_xpad[0] *= 0.99
            log_xpad[-1] *= 1.01

            self.padded_x = float_me(log_xpad)

            # Finally parse the grid
            # the grid is sized (x.size * q.size, flavours)
            reshaped_grid = grid.grid.reshape(grid.x.size, grid.q2.size, -1)

            # and pad it with 0s in x and q
            padded_grid = np.pad(reshaped_grid, ((1, 1), (1, 1), (0, 0)))
            # flatten the x and q dimensions again and store it
            self.padded_grid = float_me(padded_grid.reshape(
                -1, grid.flav.size))

            # Depending on the index of the grid, select with interpolation function should be run
            if i == 0:
                self.fn_interpolation = first_subgrid
            elif i == (total - 1):
                self.fn_interpolation = last_subgrid
            else:
                self.fn_interpolation = inner_subgrid

        if compile_functions:
            self.fn_interpolation = tf.function(self.fn_interpolation,
                                                **compilation_options)
Beispiel #7
0
    def __init__(self, dirname, fname, members, compilable=True):
        if not compilable:
            logger.warning("Running pdfflow in eager mode")
            logger.warning("Setting eager mode will affect all of TF")
            tf.config.experimental_run_functions_eagerly(True)

        self.dirname = dirname
        self.fname = fname
        self.grids = []
        info_file = os.path.join(self.dirname, self.fname, f"{fname}.info")

        # Load the info file
        with open(info_file, "r") as ifile:
            self.info = yaml.load(ifile, Loader=yaml.FullLoader)

        if members is None:
            total_members = self.info.get("NumMembers", 1)
            members = range(total_members)

        if len(members) == 1:
            logger.info("Loading member %d from %s", members[0], self.fname)
        else:
            logger.info("Loading %d members from %s", len(members), self.fname)

        for member_int in members:
            member = str(member_int).zfill(4)
            filename = os.path.join(self.dirname, fname,
                                    f"{fname}_{member}.dat")

            logger.debug("Loading %s", filename)
            grids = _load_data(filename)

            subgrids = [
                Subgrid(grid, i, len(grids)) for i, grid in enumerate(grids)
            ]
            self.grids.append(subgrids)
        self.members = members

        # Get the flavour scheme from the info file
        flavor_scheme = np.array(self.info.get("Flavors", None))
        if flavor_scheme is None:
            # fallback to getting the scheme from the first grid, as all grids should have the same number of flavours
            # if there's a failure here it should be the grid fault so no need to check from our side?
            flavor_scheme = grids[0].flav

        # Look at the flavor_scheme and ensure that it is sorted
        # save the whole thing in case it is not sorted
        self.flavor_scheme = int_me(flavor_scheme)

        flavor_scheme[flavor_scheme == PID_G.numpy()] = 0
        if all(np.diff(flavor_scheme) == 1):
            self.flavors_sorted = True
            self.flavor_shift = -flavor_scheme[0]
        else:
            # TODO can't we rely on the PDF flavours to be sorted?
            self.flavors_sorted = False
            self.flavor_shift = 0

        # Finalize by loading the alpha information form the .info file
        alpha_grids = _load_alphas(self.info)
        self.alphas_subgrids = [
            Subgrid(grid, i, len(grids), alpha_s=True)
            for i, grid in enumerate(alpha_grids)
        ]
Beispiel #8
0
import logging
import collections
import yaml

import subprocess as sp
import numpy as np

import os, sys

# import configflow before tf to set some tf options
from pdfflow.configflow import DTYPE, DTYPEINT, int_me, izero, float_me, find_pdf_path
import tensorflow as tf
from pdfflow.subgrid import Subgrid

# lhapdf gluon code
PID_G = int_me(21)
# expected input shapes to be found in this module
GRID_F = tf.TensorSpec(shape=[None], dtype=DTYPE)
GRID_I = tf.TensorSpec(shape=[None], dtype=DTYPEINT)
# instantiate logger
logger = logging.getLogger(__name__)
# create the Grid namedtuple
GridTuple = collections.namedtuple("Grid", ["x", "q2", "flav", "grid"])
AlphaTuple = collections.namedtuple("Alpha", ["q2", "grid"])


def _load_data(pdf_file):
    """
    Reads pdf from file and retrieves a list of grids
    Each grid is a tuple containing numpy arrays (x,Q2, flavours, pdf)
Beispiel #9
0
def test_int_me():
    res = int_me(4)
    assert res.dtype == DTYPEINT