Skip to content

Commit

Permalink
Merge pull request #13 from cms-nanoAOD/master
Browse files Browse the repository at this point in the history
Rebase
  • Loading branch information
IzaakWN authored May 6, 2021
2 parents 45d91d6 + c1b70c5 commit 4047e43
Show file tree
Hide file tree
Showing 19 changed files with 848 additions and 45 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
with:
submodules: recursive
- uses: actions/setup-python@v2
- uses: pre-commit/[email protected].0
- uses: pre-commit/[email protected].3
with:
extra_args: --hook-stage manual --all-files

Expand Down
41 changes: 38 additions & 3 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-18.04, windows-latest, macos-latest]
os: [ubuntu-18.04, macos-latest]

steps:
- uses: actions/checkout@v2
with:
submodules: recursive

- uses: joerick/cibuildwheel@v1.10.0
- uses: joerick/cibuildwheel@v1.11.0
env:
CIBW_SKIP: cp27*
CIBW_TEST_EXTRAS: test
Expand All @@ -47,8 +47,43 @@ jobs:
with:
path: wheelhouse/*.whl

# workaround for MSVC, can be removed when scikit-build includes https://github.com/scikit-build/scikit-build/pull/526
build_windows_wheels:
name: Wheels for Windows
runs-on: windows-latest

steps:
- uses: actions/checkout@v2
with:
submodules: recursive

- uses: ilammy/msvc-dev-cmd@v1
with:
arch: x86

- uses: joerick/[email protected]
env:
CIBW_BUILD: cp3*-win32
CIBW_TEST_EXTRAS: test
CIBW_TEST_COMMAND: pytest {project}/tests

- uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64

- uses: joerick/[email protected]
env:
CIBW_BUILD: cp3*-win_amd64
CIBW_TEST_EXTRAS: test
CIBW_TEST_COMMAND: pytest {project}/tests

- name: Upload wheels
uses: actions/upload-artifact@v2
with:
path: wheelhouse/*.whl

upload_all:
needs: [build_wheels, make_sdist]
needs: [build_wheels, build_windows_wheels, make_sdist]
runs-on: ubuntu-latest
if: github.event_name == 'release' && github.event.action == 'published'

Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,7 @@ cython_debug/

# setuptools_scm
src/*/version.py

_skbuild
src/correctionlib/cmake
src/correctionlib/include
61 changes: 32 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,38 +70,41 @@ The build process is based on setuptools, with CMake (through scikit-build)
for the C++ evaluator and its python bindings module.
Builds have been tested in Windows, OS X, and Linux, and python bindings can be compiled against both
python2 and python3, as well as from within a CMSSW environment. The python bindings are distributed as a
pip-installable package.
pip-installable package. Note that CMSSW 11_2_X and above has ROOT accessible from python 3.
To build in an environment that has python 3, you can simply
To install in an environment that has python 3, you can simply
```bash
pip install correctionlib
python3 -m pip install correctionlib
```
(possibly with `--user`, or in a virtualenv, etc.)
Note that CMSSW 11_2_X and above has ROOT accessible from python 3.

