reboost 0.5.4__py3-none-any.whl → 0.6.0__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/__init__.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import hdf5plugin
3
4
  from lgdo import lh5
4
5
 
5
6
  from ._version import version as __version__
@@ -10,4 +11,4 @@ __all__ = [
10
11
  "build_hit",
11
12
  ]
12
13
 
13
- lh5.settings.DEFAULT_HDF5_SETTINGS = {"shuffle": True, "compression": "lzf"}
14
+ lh5.settings.DEFAULT_HDF5_SETTINGS = {"compression": hdf5plugin.Zstd()}
reboost/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.5.4'
21
- __version_tuple__ = version_tuple = (0, 5, 4)
20
+ __version__ = version = '0.6.0'
21
+ __version_tuple__ = version_tuple = (0, 6, 0)
reboost/build_evt.py CHANGED
@@ -1,166 +1,134 @@
1
- """A program for combining the hits from various detectors, to build events.
1
+ from __future__ import annotations
2
2
 
3
- Is able to parse a config file with the following format config file:
3
+ import logging
4
4
 
5
- .. code-block:: yaml
5
+ import awkward as ak
6
+ import numpy as np
7
+ from dbetto import AttrsDict
8
+ from lgdo import Array, Table, VectorOfVectors, lh5
6
9
 
7
- channels:
8
- geds_on:
9
- - det001
10
- - det002
11
- geds_ac:
12
- - det003
10
+ from . import core, math, shape, utils
11
+ from .shape import group
13
12
 
14
- outputs:
15
- - energy
16
- - multiplicity
13
+ log = logging.getLogger(__name__)
17
14
 
18
- operations:
19
- energy_id:
20
- channels: geds_on
21
- aggregation_mode: gather
22
- query: "hit.energy > 25"
23
- expression: tcm.channel_id
24
15
 
25
- energy:
26
- aggregation_mode: keep_at_ch:evt.energy_id
27
- expression: "hit.energy > 25"
28
- channels: geds_on
16
+ def build_evt(
17
+ tcm: VectorOfVectors,
18
+ hitfile: str,
19
+ outfile: str | None,
20
+ channel_groups: AttrsDict,
21
+ pars: AttrsDict,
22
+ run_part: AttrsDict,
23
+ ) -> Table | None:
24
+ """Build events out of a TCM.
29
25
 
30
- multiplicity:
31
- channels: geds_on
32
- aggregation_mode: sum
33
- expression: "hit.energy > 25"
34
- initial: 0
26
+ Parameters
27
+ ----------
28
+ tcm
29
+ the time coincidence map.
30
+ hitfile
31
+ file with the hits.
32
+ outfile
33
+ the path to the output-file, if `None` with return
34
+ the events in memory.
35
+ channel_groups
36
+ a dictionary of groups of channels. For example:
35
37
 
38
+ .. code-block:: python
36
39
 
37
- Must contain:
38
- - "channels": dictionary of channel groupings
39
- - "outputs": fields for the output file
40
- - "operations": operations to perform see :func:`pygama.evt.build_evt.evaluate_expression` for more details.
41
- """
40
+ {"det1": "on", "det2": "off", "det3": "ac"}
42
41
 
43
- from __future__ import annotations
42
+ pars
43
+ A dictionary of parameters. The first key should
44
+ be the run ID, followed by different sets of parameters
45
+ arranged in groups. Run numbers should be given in the
46
+ format `"p00-r001"`, etc.
44
47
 
45
- import logging
48
+ For example:
46
49
 
47
- import awkward as ak
48
- import numpy as np
49
- from lgdo import Table
50
- from lgdo.lh5 import LH5Iterator, write
51
- from pygama.evt.build_evt import evaluate_expression
52
- from pygama.evt.utils import TCMData
50
+ .. code-block:: python
53
51
 
54
- from . import utils
52
+ {"p03-r000": {"reso": {"det1": [1, 2], "det2": [0, 1]}}}
55
53
 
56
- log = logging.getLogger(__name__)
54
+ run_part
55
+ The run partitioning file giving the number of events
56
+ for each run. This should be organized as a dictionary
57
+ with the following format:
57
58
 
59
+ .. code-block:: python
58
60
 
59
- def build_evt(
60
- hit_file: str, tcm_file: str, evt_file: str | None, config: dict, buffer: int = int(5e6)
61
- ) -> ak.Array | None:
62
- """Generates the event tier from the hit and tcm.
63
-
64
- Parameters
65
- ----------
66
- hit_file
67
- path to the hit tier file
68
- tcm_file
69
- path to the tcm tier file
70
- evt_file
71
- path to the evt tier (output) file, if `None` the :class:`Table` is returned in memory
72
- config
73
- dictionary of the configuration.
74
- buffer
75
- number of events to process simultaneously
61
+ {"p03-r000": 1000, "p03-r001": 2000}
76
62
 
