figpack 0.2.10__py3-none-any.whl → 0.2.12__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.

@@ -5,7 +5,7 @@
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-D2FnM_hN.js"></script>
8
+ <script type="module" crossorigin src="./assets/index-DvunBzII.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="./assets/index-D9a3K6eW.css">
10
10
  </head>
11
11
  <body>
@@ -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)
@@ -0,0 +1,3 @@
1
+ from .PlotlyExtension import PlotlyFigure
2
+
3
+ __all__ = ["PlotlyFigure"]
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Plotly Extension for figpack
3
+ * Provides interactive graph visualization using Plotly library
4
+ */
5
+
6
+ const loadFigureData = async (zarrGroup) => {
7
+ // Get the figure data from the zarr array
8
+ const data = await zarrGroup.file.getDatasetData(
9
+ joinPath(zarrGroup.path, "figure_data"),
10
+ {},
11
+ );
12
+ if (!data || data.length === 0) {
13
+ throw new Error("Empty figure data");
14
+ }
15
+
16
+ // Convert the uint8 array back to string
17
+ const uint8Array = new Uint8Array(data);
18
+ const decoder = new TextDecoder("utf-8");
19
+ const jsonString = decoder.decode(uint8Array);
20
+
21
+ // Parse the JSON string
22
+ const parsedData = JSON.parse(jsonString);
23
+
24
+ return parsedData;
25
+ };
26
+
27
+ (function() {
28
+ window.figpackExtensions = window.figpackExtensions || {};
29
+
30
+ window.figpackExtensions['figpack_plotly'] = {
31
+ render: async function(container, zarrGroup, width, height, onResize) {
32
+ container.innerHTML = '';
33
+
34
+ try {
35
+ const figureData = await loadFigureData(zarrGroup);
36
+
37
+ const makePlot = () => {
38
+ window.Plotly.newPlot(
39
+ container,
40
+ figureData.data || [],
41
+ {
42
+ ...figureData.layout,
43
+ width: width,
44
+ height: height,
45
+ margin: { l: 50, r: 50, t: 50, b: 50 },
46
+ },
47
+ {
48
+ responsive: true,
49
+ displayModeBar: true,
50
+ displaylogo: false,
51
+ },
52
+ )
53
+ };
54
+
55
+ makePlot();
56
+
57
+ // Handle resize events
58
+ onResize((newWidth, newHeight) => {
59
+ window.Plotly.relayout(container, {width: newWidth, height: newHeight});
60
+ });
61
+
62
+ return {
63
+ destroy: () => {
64
+ window.Plotly.purge(container);
65
+ }
66
+ };
67
+
68
+ } catch (error) {
69
+ console.error('Error rendering plotly figure:', error);
70
+ this.renderError(container, width, height, error.message);
71
+ return { destroy: () => {} };
72
+ }
73
+ },
74
+
75
+ renderError: function(container, width, height, message) {
76
+ container.innerHTML = `
77
+ <div style="
78
+ width: ${width}px;
79
+ height: ${height}px;
80
+ display: flex;
81
+ align-items: center;
82
+ justify-content: center;
83
+ background-color: #f8f9fa;
84
+ border: 1px solid #dee2e6;
85
+ color: #6c757d;
86
+ font-family: system-ui, -apple-system, sans-serif;
87
+ font-size: 14px;
88
+ text-align: center;
89
+ padding: 20px;
90
+ box-sizing: border-box;
91
+ ">
92
+ <div>
93
+ <div style="margin-bottom: 10px; font-weight: 500;">Force Graph Error</div>
94
+ <div style="font-size: 12px;">${message}</div>
95
+ </div>
96
+ </div>
97
+ `;
98
+ }
99
+ };
100
+ })();
101
+
102
+ const joinPath = function(p1, p2) {
103
+ if (p1.endsWith('/')) p1 = p1.slice(0, -1);
104
+ if (p2.startsWith('/')) p2 = p2.slice(1);
105
+ return p1 + '/' + p2;
106
+ };
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: figpack
3
- Version: 0.2.10
3
+ Version: 0.2.12
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
@@ -1,4 +1,4 @@
1
- figpack/__init__.py,sha256=E02IMyAwPn4hwSiDGEB5WbgYONLLHiTLrLeNB_Vx-xA,360
1
+ figpack/__init__.py,sha256=Cb1XSVRMpZegRqP62Tcld-PGzOpS2AO413SnbaziETg,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=ikgsofCB3R9e1-mQweaJER9z1wRBkmPtDiLJpslgWnc,1793
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=MJnJvUhYPzf_IkXjD3SZHCeQmwEAQi6QCLS2H2ksSyw,6123
14
- figpack/figpack-figure-dist/index.html,sha256=N0wnfnfGeaKqmiajhD7v8LbZsFUA5pPhqKiHD2m63PY,486
15
- figpack/figpack-figure-dist/assets/index-D2FnM_hN.js,sha256=FyaXGyCqVuyuXu1PAWyaL-7krKB3hxU4UM-7crrqo_c,1622190
13
+ figpack/core/figpack_view.py,sha256=X_EtpWTloENfRnDEJcBxXBPditaObv5BWMzO-_stAho,6297
14
+ figpack/figpack-figure-dist/index.html,sha256=KfLOqUjEskQz4IIEBQzZkvKk98OPHw0S0XMewpC5dsE,486
16
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
@@ -43,16 +43,18 @@ figpack/views/LayoutItem.py,sha256=wy8DggkIzZpU0F1zFIBceS7HpBb6lu-A3hpYINQzedk,1
43
43
  figpack/views/Markdown.py,sha256=Dl1UX5s0aC-mEx5m6jIJ839YKMNeeVzIDG-EANVrbys,1147
