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.

@@ -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-BBJJgcTp.js"></script>
9
- <link rel="stylesheet" crossorigin href="./assets/index-Cmae55E4.css">
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)
@@ -0,0 +1,3 @@
1
+ from .PlotlyExtension import PlotlyFigure
2
+
3
+ __all__ = ["PlotlyFigure"]
@@ -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
- assert frequency_delta_hz > 0, "Frequency delta must be positive"
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["frequency_min_hz"] = self.frequency_min_hz
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: figpack
3
- Version: 0.2.9
3
+ Version: 0.2.11
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=QX8aUoEzdFpu8BVOKYP17qmFLc1RHniSEbFfKJKSAxo,359
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=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=jIxMqkV9VT1slfRFAL_ePtmr9_Lmi0g3wrtuwAzx5Lo,486
15
- figpack/figpack-figure-dist/assets/index-BBJJgcTp.js,sha256=F7hfH7GV9zHexBfb84PfXraAvYd2WUm4uIJaJp1-xaw,1620758
16
- figpack/figpack-figure-dist/assets/index-Cmae55E4.css,sha256=Yg0apcYehJwQvSQIUH13S7tsfqWQDevpJsAho0dDf0g,5499
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=iRq7xPmyhnQ3GffnPC0GxKGEWnlqXY_8IOxsMqYZ1IM,967
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/PlotlyFigure.py,sha256=E33PEkWSj907Ue73bYfZQlF-JFDdWA8jNrG-buFQLgs,2174
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=h9B6RWTOfgizOMqtEu8xGJxtXAhK-XXroN6ebL-Vcr0,543
52
- figpack-0.2.9.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
53
- figpack-0.2.9.dist-info/METADATA,sha256=5hgox4NpLw0A2HQ-bUGtOpI0OThZEiRbo_EMrKKkf-o,3616
54
- figpack-0.2.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
55
- figpack-0.2.9.dist-info/entry_points.txt,sha256=l6d3siH2LxXa8qJGbjAqpIZtI5AkMSyDeoRDCzdrUto,45
56
- figpack-0.2.9.dist-info/top_level.txt,sha256=lMKGaC5xWmAYBx9Ac1iMokm42KFnJFjmkP2ldyvOo-c,8
57
- figpack-0.2.9.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-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,,
@@ -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)