From 07397bf5977d8862692d853319e505f803076c33 Mon Sep 17 00:00:00 2001 From: Wolfgang Waltenberger Date: Thu, 24 Oct 2024 13:36:29 +0200 Subject: [PATCH 01/14] ignore pyhf deprecationwarnings --- unittests/testRFails.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/unittests/testRFails.py b/unittests/testRFails.py index 59f490b9c..1f2936d46 100755 --- a/unittests/testRFails.py +++ b/unittests/testRFails.py @@ -9,6 +9,7 @@ """ +import warnings import sys import os sys.path.insert(0, "../") @@ -34,7 +35,7 @@ def removeOutputs(self, f): os.remove(fname) def testRFailPrinters(self): - + warnings.filterwarnings( action='ignore', category=DeprecationWarning ) filename = "./testFiles/rfails/mdm_r_fails.slha" from smodels.statistics import pyhfInterface @@ -93,7 +94,7 @@ def testRFailPrinters(self): self.removeOutputs(outputfile) def testRFailSummary(self): - + warnings.filterwarnings( action='ignore', category=DeprecationWarning ) out = "./unitTestOutput" dirname = "./testFiles/rfails/" from smodels.statistics import pyhfInterface From 6ebcc3bc1dc79a6c3f91ed4789ecf6aff43a080d Mon Sep 17 00:00:00 2001 From: Wolfgang Waltenberger Date: Tue, 29 Oct 2024 13:23:55 +0100 Subject: [PATCH 02/14] starting with configurable pyhf backend --- smodels/statistics/pyhfInterface.py | 51 ++++++++++++++++------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/smodels/statistics/pyhfInterface.py b/smodels/statistics/pyhfInterface.py index 11c7c8c4e..91560b509 100755 --- a/smodels/statistics/pyhfInterface.py +++ b/smodels/statistics/pyhfInterface.py @@ -18,7 +18,8 @@ from smodels.base.smodelsLogging import logger import logging logging.getLogger("pyhf").setLevel(logging.CRITICAL) -warnings.filterwarnings("ignore") +# warnings.filterwarnings("ignore") +warnings.filterwarnings("ignore", r"invalid value encountered in log") from typing import Dict, List jsonver = "" @@ -48,35 +49,41 @@ sys.exit(-1) ver = pyhf.__version__.split(".") -if ver[1] == "4" or (ver[1] == "5" and ver[2] in ["0", "1"]): - print("[SModelS:pyhfInterface] WARNING you are using pyhf v%s." % pyhf.__version__) - print("[SModelS:pyhfInterface] We recommend pyhf >= 0.5.2. Please try to update pyhf ASAP!") pyhfinfo = { "backend": "numpy", "hasgreeted": False, - "backendver": "?", + "backendver": np.version.full_version, "ver": ver, - "required": "0.6.1".split("."), + "required": "0.6.1".split("."), # the required pyhf version } -try: - pyhf.set_backend(b"pytorch") - import torch - - pyhfinfo["backend"] = "pytorch" - pyhfinfo["backendver"] = torch.__version__ - -except pyhf.exceptions.ImportBackendError as e: - print( - "[SModelS:pyhfInterface] WARNING could not set pytorch as the pyhf backend, falling back to the default." - ) - print("[SModelS:pyhfInterface] We however recommend that pytorch be installed.") - import numpy - - pyhfinfo["backendver"] = numpy.version.full_version +if ver[1] == "4" or (ver[1] == "5" and ver[2] in ["0", "1"]): + print(f"[SModelS:pyhfInterface] WARNING you are using pyhf v{pyhf.__version__}" ) + print(f"[SModelS:pyhfInterface] We recommend pyhf >= {'.'.join(required)}. Please try to update pyhf ASAP!") - warnings.filterwarnings("ignore", r"invalid value encountered in log") +def setBackend ( backend : str ) -> bool: + """ try to setup backend to + :param backend: one of: numpy, pytorch, jax, tensorflow + :returns: True, if worked, False if failed + """ + try: + pyhf.set_backend( backend ) + pyhfinfo["backend"] = backend + pyhfinfo["backendver"] = "?" + module_name = backend + if backend == "pytorch": + module_name = "torch" + from importlib.metadata import version + pyhfinfo["backendver"] = version(module_name) + return True + except (pyhf.exceptions.ImportBackendError,pyhf.exceptions.InvalidBackend) as e: + print( f"[SModelS:pyhfInterface] WARNING could not set {backend} as the pyhf backend: {e}" ) + print( f"[SModelS:pyhfInterface] falling back to {pyhfinfo['backend']}." ) + # print("[SModelS:pyhfInterface] We however recommend that pytorch be installed.") + return False + +# setBackend ( "pytorch" ) countWarning = {"llhdszero": 0} # Sets the maximum number of attempts for determining the brent bracketing interval for mu: From 6b409dcf5ce229508714c7567d16d7d9d8e848d7 Mon Sep 17 00:00:00 2001 From: Wolfgang Waltenberger Date: Tue, 29 Oct 2024 16:30:02 +0100 Subject: [PATCH 03/14] cleaning up unittests --- smodels/statistics/pyhfInterface.py | 24 +++++++++++------------- unittests/testPyhf.py | 4 ++++ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/smodels/statistics/pyhfInterface.py b/smodels/statistics/pyhfInterface.py index 91560b509..024ffa1f6 100755 --- a/smodels/statistics/pyhfInterface.py +++ b/smodels/statistics/pyhfInterface.py @@ -12,6 +12,7 @@ import jsonpatch import warnings import jsonschema +import semver import copy from scipy import optimize import numpy as np @@ -26,18 +27,15 @@ try: import importlib.metadata - jsonver = importlib.metadata.version("jsonschema") + jsonver = semver.parse_version_info(importlib.metadata.version("jsonschema")) except Exception as e: try: from jsonschema import __version__ as jsonver except Exception as e: pass -if jsonver[0] == "2": +if jsonver.major < 3: # if jsonschema.__version__[0] == "2": ## deprecated - print( - "[SModelS:pyhfInterface] jsonschema is version %s, we need > 3.x.x" - % (jsonschema.__version__) - ) + print( f"[SModelS:pyhfInterface] jsonschema is version {jsonschema.__version__}, we need > 3.x.x" ) sys.exit() import time, sys, os @@ -48,19 +46,19 @@ print("[SModelS:pyhfInterface] pyhf import failed. Is the module installed?") sys.exit(-1) -ver = pyhf.__version__.split(".") +ver = semver.parse_version_info(pyhf.__version__) pyhfinfo = { "backend": "numpy", "hasgreeted": False, "backendver": np.version.full_version, "ver": ver, - "required": "0.6.1".split("."), # the required pyhf version + "required": semver.parse_version_info("0.6.1"), # the required pyhf version } -if ver[1] == "4" or (ver[1] == "5" and ver[2] in ["0", "1"]): - print(f"[SModelS:pyhfInterface] WARNING you are using pyhf v{pyhf.__version__}" ) - print(f"[SModelS:pyhfInterface] We recommend pyhf >= {'.'.join(required)}. Please try to update pyhf ASAP!") +if ver < pyhfinfo["required"]: + print(f"[SModelS:pyhfInterface] WARNING you are using pyhf v{str(ver)}" ) + print(f"[SModelS:pyhfInterface] We recommend pyhf >= {str(required)}. Please try to update pyhf ASAP!") def setBackend ( backend : str ) -> bool: """ try to setup backend to @@ -407,7 +405,7 @@ def welcome(self): if pyhfinfo["hasgreeted"]: return logger.info( - f"Pyhf interface, we are using v{'.'.join(pyhfinfo['ver'])}, with {pyhfinfo['backend']} v{pyhfinfo['backendver']} as backend." + f"Pyhf interface, we are using v{str(pyhfinfo['ver'])}, with {pyhfinfo['backend']} v{str(pyhfinfo['backendver'])} as backend." ) pyhfinfo["hasgreeted"] = True @@ -418,7 +416,7 @@ def checkPyhfVersion(self): if pyhfinfo["ver"] < pyhfinfo["required"]: logger.warning( - f"pyhf version is {'.'.join(pyhfinfo['ver'])}. SModelS currently requires pyhf>={'.'.join(pyhfinfo['required'])}. You have been warned." + f"pyhf version is {str(pyhfinfo['ver'])}. SModelS currently requires pyhf>={str(pyhfinfo['required'])}. You have been warned." ) def rescale(self, factor): diff --git a/unittests/testPyhf.py b/unittests/testPyhf.py index 61ced8fee..105aeb583 100755 --- a/unittests/testPyhf.py +++ b/unittests/testPyhf.py @@ -60,6 +60,7 @@ def testCorruptJson1Signal(self): Tests how the module handles corrupted json files Maybe it is needed to test different types of corruptions """ + warnings.filterwarnings("ignore", category=DeprecationWarning) from smodels.base.smodelsLogging import setLogLevel setLogLevel("fatal") #Defining the channels @@ -135,6 +136,7 @@ def testCorruptJson2Signal(self): Tests how the module handles corrupted json files Maybe it is needed to test different types of corruptions """ + warnings.filterwarnings("ignore", category=DeprecationWarning) #Defining the channels modifiers = [] modifiers.append(dict(data=None, @@ -261,6 +263,7 @@ def testFullPyhfModule1(self): """ Computes the UL using the pyhfInterface module and checks if, outside of the module, this UL still gives a 95% CLs """ + warnings.filterwarnings("ignore", category=DeprecationWarning) bkg = self.simpleJson([0.8], [10]) signals = [ 0.4 ] # Make the patch by hand @@ -314,6 +317,7 @@ def testFullPyhfModule2(self): """ Same as previous but with two SRs """ + warnings.filterwarnings("ignore", category=DeprecationWarning) bkg = self.simpleJson([0.8, 0.9], [10, 11]) signals = [0.4, 0.2] # Make the patch by hand From e1939cfac146e708e9e1d3be9709324281db7837 Mon Sep 17 00:00:00 2001 From: Wolfgang Waltenberger Date: Tue, 29 Oct 2024 17:18:17 +0100 Subject: [PATCH 04/14] pyhfbackend definable --- parameters.ini | 1 + smodels/matching/modelTester.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/parameters.ini b/parameters.ini index 7f1e94b2d..b5f1eea4f 100644 --- a/parameters.ini +++ b/parameters.ini @@ -7,6 +7,7 @@ testCoverage = True ;Set True if topologies not covered by experiments (missing computeStatistics = True ;Set True to compute the likelihoods L_BSM, L_SM and L_max for EM-type results. combineSRs = True ;Set True to combine signal regions when covariance matrix or pyhf JSON likelihood is available. Caution, increases runtime! False uses only best SR (faster). #combineAnas = ATLAS-SUSY-2019-08,ATLAS-SUSY-2019-09 ; list of statistically independent analyses to combine. Works for EM-type results only. Use with care! +pyhfbackend = numpy ; This allows you to change the pyhf backend used. Possible values are pytorch, tensorflow, jax reportAllSRs = False ;Set True to report all signal regions, instead of best signal region only. experimentalFeatures = False ;Set True to enable experimental features that are not yet considered part of SModelS proper. Use only if you know what you are doing!! diff --git a/smodels/matching/modelTester.py b/smodels/matching/modelTester.py index 272eb34c7..c3c33c4bd 100644 --- a/smodels/matching/modelTester.py +++ b/smodels/matching/modelTester.py @@ -535,6 +535,12 @@ def getParameters(parameterFile): runtime.modelFile = parser.get("particles", "model") except: pass + try: + pyhfbackend = parser.get("options","pyhfbackend") + from smodels.statistics import pyhfInterface + r = pyhfInterface.setBackend ( pyhfbackend ) + except: + pass return parser From 53543747392adf2d51b52ef3b7c1d02fd7f79407 Mon Sep 17 00:00:00 2001 From: Wolfgang Waltenberger Date: Tue, 29 Oct 2024 17:20:07 +0100 Subject: [PATCH 05/14] configurable backends --- docs/manual/source/RunningSModelS.rst | 2 ++ parameters.ini | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/manual/source/RunningSModelS.rst b/docs/manual/source/RunningSModelS.rst index 9ed7f792d..9a56d39b8 100644 --- a/docs/manual/source/RunningSModelS.rst +++ b/docs/manual/source/RunningSModelS.rst @@ -138,6 +138,8 @@ Below we give more detailed information about each entry in the parameters file. * **combineSRs** (True/False): set to True to combine signal regions in |EMrs| when covariance matrix or pyhf JSON likelihood is available. Set to False to use only the most sensitive signal region (faster!). Available v1.1.3 onwards for covariance matrices and v1.2.4 onwards for full likelihoods (using pyhf). + * **pyhfbackend**: set to name of pyhf backend. Possible values are: numpy (default), pytorch, tensorflow, jax + .. _parameterFileReportAllSRs: * **reportAllSRs** (True/False): set to True to report all signal regions, instead of the best signal region only. From v3.0.0 onwards it will also include the combined SRs if combineSRs=True. Beware, the output can be long. diff --git a/parameters.ini b/parameters.ini index b5f1eea4f..b748b919c 100644 --- a/parameters.ini +++ b/parameters.ini @@ -7,7 +7,7 @@ testCoverage = True ;Set True if topologies not covered by experiments (missing computeStatistics = True ;Set True to compute the likelihoods L_BSM, L_SM and L_max for EM-type results. combineSRs = True ;Set True to combine signal regions when covariance matrix or pyhf JSON likelihood is available. Caution, increases runtime! False uses only best SR (faster). #combineAnas = ATLAS-SUSY-2019-08,ATLAS-SUSY-2019-09 ; list of statistically independent analyses to combine. Works for EM-type results only. Use with care! -pyhfbackend = numpy ; This allows you to change the pyhf backend used. Possible values are pytorch, tensorflow, jax +pyhfbackend = numpy ; This allows you to change the pyhf backend used. Possible values are numpy (default), pytorch, tensorflow, jax reportAllSRs = False ;Set True to report all signal regions, instead of best signal region only. experimentalFeatures = False ;Set True to enable experimental features that are not yet considered part of SModelS proper. Use only if you know what you are doing!! From b660fced63580bd0c3d090c386807d5bffa9e758 Mon Sep 17 00:00:00 2001 From: Wolfgang Waltenberger Date: Tue, 29 Oct 2024 17:56:36 +0100 Subject: [PATCH 06/14] finished docs --- ReleaseNotes | 1 + docs/manual/source/Installation.rst | 1 + docs/manual/source/ReleaseUpdate.rst | 1 + docs/manual/source/RunningSModelS.rst | 2 ++ smodels/statistics/pyhfInterface.py | 6 ++++-- 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ReleaseNotes b/ReleaseNotes index d0e9b88e2..b00f77d36 100644 --- a/ReleaseNotes +++ b/ReleaseNotes @@ -1,6 +1,7 @@ Release v3.0.1, Thu 24 Oct 2024 ======================================================= + * Made the pyhf backend configurable, defaulting to numpy * Bug fix for printing signal region combination results * New cluster algorithm (simpler and more stable) diff --git a/docs/manual/source/Installation.rst b/docs/manual/source/Installation.rst index 9fff36c1b..f9c95f3ed 100644 --- a/docs/manual/source/Installation.rst +++ b/docs/manual/source/Installation.rst @@ -19,6 +19,7 @@ SModelS is a Python library that requires Python version 3.6 or later. It depend .. include:: dependencies.rst +For the pyhf backend, either one of pytorch, tensorflow, and jax can be used alternatively to the default numpy. In this case, the corresponding python module needs to be installed, and the :ref:`pyhfbackend ` option needs to be configured accordingly (or a direct call of `pyhfInterface.setBackend `_ in case of python code) For performance reasons, we moreover recommend pytorch>=1.8.0 as backend for pyhf. This is, however, optional: if pytorch is not available, SModelS will use the default backend. In addition, the :ref:`cross section computers ` provided by :ref:`smodelsTools.py ` diff --git a/docs/manual/source/ReleaseUpdate.rst b/docs/manual/source/ReleaseUpdate.rst index 569a60135..fe2e0d869 100644 --- a/docs/manual/source/ReleaseUpdate.rst +++ b/docs/manual/source/ReleaseUpdate.rst @@ -36,6 +36,7 @@ The major novelties of all releases since v1.0 are as follows: New in Version 3.0.1: ^^^^^^^^^^^^^^^^^^^^^ + * Made the:ref:`pyhf backend ` configurable, defaulting to numpy, see also `pyhfInterface.setBackend `_ * Bug fix for printing signal region combination results * Replaced algorithm for :ref:`clustering SMS ` for UL results by a modified minimum spanning tree algorithm diff --git a/docs/manual/source/RunningSModelS.rst b/docs/manual/source/RunningSModelS.rst index 9a56d39b8..1515a64a7 100644 --- a/docs/manual/source/RunningSModelS.rst +++ b/docs/manual/source/RunningSModelS.rst @@ -138,6 +138,8 @@ Below we give more detailed information about each entry in the parameters file. * **combineSRs** (True/False): set to True to combine signal regions in |EMrs| when covariance matrix or pyhf JSON likelihood is available. Set to False to use only the most sensitive signal region (faster!). Available v1.1.3 onwards for covariance matrices and v1.2.4 onwards for full likelihoods (using pyhf). +.. _parameterFilePyhfbackend: + * **pyhfbackend**: set to name of pyhf backend. Possible values are: numpy (default), pytorch, tensorflow, jax .. _parameterFileReportAllSRs: diff --git a/smodels/statistics/pyhfInterface.py b/smodels/statistics/pyhfInterface.py index 024ffa1f6..2ef8ced75 100755 --- a/smodels/statistics/pyhfInterface.py +++ b/smodels/statistics/pyhfInterface.py @@ -61,8 +61,10 @@ print(f"[SModelS:pyhfInterface] We recommend pyhf >= {str(required)}. Please try to update pyhf ASAP!") def setBackend ( backend : str ) -> bool: - """ try to setup backend to - :param backend: one of: numpy, pytorch, jax, tensorflow + """ + try to setup backend to + + :param backend: one of: numpy (default), pytorch, jax, tensorflow :returns: True, if worked, False if failed """ try: From cb5ff43fcc0ea8afd8e975249dc79a10cb150ca9 Mon Sep 17 00:00:00 2001 From: Wolfgang Waltenberger Date: Tue, 29 Oct 2024 18:03:40 +0100 Subject: [PATCH 07/14] space was missing --- docs/manual/source/ReleaseUpdate.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/manual/source/ReleaseUpdate.rst b/docs/manual/source/ReleaseUpdate.rst index fe2e0d869..2aeaad2f5 100644 --- a/docs/manual/source/ReleaseUpdate.rst +++ b/docs/manual/source/ReleaseUpdate.rst @@ -36,7 +36,7 @@ The major novelties of all releases since v1.0 are as follows: New in Version 3.0.1: ^^^^^^^^^^^^^^^^^^^^^ - * Made the:ref:`pyhf backend ` configurable, defaulting to numpy, see also `pyhfInterface.setBackend `_ + * Made the :ref:`pyhf backend ` configurable, defaulting to numpy, see also `pyhfInterface.setBackend `_ * Bug fix for printing signal region combination results * Replaced algorithm for :ref:`clustering SMS ` for UL results by a modified minimum spanning tree algorithm From 2929abb17483c5fd9a6d1c6afbc5fd2e8e547fcb Mon Sep 17 00:00:00 2001 From: Wolfgang Waltenberger Date: Tue, 29 Oct 2024 19:51:32 +0100 Subject: [PATCH 08/14] dropped semver dependency --- smodels/statistics/pyhfInterface.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/smodels/statistics/pyhfInterface.py b/smodels/statistics/pyhfInterface.py index 2ef8ced75..1cc61469f 100755 --- a/smodels/statistics/pyhfInterface.py +++ b/smodels/statistics/pyhfInterface.py @@ -9,10 +9,10 @@ .. moduleauthor:: Wolfgang Waltenberger """ + import jsonpatch import warnings import jsonschema -import semver import copy from scipy import optimize import numpy as np @@ -27,13 +27,13 @@ try: import importlib.metadata - jsonver = semver.parse_version_info(importlib.metadata.version("jsonschema")) + jsonver = int(importlib.metadata.version("jsonschema")[0]) except Exception as e: try: from jsonschema import __version__ as jsonver except Exception as e: pass -if jsonver.major < 3: +if jsonver < 3: # if jsonschema.__version__[0] == "2": ## deprecated print( f"[SModelS:pyhfInterface] jsonschema is version {jsonschema.__version__}, we need > 3.x.x" ) sys.exit() @@ -46,19 +46,21 @@ print("[SModelS:pyhfInterface] pyhf import failed. Is the module installed?") sys.exit(-1) -ver = semver.parse_version_info(pyhf.__version__) +ver = pyhf.__version__ pyhfinfo = { "backend": "numpy", "hasgreeted": False, "backendver": np.version.full_version, "ver": ver, - "required": semver.parse_version_info("0.6.1"), # the required pyhf version +# "required": "0.6.1", # the required pyhf version } +""" if ver < pyhfinfo["required"]: print(f"[SModelS:pyhfInterface] WARNING you are using pyhf v{str(ver)}" ) print(f"[SModelS:pyhfInterface] We recommend pyhf >= {str(required)}. Please try to update pyhf ASAP!") +""" def setBackend ( backend : str ) -> bool: """ @@ -396,7 +398,7 @@ def __init__(self, data, cl=0.95, lumi=None ): self.alreadyBeenThere = ( False # boolean to detect wether self.signals has returned to an older value ) - self.checkPyhfVersion() + # self.checkPyhfVersion() self.welcome() def welcome(self): From ec7f2d5abbdf43ec6f19a385d069bff2b31d75e6 Mon Sep 17 00:00:00 2001 From: Wolfgang Waltenberger Date: Tue, 29 Oct 2024 19:56:20 +0100 Subject: [PATCH 09/14] dont mention pyhfbackend in parameters.ini --- parameters.ini | 1 - unittests/testRFails.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/parameters.ini b/parameters.ini index b748b919c..7f1e94b2d 100644 --- a/parameters.ini +++ b/parameters.ini @@ -7,7 +7,6 @@ testCoverage = True ;Set True if topologies not covered by experiments (missing computeStatistics = True ;Set True to compute the likelihoods L_BSM, L_SM and L_max for EM-type results. combineSRs = True ;Set True to combine signal regions when covariance matrix or pyhf JSON likelihood is available. Caution, increases runtime! False uses only best SR (faster). #combineAnas = ATLAS-SUSY-2019-08,ATLAS-SUSY-2019-09 ; list of statistically independent analyses to combine. Works for EM-type results only. Use with care! -pyhfbackend = numpy ; This allows you to change the pyhf backend used. Possible values are numpy (default), pytorch, tensorflow, jax reportAllSRs = False ;Set True to report all signal regions, instead of best signal region only. experimentalFeatures = False ;Set True to enable experimental features that are not yet considered part of SModelS proper. Use only if you know what you are doing!! diff --git a/unittests/testRFails.py b/unittests/testRFails.py index 1f2936d46..b281f31db 100755 --- a/unittests/testRFails.py +++ b/unittests/testRFails.py @@ -95,6 +95,7 @@ def testRFailPrinters(self): def testRFailSummary(self): warnings.filterwarnings( action='ignore', category=DeprecationWarning ) + warnings.filterwarnings( action='ignore', category=RuntimeWarning ) out = "./unitTestOutput" dirname = "./testFiles/rfails/" from smodels.statistics import pyhfInterface From a983b4688dec39aa8f1f63d2e02c8f67e6277a77 Mon Sep 17 00:00:00 2001 From: Wolfgang Waltenberger Date: Wed, 30 Oct 2024 17:33:00 +0100 Subject: [PATCH 10/14] removing obsolete code --- smodels/statistics/pyhfInterface.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/smodels/statistics/pyhfInterface.py b/smodels/statistics/pyhfInterface.py index 1cc61469f..4fbda233c 100755 --- a/smodels/statistics/pyhfInterface.py +++ b/smodels/statistics/pyhfInterface.py @@ -56,12 +56,6 @@ # "required": "0.6.1", # the required pyhf version } -""" -if ver < pyhfinfo["required"]: - print(f"[SModelS:pyhfInterface] WARNING you are using pyhf v{str(ver)}" ) - print(f"[SModelS:pyhfInterface] We recommend pyhf >= {str(required)}. Please try to update pyhf ASAP!") -""" - def setBackend ( backend : str ) -> bool: """ try to setup backend to From 3c4ae40664ce44bafd0422be5acb1184d2c83e2a Mon Sep 17 00:00:00 2001 From: Wolfgang Waltenberger Date: Wed, 30 Oct 2024 17:34:28 +0100 Subject: [PATCH 11/14] changed order of items in release note --- ReleaseNotes | 4 ++-- docs/manual/source/ReleaseUpdate.rst | 2 +- parameters.ini | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ReleaseNotes b/ReleaseNotes index b00f77d36..7cee31456 100644 --- a/ReleaseNotes +++ b/ReleaseNotes @@ -1,9 +1,9 @@ -Release v3.0.1, Thu 24 Oct 2024 +Release v3.0.1, Thu 31 Oct 2024 ======================================================= - * Made the pyhf backend configurable, defaulting to numpy * Bug fix for printing signal region combination results * New cluster algorithm (simpler and more stable) + * Made the pyhf backend configurable Release v3.0.0, Tue 20 Aug 2024 ======================================================= diff --git a/docs/manual/source/ReleaseUpdate.rst b/docs/manual/source/ReleaseUpdate.rst index 2aeaad2f5..1fd68b08f 100644 --- a/docs/manual/source/ReleaseUpdate.rst +++ b/docs/manual/source/ReleaseUpdate.rst @@ -36,9 +36,9 @@ The major novelties of all releases since v1.0 are as follows: New in Version 3.0.1: ^^^^^^^^^^^^^^^^^^^^^ - * Made the :ref:`pyhf backend ` configurable, defaulting to numpy, see also `pyhfInterface.setBackend `_ * Bug fix for printing signal region combination results * Replaced algorithm for :ref:`clustering SMS ` for UL results by a modified minimum spanning tree algorithm + * Made the :ref:`pyhf backend ` configurable, see also `pyhfInterface.setBackend `_ New in Version 3.0.0: ^^^^^^^^^^^^^^^^^^^^^ diff --git a/parameters.ini b/parameters.ini index 7f1e94b2d..b08473b1d 100644 --- a/parameters.ini +++ b/parameters.ini @@ -7,6 +7,7 @@ testCoverage = True ;Set True if topologies not covered by experiments (missing computeStatistics = True ;Set True to compute the likelihoods L_BSM, L_SM and L_max for EM-type results. combineSRs = True ;Set True to combine signal regions when covariance matrix or pyhf JSON likelihood is available. Caution, increases runtime! False uses only best SR (faster). #combineAnas = ATLAS-SUSY-2019-08,ATLAS-SUSY-2019-09 ; list of statistically independent analyses to combine. Works for EM-type results only. Use with care! +pyhfbackend = pytorch ;Define pyhf backend used, one of: numpy (default), pytorch, tensorflow, jax. WARNING: if backend specified is not found, we fall back to numpy! reportAllSRs = False ;Set True to report all signal regions, instead of best signal region only. experimentalFeatures = False ;Set True to enable experimental features that are not yet considered part of SModelS proper. Use only if you know what you are doing!! From 1fd582a55d1ad48681198f6279b472254d5024b9 Mon Sep 17 00:00:00 2001 From: Wolfgang Waltenberger Date: Wed, 30 Oct 2024 17:37:11 +0100 Subject: [PATCH 12/14] warning added in release note --- ReleaseNotes | 2 +- docs/manual/source/ReleaseUpdate.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ReleaseNotes b/ReleaseNotes index 7cee31456..a355ae1d7 100644 --- a/ReleaseNotes +++ b/ReleaseNotes @@ -3,7 +3,7 @@ Release v3.0.1, Thu 31 Oct 2024 * Bug fix for printing signal region combination results * New cluster algorithm (simpler and more stable) - * Made the pyhf backend configurable + * Made the pyhf backend configurable. WARNING: if backend specified is not found, we now fall back to numpy! Release v3.0.0, Tue 20 Aug 2024 ======================================================= diff --git a/docs/manual/source/ReleaseUpdate.rst b/docs/manual/source/ReleaseUpdate.rst index 1fd68b08f..46ea8d459 100644 --- a/docs/manual/source/ReleaseUpdate.rst +++ b/docs/manual/source/ReleaseUpdate.rst @@ -38,7 +38,7 @@ New in Version 3.0.1: * Bug fix for printing signal region combination results * Replaced algorithm for :ref:`clustering SMS ` for UL results by a modified minimum spanning tree algorithm - * Made the :ref:`pyhf backend ` configurable, see also `pyhfInterface.setBackend `_ + * Made the :ref:`pyhf backend ` configurable, see also `pyhfInterface.setBackend `_. WARNING: if backend specified is not found, we now fall back to numpy! New in Version 3.0.0: ^^^^^^^^^^^^^^^^^^^^^ From 164b6e18a931d9da665cce02e13fafe4f8b5a9a5 Mon Sep 17 00:00:00 2001 From: Wolfgang Waltenberger Date: Wed, 30 Oct 2024 17:48:59 +0100 Subject: [PATCH 13/14] updated example --- Example.py | 6 ++-- docs/manual/source/RunningSModelS.rst | 41 +++++++++++++++----------- docs/manual/source/examples/Example.py | 6 ++-- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/Example.py b/Example.py index b36b84166..ba0b2368d 100755 --- a/Example.py +++ b/Example.py @@ -24,6 +24,8 @@ # Set the path to the database import os +from smodels.statistics.pyhfInterface import setBackend +setBackend("pytorch") # set to one of: numpy (default), pytorch, tensorflow, jax. WARNING: if backend specified is not found, we fall back to numpy! def main(inputFile='./inputFiles/slha/lightEWinos.slha', sigmacut=0.05*fb, database = 'official'): @@ -40,9 +42,9 @@ def main(inputFile='./inputFiles/slha/lightEWinos.slha', sigmacut=0.05*fb, model = Model(BSMparticles=BSMList, SMparticles=SMList) # Path to input file (either a SLHA or LHE file) -# lhefile = 'inputFiles/lhe/gluino_squarks.lhe' + # lhefile = 'inputFiles/lhe/gluino_squarks.lhe' slhafile = os.path.abspath(inputFile) -# model.updateParticles(inputFile=lhefile) + # model.updateParticles(inputFile=lhefile) model.updateParticles(inputFile=slhafile, ignorePromptQNumbers = ['eCharge','colordim','spin']) diff --git a/docs/manual/source/RunningSModelS.rst b/docs/manual/source/RunningSModelS.rst index 1515a64a7..e6291eb60 100644 --- a/docs/manual/source/RunningSModelS.rst +++ b/docs/manual/source/RunningSModelS.rst @@ -399,11 +399,16 @@ Below we go step-by-step through this example code: .. literalinclude:: /examples/Example.py :lines: 16-25 +* *Define the pyhfbackend to use*. Specify which `pyhfbackend `_ to use. One of: numpy, pytorch, tensorflow, jax. + +.. literalinclude:: /examples/Example.py + :lines: 27-28 + * *Set the path to the database URL*. Specify which :ref:`database ` to use. It can be the path to the smodels-database folder, the path to a :ref:`pickle file ` or (starting with v1.1.3) a URL path. .. literalinclude:: /examples/Example.py - :lines: 39-39 + :lines: 36-37 * *Load the BSM particles*. By default SModelS assumes the MSSM particle content. For using SModelS @@ -411,30 +416,30 @@ Below we go step-by-step through this example code: to the path of the model file (see **particles:model** in :ref:`Parameter File `). .. literalinclude:: /examples/Example.py - :lines: 42-43 + :lines: 39-41 * *Load the model and set the path to the input file*. Load BSM and SM particle content; specify the location of the input file (must be an SLHA or LHE file, see :ref:`Basic Input `) and update particles in the model. .. literalinclude:: /examples/Example.py - :lines: 45,48,50-51 + :lines: 43,46,48-49 * *Set main options for* |decomposition|. Specify the values of :ref:`sigmacut ` and :ref:`minmassgap `: .. literalinclude:: /examples/Example.py - :lines: 54-55 + :lines: 52-53 * |Decompose| *model* using the `decomposer.decompose `_ method. The **doCompress** and **doInvisible** options turn the |mass compression| and |invisible compression| on/off. .. literalinclude:: /examples/Example.py - :lines: 59-61 + :lines: 57-59 * *Access basic information* from decomposition, using the `dictionary of SMS `_ (the dictionary has as keys the :ref:`canonical name ` for the topology and as values the list of |SMS topologies| for the corresponding canonical name): .. literalinclude:: /examples/Example.py - :lines: 64-68 + :lines: 62-66 *output:* @@ -444,7 +449,7 @@ Below we go step-by-step through this example code: * *Print information about the SMS topologies* from the decomposition: .. literalinclude:: /examples/Example.py - :lines: 71-77 + :lines: 69-75 *output:* @@ -456,7 +461,7 @@ Below we go step-by-step through this example code: Here, all results are used: .. literalinclude:: /examples/Example.py - :lines: 81 + :lines: 79 Alternatively, the `getExpResults `_ method can take as arguments specific results to be loaded and used. @@ -465,7 +470,7 @@ can take as arguments specific results to be loaded and used. Below we show how to count the number of |ULrs| and |EMrs| loaded: .. literalinclude:: /examples/Example.py - :lines: 87-94 + :lines: 85-92 *output:* @@ -478,13 +483,13 @@ can take as arguments specific results to be loaded and used. `theory prediction objects `_: .. literalinclude:: /examples/Example.py - :lines: 99 + :lines: 97 * *Print the results*. For each |expres|, loop over the corresponding |theory predictions| and print the relevant information: .. literalinclude:: /examples/Example.py - :lines: 100-109 + :lines: 98-107 *output:* @@ -495,7 +500,7 @@ can take as arguments specific results to be loaded and used. be compared to the |theory prediction| to decide whether a model is excluded or not: .. literalinclude:: /examples/Example.py - :lines: 112 + :lines: 110 *output:* @@ -508,7 +513,7 @@ can take as arguments specific results to be loaded and used. Determine the most constraining result: .. literalinclude:: /examples/Example.py - :lines: 115-121 + :lines: 113-119 *output:* @@ -519,7 +524,7 @@ can take as arguments specific results to be loaded and used. determine if the model has been excluded or not by the selected |express|: .. literalinclude:: /examples/Example.py - :lines: 122-131 + :lines: 120-129 *output:* @@ -530,17 +535,17 @@ can take as arguments specific results to be loaded and used. * *Select analyses*. Using the theory predictions, select a (user-defined) subset of analyses to be combined: .. literalinclude:: /examples/Example.py - :lines: 136-144 + :lines: 134-142 * *Combine analyses*. Using the selected analyses, combine them under the assumption they are fully uncorrelated: .. literalinclude:: /examples/Example.py - :lines: 151 + :lines: 149 * *Print the combination*. Print the *r*-values and likelihoods for the combination: .. literalinclude:: /examples/Example.py - :lines: 156-159 + :lines: 154-157 *output:* @@ -551,7 +556,7 @@ can take as arguments specific results to be loaded and used. the :ref:`missing topologies ` and print some basic information: .. literalinclude:: /examples/Example.py - :lines: 164-170 + :lines: 162-168 *output:* diff --git a/docs/manual/source/examples/Example.py b/docs/manual/source/examples/Example.py index b36b84166..ba0b2368d 100755 --- a/docs/manual/source/examples/Example.py +++ b/docs/manual/source/examples/Example.py @@ -24,6 +24,8 @@ # Set the path to the database import os +from smodels.statistics.pyhfInterface import setBackend +setBackend("pytorch") # set to one of: numpy (default), pytorch, tensorflow, jax. WARNING: if backend specified is not found, we fall back to numpy! def main(inputFile='./inputFiles/slha/lightEWinos.slha', sigmacut=0.05*fb, database = 'official'): @@ -40,9 +42,9 @@ def main(inputFile='./inputFiles/slha/lightEWinos.slha', sigmacut=0.05*fb, model = Model(BSMparticles=BSMList, SMparticles=SMList) # Path to input file (either a SLHA or LHE file) -# lhefile = 'inputFiles/lhe/gluino_squarks.lhe' + # lhefile = 'inputFiles/lhe/gluino_squarks.lhe' slhafile = os.path.abspath(inputFile) -# model.updateParticles(inputFile=lhefile) + # model.updateParticles(inputFile=lhefile) model.updateParticles(inputFile=slhafile, ignorePromptQNumbers = ['eCharge','colordim','spin']) From 8626fb1d683891d0940e7f764d57f4a826a4e9e2 Mon Sep 17 00:00:00 2001 From: Wolfgang Waltenberger Date: Wed, 30 Oct 2024 17:56:31 +0100 Subject: [PATCH 14/14] split up line in Example.py into three --- Example.py | 4 ++- docs/manual/source/RunningSModelS.rst | 38 +++++++++++++------------- docs/manual/source/examples/Example.py | 4 ++- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/Example.py b/Example.py index ba0b2368d..4c4390d35 100755 --- a/Example.py +++ b/Example.py @@ -25,7 +25,9 @@ import os from smodels.statistics.pyhfInterface import setBackend -setBackend("pytorch") # set to one of: numpy (default), pytorch, tensorflow, jax. WARNING: if backend specified is not found, we fall back to numpy! +# set pyhf backend to one of: numpy (default), pytorch, tensorflow, jax. +# WARNING: if backend specified is not found, we fall back to numpy! +setBackend("pytorch") def main(inputFile='./inputFiles/slha/lightEWinos.slha', sigmacut=0.05*fb, database = 'official'): diff --git a/docs/manual/source/RunningSModelS.rst b/docs/manual/source/RunningSModelS.rst index e6291eb60..b6bb9917b 100644 --- a/docs/manual/source/RunningSModelS.rst +++ b/docs/manual/source/RunningSModelS.rst @@ -402,13 +402,13 @@ Below we go step-by-step through this example code: * *Define the pyhfbackend to use*. Specify which `pyhfbackend `_ to use. One of: numpy, pytorch, tensorflow, jax. .. literalinclude:: /examples/Example.py - :lines: 27-28 + :lines: 27-30 * *Set the path to the database URL*. Specify which :ref:`database ` to use. It can be the path to the smodels-database folder, the path to a :ref:`pickle file ` or (starting with v1.1.3) a URL path. .. literalinclude:: /examples/Example.py - :lines: 36-37 + :lines: 38-39 * *Load the BSM particles*. By default SModelS assumes the MSSM particle content. For using SModelS @@ -416,30 +416,30 @@ Below we go step-by-step through this example code: to the path of the model file (see **particles:model** in :ref:`Parameter File `). .. literalinclude:: /examples/Example.py - :lines: 39-41 + :lines: 41-43 * *Load the model and set the path to the input file*. Load BSM and SM particle content; specify the location of the input file (must be an SLHA or LHE file, see :ref:`Basic Input `) and update particles in the model. .. literalinclude:: /examples/Example.py - :lines: 43,46,48-49 + :lines: 45,48,50-51 * *Set main options for* |decomposition|. Specify the values of :ref:`sigmacut ` and :ref:`minmassgap `: .. literalinclude:: /examples/Example.py - :lines: 52-53 + :lines: 54-55 * |Decompose| *model* using the `decomposer.decompose `_ method. The **doCompress** and **doInvisible** options turn the |mass compression| and |invisible compression| on/off. .. literalinclude:: /examples/Example.py - :lines: 57-59 + :lines: 59-61 * *Access basic information* from decomposition, using the `dictionary of SMS `_ (the dictionary has as keys the :ref:`canonical name ` for the topology and as values the list of |SMS topologies| for the corresponding canonical name): .. literalinclude:: /examples/Example.py - :lines: 62-66 + :lines: 64-68 *output:* @@ -449,7 +449,7 @@ Below we go step-by-step through this example code: * *Print information about the SMS topologies* from the decomposition: .. literalinclude:: /examples/Example.py - :lines: 69-75 + :lines: 71-77 *output:* @@ -461,7 +461,7 @@ Below we go step-by-step through this example code: Here, all results are used: .. literalinclude:: /examples/Example.py - :lines: 79 + :lines: 81 Alternatively, the `getExpResults `_ method can take as arguments specific results to be loaded and used. @@ -470,7 +470,7 @@ can take as arguments specific results to be loaded and used. Below we show how to count the number of |ULrs| and |EMrs| loaded: .. literalinclude:: /examples/Example.py - :lines: 85-92 + :lines: 87-94 *output:* @@ -483,13 +483,13 @@ can take as arguments specific results to be loaded and used. `theory prediction objects `_: .. literalinclude:: /examples/Example.py - :lines: 97 + :lines: 99 * *Print the results*. For each |expres|, loop over the corresponding |theory predictions| and print the relevant information: .. literalinclude:: /examples/Example.py - :lines: 98-107 + :lines: 100-109 *output:* @@ -500,7 +500,7 @@ can take as arguments specific results to be loaded and used. be compared to the |theory prediction| to decide whether a model is excluded or not: .. literalinclude:: /examples/Example.py - :lines: 110 + :lines: 112 *output:* @@ -513,7 +513,7 @@ can take as arguments specific results to be loaded and used. Determine the most constraining result: .. literalinclude:: /examples/Example.py - :lines: 113-119 + :lines: 115-121 *output:* @@ -524,7 +524,7 @@ can take as arguments specific results to be loaded and used. determine if the model has been excluded or not by the selected |express|: .. literalinclude:: /examples/Example.py - :lines: 120-129 + :lines: 122-131 *output:* @@ -535,17 +535,17 @@ can take as arguments specific results to be loaded and used. * *Select analyses*. Using the theory predictions, select a (user-defined) subset of analyses to be combined: .. literalinclude:: /examples/Example.py - :lines: 134-142 + :lines: 136-144 * *Combine analyses*. Using the selected analyses, combine them under the assumption they are fully uncorrelated: .. literalinclude:: /examples/Example.py - :lines: 149 + :lines: 151 * *Print the combination*. Print the *r*-values and likelihoods for the combination: .. literalinclude:: /examples/Example.py - :lines: 154-157 + :lines: 156-159 *output:* @@ -556,7 +556,7 @@ can take as arguments specific results to be loaded and used. the :ref:`missing topologies ` and print some basic information: .. literalinclude:: /examples/Example.py - :lines: 162-168 + :lines: 164-170 *output:* diff --git a/docs/manual/source/examples/Example.py b/docs/manual/source/examples/Example.py index ba0b2368d..4c4390d35 100755 --- a/docs/manual/source/examples/Example.py +++ b/docs/manual/source/examples/Example.py @@ -25,7 +25,9 @@ import os from smodels.statistics.pyhfInterface import setBackend -setBackend("pytorch") # set to one of: numpy (default), pytorch, tensorflow, jax. WARNING: if backend specified is not found, we fall back to numpy! +# set pyhf backend to one of: numpy (default), pytorch, tensorflow, jax. +# WARNING: if backend specified is not found, we fall back to numpy! +setBackend("pytorch") def main(inputFile='./inputFiles/slha/lightEWinos.slha', sigmacut=0.05*fb, database = 'official'):