Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/cache-data/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ runs:
uses: actions/cache@v4
with:
path: neopdf-data
key: data-v10
key: data-v11
- name: Download data if cache miss
if: steps.cache-data.outputs.cache-hit != 'true'
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/run-pyapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
pip install maturin
maturin develop --extras test
export NEOPDF_DATA_PATH=/usr/share/LHAPDF
pytest
pytest --verbose

# from https://github.com/NNPDF/pineappl/blob/master/.github/workflows/python.yml
find . -name '*.profraw' -exec $(rustc --print target-libdir)/../bin/llvm-profdata merge -sparse -o neopdf.profdata {} +
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Added an additional `alpha_s` grid extraction (https://github.com/Radonirinaunimi/neopdf/pull/77).
- Added a logic to compute Chebyshev interpolations in batches (https://github.com/Radonirinaunimi/neopdf/pull/64).
- Added proper LHAPDF drop-in compatibility layer for no-code migration.
- Added an interface to the Wolfram Language to allow Rust APIs to be called in
Expand Down
2 changes: 2 additions & 0 deletions maintainer/download-data.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ LHAPDF_SETS=(
NNPDF40_nnlo_as_01175
NNPDF40_nnlo_as_01185
NNPDF40_nnlo_as_01190
ABMP16_5_nnlo
ABMP16als118_5_nnlo
MSHT20nlo_as_smallrange_nf4
)

NEOPDF_SETS=(
Expand Down
44 changes: 38 additions & 6 deletions neopdf/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ pub struct SubgridData {
pub struct PdfData {
pub subgrid_data: Vec<SubgridData>,
pub pids: Vec<i32>,
pub alphas_q_values: Option<Vec<f64>>,
pub alphas_vals: Option<Vec<f64>>,
}

/// Manages the loading and parsing of LHAPDF data sets.
Expand Down Expand Up @@ -78,7 +80,17 @@ impl LhapdfSet {

let pdf_data = Self::read_data(&data_path);
let knot_array = GridArray::new(pdf_data.subgrid_data, pdf_data.pids);
(self.info.clone(), knot_array)

let mut info = self.info.clone();
if info.alphas_vals.is_empty() {
if let (Some(vals), Some(q_values)) = (pdf_data.alphas_vals, pdf_data.alphas_q_values) {
if !vals.is_empty() && !q_values.is_empty() {
info.alphas_vals = vals;
info.alphas_q_values = q_values;
}
}
}
(info, knot_array)
}

/// Reads the metadata and data for all members of the PDF set.
Expand Down Expand Up @@ -124,26 +136,45 @@ impl LhapdfSet {
let content = fs::read_to_string(path).unwrap();
let mut subgrid_data = Vec::new();
let mut flavors = Vec::new();
let mut alphas_q_values: Option<Vec<f64>> = None;
let mut alphas_vals: Option<Vec<f64>> = None;

// Split the content by "---" to separate subgrids
let blocks: Vec<&str> = content.split("---").map(|s| s.trim()).collect();

// NOTE: support cases in which `AlphaS` grid info are in `.dat` files.
if !blocks.is_empty() {
#[derive(serde::Deserialize)]
struct DatMeta {
#[serde(rename = "AlphaS_Qs", default)]
alphas_q_values: Vec<f64>,
#[serde(rename = "AlphaS_Vals", default)]
alphas_vals: Vec<f64>,
}

let metadata_block = blocks[0];
if let Ok(dat_meta) = serde_yaml::from_str::<DatMeta>(metadata_block) {
if !dat_meta.alphas_q_values.is_empty() {
alphas_q_values = Some(dat_meta.alphas_q_values);
}
if !dat_meta.alphas_vals.is_empty() {
alphas_vals = Some(dat_meta.alphas_vals);
}
}
}

for block in blocks.iter().skip(1) {
// Skip empty blocks
if block.is_empty() {
continue;
}

let mut lines = block.lines();

// Read the x knots
let x_knots_line = lines.next().unwrap();
let xs: Vec<f64> = x_knots_line
.split_whitespace()
.filter_map(|s| s.parse().ok())
.collect();

// Read the Q2 knots
let q2_knots_line = lines.next().unwrap();
let q2s: Vec<f64> = q2_knots_line
.split_whitespace()
Expand All @@ -163,7 +194,6 @@ impl LhapdfSet {
lines.next();
}

// Read the grid values
let mut grid_data = Vec::new();
for line in lines {
let values: Vec<f64> = line
Expand Down Expand Up @@ -192,6 +222,8 @@ impl LhapdfSet {
PdfData {
subgrid_data,
pids: flavors,
alphas_q_values,
alphas_vals,
}
}
}
Expand Down
21 changes: 17 additions & 4 deletions neopdf_pyapi/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

from neopdf.pdf import PDF as NeoPDF
from neopdf.pdf import LazyPDFs
from typing import List, Dict, Iterator


@pytest.fixture(scope="session")
def neo_pdf():
cached_pdf = {}

def _init_pdf(pdfname: str) -> NeoPDF:
def _init_pdf(pdfname: str) -> Dict[str, NeoPDF]:
if pdfname not in cached_pdf:
cached_pdf[pdfname] = NeoPDF(pdfname)
return cached_pdf[pdfname]
Expand All @@ -22,7 +23,7 @@ def _init_pdf(pdfname: str) -> NeoPDF:
def neo_pdfs():
cached_pdf = {}

def _init_pdf(pdfname: str) -> NeoPDF:
def _init_pdf(pdfname: str) -> Dict[str, List[NeoPDF]]:
if pdfname not in cached_pdf:
cached_pdf[pdfname] = NeoPDF.mkPDFs(pdfname)
return cached_pdf[pdfname]
Expand All @@ -34,7 +35,7 @@ def _init_pdf(pdfname: str) -> NeoPDF:
def neo_pdfs_lazy():
cached_pdf = {}

def _init_pdf(pdfname: str) -> LazyPDFs:
def _init_pdf(pdfname: str) -> Dict[str, Iterator[LazyPDFs]]:
if pdfname not in cached_pdf:
cached_pdf[pdfname] = NeoPDF.mkPDFs_lazy(pdfname)
return cached_pdf[pdfname]
Expand All @@ -46,14 +47,26 @@ def _init_pdf(pdfname: str) -> LazyPDFs:
def lha_pdf():
cached_pdf = {}

def _init_pdf(pdfname: str) -> lhapdf.PDF:
def _init_pdf(pdfname: str) -> Dict[str, lhapdf.PDF]:
if pdfname not in cached_pdf:
cached_pdf[pdfname] = lhapdf.mkPDF(pdfname)
return cached_pdf[pdfname]

return _init_pdf


@pytest.fixture(scope="session")
def lha_pdfs():
cached_pdf = {}

def _init_pdf(pdfname: str) -> Dict[str, List[lhapdf.PDF]]:
if pdfname not in cached_pdf:
cached_pdf[pdfname] = lhapdf.mkPDFs(pdfname)
return cached_pdf[pdfname]

return _init_pdf


@pytest.fixture(scope="session")
def xq2_points():
def _xq2_points(
Expand Down
19 changes: 19 additions & 0 deletions neopdf_pyapi/tests/test_pdfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ def test_xfxq2s(self, neo_pdf, lha_pdf, xq2_points, pdfname, pid):
ref = [lhapdf.xfxQ2(pid, x, q2) for x, q2 in product(xs, q2s)]
np.testing.assert_equal(res, [ref])


class TestAlphaSInterpolations:
@pytest.mark.parametrize("pdfname", ["NNPDF40_nnlo_as_01180", "MSHT20qed_an3lo"])
def test_alphasQ2(self, neo_pdf, lha_pdf, pdfname):
neopdf = neo_pdf(pdfname)
Expand All @@ -80,6 +82,23 @@ def test_alphasQ2(self, neo_pdf, lha_pdf, pdfname):
res = neopdf.alphasQ2(q2_point)
np.testing.assert_equal(res, ref)

@pytest.mark.parametrize(
"pdfname",
["ABMP16_5_nnlo", "ABMP16als118_5_nnlo", "MSHT20nlo_as_smallrange_nf4"],
)
def test_alphasQ2_member(self, neo_pdfs, lha_pdfs, pdfname):
neopdf = neo_pdfs(pdfname)
lhapdf = lha_pdfs(pdfname)

for idx in range(len(neopdf)):
qs = neopdf[idx].metadata().alphas_q()
q2_points = [q * q for q in np.linspace(qs[0], qs[-1], num=100)]

for q2_point in q2_points:
ref = lhapdf[idx].alphasQ2(q2_point)
res = neopdf[idx].alphasQ2(q2_point)
np.testing.assert_equal(res, ref)


class TestLazyLoader:
@pytest.mark.parametrize("pdfname", ["NNPDF40_nnlo_as_01180.neopdf.lz4"])
Expand Down