figpack 0.2.16__tar.gz → 0.2.17__tar.gz
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-0.2.16/figpack.egg-info → figpack-0.2.17}/PKG-INFO +1 -1
- {figpack-0.2.16 → figpack-0.2.17}/figpack/__init__.py +2 -3
- figpack-0.2.17/figpack/core/__init__.py +5 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/core/_bundle_utils.py +56 -18
- figpack-0.2.17/figpack/core/extension_view.py +41 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/core/figpack_extension.py +0 -71
- figpack-0.2.17/figpack/figpack-figure-dist/assets/index-DBwmtEpB.js +91 -0
- figpack-0.2.16/figpack/figpack-figure-dist/assets/index-D9a3K6eW.css → figpack-0.2.17/figpack/figpack-figure-dist/assets/index-DHWczh-Q.css +1 -1
- {figpack-0.2.16 → figpack-0.2.17}/figpack/figpack-figure-dist/index.html +2 -2
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/PlotlyExtension/PlotlyExtension.py +4 -50
- figpack-0.2.17/figpack/views/PlotlyExtension/_plotly_extension.py +46 -0
- figpack-0.2.17/figpack/views/PlotlyExtension/plotly_view.js +110 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/__init__.py +1 -0
- {figpack-0.2.16 → figpack-0.2.17/figpack.egg-info}/PKG-INFO +1 -1
- {figpack-0.2.16 → figpack-0.2.17}/figpack.egg-info/SOURCES.txt +3 -27
- {figpack-0.2.16 → figpack-0.2.17}/pyproject.toml +1 -1
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_extension_system.py +7 -84
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_plotly_figure.py +1 -1
- figpack-0.2.16/figpack/core/__init__.py +0 -5
- figpack-0.2.16/figpack/core/extension_view.py +0 -59
- figpack-0.2.16/figpack/figpack-figure-dist/assets/index-DtOnN02w.js +0 -846
- figpack-0.2.16/figpack/franklab/__init__.py +0 -5
- figpack-0.2.16/figpack/franklab/views/TrackAnimation.py +0 -154
- figpack-0.2.16/figpack/franklab/views/__init__.py +0 -9
- figpack-0.2.16/figpack/spike_sorting/__init__.py +0 -5
- figpack-0.2.16/figpack/spike_sorting/views/AutocorrelogramItem.py +0 -32
- figpack-0.2.16/figpack/spike_sorting/views/Autocorrelograms.py +0 -116
- figpack-0.2.16/figpack/spike_sorting/views/AverageWaveforms.py +0 -146
- figpack-0.2.16/figpack/spike_sorting/views/CrossCorrelogramItem.py +0 -35
- figpack-0.2.16/figpack/spike_sorting/views/CrossCorrelograms.py +0 -131
- figpack-0.2.16/figpack/spike_sorting/views/RasterPlot.py +0 -284
- figpack-0.2.16/figpack/spike_sorting/views/RasterPlotItem.py +0 -28
- figpack-0.2.16/figpack/spike_sorting/views/SpikeAmplitudes.py +0 -364
- figpack-0.2.16/figpack/spike_sorting/views/SpikeAmplitudesItem.py +0 -38
- figpack-0.2.16/figpack/spike_sorting/views/UnitMetricsGraph.py +0 -127
- figpack-0.2.16/figpack/spike_sorting/views/UnitSimilarityScore.py +0 -40
- figpack-0.2.16/figpack/spike_sorting/views/UnitsTable.py +0 -82
- figpack-0.2.16/figpack/spike_sorting/views/UnitsTableColumn.py +0 -40
- figpack-0.2.16/figpack/spike_sorting/views/UnitsTableRow.py +0 -36
- figpack-0.2.16/figpack/spike_sorting/views/__init__.py +0 -41
- figpack-0.2.16/figpack/views/PlotlyExtension/plotly_view.js +0 -106
- figpack-0.2.16/tests/test_average_waveforms.py +0 -105
- figpack-0.2.16/tests/test_raster_plot.py +0 -63
- figpack-0.2.16/tests/test_spike_amplitudes.py +0 -126
- figpack-0.2.16/tests/test_spike_sorting_correlograms.py +0 -169
- figpack-0.2.16/tests/test_track_animation.py +0 -231
- figpack-0.2.16/tests/test_units_table.py +0 -209
- {figpack-0.2.16 → figpack-0.2.17}/LICENSE +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/MANIFEST.in +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/README.md +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/cli.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/core/_save_figure.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/core/_server_manager.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/core/_show_view.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/core/_upload_bundle.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/core/_view_figure.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/core/config.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/core/figpack_view.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/core/zarr.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/figpack-figure-dist/assets/neurosift-logo-CLsuwLMO.png +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/Box.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/DataFrame.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/Gallery.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/GalleryItem.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/Image.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/LayoutItem.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/Markdown.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/MatplotlibFigure.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/MultiChannelTimeseries.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/PlotlyExtension/__init__.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/Spectrogram.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/Splitter.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/TabLayout.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/TabLayoutItem.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack/views/TimeseriesGraph.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack.egg-info/dependency_links.txt +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack.egg-info/entry_points.txt +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack.egg-info/requires.txt +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/figpack.egg-info/top_level.txt +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/setup.cfg +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_box.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_cli.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_core.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_dataframe.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_figpack_view.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_gallery.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_image.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_markdown.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_matplotlib_figure.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_multichannel_timeseries.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_server_manager.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_spectrogram.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_splitter.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_tablayout.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_timeseries_graph.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_upload_bundle.py +0 -0
- {figpack-0.2.16 → figpack-0.2.17}/tests/test_view_figure.py +0 -0
|
@@ -2,17 +2,16 @@
|
|
|
2
2
|
figpack - A Python package for creating shareable, interactive visualizations in the browser
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
__version__ = "0.2.
|
|
5
|
+
__version__ = "0.2.17"
|
|
6
6
|
|
|
7
7
|
from .cli import view_figure
|
|
8
|
-
from .core import FigpackView, FigpackExtension,
|
|
8
|
+
from .core import FigpackView, FigpackExtension, ExtensionView
|
|
9
9
|
from .core.zarr import Group
|
|
10
10
|
|
|
11
11
|
__all__ = [
|
|
12
12
|
"view_figure",
|
|
13
13
|
"FigpackView",
|
|
14
14
|
"FigpackExtension",
|
|
15
|
-
"ExtensionRegistry",
|
|
16
15
|
"ExtensionView",
|
|
17
16
|
"Group",
|
|
18
17
|
]
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import pathlib
|
|
3
|
+
import json
|
|
3
4
|
from typing import Set
|
|
4
5
|
|
|
5
6
|
import zarr
|
|
6
7
|
|
|
7
8
|
from .figpack_view import FigpackView
|
|
8
|
-
from .figpack_extension import
|
|
9
|
+
from .figpack_extension import FigpackExtension
|
|
9
10
|
from .extension_view import ExtensionView
|
|
10
11
|
from .zarr import Group, _check_zarr_version
|
|
11
12
|
|
|
@@ -68,6 +69,9 @@ def prepare_figure_bundle(
|
|
|
68
69
|
required_extensions = _discover_required_extensions(view)
|
|
69
70
|
_write_extension_files(required_extensions, tmpdir)
|
|
70
71
|
|
|
72
|
+
# Generate extension manifest
|
|
73
|
+
_write_extension_manifest(required_extensions, tmpdir)
|
|
74
|
+
|
|
71
75
|
zarr.consolidate_metadata(zarr_group._zarr_group.store)
|
|
72
76
|
finally:
|
|
73
77
|
if _check_zarr_version() == 3:
|
|
@@ -84,7 +88,8 @@ def _discover_required_extensions(view: FigpackView) -> Set[str]:
|
|
|
84
88
|
Returns:
|
|
85
89
|
Set of extension names required by this view hierarchy
|
|
86
90
|
"""
|
|
87
|
-
|
|
91
|
+
extension_names_discovered = set()
|
|
92
|
+
extensions_discovered = []
|
|
88
93
|
visited = set() # Prevent infinite recursion
|
|
89
94
|
|
|
90
95
|
def _collect_extensions(v: FigpackView):
|
|
@@ -95,7 +100,9 @@ def _discover_required_extensions(view: FigpackView) -> Set[str]:
|
|
|
95
100
|
|
|
96
101
|
# Check if this view is an extension view
|
|
97
102
|
if isinstance(v, ExtensionView):
|
|
98
|
-
|
|
103
|
+
if v.extension.name not in extension_names_discovered:
|
|
104
|
+
extension_names_discovered.add(v.extension.name)
|
|
105
|
+
extensions_discovered.append(v.extension)
|
|
99
106
|
|
|
100
107
|
# Recursively check all attributes that might contain child views
|
|
101
108
|
for attr_name in dir(v):
|
|
@@ -130,10 +137,10 @@ def _discover_required_extensions(view: FigpackView) -> Set[str]:
|
|
|
130
137
|
continue
|
|
131
138
|
|
|
132
139
|
_collect_extensions(view)
|
|
133
|
-
return
|
|
140
|
+
return extensions_discovered
|
|
134
141
|
|
|
135
142
|
|
|
136
|
-
def _write_extension_files(
|
|
143
|
+
def _write_extension_files(extensions, tmpdir: str) -> None:
|
|
137
144
|
"""
|
|
138
145
|
Write JavaScript files for the required extensions
|
|
139
146
|
|
|
@@ -141,20 +148,11 @@ def _write_extension_files(extension_names: Set[str], tmpdir: str) -> None:
|
|
|
141
148
|
extension_names: Set of extension names to write
|
|
142
149
|
tmpdir: Directory to write extension files to
|
|
143
150
|
"""
|
|
144
|
-
if not extension_names:
|
|
145
|
-
return
|
|
146
|
-
|
|
147
|
-
registry = ExtensionRegistry.get_instance()
|
|
148
151
|
tmpdir_path = pathlib.Path(tmpdir)
|
|
149
152
|
|
|
150
|
-
for
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
raise RuntimeError(
|
|
154
|
-
f"Extension '{extension_name}' is required but not registered"
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
# Write the main JavaScript file
|
|
153
|
+
for extension in extensions:
|
|
154
|
+
if not isinstance(extension, FigpackExtension):
|
|
155
|
+
raise ValueError("Expected a FigpackExtension instance")
|
|
158
156
|
js_filename = extension.get_javascript_filename()
|
|
159
157
|
js_path = tmpdir_path / js_filename
|
|
160
158
|
|
|
@@ -164,7 +162,7 @@ def _write_extension_files(extension_names: Set[str], tmpdir: str) -> None:
|
|
|
164
162
|
* Version: {extension.version}
|
|
165
163
|
* Generated automatically - do not edit
|
|
166
164
|
*/
|
|
167
|
-
|
|
165
|
+
|
|
168
166
|
{extension.javascript_code}
|
|
169
167
|
"""
|
|
170
168
|
|
|
@@ -187,3 +185,43 @@ def _write_extension_files(extension_names: Set[str], tmpdir: str) -> None:
|
|
|
187
185
|
"""
|
|
188
186
|
|
|
189
187
|
additional_path.write_text(additional_js_content, encoding="utf-8")
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _write_extension_manifest(extensions, tmpdir: str) -> None:
|
|
191
|
+
"""
|
|
192
|
+
Write the extension manifest file that lists all extensions and their files
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
extensions: List of FigpackExtension instances
|
|
196
|
+
tmpdir: Directory to write the manifest file to
|
|
197
|
+
"""
|
|
198
|
+
tmpdir_path = pathlib.Path(tmpdir)
|
|
199
|
+
manifest_path = tmpdir_path / "extension_manifest.json"
|
|
200
|
+
|
|
201
|
+
# Build the manifest data
|
|
202
|
+
manifest_data = {"extensions": []}
|
|
203
|
+
|
|
204
|
+
for extension in extensions:
|
|
205
|
+
if not isinstance(extension, FigpackExtension):
|
|
206
|
+
raise ValueError("Expected a FigpackExtension instance")
|
|
207
|
+
|
|
208
|
+
# Get the main script filename
|
|
209
|
+
main_script = extension.get_javascript_filename()
|
|
210
|
+
|
|
211
|
+
# Get additional script filenames
|
|
212
|
+
additional_filenames = extension.get_additional_filenames()
|
|
213
|
+
additional_scripts = list(additional_filenames.values())
|
|
214
|
+
|
|
215
|
+
extension_entry = {
|
|
216
|
+
"name": extension.name,
|
|
217
|
+
"mainScript": main_script,
|
|
218
|
+
"additionalScripts": additional_scripts,
|
|
219
|
+
"version": extension.version,
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
manifest_data["extensions"].append(extension_entry)
|
|
223
|
+
|
|
224
|
+
# Write the manifest file
|
|
225
|
+
manifest_path.write_text(
|
|
226
|
+
json.dumps(manifest_data, indent=2, ensure_ascii=False), encoding="utf-8"
|
|
227
|
+
)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base class for views that use figpack extensions
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .figpack_view import FigpackView
|
|
6
|
+
from .figpack_extension import FigpackExtension
|
|
7
|
+
from ..core.zarr import Group
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ExtensionView(FigpackView):
|
|
11
|
+
"""
|
|
12
|
+
Base class for views that are rendered by figpack extensions
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, *, extension: FigpackExtension, view_type: str):
|
|
16
|
+
"""
|
|
17
|
+
Initialize an extension-based view
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
extension_name: Name of the extension that will render this view
|
|
21
|
+
"""
|
|
22
|
+
super().__init__()
|
|
23
|
+
self.extension = extension
|
|
24
|
+
self.view_type = view_type
|
|
25
|
+
|
|
26
|
+
def _write_to_zarr_group(self, group: Group) -> None:
|
|
27
|
+
"""
|
|
28
|
+
Write the extension view metadata to a Zarr group.
|
|
29
|
+
Subclasses should call super()._write_to_zarr_group(group) first,
|
|
30
|
+
then add their own data.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
group: Zarr group to write data into
|
|
34
|
+
"""
|
|
35
|
+
# Set the view type to indicate this is an extension view
|
|
36
|
+
group.attrs["view_type"] = self.view_type
|
|
37
|
+
|
|
38
|
+
# Store the extension name so the frontend knows which extension to use
|
|
39
|
+
group.attrs["extension_name"] = self.extension.name
|
|
40
|
+
|
|
41
|
+
group.attrs["extension_version"] = self.extension.version
|
|
@@ -64,74 +64,3 @@ class FigpackExtension:
|
|
|
64
64
|
original_name: f"extension-{safe_name}-{original_name}"
|
|
65
65
|
for original_name in self.additional_files.keys()
|
|
66
66
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
class ExtensionRegistry:
|
|
70
|
-
"""
|
|
71
|
-
Singleton registry for managing figpack extensions
|
|
72
|
-
"""
|
|
73
|
-
|
|
74
|
-
_instance: Optional["ExtensionRegistry"] = None
|
|
75
|
-
|
|
76
|
-
def __init__(self):
|
|
77
|
-
self._extensions: Dict[str, FigpackExtension] = {}
|
|
78
|
-
|
|
79
|
-
@classmethod
|
|
80
|
-
def get_instance(cls) -> "ExtensionRegistry":
|
|
81
|
-
"""Get the singleton instance of the extension registry"""
|
|
82
|
-
if cls._instance is None:
|
|
83
|
-
cls._instance = cls()
|
|
84
|
-
return cls._instance
|
|
85
|
-
|
|
86
|
-
@classmethod
|
|
87
|
-
def register(cls, extension: FigpackExtension) -> None:
|
|
88
|
-
"""
|
|
89
|
-
Register an extension with the global registry
|
|
90
|
-
|
|
91
|
-
Args:
|
|
92
|
-
extension: The extension to register
|
|
93
|
-
"""
|
|
94
|
-
registry = cls.get_instance()
|
|
95
|
-
registry._register_extension(extension)
|
|
96
|
-
|
|
97
|
-
def _register_extension(self, extension: FigpackExtension) -> None:
|
|
98
|
-
"""
|
|
99
|
-
Internal method to register an extension
|
|
100
|
-
|
|
101
|
-
Args:
|
|
102
|
-
extension: The extension to register
|
|
103
|
-
"""
|
|
104
|
-
if extension.name in self._extensions:
|
|
105
|
-
existing = self._extensions[extension.name]
|
|
106
|
-
if existing.version != extension.version:
|
|
107
|
-
print(
|
|
108
|
-
f"Warning: Replacing extension '{extension.name}' "
|
|
109
|
-
f"version {existing.version} with version {extension.version}"
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
self._extensions[extension.name] = extension
|
|
113
|
-
|
|
114
|
-
def get_extension(self, name: str) -> Optional[FigpackExtension]:
|
|
115
|
-
"""
|
|
116
|
-
Get an extension by name
|
|
117
|
-
|
|
118
|
-
Args:
|
|
119
|
-
name: Name of the extension to retrieve
|
|
120
|
-
|
|
121
|
-
Returns:
|
|
122
|
-
The extension if found, None otherwise
|
|
123
|
-
"""
|
|
124
|
-
return self._extensions.get(name)
|
|
125
|
-
|
|
126
|
-
def get_all_extensions(self) -> Dict[str, FigpackExtension]:
|
|
127
|
-
"""
|
|
128
|
-
Get all registered extensions
|
|
129
|
-
|
|
130
|
-
Returns:
|
|
131
|
-
Dictionary mapping extension names to extension objects
|
|
132
|
-
"""
|
|
133
|
-
return self._extensions.copy()
|
|
134
|
-
|
|
135
|
-
def clear(self) -> None:
|
|
136
|
-
"""Clear all registered extensions (mainly for testing)"""
|
|
137
|
-
self._extensions.clear()
|