The C++ evaluator is part of the python package. If you are also using CMake you can depend on it by passing
`-Dcorrectionlib_DIR=$(python -c 'import pkg_resources; print(pkg_resources.resource_filename("correctionlib", "cmake"))')`.
The header and shared library can similarly be found as
```python
import pkg_resources
pkg_resources.resource_filename("correctionlib", "include/correction.h")
pkg_resources.resource_filename("correctionlib", "lib/libcorrectionlib.so")
If you wish to install the latest development version,
```bash
python3 -m pip install git+https://github.com/cms-nanoAOD/correctionlib.git
```
should work.

In environments where no recent CMake is available, or if you want to build against python2
(see below), you can build the C++ evaluator via:
The C++ evaluator library is distributed as part of the python package, and it can be
linked to directly without using python. If you are using CMake you can depend on it by including
the output of `correction config --cmake` in your cmake invocation. A complete cmake
example that builds a user C++ application against correctionlib and ROOT RDataFrame
can be [found here](https://gist.github.com/pieterdavid/a560e65658386d70a1720cb5afe4d3e9).

For manual compilation, include and linking definitions can similarly be found via `correction config --cflags --ldflags`.
For example, the demo application can be compiled with:
```bash
git clone --recursive [email protected]:nsmith-/correctionlib.git
cd correctionlib
make
# demo C++ binding, main function at src/demo.cc
gunzip data/examples.json.gz
./demo data/examples.json
wget https://raw.githubusercontent.com/cms-nanoAOD/correctionlib/master/src/demo.cc
g++ $(correction config --cflags --ldflags --rpath) demo.cc -o demo
```
Eventually a `correction-config` utility will be added to retrieve the header and linking flags.

If the `correction` command-line utility is not on your path for some reason, it can also be invoked via `python -m correctionlib.cli`.

To compile with python2 support, consider using python 3 :) If you considered that and still
want to use python2, follow the C++ build instructions and then call `make PYTHON=python2 correctionlib` to compile.
want to use python2, the following recipe may work:
```bash
git clone --recursive [email protected]:cms-nanoAOD/correctionlib.git
cd correctionlib
make PYTHON=python2 correctionlib
```
Inside CMSSW you should use `make PYTHON=python correctionlib` assuming `python` is the name of the scram tool you intend to link against.
This will output a `correctionlib` directory that acts as a python package, and can be moved where needed.
This package will only provide the `correctionlib._core` evaluator module, as the schema tools and high-level bindings are python3-only.
Expand All @@ -117,18 +120,18 @@ Some examples can be found in `data/conversion.py`. The `tests/` directory may a
## Developing
See CONTRIBUTING.md

[actions-badge]: https://github.com/nsmith-/correctionlib/workflows/CI/badge.svg
[actions-link]: https://github.com/nsmith-/correctionlib/actions
[actions-badge]: https://github.com/cms-nanoAOD/correctionlib/workflows/CI/badge.svg
[actions-link]: https://github.com/cms-nanoAOD/correctionlib/actions
[black-badge]: https://img.shields.io/badge/code%20style-black-000000.svg
[black-link]: https://github.com/psf/black
[conda-badge]: https://img.shields.io/conda/vn/conda-forge/correctionlib
[conda-link]: https://github.com/conda-forge/correctionlib-feedstock
[github-discussions-badge]: https://img.shields.io/static/v1?label=Discussions&message=Ask&color=blue&logo=github
[github-discussions-link]: https://github.com/nsmith-/correctionlib/discussions
[gitter-badge]: https://badges.gitter.im/https://github.com/nsmith-/correctionlib/community.svg
[gitter-link]: https://gitter.im/https://github.com/nsmith-/correctionlib/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
[github-discussions-link]: https://github.com/cms-nanoAOD/correctionlib/discussions
[gitter-badge]: https://badges.gitter.im/https://github.com/cms-nanoAOD/correctionlib/community.svg
[gitter-link]: https://gitter.im/https://github.com/cms-nanoAOD/correctionlib/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
[pypi-link]: https://pypi.org/project/correctionlib/
[pypi-platforms]: https://img.shields.io/pypi/pyversions/correctionlib
[pypi-version]: https://badge.fury.io/py/correctionlib.svg
[rtd-badge]: https://github.com/nsmith-/correctionlib/actions/workflows/docs.yml/badge.svg
[rtd-link]: https://nsmith-.github.io/correctionlib/
[rtd-badge]: https://github.com/cms-nanoAOD/correctionlib/actions/workflows/docs.yml/badge.svg
[rtd-link]: https://cms-nanoAOD.github.io/correctionlib/
11 changes: 11 additions & 0 deletions docs/highlevel.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
correctionlib.highlevel
-----------------------
High-level interface to correction evaluator module. These objects
are also available directly through the ``correctionlib`` namespace.

.. currentmodule:: correctionlib.highlevel
.. autosummary::
:toctree: _generated

Correction
CorrectionSet
3 changes: 2 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ scalar inputs that produce a scalar output.
:caption: Contents
:glob:

highlevel
schemav1
schemav2
core
convert
core


Indices and tables
Expand Down
10 changes: 9 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ maintainer_email = [email protected]
description = A generic correction library
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/nsmith-/correctionlib
url = https://github.com/cms-nanoAOD/correctionlib
license = BSD 3-Clause License
# keywords =
platforms =
Expand All @@ -34,6 +34,7 @@ install_requires =
typing-extensions;python_version<"3.8"
dataclasses;python_version<"3.7"
pydantic >=1.7.3
rich

[options.extras_require]
test =
Expand All @@ -54,6 +55,10 @@ convert =
uproot >=4.0.4
requests

[options.entry_points]
console_scripts =
correction = correctionlib.cli:main

[tool:pytest]
addopts = -rs -s -Wd
testpaths =
Expand Down Expand Up @@ -108,3 +113,6 @@ strict_equality = True

[mypy-numpy]
ignore_missing_imports = True

[mypy-uproot]
ignore_missing_imports = True
7 changes: 6 additions & 1 deletion src/correction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,12 @@ Formula::Formula(const rapidjson::Value& json, const Correction& context, bool g

std::vector<size_t> variableIdx;
for (const auto& item : json["variables"].GetArray()) {
variableIdx.push_back(context.input_index(item.GetString()));
auto idx = context.input_index(item.GetString());
if ( context.inputs()[idx].type() != Variable::VarType::real ) {
throw std::runtime_error("Formulas only accept real-valued inputs, got type "
+ context.inputs()[idx].typeStr() + " for variable " + context.inputs()[idx].name());
}
variableIdx.push_back(idx);
}

std::vector<double> params;
Expand Down
19 changes: 14 additions & 5 deletions src/correctionlib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
from .version import version as __version__

__all__ = ("__version__",)

import sys

if sys.platform.startswith("win32"):
import ctypes
import os.path

ctypes.CDLL(os.path.join(os.path.dirname(__file__), "lib", "correctionlib.dll"))
import pkg_resources

ctypes.CDLL(
pkg_resources.resource_filename(
"correctionlib", os.path.join("lib", "correctionlib.dll")
)
)


from .binding import register_pyroot_binding
from .highlevel import Correction, CorrectionSet
from .version import version as __version__

__all__ = ("__version__", "CorrectionSet", "Correction", "register_pyroot_binding")
26 changes: 26 additions & 0 deletions src/correctionlib/_core/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from typing import Iterator, Type, TypeVar, Union

import numpy

class Correction:
@property
def name(self) -> str: ...
@property
def description(self) -> str: ...
@property
def version(self) -> int: ...
def evaluate(self, *args: Union[str, int, float]) -> float: ...
def evalv(self, *args: Union[numpy.ndarray, str, int, float]) -> numpy.ndarray: ...

T = TypeVar("T", bound="CorrectionSet")

class CorrectionSet:
@classmethod
def from_file(cls: Type[T], filename: str) -> T: ...
@classmethod
def from_string(cls: Type[T], data: str) -> T: ...
@property
def schema_version(self) -> int: ...
def __getitem__(self, key: str) -> Correction: ...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[str]: ...
25 changes: 25 additions & 0 deletions src/correctionlib/binding.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
def register_pyroot_binding() -> None:
import os.path
import sys

import pkg_resources
from cppyy import gbl # PyROOT without pythonization

# maybe not the most robust solution?
if sys.platform.startswith("win32"):
lib = pkg_resources.resource_filename(
"correctionlib", os.path.join("lib", "correctionlib.dll")
)
elif sys.platform.startswith("darwin"):
lib = pkg_resources.resource_filename(
"correctionlib", os.path.join("lib", "libcorrectionlib.dylib")
)
else:
lib = pkg_resources.resource_filename(
"correctionlib", os.path.join("lib", "libcorrectionlib.so")
)
gbl.gSystem.Load(lib)
gbl.gInterpreter.AddIncludePath(
pkg_resources.resource_filename("correctionlib", "include")
)
gbl.gROOT.ProcessLine('#include "correction.h"')
Loading

0 comments on commit 4047e43

Please sign in to comment.