reboost 0.10.0a0__py3-none-any.whl → 0.10.0a2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- reboost/_version.py +2 -2
- reboost/build_hit.py +13 -6
- reboost/core.py +26 -10
- reboost/optmap/evt.py +0 -23
- reboost/units.py +18 -1
- reboost/utils.py +1 -47
- {reboost-0.10.0a0.dist-info → reboost-0.10.0a2.dist-info}/METADATA +1 -1
- {reboost-0.10.0a0.dist-info → reboost-0.10.0a2.dist-info}/RECORD +12 -12
- {reboost-0.10.0a0.dist-info → reboost-0.10.0a2.dist-info}/WHEEL +1 -1
- {reboost-0.10.0a0.dist-info → reboost-0.10.0a2.dist-info}/entry_points.txt +0 -0
- {reboost-0.10.0a0.dist-info → reboost-0.10.0a2.dist-info}/licenses/LICENSE +0 -0
- {reboost-0.10.0a0.dist-info → reboost-0.10.0a2.dist-info}/top_level.txt +0 -0
reboost/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.10.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 10, 0, '
|
|
31
|
+
__version__ = version = '0.10.0a2'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 10, 0, 'a2')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
reboost/build_hit.py
CHANGED
|
@@ -51,14 +51,15 @@ A :func:`build_hit` to parse the following configuration file:
|
|
|
51
51
|
|
|
52
52
|
t0: ak.fill_none(ak.firsts(HITS.time, axis=-1), np.nan)
|
|
53
53
|
|
|
54
|
-
evtid: ak.fill_none(ak.firsts(HITS.
|
|
54
|
+
evtid: ak.fill_none(ak.firsts(HITS.evtid, axis=-1), np.nan)
|
|
55
55
|
|
|
56
56
|
# distance to the nplus surface in mm
|
|
57
57
|
distance_to_nplus_surface_mm: reboost.hpge.distance_to_surface(
|
|
58
|
-
HITS.
|
|
58
|
+
HITS.xloc, HITS.yloc, HITS.zloc,
|
|
59
59
|
DETECTOR_OBJECTS.pyobj,
|
|
60
60
|
DETECTOR_OBJECTS.phyvol.position.eval(),
|
|
61
|
-
surface_type='nplus'
|
|
61
|
+
surface_type='nplus',
|
|
62
|
+
unit='m')
|
|
62
63
|
|
|
63
64
|
# activness based on FCCD (no TL)
|
|
64
65
|
activeness: ak.where(
|
|
@@ -75,7 +76,7 @@ A :func:`build_hit` to parse the following configuration file:
|
|
|
75
76
|
)
|
|
76
77
|
|
|
77
78
|
# summed energy of the hit accounting for activeness
|
|
78
|
-
energy_raw: ak.sum(HITS.
|
|
79
|
+
energy_raw: ak.sum(HITS.edep * HITS.activeness, axis=-1)
|
|
79
80
|
|
|
80
81
|
# energy with smearing
|
|
81
82
|
energy: reboost.math.sample_convolve(
|
|
@@ -92,7 +93,7 @@ A :func:`build_hit` to parse the following configuration file:
|
|
|
92
93
|
)
|
|
93
94
|
|
|
94
95
|
# example of low level reduction on clusters
|
|
95
|
-
energy_clustered: ak.sum(ak.unflatten(HITS.
|
|
96
|
+
energy_clustered: ak.sum(ak.unflatten(HITS.edep, HITS.clusters_lengths), axis=-1)
|
|
96
97
|
|
|
97
98
|
# example of using a reboost helper
|
|
98
99
|
steps_clustered: reboost.shape.reduction.energy_weighted_average(HITS, HITS.clusters_lengths)
|
|
@@ -115,7 +116,7 @@ A :func:`build_hit` to parse the following configuration file:
|
|
|
115
116
|
- num_scint_ph_lar
|
|
116
117
|
|
|
117
118
|
operations:
|
|
118
|
-
tot_edep_wlsr: ak.sum(HITS.edep[np.abs(HITS.zloc) <
|
|
119
|
+
tot_edep_wlsr: ak.sum(HITS.edep[np.abs(HITS.zloc) < 3], axis=-1)
|
|
119
120
|
|
|
120
121
|
- name: spms
|
|
121
122
|
|
|
@@ -180,6 +181,8 @@ from dbetto import AttrsDict
|
|
|
180
181
|
from lgdo import lh5
|
|
181
182
|
from lgdo.lh5.exceptions import LH5EncodeError
|
|
182
183
|
|
|
184
|
+
from reboost import units
|
|
185
|
+
|
|
183
186
|
from . import core, utils
|
|
184
187
|
from .iterator import GLMIterator
|
|
185
188
|
from .profile import ProfileDict
|
|
@@ -334,6 +337,7 @@ def build_hit(
|
|
|
334
337
|
expression=proc_group["hit_table_layout"],
|
|
335
338
|
time_dict=time_dict[proc_name],
|
|
336
339
|
)
|
|
340
|
+
|
|
337
341
|
else:
|
|
338
342
|
hit_table_layouted = copy.deepcopy(stps)
|
|
339
343
|
|
|
@@ -448,5 +452,8 @@ def _evaluate_operation(
|
|
|
448
452
|
time_dict=time_dict,
|
|
449
453
|
name=field,
|
|
450
454
|
)
|
|
455
|
+
if not isinstance(info, str) and "units" in info:
|
|
456
|
+
col = units.attach_units(col, info["units"])
|
|
457
|
+
units.move_units_to_flattened_data(col)
|
|
451
458
|
|
|
452
459
|
core.add_field_with_nesting(hit_table, field, col)
|
reboost/core.py
CHANGED
|
@@ -11,16 +11,25 @@ from dbetto import AttrsDict
|
|
|
11
11
|
from lgdo import lh5
|
|
12
12
|
from lgdo.types import LGDO, Table
|
|
13
13
|
|
|
14
|
-
from . import utils
|
|
14
|
+
from . import units, utils
|
|
15
15
|
from .profile import ProfileDict
|
|
16
16
|
|
|
17
17
|
log = logging.getLogger(__name__)
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def read_data_at_channel_as_ak(
|
|
21
|
-
channels: ak.Array,
|
|
21
|
+
channels: ak.Array,
|
|
22
|
+
rows: ak.Array,
|
|
23
|
+
file: str,
|
|
24
|
+
field: str,
|
|
25
|
+
group: str,
|
|
26
|
+
tab_map: dict[int, str],
|
|
27
|
+
with_units: bool = False,
|
|
22
28
|
) -> ak.Array:
|
|
23
|
-
r"""Read the data from a particular field to an
|
|
29
|
+
r"""Read the data from a particular field to an Awkward array.
|
|
30
|
+
|
|
31
|
+
This replaces the TCM like object defined by the channels and rows with the
|
|
32
|
+
corresponding data field.
|
|
24
33
|
|
|
25
34
|
Parameters
|
|
26
35
|
----------
|
|
@@ -68,7 +77,9 @@ def read_data_at_channel_as_ak(
|
|
|
68
77
|
tcm_rows = np.where(ak.flatten(channels == key))[0]
|
|
69
78
|
|
|
70
79
|
# read the data with sorted idx
|
|
71
|
-
data_ch = lh5.read(f"{group}/{tab_name}/{field}", file, idx=idx[arg_idx])
|
|
80
|
+
data_ch = lh5.read(f"{group}/{tab_name}/{field}", file, idx=idx[arg_idx])
|
|
81
|
+
units = data_ch.attrs.get("units", None)
|
|
82
|
+
data_ch = data_ch.view_as("ak")
|
|
72
83
|
|
|
73
84
|
# sort back to order for tcm
|
|
74
85
|
data_ch = data_ch[np.argsort(arg_idx)]
|
|
@@ -85,8 +96,12 @@ def read_data_at_channel_as_ak(
|
|
|
85
96
|
|
|
86
97
|
# sort the final data
|
|
87
98
|
data_flat = data_flat[np.argsort(tcm_rows_full)]
|
|
99
|
+
data_unflat = ak.unflatten(data_flat, reorder)
|
|
100
|
+
|
|
101
|
+
if with_units and units is not None:
|
|
102
|
+
return ak.with_parameter(data_unflat, "units", units)
|
|
88
103
|
|
|
89
|
-
return
|
|
104
|
+
return data_unflat
|
|
90
105
|
|
|
91
106
|
|
|
92
107
|
def evaluate_output_column(
|
|
@@ -441,6 +456,10 @@ def evaluate_hit_table_layout(
|
|
|
441
456
|
|
|
442
457
|
res = eval(group_func, globs, locs)
|
|
443
458
|
|
|
459
|
+
if isinstance(res, Table):
|
|
460
|
+
for data in res.values():
|
|
461
|
+
units.move_units_to_flattened_data(data)
|
|
462
|
+
|
|
444
463
|
if time_dict is not None:
|
|
445
464
|
time_dict.update_field(name="hit_layout", time_start=time_start)
|
|
446
465
|
|
|
@@ -519,8 +538,5 @@ def remove_columns(tab: Table, outputs: list) -> Table:
|
|
|
519
538
|
|
|
520
539
|
def merge(hit_table: Table, output_table: ak.Array | None):
|
|
521
540
|
"""Merge the table with the array."""
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
if output_table is None
|
|
525
|
-
else ak.concatenate((output_table, hit_table.view_as("ak")))
|
|
526
|
-
)
|
|
541
|
+
hit_table = hit_table.view_as("ak", with_units=True)
|
|
542
|
+
return hit_table if output_table is None else ak.concatenate((output_table, hit_table))
|
reboost/optmap/evt.py
CHANGED
|
@@ -3,10 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from collections import OrderedDict
|
|
5
5
|
from collections.abc import Generator, Iterable
|
|
6
|
-
from pathlib import Path
|
|
7
6
|
|
|
8
7
|
import numpy as np
|
|
9
|
-
from lgdo import lh5
|
|
10
8
|
from lgdo.lh5 import LH5Iterator
|
|
11
9
|
from lgdo.types import Table
|
|
12
10
|
|
|
@@ -105,27 +103,6 @@ def generate_optmap_evt(
|
|
|
105
103
|
assert had_last_chunk, "did not reach last chunk in optmap-evt building"
|
|
106
104
|
|
|
107
105
|
|
|
108
|
-
def build_optmap_evt(
|
|
109
|
-
lh5_in_file: str, lh5_out_file: str, detectors: Iterable[str | int], buffer_len: int = int(5e6)
|
|
110
|
-
) -> None:
|
|
111
|
-
"""Create a faster map for lookup of the hits in each detector, for each primary event."""
|
|
112
|
-
lh5_out_file = Path(lh5_out_file)
|
|
113
|
-
lh5_out_file_tmp = lh5_out_file.with_stem(".evt-tmp." + lh5_out_file.stem)
|
|
114
|
-
if lh5_out_file_tmp.exists():
|
|
115
|
-
msg = f"temporary output file {lh5_out_file_tmp} already exists"
|
|
116
|
-
raise RuntimeError(msg)
|
|
117
|
-
|
|
118
|
-
for vert_it_count, chunk in enumerate(generate_optmap_evt(lh5_in_file, detectors, buffer_len)):
|
|
119
|
-
log.info("store evt file %s (%d)", lh5_out_file_tmp, vert_it_count - 1)
|
|
120
|
-
lh5.write(Table(chunk), name=EVT_TABLE_NAME, lh5_file=lh5_out_file_tmp, wo_mode="append")
|
|
121
|
-
|
|
122
|
-
# after finishing the output file, rename to the actual output file name.
|
|
123
|
-
if lh5_out_file.exists():
|
|
124
|
-
msg = f"output file {lh5_out_file_tmp} already exists after writing tmp output file"
|
|
125
|
-
raise RuntimeError(msg)
|
|
126
|
-
lh5_out_file_tmp.rename(lh5_out_file)
|
|
127
|
-
|
|
128
|
-
|
|
129
106
|
def get_optical_detectors_from_geom(geom_fn) -> dict[int, str]:
|
|
130
107
|
import pyg4ometry
|
|
131
108
|
import pygeomtools
|
reboost/units.py
CHANGED
|
@@ -7,7 +7,7 @@ import awkward as ak
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import pint
|
|
9
9
|
import pyg4ometry as pg4
|
|
10
|
-
from lgdo import LGDO
|
|
10
|
+
from lgdo import LGDO, VectorOfVectors
|
|
11
11
|
|
|
12
12
|
log = logging.getLogger(__name__)
|
|
13
13
|
|
|
@@ -69,6 +69,23 @@ def attach_units(data: ak.Array | LGDO, unit: str | None) -> ak.Array | LGDO:
|
|
|
69
69
|
return data
|
|
70
70
|
|
|
71
71
|
|
|
72
|
+
def move_units_to_flattened_data(data: LGDO) -> None:
|
|
73
|
+
"""If `data` is a VectorOfVectors move units from attrs to flattened data attrs.
|
|
74
|
+
|
|
75
|
+
Parameters
|
|
76
|
+
----------
|
|
77
|
+
data
|
|
78
|
+
the nested data structure
|
|
79
|
+
"""
|
|
80
|
+
if isinstance(data, VectorOfVectors) and ("units" in data.attrs):
|
|
81
|
+
unit = data.attrs.pop("units")
|
|
82
|
+
if isinstance(data.flattened_data, VectorOfVectors):
|
|
83
|
+
data.flattened_data.attrs |= {"units": unit}
|
|
84
|
+
move_units_to_flattened_data(data.flattened_data)
|
|
85
|
+
else:
|
|
86
|
+
data.flattened_data.attrs |= {"units": unit}
|
|
87
|
+
|
|
88
|
+
|
|
72
89
|
def units_conv_ak(data: Any | LGDO | ak.Array, target_units: pint.Unit | str) -> Any | ak.Array:
|
|
73
90
|
"""Calculate numeric conversion factor to reach `target_units`, and apply to data converted to ak.
|
|
74
91
|
|
reboost/utils.py
CHANGED
|
@@ -5,7 +5,7 @@ import itertools
|
|
|
5
5
|
import logging
|
|
6
6
|
import re
|
|
7
7
|
import time
|
|
8
|
-
from collections.abc import Iterable
|
|
8
|
+
from collections.abc import Iterable
|
|
9
9
|
from contextlib import contextmanager
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
@@ -182,52 +182,6 @@ def get_file_list(path: str | None, threads: int | None = None) -> list[str]:
|
|
|
182
182
|
return [f"{(Path(path).with_suffix(''))}_t{idx}.lh5" for idx in range(threads)]
|
|
183
183
|
|
|
184
184
|
|
|
185
|
-
def copy_units(tab: Table) -> dict:
|
|
186
|
-
"""Extract a dictionary of attributes (i.e. units).
|
|
187
|
-
|
|
188
|
-
Parameters
|
|
189
|
-
----------
|
|
190
|
-
tab
|
|
191
|
-
Table to get the units from.
|
|
192
|
-
|
|
193
|
-
Returns
|
|
194
|
-
-------
|
|
195
|
-
a dictionary with the units for each field
|
|
196
|
-
in the table.
|
|
197
|
-
"""
|
|
198
|
-
units = {}
|
|
199
|
-
|
|
200
|
-
for field in tab:
|
|
201
|
-
if "units" in tab[field].attrs:
|
|
202
|
-
units[field] = tab[field].attrs["units"]
|
|
203
|
-
|
|
204
|
-
return units
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
def assign_units(tab: Table, units: Mapping) -> Table:
|
|
208
|
-
"""Copy the attributes from the map of attributes to the table.
|
|
209
|
-
|
|
210
|
-
Parameters
|
|
211
|
-
----------
|
|
212
|
-
tab
|
|
213
|
-
Table to add attributes to.
|
|
214
|
-
units
|
|
215
|
-
mapping (dictionary like) of units of each field
|
|
216
|
-
|
|
217
|
-
Returns
|
|
218
|
-
-------
|
|
219
|
-
an updated table with LGDO attributes.
|
|
220
|
-
"""
|
|
221
|
-
for field in tab:
|
|
222
|
-
if field in units:
|
|
223
|
-
if not isinstance(tab[field], VectorOfVectors):
|
|
224
|
-
tab[field].attrs["units"] = units[field]
|
|
225
|
-
else:
|
|
226
|
-
tab[field].flattened_data.attrs["units"] = units[field]
|
|
227
|
-
|
|
228
|
-
return tab
|
|
229
|
-
|
|
230
|
-
|
|
231
185
|
def _search_string(string: str):
|
|
232
186
|
"""Capture the characters matching the pattern for a function call."""
|
|
233
187
|
pattern = r"\b([a-zA-Z_][a-zA-Z0-9_\.]*)\s*\("
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: reboost
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.0a2
|
|
4
4
|
Summary: New LEGEND Monte-Carlo simulation post-processing
|
|
5
5
|
Author-email: Manuel Huber <info@manuelhu.de>, Toby Dixon <toby.dixon.23@ucl.ac.uk>, Luigi Pertoldi <gipert@pm.me>
|
|
6
6
|
Maintainer: The LEGEND Collaboration
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
reboost/__init__.py,sha256=VZz9uo7i2jgAx8Zi15SptLZnE_qcnGuNWwqkD3rYHFA,278
|
|
2
2
|
reboost/__main__.py,sha256=42koSxY2st4mMIRSAnKz06nP5HppMPxBVFf2jaHljGs,95
|
|
3
|
-
reboost/_version.py,sha256=
|
|
3
|
+
reboost/_version.py,sha256=o2SCKaFpIjZ_mxQO5CtT0P_LjixtzK8EKUUO8pTQ4Rg,714
|
|
4
4
|
reboost/build_evt.py,sha256=VXIfK_pfe_Cgym6gI8dESwONZi-v_4fll0Pn09vePQY,3767
|
|
5
5
|
reboost/build_glm.py,sha256=IerSLQfe51ZO7CQP2kmfPnOIVaDtcfw3byOM02Vaz6o,9472
|
|
6
|
-
reboost/build_hit.py,sha256=
|
|
6
|
+
reboost/build_hit.py,sha256=UjS4yp42_7D9IN-Nq1RfpyDeAcnH6THzUNCzupjRDKw,17224
|
|
7
7
|
reboost/cli.py,sha256=68EzKiWTHJ2u1RILUv7IX9HaVq6nTTM80_W_MUnWRe4,6382
|
|
8
|
-
reboost/core.py,sha256=
|
|
8
|
+
reboost/core.py,sha256=v0ze5wKqU8fmSExzNX6zUYs9E7xgwBvFY_lEJgCMbdQ,15624
|
|
9
9
|
reboost/iterator.py,sha256=qlEqRv5qOh8eIs-dyVOLYTvH-ZpQDx9fLckpcAdtWjs,6975
|
|
10
10
|
reboost/log_utils.py,sha256=VqS_9OC5NeNU3jcowVOBB0NJ6ssYvNWnirEY-JVduEA,766
|
|
11
11
|
reboost/profile.py,sha256=EOTmjmS8Rm_nYgBWNh6Rntl2XDsxdyed7yEdWtsZEeg,2598
|
|
12
|
-
reboost/units.py,sha256=
|
|
13
|
-
reboost/utils.py,sha256=
|
|
12
|
+
reboost/units.py,sha256=ZilbGI70--DZfcOx6wDHgSicH5Vc_FrajmrakyJU_gM,5619
|
|
13
|
+
reboost/utils.py,sha256=5sjavX1TqsZCWy84QVIR4JgfEfa4GVeUrUvEEI__Z1g,13558
|
|
14
14
|
reboost/daq/__init__.py,sha256=rNPhxx1Yawt3tENYhmOYSum9_TdV57ZU5kjxlWFAGuo,107
|
|
15
15
|
reboost/daq/core.py,sha256=Rs6Q-17fzEod2iX_2WqEmnqKnNRFoWTYURl3wYhFihU,9915
|
|
16
16
|
reboost/daq/utils.py,sha256=KcH6zvlInmD2YiF6V--DSYBTYudJw3G-hp2JGOcES2o,1042
|
|
@@ -26,7 +26,7 @@ reboost/optmap/__main__.py,sha256=DfzkXQ7labOe53hd7jH5pAbTW491jjQYSMLyl72L4Rk,11
|
|
|
26
26
|
reboost/optmap/cli.py,sha256=_7WBlx55eRyW_wWB-ELbFaWXin2d3xsh6Q5bFoNJaHE,8694
|
|
27
27
|
reboost/optmap/convolve.py,sha256=e3vTBurYSM4UmicIdDif6_cI04pV8khHEG5n7M_DWNg,16079
|
|
28
28
|
reboost/optmap/create.py,sha256=GmGd0-F0eWmw7ywH8pT1lKiMb60QXCq9al8Ka_ySD1Q,14382
|
|
29
|
-
reboost/optmap/evt.py,sha256=
|
|
29
|
+
reboost/optmap/evt.py,sha256=eq7NOyP3Y8ybUvl8Gw4xqyIwMqjhcoMFtNDDs0jBu7g,4577
|
|
30
30
|
reboost/optmap/mapview.py,sha256=fswwXolA6au8u8gljBKy8PSXC2W7Cy_GwOV86-duYG8,6880
|
|
31
31
|
reboost/optmap/numba_pdg.py,sha256=y8cXR5PWE2Liprp4ou7vl9do76dl84vXU52ZJD9_I7A,731
|
|
32
32
|
reboost/optmap/optmap.py,sha256=3clc1RA8jA4YJte83w085MY8zLpG-G7DBkpZ2UeKPpM,12825
|
|
@@ -36,9 +36,9 @@ reboost/shape/group.py,sha256=PY7FGUnralj1BkRl4YtguCnzvOr-ymMd4ZFVmzPCwmM,6352
|
|
|
36
36
|
reboost/shape/reduction.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
37
|
reboost/spms/__init__.py,sha256=8I6WT8i_kUPqEDnSD0aCf6A26cjKjQQZSNrvwZ3o-Ac,415
|
|
38
38
|
reboost/spms/pe.py,sha256=LwqrK1HOZWzGcNZnntaqI6r4rnDww4KW9Mao4xLFbDE,8226
|
|
39
|
-
reboost-0.10.
|
|
40
|
-
reboost-0.10.
|
|
41
|
-
reboost-0.10.
|
|
42
|
-
reboost-0.10.
|
|
43
|
-
reboost-0.10.
|
|
44
|
-
reboost-0.10.
|
|
39
|
+
reboost-0.10.0a2.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
40
|
+
reboost-0.10.0a2.dist-info/METADATA,sha256=oaef7gtpw-LErMt8M-oB5CUVAENqjo7tNTwdrkZkQzA,3880
|
|
41
|
+
reboost-0.10.0a2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
42
|
+
reboost-0.10.0a2.dist-info/entry_points.txt,sha256=DxhD6BidSWNot9BrejHJjQ7RRLmrMaBIl52T75oWTwM,93
|
|
43
|
+
reboost-0.10.0a2.dist-info/top_level.txt,sha256=q-IBsDepaY_AbzbRmQoW8EZrITXRVawVnNrB-_zyXZs,8
|
|
44
|
+
reboost-0.10.0a2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|