|
1 | 1 | from collections import defaultdict
|
| 2 | +import dataclasses |
2 | 3 | import json
|
3 | 4 | import logging
|
4 | 5 | import pathlib
|
@@ -96,39 +97,50 @@ def evolve_fit(
|
96 | 97 | else:
|
97 | 98 | raise ValueError(f"dump_eko not provided and {eko_path=} not found")
|
98 | 99 |
|
99 |
| - # Assume the EKO can be used with no rotation and open it in read-only mode |
100 |
| - # inside a try-finally block to make sure the eko is closed at the end |
101 |
| - try: |
102 |
| - eko_op = eko.EKO.read(eko_path) |
103 |
| - |
104 |
| - # Read the cards directly from the eko to make sure they are consistent |
| 100 | + # Open the EKO in read-only mode, if it needs to be manipulated keep it in memory |
| 101 | + with eko.EKO.read(eko_path) as eko_op: |
| 102 | + # Read the cards directly fro"m the eko to make sure they are consistent |
105 | 103 | theory = eko_op.theory_card
|
106 | 104 | op = eko_op.operator_card
|
107 | 105 | # And dump them to the log
|
108 | 106 | _logger.debug(f"Theory card: {json.dumps(theory.raw)}")
|
109 | 107 | _logger.debug(f"Operator card: {json.dumps(op.raw)}")
|
110 | 108 |
|
111 |
| - # Check whether it needs to be modified |
112 |
| - eko_xgrid = eko_op.xgrid |
113 |
| - if XGrid(x_grid) != eko_xgrid: |
114 |
| - eko_op.close() |
115 |
| - eko_op = eko.EKO.edit(eko_path) |
116 |
| - |
117 |
| - # This is a workaround for EKOS created with 0.13.4 |
118 |
| - # in 0.13.4 the xgrid corresponds to the (internal) interpolation grid |
119 |
| - if eko_op.metadata.version == "0.13.4": |
120 |
| - # Prepare an "identity" rotation |
121 |
| - eko_xgrid = XGrid(x_grid) |
122 |
| - |
123 |
| - for i, elem in eko_op.items(): |
124 |
| - eko_op[i] = manipulate.xgrid_reshape( |
| 109 | + eko_original_xgrid = eko_op.xgrid |
| 110 | + if XGrid(x_grid) != eko_original_xgrid: |
| 111 | + # If the xgrid of the eko is not directly usable, construct a copy in memory |
| 112 | + # by replacing the internal inventory of operators in a readonly copy |
| 113 | + new_xgrid = XGrid(x_grid) |
| 114 | + new_metadata = dataclasses.replace(eko_op.metadata, xgrid=new_xgrid) |
| 115 | + |
| 116 | + new_operators = {} |
| 117 | + for target_key in eko_op.operators: |
| 118 | + elem = eko_op[target_key.ep] |
| 119 | + |
| 120 | + if eko_op.metadata.version == "0.13.4": |
| 121 | + # For eko 0.13.4 xgrid is the internal interpolation so we need to check |
| 122 | + # whether the rotation is truly needed |
| 123 | + # <in practice> this means checking whether the operator shape matches the grid |
| 124 | + oplen = elem.operator.shape[-1] |
| 125 | + if oplen != len(eko_original_xgrid): |
| 126 | + # The operator and its xgrid have different shape |
| 127 | + # either prepare an identity, or this EKO is not supported |
| 128 | + if oplen != len(x_grid): |
| 129 | + raise ValueError( |
| 130 | + f"The operator at {eko_path} is not usable, version not supported" |
| 131 | + ) |
| 132 | + eko_original_xgrid = XGrid(x_grid) |
| 133 | + |
| 134 | + new_operators[target_key] = manipulate.xgrid_reshape( |
125 | 135 | elem,
|
126 |
| - eko_xgrid, |
| 136 | + eko_original_xgrid, |
127 | 137 | op.configs.interpolation_polynomial_degree,
|
128 | 138 | targetgrid=XGrid(x_grid),
|
129 | 139 | inputgrid=XGrid(x_grid),
|
130 | 140 | )
|
131 |
| - eko_op.xgrid = XGrid(x_grid) |
| 141 | + |
| 142 | + new_inventory = dataclasses.replace(eko_op.operators, cache=new_operators) |
| 143 | + eko_op = dataclasses.replace(eko_op, metadata=new_metadata, operators=new_inventory) |
132 | 144 |
|
133 | 145 | # Modify the info file with the fit-specific info
|
134 | 146 | info = info_file.build(theory, op, 1, info_update={})
|
@@ -178,8 +190,6 @@ def pdf_xq2(pid, x, Q2):
|
178 | 190 | )
|
179 | 191 | blocks.append(block)
|
180 | 192 | dump_evolved_replica(blocks, usr_path, replica + 1)
|
181 |
| - finally: |
182 |
| - eko_op.close() |
183 | 193 |
|
184 | 194 | # remove folder:
|
185 | 195 | # The function dump_evolved_replica uses a temporary folder
|
|
0 commit comments