diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 464ce2402377ddacbf94a9147aa958ebbd9bdf3d..bf5ccd3615ec12af29cbb647ea867e696296128e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -622,8 +622,8 @@ sanity: - cd ${CI_PROJECT_DIR}/Python # change into the Python directory - pip install --user -e '.[test]' # install the package + test deps - make all 2&>1 | tee python-test.log # this runs all of the Python tests - - echo "finished" >> python-test.log # create even an empty file... - - cd ${CI_PROJECT_DIR} # reset the directory + - cd ${CI_PROJECT_DIR} # reset the directory + coverage: '/^TOTAL\s*\d+\s*\d+\s*(.*\%)/' artifacts: when: always expire_in: 1 year diff --git a/Python/Makefile b/Python/Makefile index 59a1613fdf9cd1605eb64b675e2e2a82ba85e034..ccc13257fe572b456857657929c41d8199ad6529 100644 --- a/Python/Makefile +++ b/Python/Makefile @@ -16,7 +16,7 @@ tests: ${PYTHON} -m pytest --cov=corsika tests flake: - ${PYTHON} -m flake8 corsika + ${PYTHON} -m flake8 corsika tests black: ${PYTHON} -m black -t py37 corsika tests diff --git a/Python/corsika/__init__.py b/Python/corsika/__init__.py index cf4f1519eae59106d31ae10721fa393f8fb51c8e..f5331efad507aac2016ffe21fd4e35b027dad9b0 100644 --- a/Python/corsika/__init__.py +++ b/Python/corsika/__init__.py @@ -1,4 +1,6 @@ """ + A Python interface to CORSIKA 8. + (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu This software is distributed under the terms of the GNU General Public @@ -6,4 +8,9 @@ the license. """ +from . import io + +# all imported objects +__all__ = ["io"] + __version__: str = "8.0.0-alpha" diff --git a/Python/corsika/io/__init__.py b/Python/corsika/io/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..bd8a0d8bc7aedbd071fe40f23925a463104ec434 --- /dev/null +++ b/Python/corsika/io/__init__.py @@ -0,0 +1,14 @@ +""" + The 'io' module provides for reading CORSIKA8 output files. + + (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + + This software is distributed under the terms of the GNU General Public + Licence version 3 (GPL Version 3). See file LICENSE for a full version of + the license. +""" + +from .hist import read_hist + +# all exported objects +__all__ = ["read_hist"] diff --git a/Python/corsika/io/hist.py b/Python/corsika/io/hist.py new file mode 100644 index 0000000000000000000000000000000000000000..e12dcfd1bc828b1ea759f6051cb45694e1956e79 --- /dev/null +++ b/Python/corsika/io/hist.py @@ -0,0 +1,70 @@ +""" + This file supports reading boost_histograms from CORSIKA8. + + (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + + This software is distributed under the terms of the GNU General Public + Licence version 3 (GPL Version 3). See file LICENSE for a full version of + the license. +""" + +import boost_histogram as bh +import numpy as np + + +def read_hist(filename: str) -> bh.Histogram: + """ + Read a histogram produced with CORSIKA8's `save_hist()` function. + + Parameters + ---------- + filename: str + The filename of the .npy file containing the histogram. + + Returns + ------- + hist: bh.Histogram + An initialized bh.Histogram instance. + + Throws + ------ + ValueError: + If the histogram type is not supported. + """ + + # load the filenames + d = np.load(filename) + + # extract the axis and overflows information + axistypes = d["axistypes"].view("c") + overflow = d["overflow"] + underflow = d["underflow"] + + # this is where we store the axes that we extract from the file. + axes = [] + + # we now loop over the axes + for i, (at, has_overflow, has_underflow) in enumerate( + zip(axistypes, overflow, underflow) + ): + + # continuous histogram + if at == b"c": + axes.append( + bh.axis.Variable( + d[f"binedges_{i}"], overflow=has_overflow, underflow=has_underflow + ) + ) + # discrete histogram + elif at == b"d": + axes.append(bh.axis.IntCategory(d[f"bins_{i}"], growth=(not has_overflow))) + + # and unknown histogram type + else: + raise ValueError(f"'{at}' is not a valid C8 histogram axistype.") + + # create the histogram and fill it in + h = bh.Histogram(*axes) + h.view(flow=True)[:] = d["data"] + + return h diff --git a/Python/setup.cfg b/Python/setup.cfg index d318235ee166e27b1e147bae61daf5ef95e91f81..2544189cacdaef9ab0c8e4e6dcf730f5bff4b344 100644 --- a/Python/setup.cfg +++ b/Python/setup.cfg @@ -59,3 +59,7 @@ ignore_missing_imports = True # ignore missing types for matplotlib [mypy-matplotlib.*] ignore_missing_imports = True + +# ignore missing types for boost_histogram +[mypy-boost_histogram.*] +ignore_missing_imports = True diff --git a/Python/setup.py b/Python/setup.py index 36360358f181b35f8c36c548c3778b92436c0c7e..350fbe9fac598a11fc7a7acc33a53ee6c4be89d3 100644 --- a/Python/setup.py +++ b/Python/setup.py @@ -32,7 +32,7 @@ setup( keywords=["cosmic ray", "physics", "astronomy", "simulation"], packages=["corsika"], python_requires=">=3.6*, <4", - install_requires=["numpy", "pyyaml",], + install_requires=["numpy", "pyyaml", "boost_histogram"], extras_require={ "test": [ "pytest", diff --git a/Python/tests/test_hist.py b/Python/tests/test_hist.py new file mode 100644 index 0000000000000000000000000000000000000000..0ad70b734c0af38baf180987ed97e01de02b0740 --- /dev/null +++ b/Python/tests/test_hist.py @@ -0,0 +1,36 @@ +""" + Tests for `corsika.io.hist` + + (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + + This software is distributed under the terms of the GNU General Public + Licence version 3 (GPL Version 3). See file LICENSE for a full version of + the license. +""" +import pytest + +import corsika + + +def test_corsika_io() -> None: + """ + Test I can corsika.io without a further import. + """ + corsika.io.read_hist + + +def test_corsika_read_hist() -> None: + """ + Check that I can read in the test histograms with `read_hist`. + """ + + # try and read in a continuous histogram + + # try and read in a discrete histogram + + +def test_corsika_read_hist_fail() -> None: + """ + Check that an exception is thrown when reading + an incorrectly formatted histogram. + """