# NB: python -m pip install pyhf[xmlio]
import pyhf
!ls -lavh ../../../validation/xmlimport_input
total 1752 drwxr-xr-x 7 kratsg staff 238B Oct 16 22:20 . drwxr-xr-x 21 kratsg staff 714B Apr 4 14:26 .. drwxr-xr-x 6 kratsg staff 204B Feb 27 17:13 config drwxr-xr-x 7 kratsg staff 238B Feb 27 23:41 data -rw-r--r-- 1 kratsg staff 850K Oct 16 22:20 log drwxr-xr-x 17 kratsg staff 578B Nov 15 12:24 results -rw-r--r-- 1 kratsg staff 21K Oct 16 22:20 scan.pdf
In order to convert HistFactory XML+ROOT to the pyhf JSON spec for likelihoods, you need to point the command-line interface pyhf xml2json
at the top-level XML file. Additionally, as the HistFactory XML specification often uses relative paths, you might need to specify the base directory --basedir
from which all other files are located, as specified in the top-level XML. The command will be of the format
pyhf xml2json {top-level XML} --basedir {base directory}
This will print the JSON representation of the XML+ROOT specified. If you wish to store this as a JSON file, you simply need to redirect it
pyhf xml2json {top-level XML} --basedir {base directory} > spec.json
!pyhf xml2json --hide-progress ../../../validation/xmlimport_input/config/example.xml --basedir ../../../validation/xmlimport_input | tee xml_importexport.json
{ "channels": [ { "name": "channel1", "samples": [ { "data": [ 20.0, 10.0 ], "modifiers": [ { "data": { "hi": 1.05, "lo": 0.95 }, "name": "syst1", "type": "normsys" }, { "data": null, "name": "SigXsecOverSM", "type": "normfactor" } ], "name": "signal" }, { "data": [ 100.0, 0.0 ], "modifiers": [ { "data": null, "name": "lumi", "type": "lumi" }, { "data": [ 5.000000074505806, 0.0 ], "name": "staterror_channel1", "type": "staterror" }, { "data": { "hi": 1.05, "lo": 0.95 }, "name": "syst2", "type": "normsys" } ], "name": "background1" }, { "data": [ 0.0, 100.0 ], "modifiers": [ { "data": null, "name": "lumi", "type": "lumi" }, { "data": [ 0.0, 10.0 ], "name": "staterror_channel1", "type": "staterror" }, { "data": { "hi": 1.05, "lo": 0.95 }, "name": "syst3", "type": "normsys" } ], "name": "background2" } ] } ], "data": { "channel1": [ 122.0, 112.0 ] }, "toplvl": { "measurements": [ { "config": { "parameters": [ { "auxdata": [ 1.0 ], "bounds": [ [ 0.5, 1.5 ] ], "fixed": true, "inits": [ 1.0 ], "name": "lumi", "sigmas": [ 0.1 ] }, { "fixed": true, "name": "alpha_syst1" } ], "poi": "SigXsecOverSM" }, "name": "GaussExample" }, { "config": { "parameters": [ { "auxdata": [ 1.0 ], "bounds": [ [ 0.5, 1.5 ] ], "fixed": true, "inits": [ 1.0 ], "name": "lumi", "sigmas": [ 0.1 ] }, { "fixed": true, "name": "alpha_syst1" } ], "poi": "SigXsecOverSM" }, "name": "GammaExample" }, { "config": { "parameters": [ { "auxdata": [ 1.0 ], "bounds": [ [ 0.5, 1.5 ] ], "fixed": true, "inits": [ 1.0 ], "name": "lumi", "sigmas": [ 0.1 ] }, { "fixed": true, "name": "alpha_syst1" } ], "poi": "SigXsecOverSM" }, "name": "LogNormExample" }, { "config": { "parameters": [ { "auxdata": [ 1.0 ], "bounds": [ [ 0.5, 1.5 ] ], "fixed": true, "inits": [ 1.0 ], "name": "lumi", "sigmas": [ 0.1 ] }, { "fixed": true, "name": "alpha_syst1" } ], "poi": "SigXsecOverSM" }, "name": "ConstExample" } ], "resultprefix": "./results/example" } }
In order to convert the pyhf JSON to the HistFactory XML+ROOT spec for likelihoods, you need to point the command-line interface pyhf json2xml
at the JSON file you want to convert. As everything is specified in a single file, there is no need to deal with base directories or looking up additional files. This will produce output XML+ROOT in the --output-dir=./
directory (your current working directory), storing XML configs under --specroot=config
and the data file under --dataroot=data
. The XML configs are prefixed with --resultprefix=FitConfig
by default, so that the top-level XML file will be located at {output dir}/{prefix}.xml
. The command will be of the format
pyhf json2xml {JSON spec}
Note that the output directory must already exist.
!mkdir -p output
!pyhf json2xml xml_importexport.json --output-dir output
!ls -lavh output/*
/Users/jovyan/pyhf/src/pyhf/writexml.py:120: RuntimeWarning: invalid value encountered in true_divide attrs['HistoName'], np.divide(modifierspec['data'], sampledata).tolist() -rw-r--r-- 1 kratsg staff 822B Apr 9 09:36 output/FitConfig.xml output/config: total 8 drwxr-xr-x 3 kratsg staff 102B Apr 9 09:36 . drwxr-xr-x 5 kratsg staff 170B Apr 9 09:36 .. -rw-r--r-- 1 kratsg staff 1.0K Apr 9 09:36 FitConfig_channel1.xml output/data: total 96 drwxr-xr-x 3 kratsg staff 102B Apr 9 09:36 . drwxr-xr-x 5 kratsg staff 170B Apr 9 09:36 .. -rw-r--r-- 1 kratsg staff 46K Apr 9 09:36 data.root
!rm xml_importexport.json
!rm -rf output/