figpack 0.2.9__py3-none-any.whl → 0.2.11__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/core/extension_view.py +6 -0
- figpack/core/figpack_view.py +6 -1
- figpack/figpack-figure-dist/assets/{index-Cmae55E4.css → index-D9a3K6eW.css} +1 -1
- figpack/figpack-figure-dist/assets/{index-BBJJgcTp.js → index-DvunBzII.js} +82 -84
- figpack/figpack-figure-dist/index.html +2 -2
- figpack/spike_sorting/views/UnitMetricsGraph.py +129 -0
- figpack/spike_sorting/views/__init__.py +8 -0
- figpack/views/PlotlyExtension/PlotlyExtension.py +121 -0
- figpack/views/PlotlyExtension/__init__.py +3 -0
- figpack/views/Spectrogram.py +51 -9
- figpack/views/__init__.py +1 -1
- {figpack-0.2.9.dist-info → figpack-0.2.11.dist-info}/METADATA +1 -1
- {figpack-0.2.9.dist-info → figpack-0.2.11.dist-info}/RECORD +18 -16
- figpack/views/PlotlyFigure.py +0 -76
- {figpack-0.2.9.dist-info → figpack-0.2.11.dist-info}/WHEEL +0 -0
- {figpack-0.2.9.dist-info → figpack-0.2.11.dist-info}/entry_points.txt +0 -0
- {figpack-0.2.9.dist-info → figpack-0.2.11.dist-info}/licenses/LICENSE +0 -0
- {figpack-0.2.9.dist-info → figpack-0.2.11.dist-info}/top_level.txt +0 -0
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<link rel="icon" type="image/png" href="./assets/neurosift-logo-CLsuwLMO.png" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>figpack figure</title>
|
|
8
|
-
<script type="module" crossorigin src="./assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
8
|
+
<script type="module" crossorigin src="./assets/index-DvunBzII.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="./assets/index-D9a3K6eW.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""
|
|
2
|
+
UnitMetricsGraph view for figpack - displays unit metrics in a graph format
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import List, Optional, Union, Dict
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
import zarr
|
|
10
|
+
|
|
11
|
+
from ...core.figpack_view import FigpackView
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class UnitMetricsGraphMetric:
|
|
15
|
+
"""
|
|
16
|
+
Defines a metric with key, label, and data type
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
*,
|
|
22
|
+
key: str,
|
|
23
|
+
label: str,
|
|
24
|
+
dtype: str,
|
|
25
|
+
):
|
|
26
|
+
"""
|
|
27
|
+
Initialize a UnitMetricsGraphMetric
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
key: Unique identifier for the metric
|
|
31
|
+
label: Human-readable label for display
|
|
32
|
+
dtype: Data type of the metric ("int", "float", etc.)
|
|
33
|
+
"""
|
|
34
|
+
self.key = key
|
|
35
|
+
self.label = label
|
|
36
|
+
self.dtype = dtype
|
|
37
|
+
|
|
38
|
+
def to_dict(self) -> Dict:
|
|
39
|
+
"""Convert to dictionary for serialization"""
|
|
40
|
+
return {
|
|
41
|
+
"key": self.key,
|
|
42
|
+
"label": self.label,
|
|
43
|
+
"dtype": self.dtype,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class UnitMetricsGraphUnit:
|
|
48
|
+
"""
|
|
49
|
+
Represents a unit with its metric values
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def __init__(
|
|
53
|
+
self,
|
|
54
|
+
*,
|
|
55
|
+
unit_id: Union[str, int],
|
|
56
|
+
values: Dict[str, Union[int, float]],
|
|
57
|
+
):
|
|
58
|
+
"""
|
|
59
|
+
Initialize a UnitMetricsGraphUnit
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
unit_id: Identifier for the unit
|
|
63
|
+
values: Dictionary mapping metric keys to their values
|
|
64
|
+
"""
|
|
65
|
+
self.unit_id = unit_id
|
|
66
|
+
self.values = values
|
|
67
|
+
|
|
68
|
+
def to_dict(self) -> Dict:
|
|
69
|
+
"""Convert to dictionary for serialization"""
|
|
70
|
+
return {
|
|
71
|
+
"unit_id": str(self.unit_id),
|
|
72
|
+
"values": self.values,
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class UnitMetricsGraph(FigpackView):
|
|
77
|
+
"""
|
|
78
|
+
A view that displays unit metrics in a graph format
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
def __init__(
|
|
82
|
+
self,
|
|
83
|
+
*,
|
|
84
|
+
units: List[UnitMetricsGraphUnit],
|
|
85
|
+
metrics: List[UnitMetricsGraphMetric],
|
|
86
|
+
height: Optional[int] = None,
|
|
87
|
+
):
|
|
88
|
+
"""
|
|
89
|
+
Initialize a UnitMetricsGraph view
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
units: List of UnitMetricsGraphUnit objects containing the data
|
|
93
|
+
metrics: List of UnitMetricsGraphMetric objects defining the metrics
|
|
94
|
+
height: Height of the view in pixels
|
|
95
|
+
"""
|
|
96
|
+
self.units = units
|
|
97
|
+
self.metrics = metrics
|
|
98
|
+
self.height = height
|
|
99
|
+
|
|
100
|
+
def _write_to_zarr_group(self, group: zarr.Group) -> None:
|
|
101
|
+
"""
|
|
102
|
+
Write the UnitMetricsGraph data to a Zarr group
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
group: Zarr group to write data into
|
|
106
|
+
"""
|
|
107
|
+
# Set the view type
|
|
108
|
+
group.attrs["view_type"] = "UnitMetricsGraph"
|
|
109
|
+
|
|
110
|
+
# Set view properties
|
|
111
|
+
if self.height is not None:
|
|
112
|
+
group.attrs["height"] = self.height
|
|
113
|
+
|
|
114
|
+
# Store metrics metadata
|
|
115
|
+
metrics_metadata = [metric.to_dict() for metric in self.metrics]
|
|
116
|
+
group.attrs["metrics"] = metrics_metadata
|
|
117
|
+
|
|
118
|
+
# Store units data in a zarr array
|
|
119
|
+
units_data = [unit.to_dict() for unit in self.units]
|
|
120
|
+
units_json = json.dumps(units_data).encode("utf-8")
|
|
121
|
+
units_array = np.frombuffer(units_json, dtype=np.uint8)
|
|
122
|
+
group.create_dataset(
|
|
123
|
+
"units_data",
|
|
124
|
+
data=units_array,
|
|
125
|
+
dtype=np.uint8,
|
|
126
|
+
chunks=True,
|
|
127
|
+
compressor=zarr.Blosc(cname="zstd", clevel=3, shuffle=zarr.Blosc.SHUFFLE),
|
|
128
|
+
)
|
|
129
|
+
group.attrs["units_data_size"] = len(units_json)
|
|
@@ -15,6 +15,11 @@ from .SpikeAmplitudesItem import SpikeAmplitudesItem
|
|
|
15
15
|
from .SpikeAmplitudes import SpikeAmplitudes
|
|
16
16
|
from .RasterPlotItem import RasterPlotItem
|
|
17
17
|
from .RasterPlot import RasterPlot
|
|
18
|
+
from .UnitMetricsGraph import (
|
|
19
|
+
UnitMetricsGraph,
|
|
20
|
+
UnitMetricsGraphMetric,
|
|
21
|
+
UnitMetricsGraphUnit,
|
|
22
|
+
)
|
|
18
23
|
|
|
19
24
|
__all__ = [
|
|
20
25
|
"AutocorrelogramItem",
|
|
@@ -30,4 +35,7 @@ __all__ = [
|
|
|
30
35
|
"SpikeAmplitudes",
|
|
31
36
|
"RasterPlotItem",
|
|
32
37
|
"RasterPlot",
|
|
38
|
+
"UnitMetricsGraph",
|
|
39
|
+
"UnitMetricsGraphMetric",
|
|
40
|
+
"UnitMetricsGraphUnit",
|
|
33
41
|
]
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import numpy as np
|
|
3
|
+
import zarr
|
|
4
|
+
import urllib.request
|
|
5
|
+
import urllib.error
|
|
6
|
+
from datetime import date, datetime
|
|
7
|
+
|
|
8
|
+
from figpack import FigpackExtension, ExtensionRegistry, ExtensionView
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _download_plotly_library():
|
|
12
|
+
url = "https://cdn.plot.ly/plotly-2.35.2.min.js"
|
|
13
|
+
try:
|
|
14
|
+
with urllib.request.urlopen(url) as response:
|
|
15
|
+
return response.read().decode("utf-8")
|
|
16
|
+
except urllib.error.URLError as e:
|
|
17
|
+
raise RuntimeError(f"Failed to download plotly library from {url}: {e}")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _load_javascript_code():
|
|
21
|
+
"""Load the JavaScript code from the plotly.js file"""
|
|
22
|
+
import os
|
|
23
|
+
|
|
24
|
+
js_path = os.path.join(os.path.dirname(__file__), "plotly_view.js")
|
|
25
|
+
try:
|
|
26
|
+
with open(js_path, "r", encoding="utf-8") as f:
|
|
27
|
+
return f.read()
|
|
28
|
+
except FileNotFoundError:
|
|
29
|
+
raise FileNotFoundError(
|
|
30
|
+
f"Could not find plotly.js at {js_path}. "
|
|
31
|
+
"Make sure the JavaScript file is present in the package."
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# Download the plotly library and create the extension with additional files
|
|
36
|
+
try:
|
|
37
|
+
plotly_lib_js = _download_plotly_library()
|
|
38
|
+
additional_files = {"plotly.min.js": plotly_lib_js}
|
|
39
|
+
except Exception as e:
|
|
40
|
+
print(f"Warning: Could not download plotly library: {e}")
|
|
41
|
+
print("Extension will fall back to CDN loading")
|
|
42
|
+
additional_files = {}
|
|
43
|
+
|
|
44
|
+
# Create and register the plotly extension
|
|
45
|
+
_plotly_extension = FigpackExtension(
|
|
46
|
+
name="figpack_plotly",
|
|
47
|
+
javascript_code=_load_javascript_code(),
|
|
48
|
+
additional_files=additional_files,
|
|
49
|
+
version="1.0.0",
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
ExtensionRegistry.register(_plotly_extension)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class PlotlyFigure(ExtensionView):
|
|
56
|
+
"""
|
|
57
|
+
A Plotly graph visualization view using the plotly library.
|
|
58
|
+
|
|
59
|
+
This view displays interactive Plotly graphs
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
def __init__(self, fig):
|
|
63
|
+
"""
|
|
64
|
+
Initialize a PlotlyFigure view
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
fig: The plotly figure object
|
|
68
|
+
"""
|
|
69
|
+
# for some reason, we need to reregister here to avoid issues with pytest
|
|
70
|
+
ExtensionRegistry.register(_plotly_extension)
|
|
71
|
+
super().__init__(extension_name="figpack_plotly")
|
|
72
|
+
|
|
73
|
+
self.fig = fig
|
|
74
|
+
|
|
75
|
+
def _write_to_zarr_group(self, group: zarr.Group) -> None:
|
|
76
|
+
"""
|
|
77
|
+
Write the plotly figure data to a Zarr group
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
group: Zarr group to write data into
|
|
81
|
+
"""
|
|
82
|
+
super()._write_to_zarr_group(group)
|
|
83
|
+
|
|
84
|
+
# Convert the plotly figure to a dictionary
|
|
85
|
+
fig_dict = self.fig.to_dict()
|
|
86
|
+
|
|
87
|
+
# Convert figure data to JSON string using custom encoder
|
|
88
|
+
json_string = json.dumps(fig_dict, cls=CustomJSONEncoder)
|
|
89
|
+
|
|
90
|
+
# Convert JSON string to bytes and store in numpy array
|
|
91
|
+
json_bytes = json_string.encode("utf-8")
|
|
92
|
+
json_array = np.frombuffer(json_bytes, dtype=np.uint8)
|
|
93
|
+
|
|
94
|
+
# Store the figure data as compressed array
|
|
95
|
+
group.create_dataset(
|
|
96
|
+
"figure_data",
|
|
97
|
+
data=json_array,
|
|
98
|
+
dtype=np.uint8,
|
|
99
|
+
chunks=True,
|
|
100
|
+
compressor=zarr.Blosc(cname="zstd", clevel=3, shuffle=zarr.Blosc.SHUFFLE),
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# Store data size for reference
|
|
104
|
+
group.attrs["data_size"] = len(json_bytes)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class CustomJSONEncoder(json.JSONEncoder):
|
|
108
|
+
"""Custom JSON encoder that handles numpy arrays and datetime objects"""
|
|
109
|
+
|
|
110
|
+
def default(self, obj):
|
|
111
|
+
if isinstance(obj, np.ndarray):
|
|
112
|
+
return obj.tolist()
|
|
113
|
+
elif isinstance(obj, (np.integer, np.floating)):
|
|
114
|
+
return obj.item()
|
|
115
|
+
elif isinstance(obj, (datetime, date)):
|
|
116
|
+
return obj.isoformat()
|
|
117
|
+
elif isinstance(obj, np.datetime64):
|
|
118
|
+
return str(obj)
|
|
119
|
+
elif hasattr(obj, "isoformat"): # Handle other datetime-like objects
|
|
120
|
+
return obj.isoformat()
|
|
121
|
+
return super().default(obj)
|
figpack/views/Spectrogram.py
CHANGED
|
@@ -21,9 +21,10 @@ class Spectrogram(FigpackView):
|
|
|
21
21
|
*,
|
|
22
22
|
start_time_sec: float,
|
|
23
23
|
sampling_frequency_hz: float,
|
|
24
|
-
frequency_min_hz: float,
|
|
25
|
-
frequency_delta_hz: float,
|
|
26
24
|
data: np.ndarray,
|
|
25
|
+
frequency_min_hz: Optional[float] = None,
|
|
26
|
+
frequency_delta_hz: Optional[float] = None,
|
|
27
|
+
frequencies: Optional[np.ndarray] = None,
|
|
27
28
|
):
|
|
28
29
|
"""
|
|
29
30
|
Initialize a Spectrogram view
|
|
@@ -31,20 +32,49 @@ class Spectrogram(FigpackView):
|
|
|
31
32
|
Args:
|
|
32
33
|
start_time_sec: Starting time in seconds
|
|
33
34
|
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
35
|
data: N×M numpy array where N is timepoints and M is frequency bins
|
|
36
|
+
frequency_min_hz: Minimum frequency in Hz (for uniform bins)
|
|
37
|
+
frequency_delta_hz: Frequency bin spacing in Hz (for uniform bins)
|
|
38
|
+
frequencies: Array of frequency values (for non-uniform bins)
|
|
37
39
|
"""
|
|
38
40
|
assert data.ndim == 2, "Data must be a 2D array (timepoints × frequencies)"
|
|
39
41
|
assert sampling_frequency_hz > 0, "Sampling frequency must be positive"
|
|
40
|
-
|
|
42
|
+
|
|
43
|
+
# Validate frequency specification - exactly one method must be provided
|
|
44
|
+
uniform_specified = (
|
|
45
|
+
frequency_min_hz is not None and frequency_delta_hz is not None
|
|
46
|
+
)
|
|
47
|
+
nonuniform_specified = frequencies is not None
|
|
48
|
+
|
|
49
|
+
if uniform_specified and nonuniform_specified:
|
|
50
|
+
raise ValueError(
|
|
51
|
+
"Cannot specify both uniform (freq_min_hz, frequency_delta_hz) and non-uniform (frequencies) frequency parameters"
|
|
52
|
+
)
|
|
53
|
+
if not uniform_specified and not nonuniform_specified:
|
|
54
|
+
raise ValueError(
|
|
55
|
+
"Must specify either uniform (freq_min_hz, frequency_delta_hz) or non-uniform (frequencies) frequency parameters"
|
|
56
|
+
)
|
|
41
57
|
|
|
42
58
|
self.start_time_sec = start_time_sec
|
|
43
59
|
self.sampling_frequency_hz = sampling_frequency_hz
|
|
44
|
-
self.frequency_min_hz = frequency_min_hz
|
|
45
|
-
self.frequency_delta_hz = frequency_delta_hz
|
|
46
60
|
self.data = data.astype(np.float32) # Ensure float32 for efficiency
|
|
47
61
|
|
|
62
|
+
# Store frequency information
|
|
63
|
+
if uniform_specified:
|
|
64
|
+
assert frequency_delta_hz > 0, "Frequency delta must be positive"
|
|
65
|
+
self.uniform_frequencies = True
|
|
66
|
+
self.frequency_min_hz = frequency_min_hz
|
|
67
|
+
self.frequency_delta_hz = frequency_delta_hz
|
|
68
|
+
self.frequencies = None
|
|
69
|
+
else:
|
|
70
|
+
assert (
|
|
71
|
+
len(frequencies) == data.shape[1]
|
|
72
|
+
), f"Number of frequencies ({len(frequencies)}) must match data frequency dimension ({data.shape[1]})"
|
|
73
|
+
self.uniform_frequencies = False
|
|
74
|
+
self.frequency_min_hz = None
|
|
75
|
+
self.frequency_delta_hz = None
|
|
76
|
+
self.frequencies = np.array(frequencies, dtype=np.float32)
|
|
77
|
+
|
|
48
78
|
n_timepoints, n_frequencies = data.shape
|
|
49
79
|
self.n_timepoints = n_timepoints
|
|
50
80
|
self.n_frequencies = n_frequencies
|
|
@@ -167,13 +197,25 @@ class Spectrogram(FigpackView):
|
|
|
167
197
|
# Store metadata
|
|
168
198
|
group.attrs["start_time_sec"] = self.start_time_sec
|
|
169
199
|
group.attrs["sampling_frequency_hz"] = self.sampling_frequency_hz
|
|
170
|
-
group.attrs["
|
|
171
|
-
group.attrs["frequency_delta_hz"] = self.frequency_delta_hz
|
|
200
|
+
group.attrs["uniform_frequencies"] = self.uniform_frequencies
|
|
172
201
|
group.attrs["n_timepoints"] = self.n_timepoints
|
|
173
202
|
group.attrs["n_frequencies"] = self.n_frequencies
|
|
174
203
|
group.attrs["data_min"] = self.data_min
|
|
175
204
|
group.attrs["data_max"] = self.data_max
|
|
176
205
|
|
|
206
|
+
# Store frequency information based on type
|
|
207
|
+
if self.uniform_frequencies:
|
|
208
|
+
group.attrs["frequency_min_hz"] = self.frequency_min_hz
|
|
209
|
+
group.attrs["frequency_delta_hz"] = self.frequency_delta_hz
|
|
210
|
+
else:
|
|
211
|
+
# Store frequencies as a dataset for non-uniform case
|
|
212
|
+
group.create_dataset(
|
|
213
|
+
"frequencies",
|
|
214
|
+
data=self.frequencies,
|
|
215
|
+
compression="blosc",
|
|
216
|
+
compression_opts={"cname": "lz4", "clevel": 5, "shuffle": 1},
|
|
217
|
+
)
|
|
218
|
+
|
|
177
219
|
# Store original data with optimal chunking
|
|
178
220
|
original_chunks = self._calculate_optimal_chunk_size(self.data.shape)
|
|
179
221
|
group.create_dataset(
|
figpack/views/__init__.py
CHANGED
|
@@ -7,9 +7,9 @@ from .LayoutItem import LayoutItem
|
|
|
7
7
|
from .Markdown import Markdown
|
|
8
8
|
from .MatplotlibFigure import MatplotlibFigure
|
|
9
9
|
from .MultiChannelTimeseries import MultiChannelTimeseries
|
|
10
|
-
from .PlotlyFigure import PlotlyFigure
|
|
11
10
|
from .Spectrogram import Spectrogram
|
|
12
11
|
from .Splitter import Splitter
|
|
13
12
|
from .TabLayout import TabLayout
|
|
14
13
|
from .TabLayoutItem import TabLayoutItem
|
|
15
14
|
from .TimeseriesGraph import TimeseriesGraph
|
|
15
|
+
from .PlotlyExtension import PlotlyFigure
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
figpack/__init__.py,sha256=
|
|
1
|
+
figpack/__init__.py,sha256=dkV99qgN1ALjjQzp923hMJXVKIivfruPrK_ptSCt7oM,360
|
|
2
2
|
figpack/cli.py,sha256=xWF7J2BxUqOLvPu-Kje7Q6oGukTroXsLq8WN8vJgyw0,8321
|
|
3
3
|
figpack/core/__init__.py,sha256=V4wVdyBJ80mi9Rz8HjDSQNkqhqYB6sq4vWH3xQ10kaE,232
|
|
4
4
|
figpack/core/_bundle_utils.py,sha256=16hgTExPLkJCtGjVUCLlnbs_qgns6v01egVr3CEnUXE,6082
|
|
@@ -8,12 +8,12 @@ figpack/core/_show_view.py,sha256=-5HT1MYSeVuEoaL3RNNyoCjYsZy4Jy9XLjljUqLuvV4,51
|
|
|
8
8
|
figpack/core/_upload_bundle.py,sha256=54hdWayJJdRZdx7N9V2aH_X33KkR6hImMjN6tkBTLi8,14894
|
|
9
9
|
figpack/core/_view_figure.py,sha256=o1x1I2VKFrp2W_TStUS3fQblRW8AvGbu7Uy7MgVjofA,4186
|
|
10
10
|
figpack/core/config.py,sha256=oOR7SlP192vuFhYlS-h14HnG-kd_3gaz0vshXch2RNc,173
|
|
11
|
-
figpack/core/extension_view.py,sha256=
|
|
11
|
+
figpack/core/extension_view.py,sha256=flFj8X4XuDzzOyeOe3SBddbr_t4wbg1V3vFzJoEVAB4,1995
|
|
12
12
|
figpack/core/figpack_extension.py,sha256=EJHZpe7GsQMUnSvxcYf8374-f6n85F_k1IEelFMRFP8,4332
|
|
13
|
-
figpack/core/figpack_view.py,sha256=
|
|
14
|
-
figpack/figpack-figure-dist/index.html,sha256=
|
|
15
|
-
figpack/figpack-figure-dist/assets/index-
|
|
16
|
-
figpack/figpack-figure-dist/assets/index-
|
|
13
|
+
figpack/core/figpack_view.py,sha256=X_EtpWTloENfRnDEJcBxXBPditaObv5BWMzO-_stAho,6297
|
|
14
|
+
figpack/figpack-figure-dist/index.html,sha256=KfLOqUjEskQz4IIEBQzZkvKk98OPHw0S0XMewpC5dsE,486
|
|
15
|
+
figpack/figpack-figure-dist/assets/index-D9a3K6eW.css,sha256=ki61XkOz_TBJnU9Qyk5EgBzh2-_ilZQui2i8DHSarEo,5584
|
|
16
|
+
figpack/figpack-figure-dist/assets/index-DvunBzII.js,sha256=arbzJNLZqctCBHw9XY0xmmOf9Pv7hOvroENh3NMYY4c,1620482
|
|
17
17
|
figpack/figpack-figure-dist/assets/neurosift-logo-CLsuwLMO.png,sha256=g5m-TwrGh5f6-9rXtWV-znH4B0nHgc__0GWclRDLUHs,9307
|
|
18
18
|
figpack/franklab/__init__.py,sha256=HkehqGImJE_sE2vbPDo-HbgtEYaMICb9-230xTYvRTU,56
|
|
19
19
|
figpack/franklab/views/TrackAnimation.py,sha256=3Jv1Ri4FIwTyqNahinqhHsBH1Bv_iZrEGx12w6diJ2M,5636
|
|
@@ -28,11 +28,12 @@ figpack/spike_sorting/views/RasterPlot.py,sha256=m8Cg-KioAM3CdIJOecpyTqp71HwhQVD
|
|
|
28
28
|
figpack/spike_sorting/views/RasterPlotItem.py,sha256=iW7fuDEjSfvf5YMIwrF_6cmKvD76oCigOUMHtGgBsPI,638
|
|
29
29
|
figpack/spike_sorting/views/SpikeAmplitudes.py,sha256=UOGxReKs5WwH7iRdR-iVN3Pr6wF3AnIV15veoZZzOco,13433
|
|
30
30
|
figpack/spike_sorting/views/SpikeAmplitudesItem.py,sha256=j5Na-diY-vRUAPu0t0VkyFCSKFnQ_f5HT077mB3Cy8c,1134
|
|
31
|
+
figpack/spike_sorting/views/UnitMetricsGraph.py,sha256=Eva0YgexnHZqRH7bPQFgaqobWFz_ab6zgTb4-QZ4h2k,3381
|
|
31
32
|
figpack/spike_sorting/views/UnitSimilarityScore.py,sha256=cJA9MkETos9qHhV1tqgA7SfNEaPo-duXYCE76hSFGnA,948
|
|
32
33
|
figpack/spike_sorting/views/UnitsTable.py,sha256=M3y1IDJzSnvOaM1-QOyJOVcUcdTkVvxYhEMGd1kmUzs,2969
|
|
33
34
|
figpack/spike_sorting/views/UnitsTableColumn.py,sha256=zBnuoeILTuiVLDvtcOxqa37E5WlbR12rlwNJUeWXxY4,847
|
|
34
35
|
figpack/spike_sorting/views/UnitsTableRow.py,sha256=rEb2hMTA_pl2fTW1nOvnGir0ysfNx4uww3aekZzfWjk,720
|
|
35
|
-
figpack/spike_sorting/views/__init__.py,sha256=
|
|
36
|
+
figpack/spike_sorting/views/__init__.py,sha256=2caaV9yxi97aHoYfUWUYyyIXQSZJRtRVqmPOW9ZeG1I,1159
|
|
36
37
|
figpack/views/Box.py,sha256=TfhPFNtVEq71LCucmWk3XX2WxQLdaeRiWGm5BM0k2l4,2236
|
|
37
38
|
figpack/views/DataFrame.py,sha256=VFP-EM_Wnc1G3uimVVMJe08KKWCAZe7DvmYf5e07uTk,3653
|
|
38
39
|
figpack/views/Gallery.py,sha256=sHlZbaqxcktasmNsJnuxe8WmgUQ6iurG50JiChKSMbQ,3314
|
|
@@ -42,16 +43,17 @@ figpack/views/LayoutItem.py,sha256=wy8DggkIzZpU0F1zFIBceS7HpBb6lu-A3hpYINQzedk,1
|
|
|
42
43
|
figpack/views/Markdown.py,sha256=Dl1UX5s0aC-mEx5m6jIJ839YKMNeeVzIDG-EANVrbys,1147
|
|
43
44
|
figpack/views/MatplotlibFigure.py,sha256=YoNtZTItEjatbtNJqATm2H-Oircp5Ca6FZLjHk_B0zg,2778
|
|
44
45
|
figpack/views/MultiChannelTimeseries.py,sha256=sWr2nW1eoYR7V44wF7fac7IoQ6BOnus1nc4STkgIkYw,8501
|
|
45
|
-
figpack/views/
|
|
46
|
-
figpack/views/Spectrogram.py,sha256=RMgbj2Cli08Xag8mZBfyeUNLGw5AFeT_VISHwShxjEs,7689
|
|
46
|
+
figpack/views/Spectrogram.py,sha256=GfTNinkuMFu4dxn35MvSB4Perz84sx4LMcjUrOviz6c,9648
|
|
47
47
|
figpack/views/Splitter.py,sha256=x9jLCTlIvDy5p9ymVd0X48KDccyD6bJANhXyFgKEmtE,2007
|
|
48
48
|
figpack/views/TabLayout.py,sha256=5g3nmL95PfqgI0naqZXHMwLVo2ebDlGX01Hy9044bUw,1898
|
|
49
49
|
figpack/views/TabLayoutItem.py,sha256=xmHA0JsW_6naJze4_mQuP_Fy0Nm17p2N7w_AsmVRp8k,880
|
|
50
50
|
figpack/views/TimeseriesGraph.py,sha256=OAaCjO8fo86u_gO_frNfRGxng3tczxGDGKcJEvZo3rE,7469
|
|
51
|
-
figpack/views/__init__.py,sha256=
|
|
52
|
-
figpack
|
|
53
|
-
figpack
|
|
54
|
-
figpack-0.2.
|
|
55
|
-
figpack-0.2.
|
|
56
|
-
figpack-0.2.
|
|
57
|
-
figpack-0.2.
|
|
51
|
+
figpack/views/__init__.py,sha256=nyd3Ot2x702W4j9oBN0lK6i0DZzg9Ai41XoYCm5DeQ8,546
|
|
52
|
+
figpack/views/PlotlyExtension/PlotlyExtension.py,sha256=_-GiqzHFb9uF1O6RNKEkd85SX8z9z5kFOh8tO_9aAbk,3778
|
|
53
|
+
figpack/views/PlotlyExtension/__init__.py,sha256=80Wy1mDMWyagjuR99ECxJePIYpRQ6TSyHkB0uZoBZ_0,70
|
|
54
|
+
figpack-0.2.11.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
55
|
+
figpack-0.2.11.dist-info/METADATA,sha256=N8ftHEAJCS8R_5lHx6DxHSr5QQCWqdDAMPjQ6F084JI,3617
|
|
56
|
+
figpack-0.2.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
57
|
+
figpack-0.2.11.dist-info/entry_points.txt,sha256=l6d3siH2LxXa8qJGbjAqpIZtI5AkMSyDeoRDCzdrUto,45
|
|
58
|
+
figpack-0.2.11.dist-info/top_level.txt,sha256=lMKGaC5xWmAYBx9Ac1iMokm42KFnJFjmkP2ldyvOo-c,8
|
|
59
|
+
figpack-0.2.11.dist-info/RECORD,,
|
figpack/views/PlotlyFigure.py
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
PlotlyFigure view for figpack - displays plotly figures
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import json
|
|
6
|
-
from datetime import date, datetime
|
|
7
|
-
from typing import Any, Dict, Union
|
|
8
|
-
|
|
9
|
-
import numpy as np
|
|
10
|
-
import zarr
|
|
11
|
-
|
|
12
|
-
from ..core.figpack_view import FigpackView
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class CustomJSONEncoder(json.JSONEncoder):
|
|
16
|
-
"""Custom JSON encoder that handles numpy arrays and datetime objects"""
|
|
17
|
-
|
|
18
|
-
def default(self, obj):
|
|
19
|
-
if isinstance(obj, np.ndarray):
|
|
20
|
-
return obj.tolist()
|
|
21
|
-
elif isinstance(obj, (np.integer, np.floating)):
|
|
22
|
-
return obj.item()
|
|
23
|
-
elif isinstance(obj, (datetime, date)):
|
|
24
|
-
return obj.isoformat()
|
|
25
|
-
elif isinstance(obj, np.datetime64):
|
|
26
|
-
return str(obj)
|
|
27
|
-
elif hasattr(obj, "isoformat"): # Handle other datetime-like objects
|
|
28
|
-
return obj.isoformat()
|
|
29
|
-
return super().default(obj)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class PlotlyFigure(FigpackView):
|
|
33
|
-
"""
|
|
34
|
-
A plotly figure visualization component
|
|
35
|
-
"""
|
|
36
|
-
|
|
37
|
-
def __init__(self, fig):
|
|
38
|
-
"""
|
|
39
|
-
Initialize a PlotlyFigure view
|
|
40
|
-
|
|
41
|
-
Args:
|
|
42
|
-
fig: The plotly figure object
|
|
43
|
-
"""
|
|
44
|
-
self.fig = fig
|
|
45
|
-
|
|
46
|
-
def _write_to_zarr_group(self, group: zarr.Group) -> None:
|
|
47
|
-
"""
|
|
48
|
-
Write the plotly figure data to a Zarr group
|
|
49
|
-
|
|
50
|
-
Args:
|
|
51
|
-
group: Zarr group to write data into
|
|
52
|
-
"""
|
|
53
|
-
# Set the view type
|
|
54
|
-
group.attrs["view_type"] = "PlotlyFigure"
|
|
55
|
-
|
|
56
|
-
# Convert the plotly figure to a dictionary
|
|
57
|
-
fig_dict = self.fig.to_dict()
|
|
58
|
-
|
|
59
|
-
# Convert figure data to JSON string using custom encoder
|
|
60
|
-
json_string = json.dumps(fig_dict, cls=CustomJSONEncoder)
|
|
61
|
-
|
|
62
|
-
# Convert JSON string to bytes and store in numpy array
|
|
63
|
-
json_bytes = json_string.encode("utf-8")
|
|
64
|
-
json_array = np.frombuffer(json_bytes, dtype=np.uint8)
|
|
65
|
-
|
|
66
|
-
# Store the figure data as compressed array
|
|
67
|
-
group.create_dataset(
|
|
68
|
-
"figure_data",
|
|
69
|
-
data=json_array,
|
|
70
|
-
dtype=np.uint8,
|
|
71
|
-
chunks=True,
|
|
72
|
-
compressor=zarr.Blosc(cname="zstd", clevel=3, shuffle=zarr.Blosc.SHUFFLE),
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
# Store data size for reference
|
|
76
|
-
group.attrs["data_size"] = len(json_bytes)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|