89def expand_fragments(fragments, root_file):
90 """Resolve the for_each patterns of a domain against the histograms in a file.
91
92 A fragment without for_each is kept as it is. One with for_each is repeated
93 once per histogram matching the pattern, with its {field} placeholders filled
94 in from the match. skip_if_empty names the inputs that a repetition needs to
95 be non-empty, which is how the selections a sample does not fill are dropped.
96 """
97 paths = None
98 expanded = []
99 for fragment in fragments:
100 pattern = fragment.get("for_each")
101 if pattern is None:
102 expanded.append(fragment)
103 continue
104 if paths is None:
105 paths = histogram_paths(root_file)
106 matches = [match.groupdict()
for match
in map(pattern_to_regex(pattern).fullmatch, paths)
if match]
107 if not matches:
108 logging.info(f"No histogram matches '{pattern}', nothing to expand")
109 for fields in sorted(matches, key=lambda match: sorted(match.items())):
110 entry = {key: fill_fields(value, fields) for key, value in fragment.items()
111 if key not in ("for_each", "skip_if_empty")}
112 required = fragment.get("skip_if_empty")
113 empty = empty_input(root_file, entry, required) if required else None
114 if empty:
115 logging.info(f"'{empty}' is empty, skipping '{entry['output']}'")
116 continue
117 expanded.append(entry)
118 return expanded
119