figpack 0.2.1__py3-none-any.whl → 0.2.3__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/cli.py +60 -3
- figpack/core/_server_manager.py +304 -0
- figpack/core/_show_view.py +128 -92
- figpack/core/_upload_bundle.py +19 -9
- figpack/core/figpack_view.py +34 -2
- figpack/figpack-gui-dist/assets/index-DUR9Dmwh.js +847 -0
- figpack/figpack-gui-dist/index.html +1 -1
- figpack/franklab/__init__.py +5 -0
- figpack/franklab/views/TrackAnimation.py +153 -0
- figpack/franklab/views/__init__.py +9 -0
- figpack/spike_sorting/views/AutocorrelogramItem.py +0 -10
- figpack/spike_sorting/views/Autocorrelograms.py +2 -0
- figpack/spike_sorting/views/AverageWaveforms.py +147 -0
- figpack/spike_sorting/views/CrossCorrelogramItem.py +0 -11
- figpack/spike_sorting/views/CrossCorrelograms.py +2 -0
- figpack/spike_sorting/views/SpikeAmplitudes.py +89 -0
- figpack/spike_sorting/views/SpikeAmplitudesItem.py +38 -0
- figpack/spike_sorting/views/__init__.py +6 -0
- {figpack-0.2.1.dist-info → figpack-0.2.3.dist-info}/METADATA +3 -2
- figpack-0.2.3.dist-info/RECORD +47 -0
- figpack/figpack-gui-dist/assets/index-BqYF6BN-.js +0 -846
- figpack-0.2.1.dist-info/RECORD +0 -40
- {figpack-0.2.1.dist-info → figpack-0.2.3.dist-info}/WHEEL +0 -0
- {figpack-0.2.1.dist-info → figpack-0.2.3.dist-info}/entry_points.txt +0 -0
- {figpack-0.2.1.dist-info → figpack-0.2.3.dist-info}/licenses/LICENSE +0 -0
- {figpack-0.2.1.dist-info → figpack-0.2.3.dist-info}/top_level.txt +0 -0
figpack/core/_upload_bundle.py
CHANGED
|
@@ -133,33 +133,45 @@ def _create_or_get_figure(
|
|
|
133
133
|
total_files: int = None,
|
|
134
134
|
total_size: int = None,
|
|
135
135
|
title: str = None,
|
|
136
|
+
ephemeral: bool = False,
|
|
136
137
|
) -> dict:
|
|
137
138
|
"""
|
|
138
139
|
Create a new figure or get existing figure information
|
|
139
140
|
|
|
140
141
|
Args:
|
|
141
142
|
figure_hash: The hash of the figure
|
|
142
|
-
api_key: The API key for authentication
|
|
143
|
+
api_key: The API key for authentication (required for non-ephemeral)
|
|
143
144
|
total_files: Optional total number of files
|
|
144
145
|
total_size: Optional total size of files
|
|
145
146
|
title: Optional title for the figure
|
|
147
|
+
ephemeral: Whether to create an ephemeral figure
|
|
146
148
|
|
|
147
149
|
Returns:
|
|
148
150
|
dict: Figure information from the API
|
|
149
151
|
"""
|
|
152
|
+
# Validate API key requirement
|
|
153
|
+
if not ephemeral and api_key is None:
|
|
154
|
+
raise ValueError("API key is required for non-ephemeral figures")
|
|
155
|
+
|
|
150
156
|
payload = {
|
|
151
157
|
"figureHash": figure_hash,
|
|
152
|
-
"apiKey": api_key,
|
|
153
158
|
"figpackVersion": __version__,
|
|
154
159
|
}
|
|
155
160
|
|
|
161
|
+
# API key is optional for ephemeral figures
|
|
162
|
+
if api_key is not None:
|
|
163
|
+
payload["apiKey"] = api_key
|
|
164
|
+
|
|
156
165
|
if total_files is not None:
|
|
157
166
|
payload["totalFiles"] = total_files
|
|
158
167
|
if total_size is not None:
|
|
159
168
|
payload["totalSize"] = total_size
|
|
160
169
|
if title is not None:
|
|
161
170
|
payload["title"] = title
|
|
171
|
+
if ephemeral:
|
|
172
|
+
payload["ephemeral"] = True
|
|
162
173
|
|
|
174
|
+
# Use the same endpoint for both regular and ephemeral figures
|
|
163
175
|
response = requests.post(f"{FIGPACK_API_BASE_URL}/api/figures/create", json=payload)
|
|
164
176
|
|
|
165
177
|
if not response.ok:
|
|
@@ -212,16 +224,16 @@ def _finalize_figure(figure_url: str, api_key: str) -> dict:
|
|
|
212
224
|
return response_data
|
|
213
225
|
|
|
214
226
|
|
|
215
|
-
def _upload_bundle(
|
|
227
|
+
def _upload_bundle(
|
|
228
|
+
tmpdir: str, api_key: str, title: str = None, ephemeral: bool = False
|
|
229
|
+
) -> str:
|
|
216
230
|
"""
|
|
217
231
|
Upload the prepared bundle to the cloud using the new database-driven approach
|
|
218
232
|
"""
|
|
219
233
|
tmpdir_path = pathlib.Path(tmpdir)
|
|
220
234
|
|
|
221
235
|
# Compute deterministic figure ID based on file contents
|
|
222
|
-
print("Computing deterministic figure ID...")
|
|
223
236
|
figure_hash = _compute_deterministic_figure_hash(tmpdir_path)
|
|
224
|
-
print(f"Figure hash: {figure_hash}")
|
|
225
237
|
|
|
226
238
|
# Collect all files to upload
|
|
227
239
|
all_files = []
|
|
@@ -239,17 +251,15 @@ def _upload_bundle(tmpdir: str, api_key: str, title: str = None) -> str:
|
|
|
239
251
|
|
|
240
252
|
# Find available figure ID and create/get figure in database with metadata
|
|
241
253
|
result = _create_or_get_figure(
|
|
242
|
-
figure_hash, api_key, total_files, total_size, title=title
|
|
254
|
+
figure_hash, api_key, total_files, total_size, title=title, ephemeral=ephemeral
|
|
243
255
|
)
|
|
244
256
|
figure_info = result.get("figure", {})
|
|
245
257
|
figure_url = figure_info.get("figureUrl")
|
|
246
258
|
|
|
247
259
|
if figure_info["status"] == "completed":
|
|
248
|
-
print(f"Figure already exists
|
|
260
|
+
print(f"Figure already exists. No upload needed.")
|
|
249
261
|
return figure_url
|
|
250
262
|
|
|
251
|
-
print(f"Using figure URL: {figure_url}")
|
|
252
|
-
|
|
253
263
|
files_to_upload = all_files
|
|
254
264
|
total_files_to_upload = len(files_to_upload)
|
|
255
265
|
|
figpack/core/figpack_view.py
CHANGED
|
@@ -18,10 +18,13 @@ class FigpackView:
|
|
|
18
18
|
port: Union[int, None] = None,
|
|
19
19
|
open_in_browser: bool = False,
|
|
20
20
|
allow_origin: Union[str, None] = None,
|
|
21
|
-
upload: bool =
|
|
21
|
+
upload: Union[bool, None] = None,
|
|
22
|
+
ephemeral: Union[bool, None] = None,
|
|
22
23
|
_dev: bool = False,
|
|
23
24
|
title: Union[str, None] = None,
|
|
24
25
|
description: Union[str, None] = None,
|
|
26
|
+
inline: Union[bool, None] = None,
|
|
27
|
+
inline_height: int = 600,
|
|
25
28
|
):
|
|
26
29
|
"""
|
|
27
30
|
Display the visualization component
|
|
@@ -31,11 +34,37 @@ class FigpackView:
|
|
|
31
34
|
open_in_browser: Whether to open in browser automatically
|
|
32
35
|
allow_origin: CORS allow origin header
|
|
33
36
|
upload: Whether to upload the figure
|
|
37
|
+
ephemeral: Whether to upload as ephemeral figure (None=auto-detect, True=force ephemeral, False=force regular)
|
|
34
38
|
_dev: Development mode flag
|
|
35
39
|
title: Title for the browser tab and figure
|
|
36
40
|
description: Description text (markdown supported) for the figure
|
|
41
|
+
inline: Whether to display inline in notebook (None=auto-detect, True=force inline, False=force browser)
|
|
42
|
+
inline_height: Height in pixels for inline iframe display (default: 600)
|
|
37
43
|
"""
|
|
38
|
-
from ._show_view import
|
|
44
|
+
from ._show_view import (
|
|
45
|
+
_show_view,
|
|
46
|
+
_is_in_notebook,
|
|
47
|
+
_is_in_colab,
|
|
48
|
+
_is_in_jupyterhub,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
if ephemeral is None and upload is None:
|
|
52
|
+
# If we haven't specified both, then let's check if we're in a notebook in a non-local environment
|
|
53
|
+
if _is_in_notebook():
|
|
54
|
+
if _is_in_colab():
|
|
55
|
+
# if we are in a notebook and in colab, we should show as uploaded ephemeral
|
|
56
|
+
print("Detected Google Colab notebook environment.")
|
|
57
|
+
upload = True
|
|
58
|
+
ephemeral = True
|
|
59
|
+
if _is_in_jupyterhub():
|
|
60
|
+
# if we are in a notebook and in jupyterhub, we should show as uploaded ephemeral
|
|
61
|
+
print("Detected JupyterHub notebook environment.")
|
|
62
|
+
upload = True
|
|
63
|
+
ephemeral = True
|
|
64
|
+
|
|
65
|
+
# Validate ephemeral parameter
|
|
66
|
+
if ephemeral and not upload:
|
|
67
|
+
raise ValueError("ephemeral=True requires upload=True to be set")
|
|
39
68
|
|
|
40
69
|
if _dev:
|
|
41
70
|
if port is None:
|
|
@@ -57,8 +86,11 @@ class FigpackView:
|
|
|
57
86
|
open_in_browser=open_in_browser,
|
|
58
87
|
allow_origin=allow_origin,
|
|
59
88
|
upload=upload,
|
|
89
|
+
ephemeral=ephemeral,
|
|
60
90
|
title=title,
|
|
61
91
|
description=description,
|
|
92
|
+
inline=inline,
|
|
93
|
+
inline_height=inline_height,
|
|
62
94
|
)
|
|
63
95
|
|
|
64
96
|
def _write_to_zarr_group(self, group: zarr.Group) -> None:
|