44
44
  figpack/views/MatplotlibFigure.py,sha256=YoNtZTItEjatbtNJqATm2H-Oircp5Ca6FZLjHk_B0zg,2778
45
45
  figpack/views/MultiChannelTimeseries.py,sha256=sWr2nW1eoYR7V44wF7fac7IoQ6BOnus1nc4STkgIkYw,8501
46
- figpack/views/PlotlyFigure.py,sha256=E33PEkWSj907Ue73bYfZQlF-JFDdWA8jNrG-buFQLgs,2174
47
46
  figpack/views/Spectrogram.py,sha256=GfTNinkuMFu4dxn35MvSB4Perz84sx4LMcjUrOviz6c,9648
48
47
  figpack/views/Splitter.py,sha256=x9jLCTlIvDy5p9ymVd0X48KDccyD6bJANhXyFgKEmtE,2007
49
48
  figpack/views/TabLayout.py,sha256=5g3nmL95PfqgI0naqZXHMwLVo2ebDlGX01Hy9044bUw,1898
50
49
  figpack/views/TabLayoutItem.py,sha256=xmHA0JsW_6naJze4_mQuP_Fy0Nm17p2N7w_AsmVRp8k,880
51
50
  figpack/views/TimeseriesGraph.py,sha256=OAaCjO8fo86u_gO_frNfRGxng3tczxGDGKcJEvZo3rE,7469
52
- figpack/views/__init__.py,sha256=h9B6RWTOfgizOMqtEu8xGJxtXAhK-XXroN6ebL-Vcr0,543
53
- figpack-0.2.10.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
54
- figpack-0.2.10.dist-info/METADATA,sha256=OsZYqqvYVFnzLuCBScLUKAOLqssgHpLaGZqCzT7Q-zA,3617
55
- figpack-0.2.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
56
- figpack-0.2.10.dist-info/entry_points.txt,sha256=l6d3siH2LxXa8qJGbjAqpIZtI5AkMSyDeoRDCzdrUto,45
57
- figpack-0.2.10.dist-info/top_level.txt,sha256=lMKGaC5xWmAYBx9Ac1iMokm42KFnJFjmkP2ldyvOo-c,8
58
- figpack-0.2.10.dist-info/RECORD,,
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/views/PlotlyExtension/plotly_view.js,sha256=gCsZS0IaYGTN5a3DC2c4NmzoOxZi1xGfCAYI6WSoFpM,3596
55
+ figpack-0.2.12.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
56
+ figpack-0.2.12.dist-info/METADATA,sha256=IyjYIuqCQXp3_TFeUyfEI7XV6Ac6oJum5wq5Qo_lqN8,3617
57
+ figpack-0.2.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
58
+ figpack-0.2.12.dist-info/entry_points.txt,sha256=l6d3siH2LxXa8qJGbjAqpIZtI5AkMSyDeoRDCzdrUto,45
59
+ figpack-0.2.12.dist-info/top_level.txt,sha256=lMKGaC5xWmAYBx9Ac1iMokm42KFnJFjmkP2ldyvOo-c,8
60
+ figpack-0.2.12.dist-info/RECORD,,
@@ -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)