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.

Files changed (97) hide show
  1. {figpack-0.2.16/figpack.egg-info → figpack-0.2.17}/PKG-INFO +1 -1
  2. {figpack-0.2.16 → figpack-0.2.17}/figpack/__init__.py +2 -3
  3. figpack-0.2.17/figpack/core/__init__.py +5 -0
  4. {figpack-0.2.16 → figpack-0.2.17}/figpack/core/_bundle_utils.py +56 -18
  5. figpack-0.2.17/figpack/core/extension_view.py +41 -0
  6. {figpack-0.2.16 → figpack-0.2.17}/figpack/core/figpack_extension.py +0 -71
  7. figpack-0.2.17/figpack/figpack-figure-dist/assets/index-DBwmtEpB.js +91 -0
  8. 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
  9. {figpack-0.2.16 → figpack-0.2.17}/figpack/figpack-figure-dist/index.html +2 -2
  10. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/PlotlyExtension/PlotlyExtension.py +4 -50
  11. figpack-0.2.17/figpack/views/PlotlyExtension/_plotly_extension.py +46 -0
  12. figpack-0.2.17/figpack/views/PlotlyExtension/plotly_view.js +110 -0
  13. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/__init__.py +1 -0
  14. {figpack-0.2.16 → figpack-0.2.17/figpack.egg-info}/PKG-INFO +1 -1
  15. {figpack-0.2.16 → figpack-0.2.17}/figpack.egg-info/SOURCES.txt +3 -27
  16. {figpack-0.2.16 → figpack-0.2.17}/pyproject.toml +1 -1
  17. {figpack-0.2.16 → figpack-0.2.17}/tests/test_extension_system.py +7 -84
  18. {figpack-0.2.16 → figpack-0.2.17}/tests/test_plotly_figure.py +1 -1
  19. figpack-0.2.16/figpack/core/__init__.py +0 -5
  20. figpack-0.2.16/figpack/core/extension_view.py +0 -59
  21. figpack-0.2.16/figpack/figpack-figure-dist/assets/index-DtOnN02w.js +0 -846
  22. figpack-0.2.16/figpack/franklab/__init__.py +0 -5
  23. figpack-0.2.16/figpack/franklab/views/TrackAnimation.py +0 -154
  24. figpack-0.2.16/figpack/franklab/views/__init__.py +0 -9
  25. figpack-0.2.16/figpack/spike_sorting/__init__.py +0 -5
  26. figpack-0.2.16/figpack/spike_sorting/views/AutocorrelogramItem.py +0 -32
  27. figpack-0.2.16/figpack/spike_sorting/views/Autocorrelograms.py +0 -116
  28. figpack-0.2.16/figpack/spike_sorting/views/AverageWaveforms.py +0 -146
  29. figpack-0.2.16/figpack/spike_sorting/views/CrossCorrelogramItem.py +0 -35
  30. figpack-0.2.16/figpack/spike_sorting/views/CrossCorrelograms.py +0 -131
  31. figpack-0.2.16/figpack/spike_sorting/views/RasterPlot.py +0 -284
  32. figpack-0.2.16/figpack/spike_sorting/views/RasterPlotItem.py +0 -28
  33. figpack-0.2.16/figpack/spike_sorting/views/SpikeAmplitudes.py +0 -364
  34. figpack-0.2.16/figpack/spike_sorting/views/SpikeAmplitudesItem.py +0 -38
  35. figpack-0.2.16/figpack/spike_sorting/views/UnitMetricsGraph.py +0 -127
  36. figpack-0.2.16/figpack/spike_sorting/views/UnitSimilarityScore.py +0 -40
  37. figpack-0.2.16/figpack/spike_sorting/views/UnitsTable.py +0 -82
  38. figpack-0.2.16/figpack/spike_sorting/views/UnitsTableColumn.py +0 -40
  39. figpack-0.2.16/figpack/spike_sorting/views/UnitsTableRow.py +0 -36
  40. figpack-0.2.16/figpack/spike_sorting/views/__init__.py +0 -41
  41. figpack-0.2.16/figpack/views/PlotlyExtension/plotly_view.js +0 -106
  42. figpack-0.2.16/tests/test_average_waveforms.py +0 -105
  43. figpack-0.2.16/tests/test_raster_plot.py +0 -63
  44. figpack-0.2.16/tests/test_spike_amplitudes.py +0 -126
  45. figpack-0.2.16/tests/test_spike_sorting_correlograms.py +0 -169
  46. figpack-0.2.16/tests/test_track_animation.py +0 -231
  47. figpack-0.2.16/tests/test_units_table.py +0 -209
  48. {figpack-0.2.16 → figpack-0.2.17}/LICENSE +0 -0
  49. {figpack-0.2.16 → figpack-0.2.17}/MANIFEST.in +0 -0
  50. {figpack-0.2.16 → figpack-0.2.17}/README.md +0 -0
  51. {figpack-0.2.16 → figpack-0.2.17}/figpack/cli.py +0 -0
  52. {figpack-0.2.16 → figpack-0.2.17}/figpack/core/_save_figure.py +0 -0
  53. {figpack-0.2.16 → figpack-0.2.17}/figpack/core/_server_manager.py +0 -0
  54. {figpack-0.2.16 → figpack-0.2.17}/figpack/core/_show_view.py +0 -0
  55. {figpack-0.2.16 → figpack-0.2.17}/figpack/core/_upload_bundle.py +0 -0
  56. {figpack-0.2.16 → figpack-0.2.17}/figpack/core/_view_figure.py +0 -0
  57. {figpack-0.2.16 → figpack-0.2.17}/figpack/core/config.py +0 -0
  58. {figpack-0.2.16 → figpack-0.2.17}/figpack/core/figpack_view.py +0 -0
  59. {figpack-0.2.16 → figpack-0.2.17}/figpack/core/zarr.py +0 -0
  60. {figpack-0.2.16 → figpack-0.2.17}/figpack/figpack-figure-dist/assets/neurosift-logo-CLsuwLMO.png +0 -0
  61. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/Box.py +0 -0
  62. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/DataFrame.py +0 -0
  63. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/Gallery.py +0 -0
  64. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/GalleryItem.py +0 -0
  65. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/Image.py +0 -0
  66. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/LayoutItem.py +0 -0
  67. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/Markdown.py +0 -0
  68. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/MatplotlibFigure.py +0 -0
  69. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/MultiChannelTimeseries.py +0 -0
  70. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/PlotlyExtension/__init__.py +0 -0
  71. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/Spectrogram.py +0 -0
  72. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/Splitter.py +0 -0
  73. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/TabLayout.py +0 -0
  74. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/TabLayoutItem.py +0 -0
  75. {figpack-0.2.16 → figpack-0.2.17}/figpack/views/TimeseriesGraph.py +0 -0
  76. {figpack-0.2.16 → figpack-0.2.17}/figpack.egg-info/dependency_links.txt +0 -0
  77. {figpack-0.2.16 → figpack-0.2.17}/figpack.egg-info/entry_points.txt +0 -0
  78. {figpack-0.2.16 → figpack-0.2.17}/figpack.egg-info/requires.txt +0 -0
  79. {figpack-0.2.16 → figpack-0.2.17}/figpack.egg-info/top_level.txt +0 -0
  80. {figpack-0.2.16 → figpack-0.2.17}/setup.cfg +0 -0
  81. {figpack-0.2.16 → figpack-0.2.17}/tests/test_box.py +0 -0
  82. {figpack-0.2.16 → figpack-0.2.17}/tests/test_cli.py +0 -0
  83. {figpack-0.2.16 → figpack-0.2.17}/tests/test_core.py +0 -0
  84. {figpack-0.2.16 → figpack-0.2.17}/tests/test_dataframe.py +0 -0
  85. {figpack-0.2.16 → figpack-0.2.17}/tests/test_figpack_view.py +0 -0
  86. {figpack-0.2.16 → figpack-0.2.17}/tests/test_gallery.py +0 -0
  87. {figpack-0.2.16 → figpack-0.2.17}/tests/test_image.py +0 -0
  88. {figpack-0.2.16 → figpack-0.2.17}/tests/test_markdown.py +0 -0
  89. {figpack-0.2.16 → figpack-0.2.17}/tests/test_matplotlib_figure.py +0 -0
  90. {figpack-0.2.16 → figpack-0.2.17}/tests/test_multichannel_timeseries.py +0 -0
  91. {figpack-0.2.16 → figpack-0.2.17}/tests/test_server_manager.py +0 -0
  92. {figpack-0.2.16 → figpack-0.2.17}/tests/test_spectrogram.py +0 -0
  93. {figpack-0.2.16 → figpack-0.2.17}/tests/test_splitter.py +0 -0
  94. {figpack-0.2.16 → figpack-0.2.17}/tests/test_tablayout.py +0 -0
  95. {figpack-0.2.16 → figpack-0.2.17}/tests/test_timeseries_graph.py +0 -0
  96. {figpack-0.2.16 → figpack-0.2.17}/tests/test_upload_bundle.py +0 -0
  97. {figpack-0.2.16 → figpack-0.2.17}/tests/test_view_figure.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: figpack
3
- Version: 0.2.16
3
+ Version: 0.2.17
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
@@ -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.16"
5
+ __version__ = "0.2.17"
6
6
 
7
7
  from .cli import view_figure
8
- from .core import FigpackView, FigpackExtension, ExtensionRegistry, ExtensionView
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
  ]
@@ -0,0 +1,5 @@
1
+ from .figpack_view import FigpackView
2
+ from .figpack_extension import FigpackExtension
3
+ from .extension_view import ExtensionView
4
+
5
+ __all__ = ["FigpackView", "FigpackExtension", "ExtensionView"]
@@ -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 ExtensionRegistry
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
- extensions = set()
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
- extensions.add(v.extension_name)
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 extensions
140
+ return extensions_discovered
134
141
 
135
142
 
136
- def _write_extension_files(extension_names: Set[str], tmpdir: str) -> None:
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 extension_name in extension_names:
151
- extension = registry.get_extension(extension_name)
152
- if extension is None:
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()