Metadata-Version: 2.4
Name: hflav-fair-client
Version: 1.1.0
Summary: HFLAV FAIR client - Helper to fetch HFLAV data from Zenodo
Author: sergio, Ulrik Egede
License: GNU General Public License v3 (GPLv3)
Project-URL: Homepage, https://hflav.web.cern.ch
Project-URL: Repository, https://gitlab.cern.ch/hflav/shared/hflav-fair-client
Project-URL: Documentation, https://gitlab.cern.ch/hflav/shared/hflav-fair-client/-/tree/main/docs
Project-URL: Bug Tracker, https://gitlab.cern.ch/hflav/shared/hflav-fair-client/-/issues
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28
Requires-Dist: pydantic>=2.0
Requires-Dist: python-dateutil>=2.8
Requires-Dist: rich>=14.2.0
Requires-Dist: dependency-injector>=4.48.2
Requires-Dist: jsonpath_ng>=1.7.0
Requires-Dist: requests-cache>=1.2.1
Requires-Dist: python-dotenv>=1.2.1
Provides-Extra: test
Requires-Dist: pytest>=7.0; extra == "test"
Requires-Dist: pytest-cov>=4.0; extra == "test"
Requires-Dist: pytest-mock>=3.10; extra == "test"
Requires-Dist: pytest-benchmark>=4.0; extra == "test"
Requires-Dist: matplotlib>=3.10.7; extra == "test"
Requires-Dist: memory-profiler>=0.61.0; extra == "test"
Requires-Dist: hypothesis-jsonschema>=0.23.1; extra == "test"
Requires-Dist: hypothesis>=6.148.7; extra == "test"
Provides-Extra: dev
Requires-Dist: hflav-fair-client[test]; extra == "dev"
Requires-Dist: pysonar>=1.3.0.4086; extra == "dev"
Dynamic: license-file

# HFLAV FAIR Client

## Overview

