figpack 0.2.6__py3-none-any.whl → 0.2.8__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.
Potentially problematic release.
This version of figpack might be problematic. Click here for more details.
- figpack/__init__.py +1 -1
- figpack/figpack-figure-dist/assets/{index-HXdk2TtM.js → index-CjiTpC6i.js} +90 -89
- figpack/figpack-figure-dist/index.html +1 -1
- figpack/spike_sorting/views/RasterPlot.py +237 -26
- figpack/spike_sorting/views/SpikeAmplitudes.py +321 -36
- figpack/views/DataFrame.py +109 -0
- figpack/views/Spectrogram.py +223 -0
- figpack/views/__init__.py +2 -0
- {figpack-0.2.6.dist-info → figpack-0.2.8.dist-info}/METADATA +2 -1
- {figpack-0.2.6.dist-info → figpack-0.2.8.dist-info}/RECORD +14 -12
- {figpack-0.2.6.dist-info → figpack-0.2.8.dist-info}/WHEEL +0 -0
- {figpack-0.2.6.dist-info → figpack-0.2.8.dist-info}/entry_points.txt +0 -0
- {figpack-0.2.6.dist-info → figpack-0.2.8.dist-info}/licenses/LICENSE +0 -0
- {figpack-0.2.6.dist-info → figpack-0.2.8.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Spectrogram visualization component
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import math
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
import zarr
|
|
10
|
+
|
|
11
|
+
from ..core.figpack_view import FigpackView
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Spectrogram(FigpackView):
|
|
15
|
+
"""
|
|
16
|
+
A spectrogram visualization component for time-frequency data
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
*,
|
|
22
|
+
start_time_sec: float,
|
|
23
|
+
sampling_frequency_hz: float,
|
|
24
|
+
frequency_min_hz: float,
|
|
25
|
+
frequency_delta_hz: float,
|
|
26
|
+
data: np.ndarray,
|
|
27
|
+
):
|
|
28
|
+
"""
|
|
29
|
+
Initialize a Spectrogram view
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
start_time_sec: Starting time in seconds
|
|
33
|
+
sampling_frequency_hz: Sampling rate in Hz
|
|
34
|
+
frequency_min_hz: Minimum frequency in Hz
|
|
35
|
+
frequency_delta_hz: Frequency bin spacing in Hz
|
|
36
|
+
data: N×M numpy array where N is timepoints and M is frequency bins
|
|
37
|
+
"""
|
|
38
|
+
assert data.ndim == 2, "Data must be a 2D array (timepoints × frequencies)"
|
|
39
|
+
assert sampling_frequency_hz > 0, "Sampling frequency must be positive"
|
|
40
|
+
assert frequency_delta_hz > 0, "Frequency delta must be positive"
|
|
41
|
+
|
|
42
|
+
self.start_time_sec = start_time_sec
|
|
43
|
+
self.sampling_frequency_hz = sampling_frequency_hz
|
|
44
|
+
self.frequency_min_hz = frequency_min_hz
|
|
45
|
+
self.frequency_delta_hz = frequency_delta_hz
|
|
46
|
+
self.data = data.astype(np.float32) # Ensure float32 for efficiency
|
|
47
|
+
|
|
48
|
+
n_timepoints, n_frequencies = data.shape
|
|
49
|
+
self.n_timepoints = n_timepoints
|
|
50
|
+
self.n_frequencies = n_frequencies
|
|
51
|
+
|
|
52
|
+
# Calculate frequency bins
|
|
53
|
+
self.frequency_bins = (
|
|
54
|
+
frequency_min_hz + np.arange(n_frequencies) * frequency_delta_hz
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Calculate data range for color scaling
|
|
58
|
+
self.data_min = float(np.nanmin(data))
|
|
59
|
+
self.data_max = float(np.nanmax(data))
|
|
60
|
+
|
|
61
|
+
# Prepare downsampled arrays for efficient rendering
|
|
62
|
+
self.downsampled_data = self._compute_downsampled_data()
|
|
63
|
+
|
|
64
|
+
def _compute_downsampled_data(self) -> dict:
|
|
65
|
+
"""
|
|
66
|
+
Compute downsampled arrays at power-of-4 factors using max values only.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
dict: {factor: (ceil(N/factor), M) float32 array}, where each bin
|
|
70
|
+
contains the maximum value across the time dimension.
|
|
71
|
+
"""
|
|
72
|
+
data = self.data # (N, M), float32
|
|
73
|
+
n_timepoints, n_frequencies = data.shape
|
|
74
|
+
downsampled = {}
|
|
75
|
+
|
|
76
|
+
if n_timepoints < 4:
|
|
77
|
+
# No level with factor >= 4 fits the stop condition (factor < N)
|
|
78
|
+
return downsampled
|
|
79
|
+
|
|
80
|
+
def _first_level_from_raw(x: np.ndarray) -> np.ndarray:
|
|
81
|
+
"""Build the factor=4 level directly from the raw data."""
|
|
82
|
+
N, M = x.shape
|
|
83
|
+
n_bins = math.ceil(N / 4)
|
|
84
|
+
pad = n_bins * 4 - N
|
|
85
|
+
# Pad time axis with NaNs so max ignores the padded tail
|
|
86
|
+
x_pad = np.pad(
|
|
87
|
+
x, ((0, pad), (0, 0)), mode="constant", constant_values=np.nan
|
|
88
|
+
)
|
|
89
|
+
blk = x_pad.reshape(n_bins, 4, M) # (B, 4, M)
|
|
90
|
+
maxs = np.nanmax(blk, axis=1) # (B, M)
|
|
91
|
+
return maxs.astype(np.float32)
|
|
92
|
+
|
|
93
|
+
def _downsample4_bins(level_max: np.ndarray) -> np.ndarray:
|
|
94
|
+
"""
|
|
95
|
+
Build the next pyramid level from the previous one by grouping every 4
|
|
96
|
+
bins. Input is (B, M) -> Output is (ceil(B/4), M).
|
|
97
|
+
"""
|
|
98
|
+
B, M = level_max.shape
|
|
99
|
+
n_bins_next = math.ceil(B / 4)
|
|
100
|
+
pad = n_bins_next * 4 - B
|
|
101
|
+
lvl_pad = np.pad(
|
|
102
|
+
level_max,
|
|
103
|
+
((0, pad), (0, 0)),
|
|
104
|
+
mode="constant",
|
|
105
|
+
constant_values=np.nan,
|
|
106
|
+
)
|
|
107
|
+
blk = lvl_pad.reshape(n_bins_next, 4, M) # (B', 4, M)
|
|
108
|
+
|
|
109
|
+
# Next maxs from maxs
|
|
110
|
+
maxs = np.nanmax(blk, axis=1) # (B', M)
|
|
111
|
+
return maxs.astype(np.float32)
|
|
112
|
+
|
|
113
|
+
# Level 1: factor = 4 from raw data
|
|
114
|
+
factor = 4
|
|
115
|
+
level = _first_level_from_raw(data)
|
|
116
|
+
downsampled[factor] = level
|
|
117
|
+
|
|
118
|
+
# Higher levels: factor *= 4 each time, built from previous level
|
|
119
|
+
factor *= 4 # -> 16
|
|
120
|
+
while factor < n_timepoints / 1000:
|
|
121
|
+
level = _downsample4_bins(level)
|
|
122
|
+
downsampled[factor] = level
|
|
123
|
+
factor *= 4
|
|
124
|
+
|
|
125
|
+
return downsampled
|
|
126
|
+
|
|
127
|
+
def _calculate_optimal_chunk_size(
|
|
128
|
+
self, shape: tuple, target_size_mb: float = 5.0
|
|
129
|
+
) -> tuple:
|
|
130
|
+
"""
|
|
131
|
+
Calculate optimal chunk size for Zarr storage targeting ~5MB per chunk
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
shape: Array shape (n_timepoints, n_frequencies)
|
|
135
|
+
target_size_mb: Target chunk size in MB
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
Tuple of chunk dimensions
|
|
139
|
+
"""
|
|
140
|
+
# Calculate bytes per element (float32 = 4 bytes)
|
|
141
|
+
bytes_per_element = 4
|
|
142
|
+
target_size_bytes = target_size_mb * 1024 * 1024
|
|
143
|
+
|
|
144
|
+
n_timepoints, n_frequencies = shape
|
|
145
|
+
elements_per_timepoint = n_frequencies
|
|
146
|
+
|
|
147
|
+
# Calculate chunk size in timepoints
|
|
148
|
+
max_timepoints_per_chunk = target_size_bytes // (
|
|
149
|
+
elements_per_timepoint * bytes_per_element
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# Find next lower power of 2
|
|
153
|
+
chunk_timepoints = 2 ** math.floor(math.log2(max_timepoints_per_chunk))
|
|
154
|
+
chunk_timepoints = max(chunk_timepoints, 1) # At least 1
|
|
155
|
+
chunk_timepoints = min(chunk_timepoints, n_timepoints) # At most n_timepoints
|
|
156
|
+
|
|
157
|
+
# If n_timepoints is less than our calculated size, round down to next power of 2
|
|
158
|
+
if chunk_timepoints > n_timepoints:
|
|
159
|
+
chunk_timepoints = 2 ** math.floor(math.log2(n_timepoints))
|
|
160
|
+
|
|
161
|
+
return (chunk_timepoints, n_frequencies)
|
|
162
|
+
|
|
163
|
+
def _write_to_zarr_group(self, group: zarr.Group) -> None:
|
|
164
|
+
"""
|
|
165
|
+
Write the spectrogram data to a Zarr group
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
group: Zarr group to write data into
|
|
169
|
+
"""
|
|
170
|
+
group.attrs["view_type"] = "Spectrogram"
|
|
171
|
+
|
|
172
|
+
# Store metadata
|
|
173
|
+
group.attrs["start_time_sec"] = self.start_time_sec
|
|
174
|
+
group.attrs["sampling_frequency_hz"] = self.sampling_frequency_hz
|
|
175
|
+
group.attrs["frequency_min_hz"] = self.frequency_min_hz
|
|
176
|
+
group.attrs["frequency_delta_hz"] = self.frequency_delta_hz
|
|
177
|
+
group.attrs["n_timepoints"] = self.n_timepoints
|
|
178
|
+
group.attrs["n_frequencies"] = self.n_frequencies
|
|
179
|
+
group.attrs["data_min"] = self.data_min
|
|
180
|
+
group.attrs["data_max"] = self.data_max
|
|
181
|
+
|
|
182
|
+
# Store frequency bins
|
|
183
|
+
group.create_dataset(
|
|
184
|
+
"frequency_bins",
|
|
185
|
+
data=self.frequency_bins.astype(np.float32),
|
|
186
|
+
compression="blosc",
|
|
187
|
+
compression_opts={"cname": "lz4", "clevel": 5, "shuffle": 1},
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# Store original data with optimal chunking
|
|
191
|
+
original_chunks = self._calculate_optimal_chunk_size(self.data.shape)
|
|
192
|
+
group.create_dataset(
|
|
193
|
+
"data",
|
|
194
|
+
data=self.data,
|
|
195
|
+
chunks=original_chunks,
|
|
196
|
+
compression="blosc",
|
|
197
|
+
compression_opts={"cname": "lz4", "clevel": 5, "shuffle": 1},
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
# Store downsampled data arrays
|
|
201
|
+
downsample_factors = list(self.downsampled_data.keys())
|
|
202
|
+
group.attrs["downsample_factors"] = downsample_factors
|
|
203
|
+
|
|
204
|
+
for factor, downsampled_array in self.downsampled_data.items():
|
|
205
|
+
dataset_name = f"data_ds_{factor}"
|
|
206
|
+
|
|
207
|
+
# Calculate optimal chunks for this downsampled array
|
|
208
|
+
ds_chunks = self._calculate_optimal_chunk_size(downsampled_array.shape)
|
|
209
|
+
|
|
210
|
+
group.create_dataset(
|
|
211
|
+
dataset_name,
|
|
212
|
+
data=downsampled_array,
|
|
213
|
+
chunks=ds_chunks,
|
|
214
|
+
compression="blosc",
|
|
215
|
+
compression_opts={"cname": "lz4", "clevel": 5, "shuffle": 1},
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
print(f"Stored Spectrogram with {len(downsample_factors)} downsampled levels:")
|
|
219
|
+
print(f" Original: {self.data.shape} (chunks: {original_chunks})")
|
|
220
|
+
for factor in downsample_factors:
|
|
221
|
+
ds_shape = self.downsampled_data[factor].shape
|
|
222
|
+
ds_chunks = self._calculate_optimal_chunk_size(ds_shape)
|
|
223
|
+
print(f" Factor {factor}: {ds_shape} (chunks: {ds_chunks})")
|
figpack/views/__init__.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from .Box import Box
|
|
2
|
+
from .DataFrame import DataFrame
|
|
2
3
|
from .Gallery import Gallery
|
|
3
4
|
from .GalleryItem import GalleryItem
|
|
4
5
|
from .Image import Image
|
|
@@ -7,6 +8,7 @@ from .Markdown import Markdown
|
|
|
7
8
|
from .MatplotlibFigure import MatplotlibFigure
|
|
8
9
|
from .MultiChannelTimeseries import MultiChannelTimeseries
|
|
9
10
|
from .PlotlyFigure import PlotlyFigure
|
|
11
|
+
from .Spectrogram import Spectrogram
|
|
10
12
|
from .Splitter import Splitter
|
|
11
13
|
from .TabLayout import TabLayout
|
|
12
14
|
from .TabLayoutItem import TabLayoutItem
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: figpack
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: A Python package for creating shareable, interactive visualizations in the browser
|
|
5
5
|
Author-email: Jeremy Magland <jmagland@flatironinstitute.org>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -36,6 +36,7 @@ Requires-Dist: spikeinterface; extra == "test"
|
|
|
36
36
|
Requires-Dist: matplotlib; extra == "test"
|
|
37
37
|
Requires-Dist: plotly; extra == "test"
|
|
38
38
|
Requires-Dist: Pillow; extra == "test"
|
|
39
|
+
Requires-Dist: pandas; extra == "test"
|
|
39
40
|
Provides-Extra: dev
|
|
40
41
|
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
41
42
|
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
figpack/__init__.py,sha256=
|
|
1
|
+
figpack/__init__.py,sha256=HxAr8mGrHvxeBsPiVIzWFXNs2g74PFwMyFB8yfQK1u4,181
|
|
2
2
|
figpack/cli.py,sha256=xWF7J2BxUqOLvPu-Kje7Q6oGukTroXsLq8WN8vJgyw0,8321
|
|
3
3
|
figpack/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
figpack/core/_bundle_utils.py,sha256=JBZh2LJyu0oYHQBBVw5fF3uUNQJY_2bxVf6V7CN10FM,1884
|
|
@@ -9,9 +9,9 @@ figpack/core/_upload_bundle.py,sha256=54hdWayJJdRZdx7N9V2aH_X33KkR6hImMjN6tkBTLi
|
|
|
9
9
|
figpack/core/_view_figure.py,sha256=o1x1I2VKFrp2W_TStUS3fQblRW8AvGbu7Uy7MgVjofA,4186
|
|
10
10
|
figpack/core/config.py,sha256=oOR7SlP192vuFhYlS-h14HnG-kd_3gaz0vshXch2RNc,173
|
|
11
11
|
figpack/core/figpack_view.py,sha256=peJFkoP6HIqyNATzyucxAIq9HuCnK7SRO_-gE_rbEvg,6130
|
|
12
|
-
figpack/figpack-figure-dist/index.html,sha256=
|
|
12
|
+
figpack/figpack-figure-dist/index.html,sha256=koS5dlEb8lylfHmHnG5pBmXHlMIyK2ICrJ31aw5COmE,486
|
|
13
|
+
figpack/figpack-figure-dist/assets/index-CjiTpC6i.js,sha256=5JLWD3VReahxiEbAB0h61FJCRe4CRZVEzBlX9qUS5m0,1618290
|
|
13
14
|
figpack/figpack-figure-dist/assets/index-Cmae55E4.css,sha256=Yg0apcYehJwQvSQIUH13S7tsfqWQDevpJsAho0dDf0g,5499
|
|
14
|
-
figpack/figpack-figure-dist/assets/index-HXdk2TtM.js,sha256=GhqJkoATKYiprLAbc3V5CYUt-MtKteWLx7KUh1fjA_0,1598198
|
|
15
15
|
figpack/figpack-figure-dist/assets/neurosift-logo-CLsuwLMO.png,sha256=g5m-TwrGh5f6-9rXtWV-znH4B0nHgc__0GWclRDLUHs,9307
|
|
16
16
|
figpack/franklab/__init__.py,sha256=HkehqGImJE_sE2vbPDo-HbgtEYaMICb9-230xTYvRTU,56
|
|
17
17
|
figpack/franklab/views/TrackAnimation.py,sha256=3Jv1Ri4FIwTyqNahinqhHsBH1Bv_iZrEGx12w6diJ2M,5636
|
|
@@ -22,9 +22,9 @@ figpack/spike_sorting/views/Autocorrelograms.py,sha256=6MXOYJKUNEhJokiyOs8SGJVF9
|
|
|
22
22
|
figpack/spike_sorting/views/AverageWaveforms.py,sha256=mvMkS3wf6MpI95tlGqKxBjxZlHqJr4aqG7SZvHigIsI,5193
|
|
23
23
|
figpack/spike_sorting/views/CrossCorrelogramItem.py,sha256=uSd0i2hupteuILi_aKp7bYPYpL_PdC3CUDRMOEKUEM0,880
|
|
24
24
|
figpack/spike_sorting/views/CrossCorrelograms.py,sha256=OGQq_5t_T1zq4eFCpuTAvUIhZQu7ef7LVexKNdByMvo,4415
|
|
25
|
-
figpack/spike_sorting/views/RasterPlot.py,sha256=
|
|
25
|
+
figpack/spike_sorting/views/RasterPlot.py,sha256=m8Cg-KioAM3CdIJOecpyTqp71HwhQVDzAk3J4Xb4V-c,9940
|
|
26
26
|
figpack/spike_sorting/views/RasterPlotItem.py,sha256=iW7fuDEjSfvf5YMIwrF_6cmKvD76oCigOUMHtGgBsPI,638
|
|
27
|
-
figpack/spike_sorting/views/SpikeAmplitudes.py,sha256=
|
|
27
|
+
figpack/spike_sorting/views/SpikeAmplitudes.py,sha256=UOGxReKs5WwH7iRdR-iVN3Pr6wF3AnIV15veoZZzOco,13433
|
|
28
28
|
figpack/spike_sorting/views/SpikeAmplitudesItem.py,sha256=j5Na-diY-vRUAPu0t0VkyFCSKFnQ_f5HT077mB3Cy8c,1134
|
|
29
29
|
figpack/spike_sorting/views/UnitSimilarityScore.py,sha256=cJA9MkETos9qHhV1tqgA7SfNEaPo-duXYCE76hSFGnA,948
|
|
30
30
|
figpack/spike_sorting/views/UnitsTable.py,sha256=M3y1IDJzSnvOaM1-QOyJOVcUcdTkVvxYhEMGd1kmUzs,2969
|
|
@@ -32,6 +32,7 @@ figpack/spike_sorting/views/UnitsTableColumn.py,sha256=zBnuoeILTuiVLDvtcOxqa37E5
|
|
|
32
32
|
figpack/spike_sorting/views/UnitsTableRow.py,sha256=rEb2hMTA_pl2fTW1nOvnGir0ysfNx4uww3aekZzfWjk,720
|
|
33
33
|
figpack/spike_sorting/views/__init__.py,sha256=iRq7xPmyhnQ3GffnPC0GxKGEWnlqXY_8IOxsMqYZ1IM,967
|
|
34
34
|
figpack/views/Box.py,sha256=TfhPFNtVEq71LCucmWk3XX2WxQLdaeRiWGm5BM0k2l4,2236
|
|
35
|
+
figpack/views/DataFrame.py,sha256=VFP-EM_Wnc1G3uimVVMJe08KKWCAZe7DvmYf5e07uTk,3653
|
|
35
36
|
figpack/views/Gallery.py,sha256=sHlZbaqxcktasmNsJnuxe8WmgUQ6iurG50JiChKSMbQ,3314
|
|
36
37
|
figpack/views/GalleryItem.py,sha256=b_upJno5P3ANSulbG-h3t6Xj56tPGJ7iVxqyiZu3zaQ,1244
|
|
37
38
|
figpack/views/Image.py,sha256=hmyAHlRwj0l6fC7aNmHYJFaj-qCqyH67soERm78V5dk,3953
|
|
@@ -40,14 +41,15 @@ figpack/views/Markdown.py,sha256=Dl1UX5s0aC-mEx5m6jIJ839YKMNeeVzIDG-EANVrbys,114
|
|
|
40
41
|
figpack/views/MatplotlibFigure.py,sha256=YoNtZTItEjatbtNJqATm2H-Oircp5Ca6FZLjHk_B0zg,2778
|
|
41
42
|
figpack/views/MultiChannelTimeseries.py,sha256=sWr2nW1eoYR7V44wF7fac7IoQ6BOnus1nc4STkgIkYw,8501
|
|
42
43
|
figpack/views/PlotlyFigure.py,sha256=E33PEkWSj907Ue73bYfZQlF-JFDdWA8jNrG-buFQLgs,2174
|
|
44
|
+
figpack/views/Spectrogram.py,sha256=czjA1I_T86oNsWwXX_GHFM8WZ5UkP9nT8e8hrgav4iY,8110
|
|
43
45
|
figpack/views/Splitter.py,sha256=x9jLCTlIvDy5p9ymVd0X48KDccyD6bJANhXyFgKEmtE,2007
|
|
44
46
|
figpack/views/TabLayout.py,sha256=5g3nmL95PfqgI0naqZXHMwLVo2ebDlGX01Hy9044bUw,1898
|
|
45
47
|
figpack/views/TabLayoutItem.py,sha256=xmHA0JsW_6naJze4_mQuP_Fy0Nm17p2N7w_AsmVRp8k,880
|
|
46
48
|
figpack/views/TimeseriesGraph.py,sha256=OAaCjO8fo86u_gO_frNfRGxng3tczxGDGKcJEvZo3rE,7469
|
|
47
|
-
figpack/views/__init__.py,sha256=
|
|
48
|
-
figpack-0.2.
|
|
49
|
-
figpack-0.2.
|
|
50
|
-
figpack-0.2.
|
|
51
|
-
figpack-0.2.
|
|
52
|
-
figpack-0.2.
|
|
53
|
-
figpack-0.2.
|
|
49
|
+
figpack/views/__init__.py,sha256=h9B6RWTOfgizOMqtEu8xGJxtXAhK-XXroN6ebL-Vcr0,543
|
|
50
|
+
figpack-0.2.8.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
51
|
+
figpack-0.2.8.dist-info/METADATA,sha256=ih-mdvrks4Dxrtx1ieS82NJCAQp9QcqliCeFqWmUhkk,3616
|
|
52
|
+
figpack-0.2.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
53
|
+
figpack-0.2.8.dist-info/entry_points.txt,sha256=l6d3siH2LxXa8qJGbjAqpIZtI5AkMSyDeoRDCzdrUto,45
|
|
54
|
+
figpack-0.2.8.dist-info/top_level.txt,sha256=lMKGaC5xWmAYBx9Ac1iMokm42KFnJFjmkP2ldyvOo-c,8
|
|
55
|
+
figpack-0.2.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|