77
63
  Returns
78
64
  -------
79
- ak.Array of the evt tier data (if the data is not saved to disk)
65
+ the event file in memory as a table if no output file is specified.
80
66
  """
81
- # create the objects needed for evaluate expression
67
+ tcm_tables = utils.get_table_names(tcm)
68
+ tcm_ak = tcm.view_as("ak")
69
+
70
+ # loop over the runs
71
+ cum_sum = 0
72
+ tab = None
73
+
74
+ for idx, (run_full, n_event) in enumerate(run_part.items()):
75
+ period, run = run_full.split("-")
76
+ pars_tmp = pars[run_full]
82
77
 
83
- file_info = {
84
- "hit": (hit_file, "hit", "det{:03}"),
85
- "evt": (evt_file, "evt"),
86
- }
78
+ # create an output table
79
+ out_tab = Table(size=n_event)
87
80
 
88
- # iterate through the TCM
81
+ tcm_tmp = tcm_ak[cum_sum : cum_sum + n_event]
89
82
 
90
- out_ak = ak.Array([])
91
- mode = "overwrite_file"
83
+ # usabilities
92
84
 
93
- # get channel groupings
94
- channels = {}
95
- for group, info in config["channels"].items():
96
- if isinstance(info, str):
97
- channels[group] = [info]
85
+ is_off = shape.group.get_isin_group(
86
+ tcm_tmp.table_key, channel_groups, tcm_tables, group="off"
87
+ )
88
+
89
+ # filter out off channels
90
+ channels = tcm_tmp.table_key[~is_off]
91
+ rows = tcm_tmp.row_in_table[~is_off]
92
+ out_tab.add_field("channel", VectorOfVectors(channels))
93
+ out_tab.add_field("row_in_table", VectorOfVectors(rows))
94
+
95
+ out_tab.add_field("period", Array(np.ones(len(channels)) * int(period[1:])))
96
+ out_tab.add_field("run", Array(np.ones(len(channels)) * int(run[1:])))
98
97
 
99
- elif isinstance(info, list):
100
- channels[group] = info
98
+ # now check for channels in ac
99
+ is_good = group.get_isin_group(channels, channel_groups, tcm_tables, group="on")
101
100
 
102
- for tcm_lh5 in LH5Iterator(tcm_file, "tcm", buffer_len=buffer):
103
- tcm_lh5_sel = tcm_lh5
104
- tcm_ak = tcm_lh5_sel.view_as("ak")
101
+ # get energy
102
+ energy_true = core.read_data_at_channel_as_ak(
103
+ channels, rows, hitfile, "energy", "hit", tcm_tables
104
+ )
105
105
 
106
- tcm = TCMData(
107
- id=np.array(ak.flatten(tcm_ak.array_id)),
108
- idx=np.array(ak.flatten(tcm_ak.array_idx)),
109
- cumulative_length=np.array(np.cumsum(ak.num(tcm_ak.array_id, axis=-1))),
106
+ energy = math.stats.apply_energy_resolution(
107
+ energy_true,
108
+ channels,
109
+ tcm_tables,
110
+ pars_tmp.reso,
111
+ lambda energy, sig0, sig1: np.sqrt(energy * sig1**2 + sig0**2),
110
112
  )
111
113
 
112
- n_rows = len(tcm.cumulative_length)
113
- out_tab = Table(size=n_rows)
114
+ out_tab.add_field("is_good", VectorOfVectors(is_good[energy > 25]))
114
115
 
115
- for name, info in config["operations"].items():
116
- msg = f"computing field {name}"
117
- log.debug(msg)
116
+ out_tab.add_field("energy", VectorOfVectors(energy[energy > 25]))
117
+ out_tab.add_field("multiplicity", Array(ak.sum(energy > 25, axis=-1).to_numpy()))
118
118
 
119
- defaultv = info.get("initial", np.nan)
120
- if isinstance(defaultv, str) and (defaultv in ["np.nan", "np.inf", "-np.inf"]):
121
- defaultv = eval(defaultv)
119
+ # write table
120
+ wo_mode = "of" if idx == 0 else "append"
122
121
 
123
- channels_use = utils.get_channels_from_groups(info.get("channels", []), channels)
124
- channels_exclude = utils.get_channels_from_groups(
125
- info.get("exclude_channels", []), channels
126
- )
122
+ # add attrs
123
+ out_tab.attrs["tables"] = tcm.attrs["tables"]
127
124
 
128
- if "aggregation_mode" not in info:
129
- field = out_tab.eval(
130
- info["expression"].replace("evt.", ""), info.get("parameters", {})
131
- )
132
- else:
133
- field = evaluate_expression(
134
- file_info,
135
- tcm,
136
- channels_use,
137
- table=out_tab,
138
- mode=info["aggregation_mode"],
139
- expr=info["expression"],
140
- query=info.get("query", None),
141
- sorter=info.get("sort", None),
142
- channels_skip=channels_exclude,
143
- default_value=defaultv,
144
- n_rows=n_rows,
145
- )
146
-
147
- msg = f"field {field}"
148
- log.debug(msg)
149
- out_tab.add_field(name, field)
150
-
151
- # remove fields if necessary
152
- existing_cols = list(out_tab.keys())
153
- for col in existing_cols:
154
- if col not in config["outputs"]:
155
- out_tab.remove_column(col, delete=True)
156
-
157
- # write
158
- if evt_file is not None:
159
- write(out_tab, "evt", evt_file, wo_mode=mode)
160
- mode = "append"
125
+ if outfile is not None:
126
+ lh5.write(out_tab, "evt", outfile, wo_mode=wo_mode)
161
127
  else:
162
- out_ak = ak.concatenate((out_ak, out_tab.view_as("ak")))
128
+ tab = (
129
+ ak.concatenate((tab, out_tab.view_as("ak")))
130
+ if tab is not None
131
+ else out_tab.view_as("ak")
132
+ )
163
133
 
164
- if evt_file is None:
165
- return out_ak
166
- return None
134
+ return Table(tab)
reboost/core.py CHANGED
@@ -5,7 +5,9 @@ import time
5
5
  from typing import Any
6
6
 
7
7
  import awkward as ak
8
+ import numpy as np
8
9
  from dbetto import AttrsDict
10
+ from lgdo import lh5
9
11
  from lgdo.types import LGDO, Table
10
12
 
11
13
  from . import utils
@@ -14,6 +16,78 @@ from .profile import ProfileDict
14
16
  log = logging.getLogger(__name__)
15
17
 
16
18
 
19
+ def read_data_at_channel_as_ak(
20
+ channels: ak.Array, rows: ak.Array, file: str, field: str, group: str, tab_map: dict[int, str]
21
+ ) -> ak.Array:
22
+ r"""Read the data from a particular field to an awkward array. This replaces the TCM like object defined by the channels and rows with the corresponding data field.
23
+
24
+ Parameters
25
+ ----------
26
+ channels
27
+ Array of the channel indices (uids).
28
+ rows
29
+ Array of the rows in the files to gather data from.
30
+ file
31
+ File to read the data from.
32
+ field
33
+ the field to read.
34
+ group
35
+ the group to read data from (eg. `hit` or `stp`.)
36
+ tab_map
37
+ mapping between indices and table names. Of the form:
38
+
39
+ .. code:: python
40
+
41
+ {NAME: UID}
42
+
43
+ For example:
44
+
45
+ .. code:: python
46
+
47
+ {"det001": 1, "det002": 2}
48
+
49
+ Returns
50
+ -------
51
+ an array with the data, of the same same as the channels and rows.
52
+ """
53
+ # initialise the output
54
+ data_flat = None
55
+ tcm_rows_full = None
56
+
57
+ # save the unflattening
58
+ reorder = ak.num(rows)
59
+
60
+ for tab_name, key in tab_map.items():
61
+ # get the rows to read
62
+
63
+ idx = ak.flatten(rows[channels == key]).to_numpy()
64
+ arg_idx = np.argsort(idx)
65
+
66
+ # get the rows in the flattened data we want to append to
67
+ tcm_rows = np.where(ak.flatten(channels == key))[0]
68
+
69
+ # read the data with sorted idx
70
+ data_ch = lh5.read(f"{group}/{tab_name}/{field}", file, idx=idx[arg_idx]).view_as("ak")
71
+
72
+ # sort back to order for tcm
73
+ data_ch = data_ch[np.argsort(arg_idx)]
74
+
75
+ # append to output
76
+ data_flat = ak.concatenate((data_flat, data_ch)) if data_flat is not None else data_ch
77
+ tcm_rows_full = (
78
+ np.concatenate((tcm_rows_full, tcm_rows)) if tcm_rows_full is not None else tcm_rows
79
+ )
80
+
81
+ if len(data_flat) != len(tcm_rows_full):
82
+ msg = "every index in the tcm should have been read"
83
+ raise ValueError(msg)
84
+
85
+ # sort the final data
86
+ data_flat = data_flat[np.argsort(tcm_rows_full)]
87
+
88
+ return ak.unflatten(data_flat, reorder)
89
+
90
+
17
91
  def evaluate_output_column(
18
92
  hit_table: Table,
19
93
  expression: str,
reboost/math/stats.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
+ from typing import Callable
4
5
 
5
6
  import awkward as ak
6
7
  import numpy as np
@@ -10,7 +11,68 @@ from numpy.typing import ArrayLike
10
11
  log = logging.getLogger(__name__)
11
12
 
12
13
 
13
- def gaussian_sample(mu: ArrayLike, sigma: ArrayLike | float, *, seed: int = 999) -> Array:
14
+ def get_resolution(
15
+ energies: ak.Array, channels: ak.Array, tcm_tables: dict, reso_pars: dict, reso_func: Callable
16
+ ) -> ak.Array:
17
+ """Get the resolution for each energy.
18
+
19
+ Parameters
20
+ ----------
21
+ energies
22
+ the energies to smear
23
+ channels
24
+ the channel index for each energy
25
+ tcm_tables
26
+ the mapping from indices to channel names.
27
+ reso_pars
28
+ the pars for each channel.
29
+ reso_func
30
+ the function to compute the resolution.
31
+ """
32
+ n_pars = len(reso_pars[next(iter(reso_pars))])
33
+
34
+ pars_shaped = []
35
+
36
+ for _ in range(n_pars):
37
+ pars_shaped.append(np.zeros(len(ak.flatten(channels))))
38
+
39
+ num = ak.num(channels, axis=-1)
40
+
41
+ for key, value in tcm_tables.items():
42
+ for i in range(n_pars):
43
+ pars_shaped[i][ak.flatten(channels) == value] = reso_pars[key][i]
44
+
45
+ ch_reso = reso_func(ak.flatten(energies), *pars_shaped)
46
+ return ak.unflatten(ch_reso, num)
47
+
48
+
49
+ def apply_energy_resolution(
50
+ energies: ak.Array, channels: ak.Array, tcm_tables: dict, reso_pars: dict, reso_func: Callable
51
+ ):
52
+ """Apply the energy resolution sampling to an array with many channels.
53
+
54
+ Parameters
55
+ ----------
56
+ energies
57
+ the energies to smear
58
+ channels
59
+ the channel index for each energy
60
+ tcm_tables
61
+ the mapping from indices to channel names.
62
+ reso_pars
63
+ the pars for each channel.
64
+ reso_func
65
+ the function to compute the resolution.
66
+ """
67
+ num = ak.num(channels, axis=-1)
68
+
69
+ ch_reso = get_resolution(energies, channels, tcm_tables, reso_pars, reso_func)
70
+ energies_flat_smear = gaussian_sample(ak.flatten(energies), ak.flatten(ch_reso))
71
+
72
+ return ak.unflatten(energies_flat_smear, num)
73
+
74
+
75
+ def gaussian_sample(mu: ArrayLike, sigma: ArrayLike | float, *, seed: int | None = None) -> Array:
14
76
  r"""Generate samples from a gaussian.
