From 2bc2ca84708c944de8deb964f95fae4eee9e3533 Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Fri, 13 Oct 2023 21:50:48 +0100 Subject: [PATCH 01/20] ci: add ROOT v6.28 and Python v3.11 to test matrix --- .github/workflows/tests.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 34ae11ff..4cb366c8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -25,19 +25,25 @@ jobs: strategy: matrix: os: [ubuntu-latest] - root-version: ["6.24", "6.26"] - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] + root-version: ["6.24", "6.26", "6.28"] + python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"] exclude: - root-version: "6.24" python-version: "3.10" + - root-version: "6.24" + python-version: "3.11" - root-version: "6.26" python-version: "3.6" - root-version: "6.26" python-version: "3.7" + - root-version: "6.28" + python-version: "3.6" + - root-version: "6.28" + python-version: "3.7" include: - os: macos-latest - root-version: "6.26" - python-version: "3.10" + root-version: "6.28" + python-version: "3.11" steps: - uses: actions/checkout@v3 From 674a872916c8b87c493c2b11d29e6127b7e486e7 Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Fri, 13 Oct 2023 22:18:18 +0100 Subject: [PATCH 02/20] docs: add "Adding resource links or files" etc. * Add hepdata_lib.c_file_reader and hepdata_lib.helpers modules. * Pin Sphinx<7 since docs fail to be built with Sphinx v7. * Replace m2r2 with sphinx-mdinclude to avoid Mistune conflict. * Replace deprecated "python setup.py test" with "pytest tests". * Add section to "Developer information" about building docs. * Add sections to "Usage" on "Adding resource links or files". * Mention that venv can be used instead of virtualenv/virtualenvwrapper. --- docs/Makefile | 2 +- docs/conf.py | 8 +-- docs/contributing.rst | 4 +- docs/dev.rst | 28 +++++++---- docs/requirements.txt | 4 +- docs/setup.rst | 11 ++++- docs/source/hepdata_lib.rst | 10 ++++ docs/usage.rst | 99 ++++++++++++++++++++++++++----------- 8 files changed, 116 insertions(+), 50 deletions(-) diff --git a/docs/Makefile b/docs/Makefile index 263d1a72..620e9826 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -2,7 +2,7 @@ # # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = -W --keep-going SPHINXBUILD = sphinx-build SPHINXPROJ = hepdata_lib SOURCEDIR = . diff --git a/docs/conf.py b/docs/conf.py index 9a92cc46..d5cd4169 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -35,7 +35,7 @@ def __getattr__(cls, name): # -- Project information ----------------------------------------------------- project = 'hepdata_lib' -copyright = '2018-2022, Andreas Albert, Clemens Lange' +copyright = '2018-2023, Andreas Albert, Clemens Lange' author = 'Andreas Albert, Clemens Lange' # The short X.Y version @@ -55,7 +55,7 @@ def __getattr__(cls, name): # ones. extensions = [ 'sphinx.ext.githubpages', - 'm2r2', + 'sphinx_mdinclude', 'sphinx.ext.autodoc' ] @@ -76,7 +76,7 @@ def __getattr__(cls, name): # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = 'en' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -103,7 +103,7 @@ def __getattr__(cls, name): # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +# html_static_path = ['_static'] # Custom sidebar templates, must be a dictionary that maps document names # to template names. diff --git a/docs/contributing.rst b/docs/contributing.rst index cd762b33..3528c3dd 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -34,7 +34,7 @@ The files in which the versions are updated as well as the current version can b .. _sec-dev-pypi: Uploading to PyPI ------------------------------ +----------------- Once a new version has been tagged, the package should be uploaded to the Python Package Index (PyPI_). For the markdown formatting to work, ``twine>=1.11.0`` is required. @@ -72,7 +72,7 @@ You should then find the new version at `this location`_. You need to be a maint .. _python packaging documentation: https://packaging.python.org/tutorials/packaging-projects/ Creating a new release automatically via an issue ------------------------------ +------------------------------------------------- Opening an new issue automatically creates a new release if: diff --git a/docs/dev.rst b/docs/dev.rst index c105498d..39e4c2c0 100644 --- a/docs/dev.rst +++ b/docs/dev.rst @@ -1,21 +1,22 @@ Developer information -====================== +===================== The testing system --------------------- +------------------ While further developing the code base, we want to ensure that any changes we make do not accidentally break existing functionality. For this purpose, we use continuous integration via GitHub Actions_. Practically, this means that we define a set of test code that is automatically run in a predefined environment every time we push to a branch or create a pull request. If the test code runs successfully, we know that everything works as expected. -To run the tests, move into the ``hepdata_lib`` directory and run +To run the tests, move into the ``hepdata_lib`` directory while in your virtual environment and run :: - python setup.py test + pip install -e ".[test]" + pytest tests It is a good idea to run the tests manually to ensure that your changes do not cause any issues. Definition of test cases -+++++++++++++++++++++++++ +++++++++++++++++++++++++ Test cases are defined in the ``test`` subfolder of the repository. Independent sets of test code are defined in individual files in that directory, with each files being named like ``test_*.py``. @@ -40,12 +41,12 @@ If all functions run without raising exceptions, the test is considered to be pa When to test -~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~ Tests should be added any time functionality is added. If functionality is modified, so should the tests. What to test -~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~ Generally, the tests should ensure that the code behaves as expected, whatever that may mean. They should be sufficiently rigorous to make sure that nothing can break silently, and that outputs are correct. @@ -57,7 +58,7 @@ Broad inspiration for aspects to check: How to test -~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~ The ``TestCase`` base class provides functionality to help implement simple checks to verify the behavior. A test can immediately be made to fail by calling ``self.fail()``. For convenience, additional functions like ``assertTrue``, ``assertFalse``, etc. are provided, which work like normal python assertions. If the assertion fails, the test is considered to be failed. Additionally, the ``assertRaises`` method can be used as a context to ensure that exceptions are raised as expected. Here's a simple example: @@ -95,10 +96,17 @@ Note that this is an overly simple example case: In a real testing case, you sho Check out the unittest package documentation_ for details of the available testing functionality. +.. _Actions: https://docs.github.com/en/actions +.. _documentation: https://docs.python.org/2/library/unittest.html#unittest.TestCase + +Building the documentation +-------------------------- +After installing the ``hepdata_lib`` package, move into the ``hepdata_lib/docs`` directory and install the additional necessary packages into your virtual environment: +:: + pip install -r requirements.txt -.. _Actions: https://docs.github.com/en/actions -.. _documentation: https://docs.python.org/2/library/unittest.html#unittest.TestCase +Then you can build the documentation locally with Sphinx using ``make html`` and view the output by opening a web browser at ``_build/html/index.html``. \ No newline at end of file diff --git a/docs/requirements.txt b/docs/requirements.txt index d7062796..d522aaac 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,4 @@ -m2r2==0.3.3 +Sphinx<7 sphinx_rtd_theme docutils==0.19 -mistune<2.0.0 +sphinx-mdinclude \ No newline at end of file diff --git a/docs/setup.rst b/docs/setup.rst index 802e0d74..e727aa52 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -47,7 +47,7 @@ If you would like to develop the code, you need to install the package from the :: cd $SOMEPATH - git clone git@github.com:HEPData/hepdata_lib.git + git clone https://github.com/HEPData/hepdata_lib.git workon myhepdata # activate virtual environment! pip install -e $SOMEPATH/hepdata_lib @@ -92,6 +92,15 @@ You can always activate the virtual environment in another shell by calling the workon hepdata_git python myscript.py # Execute script using development branch +Alternatively, if you don't want to install the additional virtualenv_ and virtualenvwrapper_ packages, you can simply +use the venv_ module from the Python standard library. + +:: + + python3 -m venv env + source env/bin/activate + +.. _venv: https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#creating-a-virtual-environment Setup on lxplus with CMSSW -------------------------- diff --git a/docs/source/hepdata_lib.rst b/docs/source/hepdata_lib.rst index 4397e06e..6e9f254d 100644 --- a/docs/source/hepdata_lib.rst +++ b/docs/source/hepdata_lib.rst @@ -9,6 +9,16 @@ Module contents :undoc-members: :show-inheritance: +.. automodule:: hepdata_lib.c_file_reader + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: hepdata_lib.helpers + :members: + :undoc-members: + :show-inheritance: + .. automodule:: hepdata_lib.root_utils :members: :undoc-members: diff --git a/docs/usage.rst b/docs/usage.rst index 3bd3ecba..13e2a1fa 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -1,5 +1,5 @@ Usage -======================= +===== The library aims to offer tools for two main operations: @@ -11,7 +11,7 @@ All of this happens in a user-friendly python interface. :ref:`sec-usage-reading In the following sections, there are HEPData and its data format ------------------------------ +--------------------------- The HEPData data model revolves around **Tables** and **Variables**. At its core, a Variable is a one-dimensional array of numbers with some additional (meta-)data, such as uncertainties, units, etc. assigned to it. A Table is simply a set of multiple Variables. This definition will immediately make sense to you when you think of a general table, which has multiple columns representing different variables. @@ -19,10 +19,10 @@ The HEPData data model revolves around **Tables** and **Variables**. At its core .. _sec-usage-reading: Reading data -------------------------------- +------------ Reading from plain text -+++++++++++++++++++++++++++++++ ++++++++++++++++++++++++ If you save your data in a text file, a simple-to-use tool is the ``numpy.loadtxt`` function, which loads column-wise data from plain-text files and returns it as a ``numpy.array``. @@ -40,7 +40,7 @@ For documentation on the `loadtxt` function, please refer the `numpy documentati Reading from ROOT files -+++++++++++++++++++++++++++++++ ++++++++++++++++++++++++ In many cases, data in the experiments is available as one of various ROOT data types, such as ``TGraphs``, ``TH1``, ``TH2``, etc, which are saved in ``*.root`` files. @@ -81,7 +81,7 @@ An `example notebook`_ shows how to read histograms from a ROOT file. .. _sec-usage-writing: Writing data -------------------------------- +------------ Following the HEPData data model, the hepdata_lib implements four main classes for writing data: @@ -94,7 +94,7 @@ Following the HEPData data model, the hepdata_lib implements four main classes f .. _sec-usage-submission: The Submission object -+++++++++++++++++++++++++++++++ ++++++++++++++++++++++ The Submission object is the central object where all threads come together. It represents the whole HEPData entry and thus carries the top-level meta data that is equally valid for all the tables and variables you may want to enter. The object is also used to create the physical submission files you will upload to the HEPData web interface. @@ -112,12 +112,40 @@ The ``create_files`` function writes all the YAML output files you need and pack **Please note**: creating the output files also creates a ``submission`` folder containing the individual files going into the tarball. This folder exists merely for convenience, in order to make it easy to inspect each individual file. It is not recommended to attempt to manually manage or edit the files in the folder, and there is no guarantee that ``hepdata_lib`` will handle any of the changes you make in a graceful manner. As far as we are aware, there is no use case where manual editing of the files is necessary. If you have such a use case, please report it in a Github issue. +.. _sec-usage-resource: + +Adding resource links or files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Additional resources, hosted either externally or locally, can be linked with the ``add_additional_resource`` function of the Submission object. + +:: + + sub.add_additional_resource("Web page with auxiliary material", "https://atlas.web.cern.ch/Atlas/GROUPS/PHYSICS/PAPERS/STDM-2012-02/") + sub.add_additional_resource("Some file", "root_file.root", copy_file=True) + sub.add_additional_resource("Archive of full likelihoods in the HistFactory JSON format", "Likelihoods.tar.gz", copy_file=True, type="HistFactory") + +The first argument is a ``description`` and the second is the ``location`` of the external link or local resource file. +The optional argument ``copy_file=True`` (default value of ``False``) will copy a local file into the output directory. +The optional argument ``type="HistFactory"`` (default value of ``None``) can be used to identify statistical models provided in the HistFactory JSON +format rather than relying on certain trigger words in the ``description`` (see `pyhf section of submission documentation`_). + +The ``add_link`` function can alternatively be used to add a link to an external resource: + +:: + + sub.add_link("Web page with auxiliary material", "https://atlas.web.cern.ch/Atlas/GROUPS/PHYSICS/PAPERS/STDM-2012-02/") + +Again, the first argument is a ``description`` and the second is the ``location`` of the external link. + +.. _`pyhf section of submission documentation`: https://hepdata-submission.readthedocs.io/en/latest/analyses.html#pyhf + Adding links to related records ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -To add a link to a related record object, you can use the `add_related_recid` function of the Submission object. +To add a link to a related record object, you can use the ``add_related_recid`` function of the Submission object. -**Please note**: Values must be entered as integers. +**Please note**: values must be entered as integers. :: @@ -125,17 +153,17 @@ To add a link to a related record object, you can use the `add_related_recid` fu sub.add_related_recid(2) sub.add_related_recid(3) -In this example, we are adding a link to the submission with the record ID value of `"1"`. +In the last example, we are adding a link to the submission with the record ID value of ``3``. -The documentation for this feature can be found here: (`Linking Records`_). +The documentation for this feature can be found here: `Linking records`_. -.. _`Linking Records` : https://hepdata-submission.readthedocs.io/en/latest/bidirectional.html#linking-records +.. _`Linking records`: https://hepdata-submission.readthedocs.io/en/latest/bidirectional.html#linking-records .. _sec-usage-tab-var: Tables and Variables -+++++++++++++++++++++++++++++++ +++++++++++++++++++++ The real data is stored in Variables and Tables. Variables come in two flavors: *independent* and *dependent*. Whether a variable is independent or dependent may change with context, but the general idea is that the independent variable is what you put in, the dependent variable is what comes out. Example: if you calculate a cross-section limit as a function of the mass of a hypothetical new particles, the mass would be independent, the limit dependent. The number of either type of variables is not limited, so if you have a scenario where you give N results as a function of M model parameters, you can have N dependent and M independent variables. All the variables are then bundled up and added into a Table object. @@ -172,7 +200,7 @@ That's it! We have successfully created the Table and Variables and stored our r After we have done this, the table will be included in the output files the ``Submission.create_files`` function writes (see :ref:`sec-usage-submission`). Binned Variables -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^ The above example uses unbinned Variables, which means that every point is simply a single number reflecting a localized value. In many cases, it is useful to use binned Variables, e.g. to represent the x axis of a histogram. In this case, everything works the same way as in the unbinned case, except that we have to specify ``is_binned=True`` in the Variable constructor, and change how we format the list of values: @@ -186,7 +214,7 @@ In this case, everything works the same way as in the unbinned case, except that The list of values has an entry for each bin of the Variable. The entry is a tuple, where the first entry represents the lower edge of the bin, while the second entry represents the upper edge of the bin. You can simply plug this definition into the code snippet of the unbinned case above to go from an unbinned mass to a binned value. Note that binning a Variable only really makes sense for independent variables. Two-dimensional plots -^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^ In some cases, you may want to define information based on multiple parameters, e.g. in the case of a two-dimensional histogram (TH2 in ROOT). This can be easily accomplished by defining two independent Variables in the same Table: @@ -225,9 +253,9 @@ One common use case with more than one independent Variable is that of correlati .. _available here: https://github.com/HEPData/hepdata_lib/blob/master/examples/correlation.ipynb -Adding a plot thumb nail to a table -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -HepData supports the addition of thumb nail images to each table. This makes it easier for the consumer of your entry to find what they are looking for, since they can simply look for the table that has the thumb nail of the plot they are interested in. +Adding a plot thumb nail to a table +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +HEPData supports the addition of thumb nail images to each table. This makes it easier for the consumer of your entry to find what they are looking for, since they can simply look for the table that has the thumb nail of the plot they are interested in. If you have the full-size plot available on your drive, you can add it to your entry very easily: :: @@ -236,12 +264,25 @@ If you have the full-size plot available on your drive, you can add it to your e The library code then takes care of all the necessary steps, like converting the image to the right format and size, and copying it into your submission folder. The conversion relies on the ImageMagick library, and will only work if the ``convert`` command is available on your machine. +Adding resource links or files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Additional resources, hosted either externally or locally, can be linked with the ``add_additional_resource`` function of the Table object, in the same way as for the Submission object. + +:: + + table.add_additional_resource("Web page with auxiliary material", "https://atlas.web.cern.ch/Atlas/GROUPS/PHYSICS/PAPERS/STDM-2012-02/") + table.add_additional_resource("Some file", "root_file.root", copy_file=True) + +For a description of the arguments, see :ref:`sec-usage-resource` for the Submission object. +A possible use case is to attach the data for the table in its original format before it was transformed into the HEPData YAML format. + Adding keywords to a table -^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^ -To make hepdata entries more searchable, keywords should be used to define what information is shown in a table. HEPData keeps track of keywords separately from the rest of the information in an entry, and provides dedicated functionalities to search for and filter by a given set of keywords. If a user is e.g. interested in finding all tables relevant to graviton production, they can do so quite easily if the tables are labelled properly. This procedure becomes much harder, or even impossible, if no keywords are used. It is therefore considered good practice to add a number of sensible keywords to your tables. +To make HEPData entries more searchable, keywords should be used to define what information is shown in a table. HEPData keeps track of keywords separately from the rest of the information in an entry, and provides dedicated functionalities to search for and filter by a given set of keywords. If a user is e.g. interested in finding all tables relevant to graviton production, they can do so quite easily if the tables are labelled properly. This procedure becomes much harder, or even impossible, if no keywords are used. It is therefore considered good practice to add a number of sensible keywords to your tables. -The keywords are stored as a simply dictionary for each table: +The keywords are stored as a simple dictionary for each table: :: @@ -257,28 +298,26 @@ Lists of recognized keywords are available from the hepdata documentation for `O .. _`Phrases`: https://hepdata-submission.readthedocs.io/en/latest/keywords/phrases.html .. _`Particles`: https://hepdata-submission.readthedocs.io/en/latest/keywords/partlist.html - Adding links to related tables -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -To add a link to a related table object, you can use the `add_related_doi` function of the Table class. +To add a link to a related table object, you can use the ``add_related_doi`` function of the Table class. -**Please note**: Your DOIs must match the format: `10.17182/hepdata.[RecordID].v[Version]/t[Table]` +**Please note**: your DOIs must match the format: ``10.17182/hepdata.[RecordID].v[Version]/t[Table]``. :: table.add_related_doi("10.17182/hepdata.72886.v2/t3") table.add_related_doi("10.17182/hepdata.12882.v1/t2") -In this example, we are adding a link to the table with a DOI value of: `10.17182/hepdata.12882.v1/t2 `__. - +In the second example, we are adding a link to the table with a DOI value of `10.17182/hepdata.12882.v1/t2 `_. -The documentation for this feature can be found here: `Linking Tables`_. +The documentation for this feature can be found here: `Linking tables`_. -.. _`Linking Tables` : https://hepdata-submission.readthedocs.io/en/latest/bidirectional.html#linking-tables +.. _`Linking tables`: https://hepdata-submission.readthedocs.io/en/latest/bidirectional.html#linking-tables Uncertainties -++++++++++++++++++++++++++++++++ ++++++++++++++ In many cases, you will want to give uncertainties on the central values provided in the Variable objects. Uncertainties can be *symmetric* or *asymmetric* (up and down variations of the central value either have the same or different magnitudes). For symmetric uncertainties, the values of the uncertainties are simply stored as a one-dimensional list. For asymmetric uncertainties, the up- and downward variations are stored as a list of two-component tuples: From e9a4bde6d90c0ce782d1354635c55dfbdb7142ba Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Fri, 13 Oct 2023 22:21:40 +0100 Subject: [PATCH 03/20] examples: use add_additional_resource in notebooks --- examples/Getting_started.ipynb | 64 ++++++++++++-------- examples/combine_limits.ipynb | 47 ++++++++------- examples/correlation.ipynb | 28 +++++---- examples/plots/correlation.png | Bin 17802 -> 17797 bytes examples/read_c_file.ipynb | 95 +++++++++++++----------------- examples/reading_histograms.ipynb | 75 +++++++---------------- 6 files changed, 143 insertions(+), 166 deletions(-) diff --git a/examples/Getting_started.ipynb b/examples/Getting_started.ipynb index 91c8fec1..e940c44c 100644 --- a/examples/Getting_started.ipynb +++ b/examples/Getting_started.ipynb @@ -35,7 +35,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Welcome to JupyROOT 6.14/04\n" + "Welcome to JupyROOT 6.28/06\n" ] } ], @@ -80,7 +80,8 @@ "submission.read_abstract(\"example_inputs/abstract.txt\")\n", "submission.add_link(\"Webpage with all figures and tables\", \"https://cms-results.web.cern.ch/cms-results/public-results/publications/B2G-16-029/\")\n", "submission.add_link(\"arXiv\", \"http://arxiv.org/abs/arXiv:1802.09407\")\n", - "submission.add_record_id(1657397, \"inspire\")" + "submission.add_record_id(1657397, \"inspire\")\n", + "submission.add_additional_resource(\"Original abstract file\", \"example_inputs/abstract.txt\", copy_file=True) # for illustration, probably not useful" ] }, { @@ -103,16 +104,16 @@ "name": "stdout", "output_type": "stream", "text": [ - "mass BulkG Wprime\r\n", - "------- ------- -------\r\n", - "1000.0 0.4651 0.45136\r\n", - "1200.0 0.50336 0.5109\r\n", - "1400.0 0.5126 0.54016\r\n", - "1600.0 0.52474 0.5513\r\n", - "1800.0 0.531 0.56724\r\n", - "2000.0 0.5391 0.5728\r\n", - "2500.0 0.549430894308 0.585602409637\r\n", - "3000.0 0.55378 0.58952\r\n" + "mass BulkG Wprime\n", + "------- ------- -------\n", + "1000.0 0.4651 0.45136\n", + "1200.0 0.50336 0.5109\n", + "1400.0 0.5126 0.54016\n", + "1600.0 0.52474 0.5513\n", + "1800.0 0.531 0.56724\n", + "2000.0 0.5391 0.5728\n", + "2500.0 0.549430894308 0.585602409637\n", + "3000.0 0.55378 0.58952\n" ] } ], @@ -267,7 +268,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This is all that's needed for the table/figure. We still need it to the submission:" + "If you want, the original data file can be attached to the table as an additional resource file." ] }, { @@ -275,6 +276,22 @@ "execution_count": 11, "metadata": {}, "outputs": [], + "source": [ + "table.add_additional_resource(\"Original data file\", \"example_inputs/effacc_signal.txt\", copy_file=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is all that's needed for the table/figure. We still need it to the submission:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], "source": [ "submission.add_table(table)" ] @@ -288,7 +305,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -305,12 +322,12 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "outdir = \"example_output\"\n", - "submission.create_files(outdir,remove_old=True)" + "submission.create_files(outdir, remove_old=True)" ] }, { @@ -322,14 +339,14 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "submission.tar.gz\r\n" + "submission.tar.gz\n" ] } ], @@ -346,14 +363,15 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "additional_figure_1.yaml signalEffVsMass.png submission.yaml thumb_signalEffVsMass.png\r\n" + "abstract.txt effacc_signal.txt submission.yaml\n", + "additional_figure_1.yaml signalEffVsMass.png thumb_signalEffVsMass.png\n" ] } ], @@ -364,7 +382,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -378,9 +396,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.11.6" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/combine_limits.ipynb b/examples/combine_limits.ipynb index 2a1fa151..2f614f91 100644 --- a/examples/combine_limits.ipynb +++ b/examples/combine_limits.ipynb @@ -20,7 +20,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Welcome to JupyROOT 6.14/00\n" + "Welcome to JupyROOT 6.28/06\n" ] } ], @@ -275,6 +275,7 @@ "table.add_variable(d)\n", "table.add_variable(obs)\n", "table.add_variable(exp)\n", + "table.add_additional_resource(\"ROOT file\", \"example_inputs/WWmerged.higgsCombineTest.Asymptotic.root\", copy_file=True) # optional\n", "submission.add_table(table)\n", "submission.create_files(\"example_output\",remove_old=True)" ] @@ -288,8 +289,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "Figure_006-a.png figure_4a.yaml signalEffVsMass.png thumb_Figure_006-a.png\r\n", - "additional_figure_1.yaml figure_6a.yaml submission.yaml thumb_signalEffVsMass.png\r\n" + "Figure_006-a.png\n", + "WWmerged.higgsCombineTest.Asymptotic.root\n", + "figure_6a.yaml\n", + "submission.yaml\n", + "thumb_Figure_006-a.png\n" ] } ], @@ -300,40 +304,35 @@ { "cell_type": "code", "execution_count": 7, - "metadata": {}, + "metadata": { + "scrolled": true + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "dependent_variables:\r\n", - "- header:\r\n", - " name: Cross section upper limit at 95% CL\r\n", - " units: pb\r\n", - " qualifiers:\r\n", - " - name: Limit\r\n", - " value: Observed\r\n", - " - name: SQRT(S)\r\n", - " units: TeV\r\n", - " value: 13\r\n" + "dependent_variables:\n", + "- header:\n", + " name: Cross section upper limit at 95% CL\n", + " units: pb\n", + " qualifiers:\n", + " - name: Limit\n", + " value: Observed\n", + " - name: SQRT(S)\n", + " units: TeV\n", + " value: 13\n" ] } ], "source": [ "!head example_output/figure_6a.yaml" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -347,9 +346,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.11.6" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/correlation.ipynb b/examples/correlation.ipynb index 589047b0..f752ab5a 100644 --- a/examples/correlation.ipynb +++ b/examples/correlation.ipynb @@ -28,7 +28,14 @@ "name": "stdout", "output_type": "stream", "text": [ - "Welcome to JupyROOT 6.16/00\n" + "Welcome to JupyROOT 6.28/06\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Info in : png file plots/correlation.png has been created\n" ] } ], @@ -102,7 +109,7 @@ { "data": { "text/plain": [ - "['y_edges', 'x_edges', 'dz', 'y', 'x', 'z']" + "dict_keys(['x', 'y', 'x_edges', 'y_edges', 'z', 'dz', 'x_labels', 'y_labels'])" ] }, "execution_count": 3, @@ -269,7 +276,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "-rw-r--r-- 1 albert albert 580 Apr 12 12:48 submission.tar.gz\r\n" + "-rw-r--r-- 1 watt staff 4820 13 Oct 19:14 submission.tar.gz\n" ] } ], @@ -278,11 +285,12 @@ "table = Table(\"Correlation coefficients between signal region bins\")\n", "for var in [x,y,correlation]:\n", " table.add_variable(var)\n", + "table.add_additional_resource(\"ROOT file\", \"correlation.root\", copy_file=True) # optional\n", "\n", "# Create the submission object and write output\n", "sub = Submission()\n", "sub.add_table(table)\n", - "sub.create_files(\"./output/\",remove_old=True)\n", + "sub.create_files(\"./output/\", remove_old=True)\n", "\n", "!ls -l submission.tar.gz" ] @@ -297,23 +305,23 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 2", + "display_name": "Python 3 (ipykernel)", "language": "python", - "name": "python2" + "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 2 + "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.15rc1" + "pygments_lexer": "ipython3", + "version": "3.11.6" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/plots/correlation.png b/examples/plots/correlation.png index 8e4eefc2e63c15744555b9c164ab18491e642ec2..68e3b174828a36e04b343ce76c5c49a985b08513 100644 GIT binary patch literal 17797 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
eV>WhGyKx_93s4|{-vPwZ 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�Tig(gh>- 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: \n", - " The StreamerInfo of class RooExpensiveObjectCache read from file example_inputs/mlfit_lm_1000.root\n", - " has the same version (=2) as the active class but a different checksum.\n", - " You should update the version to ClassDef(RooExpensiveObjectCache,3).\n", - " Do not try to write objects with the current class definition,\n", - " the files will not be readable.\n", - "\n", - "Warning in : The following data member of\n", - "the on-file layout version 2 of class 'RooExpensiveObjectCache' differs from \n", - "the in-memory layout version 2:\n", - " map _map; //\n", - "vs\n", - " map _map; //\n" - ] - } - ], + "outputs": [], "source": [ "from hepdata_lib import RootFileReader\n", "\n", @@ -126,7 +95,7 @@ { "data": { "text/plain": [ - "dict_keys(['x', 'y', 'x_edges', 'dy'])" + "dict_keys(['x', 'y', 'x_edges', 'x_labels', 'dy'])" ] }, "execution_count": 4, @@ -157,6 +126,7 @@ "x \n", "y \n", "x_edges \n", + "x_labels \n", "dy \n" ] } @@ -256,6 +226,10 @@ "table.add_variable(wjets)\n", "table.add_variable(data)\n", "\n", + "table.add_additional_resource(\"Background ROOT file\", \"example_inputs/mlfit_lm_1000.root\", copy_file=True) # optional\n", + "table.add_additional_resource(\"Data ROOT file\", \"example_inputs/Data_cat0_singleH.root\", copy_file=True) # optional\n", + "table.add_additional_resource(\"Signal ROOT file\", \"example_inputs/BprimeBToHB1000_cat0_singleH.root\", copy_file=True) # optional\n", + "\n", "submission.add_table(table)\n", "\n", "submission.create_files(\"example_output\",remove_old=True)" @@ -270,34 +244,27 @@ "name": "stdout", "output_type": "stream", "text": [ - "dependent_variables:\r\n", - "- header:\r\n", - " name: Number of signal events\r\n", - " units: ''\r\n", - " values:\r\n", - " - value: 0.95335\r\n", - " - value: 0.83057\r\n", - " - value: 3.5395\r\n", - " - value: 1.8212\r\n", - " - value: 0.04857\r\n" + "dependent_variables:\n", + "- header:\n", + " name: Number of signal events\n", + " values:\n", + " - value: 0.95335\n", + " - value: 0.83057\n", + " - value: 3.5395\n", + " - value: 1.8212\n", + " - value: 0.04857\n", + " - value: 0.047358\n" ] } ], "source": [ "!head example_output/figure_4a.yaml" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -311,9 +278,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.10" + "version": "3.11.6" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } From 666f7991157f0ded2765c08bc393d7679120236e Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Fri, 13 Oct 2023 22:28:01 +0100 Subject: [PATCH 04/20] hepdata_lib: add "type" to add_additional_resource * Allow for type="HistFactory" to be passed as an additional argument. * Extend test_submission.py to test the additional "type" argument. * Add newlines to docstring of round_value_and_uncertainty for Sphinx. --- hepdata_lib/__init__.py | 11 ++++++++--- hepdata_lib/helpers.py | 2 ++ tests/test_submission.py | 4 ++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/hepdata_lib/__init__.py b/hepdata_lib/__init__.py index 8a05d631..3dfa17fe 100644 --- a/hepdata_lib/__init__.py +++ b/hepdata_lib/__init__.py @@ -55,7 +55,7 @@ def __init__(self): self.files_to_copy = [] self.additional_resources = [] - def add_additional_resource(self, description, location, copy_file=False): + def add_additional_resource(self, description, location, copy_file=False, type=None): """ Add any kind of additional resource. If copy_file is set to False, the location and description will be added as-is. @@ -73,10 +73,12 @@ def add_additional_resource(self, description, location, copy_file=False): :type description: string. :param location: Can be either a URL pointing to a web-based resource or a local file path. - :type: string + :type location: string :param copy_file: If set to true, will attempt to copy a local file to the tar ball. :type copy_file: bool + + :param type: Type of the resource file. Currently, only "HistFactory" has any effect. """ resource = {} @@ -89,6 +91,9 @@ def add_additional_resource(self, description, location, copy_file=False): else: resource["location"] = location + if type: + resource["type"] = type + self.additional_resources.append(resource) def copy_files(self, outdir): @@ -495,7 +500,7 @@ def __init__(self): self.related_records = [] self.add_additional_resource( "Created with hepdata_lib " + __version__, - "https://zenodo.org/record/4946277") + "https://doi.org/10.5281/zenodo.1217998") @staticmethod def get_license(): diff --git a/hepdata_lib/helpers.py b/hepdata_lib/helpers.py index c539ff33..788fba04 100644 --- a/hepdata_lib/helpers.py +++ b/hepdata_lib/helpers.py @@ -161,9 +161,11 @@ def round_value_and_uncertainty(cont, val_key="y", unc_key="dy", sig_digits_unc= round values and uncertainty according to the precision of the uncertainty, and also round uncertainty to a given number of significant digits Typical usage: + reader = RootFileReader("rootfile.root") data = reader.read_hist_1d("histogramName") round_value_and_uncertainty(data,"y","dy",2) + will round data["y"] to match the precision of data["dy"] for each element, after rounding each element of data["dy"] to 2 significant digits e.g. 26.5345 +/- 1.3456 --> 26.5 +/- 1.3 diff --git a/tests/test_submission.py b/tests/test_submission.py index 3fa0275a..f0c97014 100644 --- a/tests/test_submission.py +++ b/tests/test_submission.py @@ -41,7 +41,7 @@ def test_additional_resource_size(self): test_submission = Submission() self.addCleanup(os.remove, testpath) - # Check with non-existant file + # Check with non-existent file with self.assertRaises(RuntimeError): test_submission.add_additional_resource("Some description", testpath, copy_file=True) @@ -60,7 +60,7 @@ def test_additional_resource_size(self): with open(testpath, "wb") as testfile: testfile.write(bytes("\0" * size, "utf-8")) try: - test_submission.add_additional_resource("Some description", testpath, copy_file=True) + test_submission.add_additional_resource("Some description", testpath, copy_file=True, type="HistFactory") except RuntimeError: self.fail("Submission.add_additional_resource raised an unexpected RuntimeError.") From 21563175b1294b42c91d867075783ab8a7aa0c10 Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Fri, 13 Oct 2023 22:33:26 +0100 Subject: [PATCH 05/20] .gitignore: add files output by example notebooks --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 88cc61b4..b6e21337 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # output from examples examples/submission.tar.gz examples/example_output/ +examples/output/ +examples/correlation.root # test output submission.tar.gz From 2dbb58e6bab91e0d5bbadb4b877030eb064575ad Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Fri, 13 Oct 2023 22:36:40 +0100 Subject: [PATCH 06/20] .readthedocs.yml: install hepdata_lib package * Installation needed to build the module index. * Add "fail_on_warning: true" to avoid building broken docs. --- .readthedocs.yml | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index a36db8a1..0d9a16f7 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -5,19 +5,26 @@ # Required version: 2 -# Build documentation in the docs/ directory with Sphinx +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +# Build documentation in the "docs/" directory with Sphinx sphinx: configuration: docs/conf.py - -# Build documentation with MkDocs -#mkdocs: -# configuration: mkdocs.yml + # Fail on all warnings to avoid broken references + fail_on_warning: true # Optionally build your docs in additional formats such as PDF and ePub formats: all -# Optionally set the version of Python and requirements required to build your docs +# Optional but recommended, declare the Python requirements required +# to build your documentation +# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html python: - version: 3.7 install: - - requirements: docs/requirements.txt + - requirements: docs/requirements.txt + - method: pip + path: . \ No newline at end of file From 9ddc488f2357b0ed1678817dc9e0ffe7360b6992 Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Fri, 13 Oct 2023 22:42:36 +0100 Subject: [PATCH 07/20] README.md: fix links to Jupyter notebooks * Links to Jupyter notebooks previously broken on "Read the Docs". * Binder links need to be given on a separate line to work properly. * Add link to "Read the Docs" so it appears on main GitHub repo page. --- README.md | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 04be1da6..93d3d29d 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Library for getting your data into HEPData +- Documentation: https://hepdata-lib.readthedocs.io + ## Installation It is highly recommended you install `hepdata_lib` into a [virtual environment](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/). @@ -53,11 +55,25 @@ Unpacking the image can take a few minutes the first time you use it. Please be There are a few more examples available that can directly be run using the [binder](https://mybinder.org/) links below or using [SWAN](https://swan.cern.ch/) (CERN-only, please use LCG release LCG_94 or later) and selecting the corresponding notebook manually: -- [Reading in text files](examples/Getting_started.ipynb) [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/Getting_started.ipynb) -- [Reading in a CMS combine ntuple](examples/combine_limits.ipynb) [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/combine_limits.ipynb) -- [Reading in ROOT histograms](examples/reading_histograms.ipynb) [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/reading_histograms.ipynb) -- [Reading a correlation matrix](examples/correlation.ipynb) [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/correlation.ipynb) -- [Reading TGraph and TGraphError from '.C' files](examples/read_c_file.ipynb) [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/read_c_file.ipynb) +- [Reading in text files](https://github.com/HEPData/hepdata_lib/blob/master/examples/Getting_started.ipynb)\ +[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/Getting_started.ipynb) +

+ +- [Reading in a CMS combine ntuple](https://github.com/HEPData/hepdata_lib/blob/master/examples/combine_limits.ipynb)\ +[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/combine_limits.ipynb) +

+ +- [Reading in ROOT histograms](https://github.com/HEPData/hepdata_lib/blob/master/examples/reading_histograms.ipynb)\ +[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/reading_histograms.ipynb) +

+ +- [Reading a correlation matrix](https://github.com/HEPData/hepdata_lib/blob/master/examples/correlation.ipynb)\ +[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/correlation.ipynb) +

+ +- [Reading TGraph and TGraphError from '.C' files](https://github.com/HEPData/hepdata_lib/blob/master/examples/read_c_file.ipynb) +[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/read_c_file.ipynb) +

## External dependencies From 8f1a167603f424277ca2d31dc7da74a503e507ac Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Fri, 13 Oct 2023 22:49:40 +0100 Subject: [PATCH 08/20] setup.py: add extras_require w/ test requirements * Needed to install test dependencies with: pip install -e ".[test]" * Remove deprecated "setup_requires" and "tests_require". * Add Python v3.11 to "Classifiers". --- setup.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 259db6bb..f1d70ef2 100644 --- a/setup.py +++ b/setup.py @@ -33,18 +33,22 @@ 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', ], keywords='HEPData physics OpenData', packages=find_packages(exclude=['contrib', 'docs', 'tests']), zip_safe=False, python_requires='>=3.6', install_requires=DEPS, - setup_requires=['pytest-runner', 'pytest-cov'], - tests_require=[ - 'pytest', - 'papermill', - 'pylint==2.9.6', - ], + extras_require={ + 'test': [ + 'ipykernel', + 'papermill', + 'pylint==2.9.6', + 'pytest', + 'pytest-cov', + ] + }, project_urls={ 'Documentation': 'https://hepdata-lib.readthedocs.io', 'Bug Reports': 'https://github.com/HEPData/hepdata_lib/issues', From 1aea7b2577bf41e2be9ba1b5def28c1682eb53bb Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Sat, 14 Oct 2023 02:01:16 +0100 Subject: [PATCH 09/20] ci: remove Python v3.11 from test matrix * Python v3.11 incompatible with pylint v2.9.6 (installs wrapt v1.12.1). * Add upper pin python_requires='>=3.6,<3.11' in setup.py. * Use Python v3.10 in "Read the Docs" configuration file. --- .github/workflows/tests.yml | 6 ++---- .readthedocs.yml | 2 +- setup.py | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4cb366c8..38ed3913 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,12 +26,10 @@ jobs: matrix: os: [ubuntu-latest] root-version: ["6.24", "6.26", "6.28"] - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] exclude: - root-version: "6.24" python-version: "3.10" - - root-version: "6.24" - python-version: "3.11" - root-version: "6.26" python-version: "3.6" - root-version: "6.26" @@ -43,7 +41,7 @@ jobs: include: - os: macos-latest root-version: "6.28" - python-version: "3.11" + python-version: "3.10" steps: - uses: actions/checkout@v3 diff --git a/.readthedocs.yml b/.readthedocs.yml index 0d9a16f7..b52988e9 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -9,7 +9,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.11" + python: "3.10" # Build documentation in the "docs/" directory with Sphinx sphinx: diff --git a/setup.py b/setup.py index f1d70ef2..e645fd23 100644 --- a/setup.py +++ b/setup.py @@ -33,12 +33,11 @@ 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', ], keywords='HEPData physics OpenData', packages=find_packages(exclude=['contrib', 'docs', 'tests']), zip_safe=False, - python_requires='>=3.6', + python_requires='>=3.6,<3.11', install_requires=DEPS, extras_require={ 'test': [ From dfa0a899ea7ec6380ecd44af80cf4525969fe925 Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Sat, 14 Oct 2023 02:04:12 +0100 Subject: [PATCH 10/20] docs: add "Analysing the code" section on Pylint * Change "type" to "file_type" in argument of add_additional_resource. * Disable some messages from Pylint when run on my local installation. --- docs/dev.rst | 13 ++++++++++++- docs/usage.rst | 4 ++-- hepdata_lib/__init__.py | 8 ++++---- hepdata_lib/c_file_reader.py | 2 +- hepdata_lib/helpers.py | 2 +- tests/test_cfilereader.py | 2 +- tests/test_execute_command.py | 2 +- tests/test_helpers.py | 8 ++++---- tests/test_output.py | 2 +- tests/test_rootfilereader.py | 4 ++-- tests/test_submission.py | 5 +++-- tests/test_table.py | 2 +- tests/test_uncertainty.py | 2 +- tests/test_variable.py | 2 +- 14 files changed, 35 insertions(+), 23 deletions(-) diff --git a/docs/dev.rst b/docs/dev.rst index 39e4c2c0..7786a0f2 100644 --- a/docs/dev.rst +++ b/docs/dev.rst @@ -109,4 +109,15 @@ After installing the ``hepdata_lib`` package, move into the ``hepdata_lib/docs`` pip install -r requirements.txt -Then you can build the documentation locally with Sphinx using ``make html`` and view the output by opening a web browser at ``_build/html/index.html``. \ No newline at end of file +Then you can build the documentation locally with Sphinx using ``make html`` and view the output by opening a web browser at ``_build/html/index.html``. + + +Analysing the code +------------------ + +:: + + pylint hepdata_lib/*.py + pylint tests/*.py --rcfile=tests/pylintrc + +These commands are run by GitHub Actions, so you should first check locally that no issues are flagged. \ No newline at end of file diff --git a/docs/usage.rst b/docs/usage.rst index 13e2a1fa..46079fcc 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -123,11 +123,11 @@ Additional resources, hosted either externally or locally, can be linked with th sub.add_additional_resource("Web page with auxiliary material", "https://atlas.web.cern.ch/Atlas/GROUPS/PHYSICS/PAPERS/STDM-2012-02/") sub.add_additional_resource("Some file", "root_file.root", copy_file=True) - sub.add_additional_resource("Archive of full likelihoods in the HistFactory JSON format", "Likelihoods.tar.gz", copy_file=True, type="HistFactory") + sub.add_additional_resource("Archive of full likelihoods in the HistFactory JSON format", "Likelihoods.tar.gz", copy_file=True, file_type="HistFactory") The first argument is a ``description`` and the second is the ``location`` of the external link or local resource file. The optional argument ``copy_file=True`` (default value of ``False``) will copy a local file into the output directory. -The optional argument ``type="HistFactory"`` (default value of ``None``) can be used to identify statistical models provided in the HistFactory JSON +The optional argument ``file_type="HistFactory"`` (default value of ``None``) can be used to identify statistical models provided in the HistFactory JSON format rather than relying on certain trigger words in the ``description`` (see `pyhf section of submission documentation`_). The ``add_link`` function can alternatively be used to add a link to an external resource: diff --git a/hepdata_lib/__init__.py b/hepdata_lib/__init__.py index 3dfa17fe..3862e98c 100644 --- a/hepdata_lib/__init__.py +++ b/hepdata_lib/__init__.py @@ -55,7 +55,7 @@ def __init__(self): self.files_to_copy = [] self.additional_resources = [] - def add_additional_resource(self, description, location, copy_file=False, type=None): + def add_additional_resource(self, description, location, copy_file=False, file_type=None): """ Add any kind of additional resource. If copy_file is set to False, the location and description will be added as-is. @@ -78,7 +78,7 @@ def add_additional_resource(self, description, location, copy_file=False, type=N :param copy_file: If set to true, will attempt to copy a local file to the tar ball. :type copy_file: bool - :param type: Type of the resource file. Currently, only "HistFactory" has any effect. + :param file_type: Type of the resource file. Currently, only "HistFactory" has any effect. """ resource = {} @@ -91,8 +91,8 @@ def add_additional_resource(self, description, location, copy_file=False, type=N else: resource["location"] = location - if type: - resource["type"] = type + if file_type: + resource["type"] = file_type self.additional_resources.append(resource) diff --git a/hepdata_lib/c_file_reader.py b/hepdata_lib/c_file_reader.py index 5b43d044..98051616 100644 --- a/hepdata_lib/c_file_reader.py +++ b/hepdata_lib/c_file_reader.py @@ -1,6 +1,6 @@ """.C file reader""" import io -from array import array +from array import array # pylint: disable-msg=E0611 from future.utils import raise_from from ROOT import TGraph, TGraphErrors import hepdata_lib.root_utils as ru diff --git a/hepdata_lib/helpers.py b/hepdata_lib/helpers.py index 788fba04..f5f4fb30 100644 --- a/hepdata_lib/helpers.py +++ b/hepdata_lib/helpers.py @@ -68,7 +68,7 @@ def get_number_precision(value): if value == 0 or isinstance(value, str) or np.isnan(value) or np.isinf(value): return value - return math.ceil(math.log10(abs(value))) + return math.ceil(math.log10(abs(value))) # pylint: disable-msg=I1101 def relative_round(value, relative_digits): diff --git a/tests/test_cfilereader.py b/tests/test_cfilereader.py index a6660339..611d6a06 100644 --- a/tests/test_cfilereader.py +++ b/tests/test_cfilereader.py @@ -3,7 +3,7 @@ from unittest import TestCase import os import numpy as np -from hepdata_lib.c_file_reader import CFileReader +from hepdata_lib.c_file_reader import CFileReader # pylint: disable-msg=E0401 class TestCFileReader(TestCase): """Test the CFileReader class.""" diff --git a/tests/test_execute_command.py b/tests/test_execute_command.py index 739caf7d..a0dd48e1 100644 --- a/tests/test_execute_command.py +++ b/tests/test_execute_command.py @@ -1,7 +1,7 @@ # !/usr/bin/env python """Test execute_command() function.""" from unittest import TestCase -from hepdata_lib.helpers import execute_command +from hepdata_lib.helpers import execute_command # pylint: disable-msg=E0401 class TestExecuteCommand(TestCase): """Test execute_command() function.""" diff --git a/tests/test_helpers.py b/tests/test_helpers.py index d3857f71..43e3f9ff 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -4,10 +4,10 @@ import numpy as np -from hepdata_lib.helpers import relative_round -from hepdata_lib.helpers import get_number_precision -from hepdata_lib.helpers import get_value_precision_wrt_reference -from hepdata_lib.helpers import round_value_and_uncertainty +from hepdata_lib.helpers import relative_round # pylint: disable-msg=E0401 +from hepdata_lib.helpers import get_number_precision # pylint: disable-msg=E0401 +from hepdata_lib.helpers import get_value_precision_wrt_reference # pylint: disable-msg=E0401 +from hepdata_lib.helpers import round_value_and_uncertainty # pylint: disable-msg=E0401 class TestHelpers(TestCase): diff --git a/tests/test_output.py b/tests/test_output.py index 5a505189..80ecc87d 100644 --- a/tests/test_output.py +++ b/tests/test_output.py @@ -6,7 +6,7 @@ import os import yaml from test_utilities import tmp_directory_name -from hepdata_lib import Submission, Table, Variable +from hepdata_lib import Submission, Table, Variable # pylint: disable-msg=E0401 class TestOutput(TestCase): """Test output""" diff --git a/tests/test_rootfilereader.py b/tests/test_rootfilereader.py index aaf350b9..789e6bb6 100644 --- a/tests/test_rootfilereader.py +++ b/tests/test_rootfilereader.py @@ -1,13 +1,13 @@ #!/usr/bin/env python """Test RootFileReader.""" from unittest import TestCase -from array import array +from array import array # pylint: disable-msg=E0611 import os import ctypes import numpy as np import ROOT from test_utilities import float_compare, tuple_compare, histogram_compare_1d, make_tmp_root_file -from hepdata_lib.root_utils import RootFileReader +from hepdata_lib.root_utils import RootFileReader # pylint: disable-msg=E0401 class TestRootFileReader(TestCase): diff --git a/tests/test_submission.py b/tests/test_submission.py index f0c97014..e0af8f7c 100644 --- a/tests/test_submission.py +++ b/tests/test_submission.py @@ -6,7 +6,7 @@ from unittest import TestCase import tarfile from test_utilities import tmp_directory_name -from hepdata_lib import Submission, Table, Variable, Uncertainty +from hepdata_lib import Submission, Table, Variable, Uncertainty # pylint: disable-msg=E0401 class TestSubmission(TestCase): """Test the Submission class.""" @@ -60,7 +60,8 @@ def test_additional_resource_size(self): with open(testpath, "wb") as testfile: testfile.write(bytes("\0" * size, "utf-8")) try: - test_submission.add_additional_resource("Some description", testpath, copy_file=True, type="HistFactory") + test_submission.add_additional_resource("Some description", testpath, + copy_file=True, file_type="HistFactory") except RuntimeError: self.fail("Submission.add_additional_resource raised an unexpected RuntimeError.") diff --git a/tests/test_table.py b/tests/test_table.py index 31538c4a..eab60d92 100644 --- a/tests/test_table.py +++ b/tests/test_table.py @@ -5,7 +5,7 @@ from unittest import TestCase from test_utilities import tmp_directory_name -from hepdata_lib import Table, Variable, Uncertainty +from hepdata_lib import Table, Variable, Uncertainty # pylint: disable-msg=E0401 class TestTable(TestCase): """Test the Table class.""" diff --git a/tests/test_uncertainty.py b/tests/test_uncertainty.py index bb08e7b5..252c5002 100644 --- a/tests/test_uncertainty.py +++ b/tests/test_uncertainty.py @@ -3,7 +3,7 @@ import random from unittest import TestCase import test_utilities -from hepdata_lib import Variable, Uncertainty +from hepdata_lib import Variable, Uncertainty # pylint: disable-msg=E0401 class TestUncertainty(TestCase): diff --git a/tests/test_variable.py b/tests/test_variable.py index 0048ad8f..d4c26f73 100644 --- a/tests/test_variable.py +++ b/tests/test_variable.py @@ -3,7 +3,7 @@ import random from unittest import TestCase import test_utilities -from hepdata_lib import Variable, Uncertainty +from hepdata_lib import Variable, Uncertainty # pylint: disable-msg=E0401 class TestVariable(TestCase): From a57b92fbfa89a56daab8a6087f350312a81a5d1f Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Sat, 14 Oct 2023 03:22:42 +0100 Subject: [PATCH 11/20] hepdata_lib: add type of new "file_type" argument --- hepdata_lib/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hepdata_lib/__init__.py b/hepdata_lib/__init__.py index 3862e98c..7897b7c8 100644 --- a/hepdata_lib/__init__.py +++ b/hepdata_lib/__init__.py @@ -70,7 +70,7 @@ def add_additional_resource(self, description, location, copy_file=False, file_t submission object is called. :param description: Description of what the resource is. - :type description: string. + :type description: string :param location: Can be either a URL pointing to a web-based resource or a local file path. :type location: string @@ -79,6 +79,7 @@ def add_additional_resource(self, description, location, copy_file=False, file_t :type copy_file: bool :param file_type: Type of the resource file. Currently, only "HistFactory" has any effect. + :type file_type: string """ resource = {} From db2719528a9f89b7a1555abae09134a35b667b5c Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Sat, 14 Oct 2023 03:24:25 +0100 Subject: [PATCH 12/20] README.mb: fix Zenodo badge & give Python versions --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 93d3d29d..edf1a09d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # hepdata_lib -[![DOI](https://zenodo.org/badge/129248575.svg)](https://zenodo.org/badge/latestdoi/129248575) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1217998.svg)](https://doi.org/10.5281/zenodo.1217998) [![PyPI version](https://badge.fury.io/py/hepdata-lib.svg)](https://badge.fury.io/py/hepdata-lib) [![Actions Status](https://github.com/HEPData/hepdata_lib/workflows/tests/badge.svg)](https://github.com/HEPData/hepdata_lib/actions) [![Coverage Status](https://codecov.io/gh/HEPData/hepdata_lib/graph/badge.svg?branch=master)](https://codecov.io/gh/HEPData/hepdata_lib?branch=master) @@ -11,6 +11,8 @@ Library for getting your data into HEPData - Documentation: https://hepdata-lib.readthedocs.io +This code works with Python 3.6, 3.7, 3.8, 3.9 or 3.10. + ## Installation It is highly recommended you install `hepdata_lib` into a [virtual environment](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/). From c5f19dbe3e1726e7a19722467e66dce7c9834acc Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Sat, 14 Oct 2023 23:04:42 +0100 Subject: [PATCH 13/20] setup.py: remove upper bound on python_requires --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e645fd23..181c8f3e 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ keywords='HEPData physics OpenData', packages=find_packages(exclude=['contrib', 'docs', 'tests']), zip_safe=False, - python_requires='>=3.6,<3.11', + python_requires='>=3.6', install_requires=DEPS, extras_require={ 'test': [ From f4e311c09bcb0eb9963dd1b017d6848552735d48 Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Sat, 14 Oct 2023 23:06:27 +0100 Subject: [PATCH 14/20] docs: reinstate SSH URL for "git clone" * Also link to the GitHub docs for both HTTPS URLs and SSH URLs. --- docs/setup.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/setup.rst b/docs/setup.rst index e727aa52..ae7af7f9 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -42,12 +42,18 @@ Setup for developers The general comments about installing a python package (see :ref:`sec-setup-users`) apply here, too. Use a virtual environment (see :ref:`sec-setup-virtualenv`)! -If you would like to develop the code, you need to install the package from the up-to-date git repository rather than the stable release in pypi. To do this, you can use the pip `-e` syntax: +If you would like to develop the code, you need to install the package from the up-to-date `GitHub repository`_ rather than the stable release in PyPI. To do this, you can use the pip `-e` syntax. +The GitHub repository can be cloned using either an `HTTPS URL`_ or an `SSH URL`_. + +.. _GitHub repository: https://github.com/HEPData/hepdata_lib +.. _HTTPS URL: https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls +.. _SSH URL: https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-ssh-urls :: cd $SOMEPATH git clone https://github.com/HEPData/hepdata_lib.git + OR git clone git@github.com:HEPData/hepdata_lib.git workon myhepdata # activate virtual environment! pip install -e $SOMEPATH/hepdata_lib From 77cc768df2cf33a618b20a0bf9b26a18f2e92196 Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Sun, 15 Oct 2023 18:28:43 +0100 Subject: [PATCH 15/20] ci: add Python 3.11 for tests but skip pylint step * The pylint step can be added back in after #234 is resolved. --- .github/workflows/tests.yml | 8 +++++--- .readthedocs.yml | 2 +- README.md | 2 +- setup.py | 1 + 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 38ed3913..5b7cd3fa 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,10 +26,12 @@ jobs: matrix: os: [ubuntu-latest] root-version: ["6.24", "6.26", "6.28"] - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] + python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"] exclude: - root-version: "6.24" python-version: "3.10" + - root-version: "6.24" + python-version: "3.11" - root-version: "6.26" python-version: "3.6" - root-version: "6.26" @@ -41,7 +43,7 @@ jobs: include: - os: macos-latest root-version: "6.28" - python-version: "3.10" + python-version: "3.11" steps: - uses: actions/checkout@v3 @@ -108,7 +110,7 @@ jobs: path: examples/*.html - name: Run pylint - if: ${{ always() }} + if: ${{ always() && matrix.python-version != '3.11' }} run: | python -m pylint hepdata_lib/*.py python -m pylint tests/*.py --rcfile=tests/pylintrc diff --git a/.readthedocs.yml b/.readthedocs.yml index b52988e9..0d9a16f7 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -9,7 +9,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.10" + python: "3.11" # Build documentation in the "docs/" directory with Sphinx sphinx: diff --git a/README.md b/README.md index edf1a09d..f56f901e 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Library for getting your data into HEPData - Documentation: https://hepdata-lib.readthedocs.io -This code works with Python 3.6, 3.7, 3.8, 3.9 or 3.10. +This code works with Python 3.6, 3.7, 3.8, 3.9, 3.10 or 3.11. ## Installation diff --git a/setup.py b/setup.py index 181c8f3e..f1d70ef2 100644 --- a/setup.py +++ b/setup.py @@ -33,6 +33,7 @@ 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', ], keywords='HEPData physics OpenData', packages=find_packages(exclude=['contrib', 'docs', 'tests']), From 7d829b0dca78a00d7e486ee3332e98cc9d2a1085 Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Sun, 15 Oct 2023 18:34:33 +0100 Subject: [PATCH 16/20] Revert "ci: add Python 3.11 for tests but skip pylint step" This reverts commit 77cc768df2cf33a618b20a0bf9b26a18f2e92196. The "Run pytest" step of the CI also fails with Python 3.11. --- .github/workflows/tests.yml | 8 +++----- .readthedocs.yml | 2 +- README.md | 2 +- setup.py | 1 - 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5b7cd3fa..38ed3913 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,12 +26,10 @@ jobs: matrix: os: [ubuntu-latest] root-version: ["6.24", "6.26", "6.28"] - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] exclude: - root-version: "6.24" python-version: "3.10" - - root-version: "6.24" - python-version: "3.11" - root-version: "6.26" python-version: "3.6" - root-version: "6.26" @@ -43,7 +41,7 @@ jobs: include: - os: macos-latest root-version: "6.28" - python-version: "3.11" + python-version: "3.10" steps: - uses: actions/checkout@v3 @@ -110,7 +108,7 @@ jobs: path: examples/*.html - name: Run pylint - if: ${{ always() && matrix.python-version != '3.11' }} + if: ${{ always() }} run: | python -m pylint hepdata_lib/*.py python -m pylint tests/*.py --rcfile=tests/pylintrc diff --git a/.readthedocs.yml b/.readthedocs.yml index 0d9a16f7..b52988e9 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -9,7 +9,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.11" + python: "3.10" # Build documentation in the "docs/" directory with Sphinx sphinx: diff --git a/README.md b/README.md index f56f901e..edf1a09d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Library for getting your data into HEPData - Documentation: https://hepdata-lib.readthedocs.io -This code works with Python 3.6, 3.7, 3.8, 3.9, 3.10 or 3.11. +This code works with Python 3.6, 3.7, 3.8, 3.9 or 3.10. ## Installation diff --git a/setup.py b/setup.py index f1d70ef2..181c8f3e 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,6 @@ 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', ], keywords='HEPData physics OpenData', packages=find_packages(exclude=['contrib', 'docs', 'tests']), From f11eb352dce320847fa4ffd7b87ae49e1198785e Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Wed, 18 Oct 2023 12:47:12 +0100 Subject: [PATCH 17/20] ci/docs: rename master to main and improve docs * Renamed 'master' branch to 'main' as with other HEPData repositories. * Upgrade actions in GitHub Actions workflows to close Dependabot PRs. * Revert to an SSH URL for main "git clone" with HTTPS URL in text. * Remove recommendation to use virtualenv/virtualenvwrapper not 'venv'. --- .github/workflows/docker.yml | 8 ++--- .github/workflows/release.yml | 4 +-- .github/workflows/tests.yml | 10 +++--- README.md | 24 +++++++------- docs/contributing.rst | 8 ++--- docs/setup.rst | 59 +++++++++++++++++------------------ docs/usage.rst | 10 +++--- 7 files changed, 60 insertions(+), 63 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 409e3810..24e0a9b8 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -21,10 +21,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Log in to the Container registry - uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -32,12 +32,12 @@ jobs: - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - name: Build and push Docker image - uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + uses: docker/build-push-action@v5 with: context: . push: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1962953f..0878a6e5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,7 +53,7 @@ jobs: with: github_token: ${{ secrets.access_token }} tags: true - branch: master + branch: main # Action to build and publish distribution to PyPI and TestPyPI build-and-publish: @@ -147,6 +147,6 @@ jobs: # Close issue - name: Close Issue - uses: peter-evans/close-issue@v1 + uses: peter-evans/close-issue@v3 with: issue-number: ${{ github.event.issue.number }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 38ed3913..45a4e603 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,7 +4,7 @@ on: push: pull_request: branches: - - master + - main workflow_dispatch: # Needed for micromamba pickup @@ -17,11 +17,11 @@ jobs: # Setup the Python that the ROOT binary was built against runs-on: ${{ matrix.os }} - # On push events run the CI only on master by default, but run on any branch if the commit message contains '[ci all]' + # On push events run the CI only on main by default, but run on any branch if the commit message contains '[ci all]' if: >- github.event_name != 'push' - || (github.event_name == 'push' && github.ref == 'refs/heads/master') - || (github.event_name == 'push' && github.ref != 'refs/heads/master' && contains(github.event.head_commit.message, '[ci all]')) + || (github.event_name == 'push' && github.ref == 'refs/heads/main') + || (github.event_name == 'push' && github.ref != 'refs/heads/main' && contains(github.event.head_commit.message, '[ci all]')) strategy: matrix: os: [ubuntu-latest] @@ -44,7 +44,7 @@ jobs: python-version: "3.10" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Micromamba environment uses: mamba-org/provision-with-micromamba@v15 diff --git a/README.md b/README.md index edf1a09d..d8047a9b 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1217998.svg)](https://doi.org/10.5281/zenodo.1217998) [![PyPI version](https://badge.fury.io/py/hepdata-lib.svg)](https://badge.fury.io/py/hepdata-lib) [![Actions Status](https://github.com/HEPData/hepdata_lib/workflows/tests/badge.svg)](https://github.com/HEPData/hepdata_lib/actions) -[![Coverage Status](https://codecov.io/gh/HEPData/hepdata_lib/graph/badge.svg?branch=master)](https://codecov.io/gh/HEPData/hepdata_lib?branch=master) +[![Coverage Status](https://codecov.io/gh/HEPData/hepdata_lib/graph/badge.svg?branch=main)](https://codecov.io/gh/HEPData/hepdata_lib?branch=main) [![Documentation Status](https://readthedocs.org/projects/hepdata-lib/badge/)](http://hepdata-lib.readthedocs.io/) [![Docker image](https://github.com/HEPData/hepdata_lib/actions/workflows/docker.yml/badge.svg)](https://github.com/HEPData/hepdata_lib/pkgs/container/hepdata_lib) @@ -27,7 +27,7 @@ If you are not sure about your Python environment, please also see below how to For using `hepdata_lib`, you don't even need to install it, but can use the [binder](https://mybinder.org/) or [SWAN](https://swan.cern.ch/) (CERN-only) services using one of the buttons below and following the instructions in the notebook with name [Getting_started](examples/Getting_started.ipynb): -[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/Getting_started.ipynb) +[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/main?filepath=examples/Getting_started.ipynb) [![SWAN](https://swanserver.web.cern.ch/swanserver/images/badge_swan_white_150.png)](https://cern.ch/swanserver/cgi-bin/go/?projurl=https://github.com/HEPData/hepdata_lib.git) You can also use the Docker image: @@ -57,24 +57,24 @@ Unpacking the image can take a few minutes the first time you use it. Please be There are a few more examples available that can directly be run using the [binder](https://mybinder.org/) links below or using [SWAN](https://swan.cern.ch/) (CERN-only, please use LCG release LCG_94 or later) and selecting the corresponding notebook manually: -- [Reading in text files](https://github.com/HEPData/hepdata_lib/blob/master/examples/Getting_started.ipynb)\ -[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/Getting_started.ipynb) +- [Reading in text files](https://github.com/HEPData/hepdata_lib/blob/main/examples/Getting_started.ipynb)\ +[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/main?filepath=examples/Getting_started.ipynb)

-- [Reading in a CMS combine ntuple](https://github.com/HEPData/hepdata_lib/blob/master/examples/combine_limits.ipynb)\ -[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/combine_limits.ipynb) +- [Reading in a CMS combine ntuple](https://github.com/HEPData/hepdata_lib/blob/main/examples/combine_limits.ipynb)\ +[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/main?filepath=examples/combine_limits.ipynb)

-- [Reading in ROOT histograms](https://github.com/HEPData/hepdata_lib/blob/master/examples/reading_histograms.ipynb)\ -[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/reading_histograms.ipynb) +- [Reading in ROOT histograms](https://github.com/HEPData/hepdata_lib/blob/main/examples/reading_histograms.ipynb)\ +[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/main?filepath=examples/reading_histograms.ipynb)

-- [Reading a correlation matrix](https://github.com/HEPData/hepdata_lib/blob/master/examples/correlation.ipynb)\ -[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/correlation.ipynb) +- [Reading a correlation matrix](https://github.com/HEPData/hepdata_lib/blob/main/examples/correlation.ipynb)\ +[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/main?filepath=examples/correlation.ipynb)

-- [Reading TGraph and TGraphError from '.C' files](https://github.com/HEPData/hepdata_lib/blob/master/examples/read_c_file.ipynb) -[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/master?filepath=examples/read_c_file.ipynb) +- [Reading TGraph and TGraphError from '.C' files](https://github.com/HEPData/hepdata_lib/blob/main/examples/read_c_file.ipynb) +[![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/main?filepath=examples/read_c_file.ipynb)

## External dependencies diff --git a/docs/contributing.rst b/docs/contributing.rst index 3528c3dd..87b04015 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -13,7 +13,7 @@ Please see :ref:`sec-setup-developers` on how to set up the library for developm Using bumpversion ----------------------------- -bumpversion_ allows to update the library version consistently over all files. Please do not change the version manually, but use the following steps instead after a pull request has been merged into the ``master`` branch. Depending on the amount of changes, choose accordingly from: +bumpversion_ allows to update the library version consistently over all files. Please do not change the version manually, but use the following steps instead after a pull request has been merged into the ``main`` branch. Depending on the amount of changes, choose accordingly from: - ``patch`` = ``+0.0.1`` - ``minor`` = ``+0.1.0`` @@ -24,10 +24,10 @@ Execute the following commands: :: pip install --upgrade bumpversion - git checkout master + git checkout main git pull bumpversion patch # adjust accordingly - git push origin master --tags + git push origin main --tags The files in which the versions are updated as well as the current version can be found in the `.bumpversion.cfg`_. You need appropriate rights for the repository to be able to push the tag. @@ -65,7 +65,7 @@ You should then find the new version at `this location`_. You need to be a maint .. _bumpversion: https://github.com/peritus/bumpversion -.. _.bumpversion.cfg: https://github.com/HEPData/hepdata_lib/blob/master/.bumpversion.cfg +.. _.bumpversion.cfg: https://github.com/HEPData/hepdata_lib/blob/main/.bumpversion.cfg .. _PyPI: https://pypi.org .. _PyPI test server: https://test.pypi.org/project/hepdata_lib/ .. _this location: https://pypi.org/project/hepdata_lib/ diff --git a/docs/setup.rst b/docs/setup.rst index ae7af7f9..22b63d40 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -9,7 +9,7 @@ Setup for users With Python 3 locally available +++++++++++++++++++++++++++++++ -The library is available for installation as a pypi package and can be installed from the terminal with pip: +The library is available for installation as a PyPI package and can be installed from the terminal with ``pip``: :: @@ -42,22 +42,24 @@ Setup for developers The general comments about installing a python package (see :ref:`sec-setup-users`) apply here, too. Use a virtual environment (see :ref:`sec-setup-virtualenv`)! -If you would like to develop the code, you need to install the package from the up-to-date `GitHub repository`_ rather than the stable release in PyPI. To do this, you can use the pip `-e` syntax. -The GitHub repository can be cloned using either an `HTTPS URL`_ or an `SSH URL`_. - -.. _GitHub repository: https://github.com/HEPData/hepdata_lib -.. _HTTPS URL: https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls -.. _SSH URL: https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-ssh-urls +If you would like to develop the code, you need to install the package from the up-to-date `GitHub repository`_ rather than the stable release in PyPI. To do this, you can use the pip ``-e`` syntax. +The GitHub repository can be cloned using either an `HTTPS URL`_ (``git clone https://github.com/HEPData/hepdata_lib.git``) +or an `SSH URL`_: :: cd $SOMEPATH - git clone https://github.com/HEPData/hepdata_lib.git - OR git clone git@github.com:HEPData/hepdata_lib.git + git clone git@github.com:HEPData/hepdata_lib.git + cd $SOMEPATH/hepdata_lib - workon myhepdata # activate virtual environment! + python3 -m venv myhepdata + source myhepdata/bin/activate # activate virtual environment! pip install -e $SOMEPATH/hepdata_lib +.. _GitHub repository: https://github.com/HEPData/hepdata_lib +.. _HTTPS URL: https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls +.. _SSH URL: https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-ssh-urls + Any changes you now make in your local copy of the repository (editing files, checking out different branches...) will be picked up by the python installation in your virtual environment. @@ -68,45 +70,40 @@ Setting up a virtual environment The goal of a virtual environment is to have a clean python copy to work with for each of possibly many projects you work on. This makes it easy to keep track of which python packages you installed for what purpose and gives you a way of installing different versions of the package. -For documentation on how to set up and work with virtual environments, please check out the virtualenv_ and virtualenvwrapper_ packages. +For documentation on how to set up and work with virtual environments, please check out `Installing packages using pip and virtual environments`_. +The venv_ module has been provided in the standard Python library since Python 3.3, avoiding the need to install +separate virtualenv_ and virtualenvwrapper_ packages as was the case with earlier Python versions. -.. _virtualenv: https://pypi.org/project/virtualenv/ -.. _virtualenvwrapper: https://virtualenvwrapper.readthedocs.io/en/latest/ - -Once you have both of them setup, you can create a virtual environment to work in: +You can create a virtual environment to work in: :: - mkvirtualenv hepdata_pypi + python3 -m venv hepdata_pypi + source hepdata_pypi/bin/activate pip install hepdata_lib You can then have a second virtual environment for installing the development branch: :: - mkvirtualenv hepdata_git + python3 -m venv hepdata_pypi hepdata_git + source hepdata_git/bin/activate pip install -e $SOMEPATH/hepdata_lib -You can always activate the virtual environment in another shell by calling the workon command, which also allows you to easily switch between the two instances: +You can always activate the virtual environment in another shell by sourcing the relevant ``activate`` script, +which also allows you to easily switch between the two instances: :: - workon hepdata_pypi - python myscript.py # Execute script using pypi package - - - workon hepdata_git - python myscript.py # Execute script using development branch + source hepdata_pypi/bin/activate + python myscript.py # Execute script using pypi package -Alternatively, if you don't want to install the additional virtualenv_ and virtualenvwrapper_ packages, you can simply -use the venv_ module from the Python standard library. - -:: - - python3 -m venv env - source env/bin/activate +.. _`Installing packages using pip and virtual environments`: https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/ .. _venv: https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#creating-a-virtual-environment +.. _virtualenv: https://pypi.org/project/virtualenv/ +.. _virtualenvwrapper: https://virtualenvwrapper.readthedocs.io/en/latest/ + Setup on lxplus with CMSSW -------------------------- diff --git a/docs/usage.rst b/docs/usage.rst index 46079fcc..8d450e32 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -35,7 +35,7 @@ which loads column-wise data from plain-text files and returns it as a ``numpy.a A detailed example is available here_. For documentation on the `loadtxt` function, please refer the `numpy documentation`_. -.. _here: https://github.com/HEPData/hepdata_lib/blob/master/examples/Getting_started.ipynb +.. _here: https://github.com/HEPData/hepdata_lib/blob/main/examples/Getting_started.ipynb .. _numpy documentation: https://docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html @@ -76,7 +76,7 @@ For detailed descriptions of the extraction logic and returned data, please refe An `example notebook`_ shows how to read histograms from a ROOT file. -.. _example notebook: https://github.com/HEPData/hepdata_lib/blob/master/examples/reading_histograms.ipynb +.. _example notebook: https://github.com/HEPData/hepdata_lib/blob/main/examples/reading_histograms.ipynb .. _sec-usage-writing: @@ -251,7 +251,7 @@ Note that you can add as many dependent Variables as you would like, and that yo One common use case with more than one independent Variable is that of correlation matrices. A detailed example implementation of this case is `available here`_. -.. _available here: https://github.com/HEPData/hepdata_lib/blob/master/examples/correlation.ipynb +.. _available here: https://github.com/HEPData/hepdata_lib/blob/main/examples/correlation.ipynb Adding a plot thumb nail to a table ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -267,7 +267,7 @@ The library code then takes care of all the necessary steps, like converting the Adding resource links or files ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Additional resources, hosted either externally or locally, can be linked with the ``add_additional_resource`` function of the Table object, in the same way as for the Submission object. +In the same way as for the Submission object, additional resources, hosted either externally or locally, can be linked with the ``add_additional_resource`` function of the Table object. :: @@ -293,7 +293,7 @@ In this example, we specify that the observables shown in a table are acceptance Lists of recognized keywords are available from the hepdata documentation for `Observables`_, `Phrases`_, and `Particles`_. -.. _`examples`: https://github.com/HEPData/hepdata_lib/blob/master/examples/Getting_started.ipynb +.. _`examples`: https://github.com/HEPData/hepdata_lib/blob/main/examples/Getting_started.ipynb .. _`Observables`: https://hepdata-submission.readthedocs.io/en/latest/keywords/observables.html .. _`Phrases`: https://hepdata-submission.readthedocs.io/en/latest/keywords/phrases.html .. _`Particles`: https://hepdata-submission.readthedocs.io/en/latest/keywords/partlist.html From 0d77f11dad5560b99ffb7e3892ef283364da038c Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Wed, 18 Oct 2023 12:54:03 +0100 Subject: [PATCH 18/20] pylint: remove 'disable-msg' and fix imports * Remove 'disable-msg' comments introduced in commit dfa0a899ea7ec6380ecd44af80cf4525969fe925. * Add empty "__init__.py" file to tests/ directory. * Add 'math' and 'array' modules to extension-pkg-whitelist in pylintrc. * test_utilities.py needs to be a relative import after hepdata_lib. * With these changes, pylint now gives 10.00/10 on my local setup. --- hepdata_lib/c_file_reader.py | 2 +- hepdata_lib/helpers.py | 2 +- pylintrc | 2 +- tests/__init__.py | 1 + tests/pylintrc | 2 +- tests/test_cfilereader.py | 2 +- tests/test_execute_command.py | 2 +- tests/test_helpers.py | 8 ++++---- tests/test_output.py | 4 ++-- tests/test_rootfilereader.py | 6 +++--- tests/test_submission.py | 4 ++-- tests/test_table.py | 4 ++-- tests/test_uncertainty.py | 14 +++++++------- tests/test_variable.py | 8 ++++---- 14 files changed, 31 insertions(+), 30 deletions(-) create mode 100644 tests/__init__.py diff --git a/hepdata_lib/c_file_reader.py b/hepdata_lib/c_file_reader.py index 98051616..5b43d044 100644 --- a/hepdata_lib/c_file_reader.py +++ b/hepdata_lib/c_file_reader.py @@ -1,6 +1,6 @@ """.C file reader""" import io -from array import array # pylint: disable-msg=E0611 +from array import array from future.utils import raise_from from ROOT import TGraph, TGraphErrors import hepdata_lib.root_utils as ru diff --git a/hepdata_lib/helpers.py b/hepdata_lib/helpers.py index f5f4fb30..788fba04 100644 --- a/hepdata_lib/helpers.py +++ b/hepdata_lib/helpers.py @@ -68,7 +68,7 @@ def get_number_precision(value): if value == 0 or isinstance(value, str) or np.isnan(value) or np.isinf(value): return value - return math.ceil(math.log10(abs(value))) # pylint: disable-msg=I1101 + return math.ceil(math.log10(abs(value))) def relative_round(value, relative_digits): diff --git a/pylintrc b/pylintrc index dc2928b6..5692e40a 100644 --- a/pylintrc +++ b/pylintrc @@ -3,7 +3,7 @@ # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code -extension-pkg-whitelist= +extension-pkg-whitelist=math,array # Add files or directories to the blacklist. They should be base names, not # paths. diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..0223698f --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""hepdata_lib tests""" diff --git a/tests/pylintrc b/tests/pylintrc index 103ef0bd..de04717a 100644 --- a/tests/pylintrc +++ b/tests/pylintrc @@ -3,7 +3,7 @@ # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code -extension-pkg-whitelist= +extension-pkg-whitelist=array # Add files or directories to the blacklist. They should be base names, not # paths. diff --git a/tests/test_cfilereader.py b/tests/test_cfilereader.py index 611d6a06..a6660339 100644 --- a/tests/test_cfilereader.py +++ b/tests/test_cfilereader.py @@ -3,7 +3,7 @@ from unittest import TestCase import os import numpy as np -from hepdata_lib.c_file_reader import CFileReader # pylint: disable-msg=E0401 +from hepdata_lib.c_file_reader import CFileReader class TestCFileReader(TestCase): """Test the CFileReader class.""" diff --git a/tests/test_execute_command.py b/tests/test_execute_command.py index a0dd48e1..739caf7d 100644 --- a/tests/test_execute_command.py +++ b/tests/test_execute_command.py @@ -1,7 +1,7 @@ # !/usr/bin/env python """Test execute_command() function.""" from unittest import TestCase -from hepdata_lib.helpers import execute_command # pylint: disable-msg=E0401 +from hepdata_lib.helpers import execute_command class TestExecuteCommand(TestCase): """Test execute_command() function.""" diff --git a/tests/test_helpers.py b/tests/test_helpers.py index 43e3f9ff..d3857f71 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -4,10 +4,10 @@ import numpy as np -from hepdata_lib.helpers import relative_round # pylint: disable-msg=E0401 -from hepdata_lib.helpers import get_number_precision # pylint: disable-msg=E0401 -from hepdata_lib.helpers import get_value_precision_wrt_reference # pylint: disable-msg=E0401 -from hepdata_lib.helpers import round_value_and_uncertainty # pylint: disable-msg=E0401 +from hepdata_lib.helpers import relative_round +from hepdata_lib.helpers import get_number_precision +from hepdata_lib.helpers import get_value_precision_wrt_reference +from hepdata_lib.helpers import round_value_and_uncertainty class TestHelpers(TestCase): diff --git a/tests/test_output.py b/tests/test_output.py index 80ecc87d..37eec651 100644 --- a/tests/test_output.py +++ b/tests/test_output.py @@ -5,8 +5,8 @@ import shutil import os import yaml -from test_utilities import tmp_directory_name -from hepdata_lib import Submission, Table, Variable # pylint: disable-msg=E0401 +from hepdata_lib import Submission, Table, Variable +from .test_utilities import tmp_directory_name class TestOutput(TestCase): """Test output""" diff --git a/tests/test_rootfilereader.py b/tests/test_rootfilereader.py index 789e6bb6..7ede5f49 100644 --- a/tests/test_rootfilereader.py +++ b/tests/test_rootfilereader.py @@ -1,13 +1,13 @@ #!/usr/bin/env python """Test RootFileReader.""" from unittest import TestCase -from array import array # pylint: disable-msg=E0611 +from array import array import os import ctypes import numpy as np import ROOT -from test_utilities import float_compare, tuple_compare, histogram_compare_1d, make_tmp_root_file -from hepdata_lib.root_utils import RootFileReader # pylint: disable-msg=E0401 +from hepdata_lib.root_utils import RootFileReader +from .test_utilities import float_compare, tuple_compare, histogram_compare_1d, make_tmp_root_file class TestRootFileReader(TestCase): diff --git a/tests/test_submission.py b/tests/test_submission.py index e0af8f7c..f86b05be 100644 --- a/tests/test_submission.py +++ b/tests/test_submission.py @@ -5,8 +5,8 @@ import string from unittest import TestCase import tarfile -from test_utilities import tmp_directory_name -from hepdata_lib import Submission, Table, Variable, Uncertainty # pylint: disable-msg=E0401 +from hepdata_lib import Submission, Table, Variable, Uncertainty +from .test_utilities import tmp_directory_name class TestSubmission(TestCase): """Test the Submission class.""" diff --git a/tests/test_table.py b/tests/test_table.py index eab60d92..6989c7c7 100644 --- a/tests/test_table.py +++ b/tests/test_table.py @@ -4,8 +4,8 @@ import shutil from unittest import TestCase -from test_utilities import tmp_directory_name -from hepdata_lib import Table, Variable, Uncertainty # pylint: disable-msg=E0401 +from hepdata_lib import Table, Variable, Uncertainty +from .test_utilities import tmp_directory_name class TestTable(TestCase): """Test the Table class.""" diff --git a/tests/test_uncertainty.py b/tests/test_uncertainty.py index 252c5002..3dd70a12 100644 --- a/tests/test_uncertainty.py +++ b/tests/test_uncertainty.py @@ -2,8 +2,8 @@ """Test Uncertainty.""" import random from unittest import TestCase -import test_utilities -from hepdata_lib import Variable, Uncertainty # pylint: disable-msg=E0401 +from hepdata_lib import Variable, Uncertainty +from .test_utilities import float_compare, tuple_compare class TestUncertainty(TestCase): @@ -32,16 +32,16 @@ def test_scale_values(self): testvar.scale_values(factor) scaled_values = [factor * x for x in values] scaled_uncertainty = [factor * x for x in uncertainty] - self.assertTrue(all(test_utilities.float_compare(x, y) + self.assertTrue(all(float_compare(x, y) for x, y in zip(testvar.values, scaled_values))) - self.assertTrue(all(test_utilities.float_compare(x, y) + self.assertTrue(all(float_compare(x, y) for x, y in zip(testunc.values, scaled_uncertainty))) # Check that inverse also works testvar.scale_values(1. / factor) - self.assertTrue(all(test_utilities.float_compare(x, y) + self.assertTrue(all(float_compare(x, y) for x, y in zip(testvar.values, values))) - self.assertTrue(all(test_utilities.float_compare(x, y) + self.assertTrue(all(float_compare(x, y) for x, y in zip(testunc.values, uncertainty))) def test_set_values_from_intervals(self): @@ -68,7 +68,7 @@ def test_set_values_from_intervals(self): testunc.set_values_from_intervals(intervals, nominal=values) # Check that both agree - self.assertTrue(all((test_utilities.tuple_compare(tup1, tup2) + self.assertTrue(all((tuple_compare(tup1, tup2) for tup1, tup2 in zip(testunc.values, refunc.values)))) def test_mixed_uncertainties(self): diff --git a/tests/test_variable.py b/tests/test_variable.py index d4c26f73..db73d1b9 100644 --- a/tests/test_variable.py +++ b/tests/test_variable.py @@ -2,8 +2,8 @@ """Test Variable.""" import random from unittest import TestCase -import test_utilities -from hepdata_lib import Variable, Uncertainty # pylint: disable-msg=E0401 +from hepdata_lib import Variable, Uncertainty +from .test_utilities import tuple_compare class TestVariable(TestCase): @@ -23,12 +23,12 @@ def test_scale_values(self): # Check that scaling works testvar.scale_values(factor) scaled_values = [(factor * x[0], factor * x[1]) for x in values] - assert(all(test_utilities.tuple_compare(x, y) + assert(all(tuple_compare(x, y) for x, y in zip(testvar.values, scaled_values))) # Check that inverse also works testvar.scale_values(1. / factor) - self.assertTrue(all(test_utilities.tuple_compare(x, y) + self.assertTrue(all(tuple_compare(x, y) for x, y in zip(testvar.values, values))) def test_add_uncertainty(self): From 497d462f2639f1b96ae1d35e0432cdbe824e1726 Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Thu, 19 Oct 2023 12:25:14 +0100 Subject: [PATCH 19/20] docs: tweak "Further examples" etc. * Tweak "Further examples" so Binder on same line as text on GitHub. * Remove pin on docutils==0.19, as not needed in recent Sphinx versions. * Fix a copy-and-paste typo in setup.rst. --- README.md | 12 ++++-------- docs/requirements.txt | 1 - docs/setup.rst | 2 +- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index d8047a9b..ce20b896 100644 --- a/README.md +++ b/README.md @@ -57,22 +57,18 @@ Unpacking the image can take a few minutes the first time you use it. Please be There are a few more examples available that can directly be run using the [binder](https://mybinder.org/) links below or using [SWAN](https://swan.cern.ch/) (CERN-only, please use LCG release LCG_94 or later) and selecting the corresponding notebook manually: -- [Reading in text files](https://github.com/HEPData/hepdata_lib/blob/main/examples/Getting_started.ipynb)\ +- [Reading in text files](https://github.com/HEPData/hepdata_lib/blob/main/examples/Getting_started.ipynb) [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/main?filepath=examples/Getting_started.ipynb)

- -- [Reading in a CMS combine ntuple](https://github.com/HEPData/hepdata_lib/blob/main/examples/combine_limits.ipynb)\ +- [Reading in a CMS combine ntuple](https://github.com/HEPData/hepdata_lib/blob/main/examples/combine_limits.ipynb) [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/main?filepath=examples/combine_limits.ipynb)

- -- [Reading in ROOT histograms](https://github.com/HEPData/hepdata_lib/blob/main/examples/reading_histograms.ipynb)\ +- [Reading in ROOT histograms](https://github.com/HEPData/hepdata_lib/blob/main/examples/reading_histograms.ipynb) [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/main?filepath=examples/reading_histograms.ipynb)

- -- [Reading a correlation matrix](https://github.com/HEPData/hepdata_lib/blob/main/examples/correlation.ipynb)\ +- [Reading a correlation matrix](https://github.com/HEPData/hepdata_lib/blob/main/examples/correlation.ipynb) [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/main?filepath=examples/correlation.ipynb)

- - [Reading TGraph and TGraphError from '.C' files](https://github.com/HEPData/hepdata_lib/blob/main/examples/read_c_file.ipynb) [![Binder](https://mybinder.org/badge.svg)](https://mybinder.org/v2/gh/HEPData/hepdata_lib/main?filepath=examples/read_c_file.ipynb)

diff --git a/docs/requirements.txt b/docs/requirements.txt index d522aaac..56ffd984 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,3 @@ Sphinx<7 sphinx_rtd_theme -docutils==0.19 sphinx-mdinclude \ No newline at end of file diff --git a/docs/setup.rst b/docs/setup.rst index 22b63d40..d02ca994 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -86,7 +86,7 @@ You can then have a second virtual environment for installing the development br :: - python3 -m venv hepdata_pypi hepdata_git + python3 -m venv hepdata_git source hepdata_git/bin/activate pip install -e $SOMEPATH/hepdata_lib From 8b318b3662fae0561a6a941382958974de64a466 Mon Sep 17 00:00:00 2001 From: Graeme Watt Date: Fri, 20 Oct 2023 15:34:18 +0100 Subject: [PATCH 20/20] docs: correct link to Python venv module --- docs/setup.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/setup.rst b/docs/setup.rst index d02ca994..9c4564f9 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -100,7 +100,7 @@ which also allows you to easily switch between the two instances: .. _`Installing packages using pip and virtual environments`: https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/ -.. _venv: https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#creating-a-virtual-environment +.. _venv: https://docs.python.org/3/library/venv.html .. _virtualenv: https://pypi.org/project/virtualenv/ .. _virtualenvwrapper: https://virtualenvwrapper.readthedocs.io/en/latest/