1
+ """
2
+ pyhf workspaces hold the three data items:
3
+
4
+ * the statistical model p(data|parameters)
5
+ * the observed data (optional)
6
+ * fit configurations ("measurements")
7
+ """
1
8
import logging
2
9
import jsonpatch
3
10
from . import exceptions
11
18
12
19
class Workspace (_ChannelSummaryMixin , dict ):
13
20
"""
14
- A JSON-serializable object that is built from an object that follows the `workspace.json` schema.
21
+ A JSON-serializable object that is built from an object that follows the :obj: `workspace.json` ` schema <https://scikit-hep.org/pyhf/likelihood.html#workspace>`__ .
15
22
"""
16
23
17
24
def __init__ (self , spec , ** config_kwargs ):
25
+ """Workspaces hold the model, data and measurements."""
18
26
super (Workspace , self ).__init__ (spec , channels = spec ['channels' ])
19
27
self .schema = config_kwargs .pop ('schema' , 'workspace.json' )
20
28
self .version = config_kwargs .pop ('version' , None )
@@ -31,20 +39,25 @@ def __init__(self, spec, **config_kwargs):
31
39
self .observations [obs ['name' ]] = obs ['data' ]
32
40
33
41
def __eq__ (self , other ):
42
+ """Equality is defined as equal dict representations."""
34
43
if not isinstance (other , Workspace ):
35
44
return False
36
45
return dict (self ) == dict (other )
37
46
38
47
def __ne__ (self , other ):
48
+ """Negation of equality."""
39
49
return not self == other
40
50
41
51
def __repr__ (self ):
52
+ """Representation of the Workspace."""
42
53
return object .__repr__ (self )
43
54
44
55
# NB: this is a wrapper function to validate the returned measurement object against the spec
45
56
def get_measurement (self , ** config_kwargs ):
46
57
"""
47
- Get (or create) a measurement object using the following logic:
58
+ Get (or create) a measurement object.
59
+
60
+ The following logic is used:
48
61
49
62
1. if the poi name is given, create a measurement object for that poi
50
63
2. if the measurement name is given, find the measurement for the given name
@@ -61,15 +74,14 @@ def get_measurement(self, **config_kwargs):
61
74
62
75
Returns:
63
76
:obj:`dict`: A measurement object adhering to the schema defs.json#/definitions/measurement
77
+
64
78
"""
65
79
m = self ._get_measurement (** config_kwargs )
66
80
utils .validate (m , 'measurement.json' , self .version )
67
81
return m
68
82
69
83
def _get_measurement (self , ** config_kwargs ):
70
- """
71
- See `Workspace::get_measurement`.
72
- """
84
+ """See `Workspace::get_measurement`."""
73
85
poi_name = config_kwargs .get ('poi_name' )
74
86
if poi_name :
75
87
return {
@@ -118,6 +130,7 @@ def model(self, **config_kwargs):
118
130
119
131
Returns:
120
132
~pyhf.pdf.Model: A model object adhering to the schema model.json
133
+
121
134
"""
122
135
measurement = self .get_measurement (** config_kwargs )
123
136
log .debug (
@@ -150,8 +163,8 @@ def data(self, model, with_aux=True):
150
163
151
164
Returns:
152
165
:obj:`list`: data
153
- """
154
166
167
+ """
155
168
try :
156
169
observed_data = sum (
157
170
(self .observations [c ] for c in model .config .channels ), []
@@ -178,8 +191,7 @@ def _prune_and_rename(
178
191
rename_measurements = {},
179
192
):
180
193
"""
181
- Return a new, pruned, renamed workspace specification. This will not
182
- modify the original workspace.
194
+ Return a new, pruned, renamed workspace specification. This will not modify the original workspace.
183
195
184
196
Pruning removes pieces of the workspace whose name or type matches the
185
197
user-provided lists. The pruned, renamed workspace must also be a valid
@@ -208,6 +220,7 @@ def _prune_and_rename(
208
220
209
221
Returns:
210
222
~pyhf.workspace.Workspace: A new workspace object with the specified components removed or renamed
223
+
211
224
"""
212
225
newspec = {
213
226
'channels' : [
@@ -276,8 +289,7 @@ def prune(
276
289
self , modifiers = [], modifier_types = [], samples = [], channels = [], measurements = []
277
290
):
278
291
"""
279
- Return a new, pruned workspace specification. This will not modify the
280
- original workspace.
292
+ Return a new, pruned workspace specification. This will not modify the original workspace.
281
293
282
294
The pruned workspace must also be a valid workspace.
283
295
@@ -290,6 +302,7 @@ def prune(
290
302
291
303
Returns:
292
304
~pyhf.workspace.Workspace: A new workspace object with the specified components removed
305
+
293
306
"""
294
307
return self ._prune_and_rename (
295
308
prune_modifiers = modifiers ,
@@ -302,8 +315,8 @@ def prune(
302
315
def rename (self , modifiers = {}, samples = {}, channels = {}, measurements = {}):
303
316
"""
304
317
Return a new workspace specification with certain elements renamed.
305
- This will not modify the original workspace.
306
318
319
+ This will not modify the original workspace.
307
320
The renamed workspace must also be a valid workspace.
308
321
309
322
Args:
@@ -314,6 +327,7 @@ def rename(self, modifiers={}, samples={}, channels={}, measurements={}):
314
327
315
328
Returns:
316
329
~pyhf.workspace.Workspace: A new workspace object with the specified components renamed
330
+
317
331
"""
318
332
return self ._prune_and_rename (
319
333
rename_modifiers = modifiers ,
@@ -325,8 +339,7 @@ def rename(self, modifiers={}, samples={}, channels={}, measurements={}):
325
339
@classmethod
326
340
def combine (cls , left , right ):
327
341
"""
328
- Return a new workspace specification that is the combination of the two
329
- workspaces.
342
+ Return a new workspace specification that is the combination of the two workspaces.
330
343
331
344
The new workspace must also be a valid workspace. A combination of
332
345
workspaces is done by combining the set of:
@@ -352,6 +365,7 @@ def combine(cls, left, right):
352
365
353
366
Returns:
354
367
~pyhf.workspace.Workspace: A new combined workspace object
368
+
355
369
"""
356
370
common_channels = set (left .channels ).intersection (right .channels )
357
371
if common_channels :
0 commit comments