The HFLAV FAIR Client is a Python library designed to facilitate access to and processing of [HFLAV (Heavy Flavor Averaging Group)](https://hflav.web.cern.ch/) data from [Zenodo](https://zenodo.org/communities/hflav). The library provides a unified interface for querying, transforming, and using that data, adhering to FAIR (Findable, Accessible, Interoperable, Reusable) principles.

## Installation

### Install from PyPi

- python -m pip install hflav-fair-client

### Install from source


1. `git clone ssh://git@gitlab.cern.ch:7999/hflav/shared/hflav-fair-client.git`
2. `cd hflav-fair-client`
3. `python -m venv .venv`
4. `source .venv/bin/activate`
5. `pip install .`

### Install in editable mode (for development)

```bash
pip install -e ".[dev]"
```

## Quick Start

Below are simple examples showing how to retrieve and work with results from an HFLAV Zenodo record.

### Example 1: Load a specific record by ID and navigate the information

```python
from hflav_fair_client.services.service import Service

service = Service()

# Load a specific file from a known Zenodo record
data = service.load_data_file(
  record_id=19446771,
)

# Use attribute-chain navigation to list groups
for g in data.groups:
    print(g.name)

# Use attribute-chain navigation to list names and averages in the group
#   'alpha_CKM'
[f'{a.name} : {a.average.value.central}±{a.average.value.uncertainty}' for a in data.groups(name='ASLd and ASLs').averages]
```
```
['ASLd : -0.0021±0.0017', 'ASLs : -0.0006±0.0028']
```


### Example 2: Get the bibtex record for citing these results
Building on the data object from the previous example

```python
bibtex = data.reference.bibtex
print(bibtex)
```
```
@article{HeavyFlavorAveragingGroupHFLAV:2024ctg:19446771,
    author = "Banerjee, Sw. and others",
    collaboration = "Heavy Flavor Averaging Group (HFLAV)",
    title = "{Averages of b-hadron, c-hadron, and {\ensuremath{\tau}}-lepton properties as of 2023}",
    eprint = "2411.18639",
    archivePrefix = "arXiv",
    primaryClass = "hep-ex",
    doi = "10.1103/x87q-tld5",
    journal = "Phys. Rev. D",
    volume = "113",
    number = "1",
    pages = "012008",
    year = "2026",
    note = "{with specific result from \href{https://doi.org/10.5281/zenodo.19446771}{{\texttt{doi:10.5281/zenodo.19446771}}}}"
}
```

### Example 3: Search within the loaded record

```python
# Search within the loaded data for averages using a specific paper
from hflav_fair_client.models.hflav_data_searching import HflavDataSearching, SearchOperators

searcher = HflavDataSearching(data)
results = searcher.get_data_object_from_key_and_value(
    object_name="groups",
    key_name="doi",
    operator=SearchOperators.EQUALS,
    value="10.1103/PhysRevD.86.072009",
)
[r.name for r in results]
```
```
['ASLd and ASLs']
```

### Example 4: Load a local data file

Files are cached locally after you download, so usually no need for this.

```python
from hflav_fair_client.services.service import Service
from hflav_fair_client.models.hflav_data_searching import HflavDataSearching, SearchOperators

service = Service()

# Load a local JSON data file
data = service.load_local_data_file_from_path(
    file_path="HFLAV.json",
)
```

### Example 5: Print template record to understand structure
Here we show the complete set of information that may be available in the Zenodo record. Not all files will have all information. Note that this is just a template and the actual results should not be used.

```python
from hflav_fair_client.services.service import Service
from hflav_fair_client.processing.data_visualizer import DataVisualizer

service = Service()

# Load a specific file from a known Zenodo record
data = service.load_data_file(
  record_id=11157259,
)

print('Data in template. Use this to inform about structure, not the actual results.)
dv = DataVisualizer()
dv.print_json_data(data)
```


### Example 5: Search for HFLAV records on Zenodo and load data

This can be used to search for a given Zenodo record.

```python
from hflav_fair_client.filters.search_filters import QueryBuilder, SortOptions
from hflav_fair_client.services.service import Service

# Get the service
from hflav_fair_client.filters.search_filters import QueryBuilder, SortOptions
service = Service()

# Build a query to search for HFLAV records on Zenodo
query = (
    QueryBuilder()
    .with_text(field="title", value="HFLAV")
    .with_pagination(size=5, page=1)
    .order_by(field=SortOptions.MOSTRECENT)
    .build()
)

# Search Zenodo and automatically load the first matching data file
data = service.search_and_load_data_file(query=query)

# Access the loaded data (returned as a SimpleNamespace object)
print(data.doi)
```


### Example 6: Combine multiple filters using merge

```python
from hflav_fair_client.filters.search_filters import (
    QueryBuilder,
    SortOptions,
    AndFilter,
    OrFilter,
    NotFilter,
)
from hflav_fair_client.services.service import Service
import datetime

service = Service()

# First query builder: filter by version number with NOT combinator
query1 = (
    QueryBuilder()
    .with_number(field="version", value=2, operator=">=")
    .apply_combinator(NotFilter)
)

# Second query builder: filter by title and date range with OR combinator
query2 = (
    QueryBuilder()
    .with_text(field="title", value="HFLAV")
    .with_date_range(
        field="created",
        start_date=datetime.datetime(2022, 1, 1),
        end_date=datetime.datetime(2025, 12, 31),
    )
    .apply_combinator(OrFilter)
)

# Create a new query builder and merge both previous queries
combined_query = (
    QueryBuilder()
    .with_pagination(size=5, page=1)
    .order_by(field=SortOptions.MOSTRECENT)
    .merge_filters(query1)
    .merge_filters(query2)
    .build()  # Uses AndFilter by default to combine the merged filters
)

# Use the combined query to search and load data
data = service.search_and_load_data_file(query=combined_query)
print(data.metadata.title)
```

## Configuring environment variables

All the environment variables available can be seen in the `EnvironmentVariables` enum inside the [config](hflav_fair_client/config.py) file.

| Variable                   | Description                  | Default             |
| -------------------------- | ---------------------------- | ------------------- |
| `HFLAV_CACHE_NAME`         | Name of the local HTTP cache | `hflav_cache`       |
| `HFLAV_CACHE_EXPIRE_AFTER` | Cache expiry time in seconds | `2592000` (30 days) |

To use environment variables in your code, simply modify the `.env` file:

```env
HFLAV_CACHE_NAME=my_cache
HFLAV_CACHE_EXPIRE_AFTER=2592000
```

## Releasing to PyPI

Releases are published automatically from GitLab CI when you create a tag that matches `vX.Y.Z`.

Release requirements:

- The Git tag must be named like `v1.2.3`.
- The version in [pyproject.toml](pyproject.toml) must be `1.2.3`.
- GitLab CI must have a masked CI/CD variable named `PYPI_API_TOKEN`.

Release flow:

1. Update the version in [pyproject.toml](pyproject.toml).
2. Create and push a matching Git tag, for example `v1.2.3`.
3. GitLab CI builds the distribution, checks the metadata, and uploads the package to PyPI.

The release pipeline validates the tag/version pair before publishing, so mismatched versions fail early.