15
77
 
16
78
  Based on:
reboost/shape/group.py CHANGED
@@ -4,11 +4,49 @@ import logging
4
4
 
5
5
  import awkward as ak
6
6
  import numpy as np
7
+ from dbetto import AttrsDict
7
8
  from lgdo import Table, VectorOfVectors
9
+ from numpy.typing import ArrayLike
8
10
 
9
11
  log = logging.getLogger(__name__)
10
12
 
11
13
 
14
+ def isin(channels: ak.Array, chan_list: list):
15
+ """Check if each element of the awkward array channels is in the channel list."""
16
+ num_channels = ak.num(channels, axis=-1)
17
+ channels_flat = ak.flatten(channels)
18
+ isin = np.isin(channels_flat, chan_list)
19
+
20
+ # unflatten
21
+ return ak.unflatten(isin, num_channels)
22
+
23
+
24
+ def get_isin_group(
25
+ channels: ArrayLike, groups: AttrsDict, tcm_tables: dict, group: str = "off"
26
+ ) -> ak.Array:
27
+ """For each channel check if it is in the group.
28
+
29
+ Parameters
30
+ ----------
31
+ channels
32
+ Array of the channel indices.
33
+ groups
34
+ A mapping of the group for every channel name.
35
+ tcm_tables
36
+ the mapping of indices to table names
37
+ group
38
+ the group to select.
39
+
40
+ Returns
41
+ -------
42
+ an awkward array of the same shape of channels of booleans.
43
+ """
44
+ usability = {uid: groups[name] for name, uid in tcm_tables.items()}
45
+ group_idx = [key for key, item in usability.items() if item == group]
46
+
47
+ return isin(channels, group_idx)
48
+
49
+
12
50
  def _sort_data(obj: ak.Array, *, time_name: str = "time", evtid_name: str = "evtid") -> ak.Array:
13
51
  """Sort the data by evtid then time.
14
52
 
reboost/utils.py CHANGED
@@ -18,10 +18,47 @@ from .profile import ProfileDict
18
18
  log = logging.getLogger(__name__)
19
19
 
20
20
 
21
+ def get_table_names(tcm: VectorOfVectors) -> dict:
22
+ """Extract table names from tcm.attrs['tables'] and return them as a dictionary."""
23
+ raw = tcm.attrs["tables"]
24
+ cleaned = raw.strip("[]").replace(" ", "").replace("'", "")
25
+ tables = cleaned.split(",")
26
+ tables = [tab.split("/")[-1] for tab in tables]
27
+
28
+ return {name: idx for idx, name in enumerate(tables)}
29
+
30
+
21
31
  def get_wo_mode(
22
32
  group: int, out_det: int, in_det: int, chunk: int, new_hit_file: bool, overwrite: bool = False
23
- ):
24
- """Get the mode for lh5 file writing."""
33
+ ) -> str:
34
+ """Get the mode for lh5 file writing.
35
+
36
+ If all indices are 0 and we are writing a new output file
37
+ then the mode "overwrite_file" is used (if the overwrite) flag
38
+ is set, otherwise the mode "write_safe" is used.
39
+
40
+ Otherwise the code choses between "append_column" if this is the
41
+ first time a group is being written to the file, or "append"
42
+
43
+ Parameters
44
+ ----------
45
+ group
46
+ the index of the processing group
47
+ out_det
48
+ the index of the output detector
49
+ in_det
50
+ the index of the input detector
51
+ chunk
52
+ the chunk index
53
+ new_hit_file
54
+ a flag of whether we are writing a new hit file
55
+ overwrite
56
+ a flag of whether to overwrite the old file.
57
+
58
+ Returns
59
+ -------
60
+ the mode for IO
61
+ """
25
62
  indices = [group, out_det, in_det, chunk]
26
63
 
27
64
  good_idx = all(i == 0 for i in indices)
@@ -30,9 +67,10 @@ def get_wo_mode(
30
67
  return "overwrite_file" if overwrite else "write_safe"
31
68
 
32
69
  # if we have a detector not the first and chunk 0 append column
33
- is_append = ((in_det > 0) or (out_det > 0)) & (chunk == 0)
34
- is_append = is_append or (in_det == 0 and out_det == 0 and chunk == 0 and group > 0)
35
- if is_append:
70
+ is_ac = ((in_det > 0) or (out_det > 0)) & (chunk == 0)
71
+ is_ac = is_ac or (in_det == 0 and out_det == 0 and chunk == 0 and (group > 0))
72
+
73
+ if is_ac and new_hit_file:
36
74
  return "append_column"
37
75
  return "append"
38
76
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reboost
3
- Version: 0.5.4
3
+ Version: 0.6.0
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
@@ -696,6 +696,7 @@ Classifier: Topic :: Scientific/Engineering
696
696
  Requires-Python: >=3.9
697
697
  Description-Content-Type: text/markdown
698
698
  License-File: LICENSE
699
+ Requires-Dist: hdf5plugin
699
700
  Requires-Dist: colorlog
700
701
  Requires-Dist: numpy
701
702
  Requires-Dist: scipy
@@ -1,22 +1,22 @@
1
- reboost/__init__.py,sha256=3cYLf7XEyFRX5GK8f50gY4ecGR5O5HORITpDthOFpOg,265
2
- reboost/_version.py,sha256=dcAaO0Qe1IlOwiMsqG0TVZdK_BIVQUv1DNRmnBueT2I,511
3
- reboost/build_evt.py,sha256=yH0bf4bwbp4feWV3JgvSAD5RcvhOX6c9PhH8FAe3Xv4,4710
1
+ reboost/__init__.py,sha256=VZz9uo7i2jgAx8Zi15SptLZnE_qcnGuNWwqkD3rYHFA,278
2
+ reboost/_version.py,sha256=jF9TuoEIJRaca3ScKo6qaz6PzaMlu7jjuSQIrJ3nX4U,511
3
+ reboost/build_evt.py,sha256=VXIfK_pfe_Cgym6gI8dESwONZi-v_4fll0Pn09vePQY,3767
4
4
  reboost/build_glm.py,sha256=IerSLQfe51ZO7CQP2kmfPnOIVaDtcfw3byOM02Vaz6o,9472
5
5
  reboost/build_hit.py,sha256=23JL5B7qThdHZqAK_HWoytqcEOWDhGsk4n5UMtojJ1c,15513
6
6
  reboost/cli.py,sha256=HZgqUZK0tSmnlGqoXjrbmLitW_i001TzibxvDrRxLLg,6324
7
- reboost/core.py,sha256=pUco_IaTKf50PTVrtyFwoYveJVS58mqs9P3TUrtEyjs,12827
7
+ reboost/core.py,sha256=WGbWe2rcfMDEaehVyw7peqAHoTFWoCu5J6CdWHC5aWA,14974
8
8
  reboost/iterator.py,sha256=fATFDxu2PUc0e48OdJJujZo2kwykfRLH1oBtcB-s5pM,6905
9
9
  reboost/log_utils.py,sha256=VqS_9OC5NeNU3jcowVOBB0NJ6ssYvNWnirEY-JVduEA,766
10
10
  reboost/profile.py,sha256=EOTmjmS8Rm_nYgBWNh6Rntl2XDsxdyed7yEdWtsZEeg,2598
11
11
  reboost/units.py,sha256=3EH8XlpbsObdu5vLgxhm1600L6UNYD5jng4SjJT_1QE,2202
12
- reboost/utils.py,sha256=0xU68p0YSnDKTyLdso8zX4JYrGTVCjIiTBx7cuSCz98,9820
12
+ reboost/utils.py,sha256=WT2jlyRT3LEMBEBRJtYIat3KIIZKocv4rHlTViBbhYM,10938
13
13
  reboost/hpge/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  reboost/hpge/psd.py,sha256=jAUAoQ_PMz76wyA1NXYHNKtOwoCnRT3My8_LCFrKi-U,13860
15
15
  reboost/hpge/surface.py,sha256=lbWcFnFFWKxtFKs755GyM9US_IfyxaoM6MpOIZgIMM0,7478
16
16
  reboost/hpge/utils.py,sha256=0Rx4HubCOm8JMECjWcAJXfAch9OkSlRpUkdsSlzwZ2E,2830
17
17
  reboost/math/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  reboost/math/functions.py,sha256=OymiYTcA0NXxxm-MBDw5kqyNwHoLCmuv4J48AwnSrbU,5633
19
- reboost/math/stats.py,sha256=iiOEi87x93kqPWeSmlRiA5Oe-R8XR-plm6Z532PhC9M,1401
19
+ reboost/math/stats.py,sha256=cG-6mQx33Dzpv3ABkHLEwC104WJ_PMgbWtmjg37SBj4,3164
20
20
  reboost/optmap/__init__.py,sha256=imvuyld-GLw8qdwqW-lXCg2feptcTyQo3wIzPvDHwmY,93
21
21
  reboost/optmap/cli.py,sha256=SzbPRgsbR5Llm3aSJubH02Ym8FQyTH7kvuLjK7faLiY,9572
22
22
  reboost/optmap/convolve.py,sha256=_volpLmhW5mOPA0KkzXRyHyqkj4_zDSnvfHv1Dtuxm8,14390
@@ -27,11 +27,11 @@ reboost/optmap/numba_pdg.py,sha256=y8cXR5PWE2Liprp4ou7vl9do76dl84vXU52ZJD9_I7A,7
27
27
  reboost/optmap/optmap.py,sha256=j4rfbQ84PYSpE-BvP4Rdt96ZjPdwy8P4e4eZz1mATys,12817
28
28
  reboost/shape/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  reboost/shape/cluster.py,sha256=RIvBlhHzp88aaUZGofp5SD9bimnoiqIOddhQ84jiwoM,8135
30
- reboost/shape/group.py,sha256=_z2qCOret3E-kj-nrp1-J5j2lEwQpgfYdQp2pgpDHR8,4449
30
+ reboost/shape/group.py,sha256=gOCYgir2gZqmW1JXtbNRPlQqP0gmUcbe7RVb9CbY1pU,5540
31
31
  reboost/shape/reduction.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
- reboost-0.5.4.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
33
- reboost-0.5.4.dist-info/METADATA,sha256=mFAy4qMlKnuWJB8V8FwF4Y5fdu-pw5ThJP3WYZGS9Ws,44248
34
- reboost-0.5.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
- reboost-0.5.4.dist-info/entry_points.txt,sha256=DxhD6BidSWNot9BrejHJjQ7RRLmrMaBIl52T75oWTwM,93
36
- reboost-0.5.4.dist-info/top_level.txt,sha256=q-IBsDepaY_AbzbRmQoW8EZrITXRVawVnNrB-_zyXZs,8
37
- reboost-0.5.4.dist-info/RECORD,,
32
+ reboost-0.6.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
33
+ reboost-0.6.0.dist-info/METADATA,sha256=QGF9b0vthakVY3Wl9OUQnPIyAv3IYpui4WK9Zkp7Nwo,44274
34
+ reboost-0.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
+ reboost-0.6.0.dist-info/entry_points.txt,sha256=DxhD6BidSWNot9BrejHJjQ7RRLmrMaBIl52T75oWTwM,93
36
+ reboost-0.6.0.dist-info/top_level.txt,sha256=q-IBsDepaY_AbzbRmQoW8EZrITXRVawVnNrB-_zyXZs,8
37
+ reboost-0.6.0.dist-info/RECORD,,