@@ -583,16 +583,40 @@ def _prune_and_rename(
583
583
),
584
584
)
585
585
for modifier in sample ['modifiers' ]
586
- if modifier ['name' ] not in prune_modifiers
587
- and modifier ['type' ] not in prune_modifier_types
586
+ if (
587
+ channel ['name' ] not in prune_channels
588
+ and prune_channels != []
589
+ ) # want to remove only if channel is in prune_channels or if prune_channels is empty, i.e. we want to prune this modifier for every channel
590
+ or (
591
+ sample ['name' ] not in prune_samples
592
+ and prune_samples != []
593
+ ) # want to remove only if sample is in prune_samples or if prune_samples is empty, i.e. we want to prune this modifier for every sample
594
+ or (
595
+ modifier ['name' ] not in prune_modifiers
596
+ and modifier ['type' ] not in prune_modifier_types
597
+ )
598
+ or prune_measurements
599
+ != [] # need to keep the modifier in case it is used in another measurement
588
600
],
589
601
}
590
602
for sample in channel ['samples' ]
591
- if sample ['name' ] not in prune_samples
603
+ if (
604
+ channel ['name' ] not in prune_channels
605
+ and prune_channels != []
606
+ ) # want to remove only if channel is in prune_channels or if prune_channels is empty, i.e. we want to prune this sample for every channel
607
+ or sample ['name' ] not in prune_samples
608
+ or prune_modifiers
609
+ != [] # we only want to remove this sample if we did not specify modifiers to prune
610
+ or prune_modifier_types != []
592
611
],
593
612
}
594
613
for channel in self ['channels' ]
595
614
if channel ['name' ] not in prune_channels
615
+ or ( # we only want to remove this channel if we did not specify any samples or modifiers to prune
616
+ prune_samples != []
617
+ or prune_modifiers != []
618
+ or prune_modifier_types != []
619
+ )
596
620
],
597
621
'measurements' : [
598
622
{
@@ -607,8 +631,14 @@ def _prune_and_rename(
607
631
parameter ['name' ], parameter ['name' ]
608
632
),
609
633
)
610
- for parameter in measurement ['config' ]['parameters' ]
611
- if parameter ['name' ] not in prune_modifiers
634
+ for parameter in measurement ['config' ][
635
+ 'parameters'
636
+ ] # we only want to remove this parameter if measurement is in prune_measurements or if prune_measurements is empty
637
+ if (
638
+ measurement ['name' ] not in prune_measurements
639
+ and prune_measurements != []
640
+ )
641
+ or parameter ['name' ] not in prune_modifiers
612
642
],
613
643
'poi' : rename_modifiers .get (
614
644
measurement ['config' ]['poi' ], measurement ['config' ]['poi' ]
@@ -617,6 +647,8 @@ def _prune_and_rename(
617
647
}
618
648
for measurement in self ['measurements' ]
619
649
if measurement ['name' ] not in prune_measurements
650
+ or prune_modifiers
651
+ != [] # we only want to remove this measurement if we did not specify parameters to remove
620
652
],
621
653
'observations' : [
622
654
dict (
@@ -625,6 +657,11 @@ def _prune_and_rename(
625
657
)
626
658
for observation in self ['observations' ]
627
659
if observation ['name' ] not in prune_channels
660
+ or ( # we only want to remove this channel if we did not specify any samples or modifiers to prune
661
+ prune_samples != []
662
+ or prune_modifiers != []
663
+ or prune_modifier_types != []
664
+ )
628
665
],
629
666
'version' : self ['version' ],
630
667
}
@@ -637,6 +674,7 @@ def prune(
637
674
samples = None ,
638
675
channels = None ,
639
676
measurements = None ,
677
+ mode = "logical_or" ,
640
678
):
641
679
"""
642
680
Return a new, pruned workspace specification. This will not modify the original workspace.
@@ -649,6 +687,7 @@ def prune(
649
687
samples: A :obj:`list` of samples to prune.
650
688
channels: A :obj:`list` of channels to prune.
651
689
measurements: A :obj:`list` of measurements to prune.
690
+ mode (:obj: string): `logical_or` or `logical_and` to chain pruning with a logical OR or a logical AND, respectively. Default: `logical_or`.
652
691
653
692
Returns:
654
693
~pyhf.workspace.Workspace: A new workspace object with the specified components removed
@@ -657,19 +696,41 @@ def prune(
657
696
~pyhf.exceptions.InvalidWorkspaceOperation: An item name to prune does not exist in the workspace.
658
697
659
698
"""
699
+
700
+ if mode not in ["logical_and" , "logical_or" ]:
701
+ raise ValueError (
702
+ "Pruning mode must be either `logical_and` or `logical_or`."
703
+ )
704
+
660
705
# avoid mutable defaults
661
706
modifiers = [] if modifiers is None else modifiers
662
707
modifier_types = [] if modifier_types is None else modifier_types
663
708
samples = [] if samples is None else samples
664
709
channels = [] if channels is None else channels
665
710
measurements = [] if measurements is None else measurements
666
711
667
- return self ._prune_and_rename (
668
- prune_modifiers = modifiers ,
669
- prune_modifier_types = modifier_types ,
670
- prune_samples = samples ,
671
- prune_channels = channels ,
672
- prune_measurements = measurements ,
712
+ if mode == "logical_and" :
713
+ if samples != [] and measurements != []:
714
+ raise ValueError (
715
+ "Pruning of measurements and samples cannot be run with mode `logical_and`."
716
+ )
717
+ if modifier_types != [] and measurements != []:
718
+ raise ValueError (
719
+ "Pruning of measurements and modifier_types cannot be run with mode `logical_and`."
720
+ )
721
+ return self ._prune_and_rename (
722
+ prune_modifiers = modifiers ,
723
+ prune_modifier_types = modifier_types ,
724
+ prune_samples = samples ,
725
+ prune_channels = channels ,
726
+ prune_measurements = measurements ,
727
+ )
728
+ return (
729
+ self ._prune_and_rename (prune_modifiers = modifiers )
730
+ ._prune_and_rename (prune_modifier_types = modifier_types )
731
+ ._prune_and_rename (prune_samples = samples )
732
+ ._prune_and_rename (prune_channels = channels )
733
+ ._prune_and_rename (prune_measurements = measurements )
673
734
)
674
735
675
736
def rename (self , modifiers = None , samples = None , channels = None , measurements = None ):
0 commit comments