figpack 0.2.17__py3-none-any.whl → 0.2.40__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.
Files changed (44) hide show
  1. figpack/__init__.py +1 -1
  2. figpack/cli.py +288 -2
  3. figpack/core/_bundle_utils.py +40 -7
  4. figpack/core/_file_handler.py +195 -0
  5. figpack/core/_save_figure.py +12 -8
  6. figpack/core/_server_manager.py +146 -7
  7. figpack/core/_show_view.py +2 -2
  8. figpack/core/_upload_bundle.py +63 -53
  9. figpack/core/_view_figure.py +48 -12
  10. figpack/core/_zarr_consolidate.py +185 -0
  11. figpack/core/extension_view.py +9 -5
  12. figpack/core/figpack_extension.py +1 -1
  13. figpack/core/figpack_view.py +52 -21
  14. figpack/core/zarr.py +2 -2
  15. figpack/extensions.py +356 -0
  16. figpack/figpack-figure-dist/assets/index-ST_DU17U.js +95 -0
  17. figpack/figpack-figure-dist/assets/index-V5m_wCvw.css +1 -0
  18. figpack/figpack-figure-dist/index.html +6 -2
  19. figpack/views/Box.py +4 -4
  20. figpack/views/CaptionedView.py +64 -0
  21. figpack/views/DataFrame.py +1 -1
  22. figpack/views/Gallery.py +2 -2
  23. figpack/views/Iframe.py +43 -0
  24. figpack/views/Image.py +2 -3
  25. figpack/views/Markdown.py +8 -4
  26. figpack/views/MatplotlibFigure.py +1 -1
  27. figpack/views/MountainLayout.py +72 -0
  28. figpack/views/MountainLayoutItem.py +50 -0
  29. figpack/views/MultiChannelTimeseries.py +1 -1
  30. figpack/views/PlotlyExtension/PlotlyExtension.py +14 -14
  31. figpack/views/Spectrogram.py +3 -1
  32. figpack/views/Splitter.py +3 -3
  33. figpack/views/TabLayout.py +2 -2
  34. figpack/views/TimeseriesGraph.py +113 -20
  35. figpack/views/__init__.py +4 -0
  36. {figpack-0.2.17.dist-info → figpack-0.2.40.dist-info}/METADATA +25 -1
  37. figpack-0.2.40.dist-info/RECORD +50 -0
  38. figpack/figpack-figure-dist/assets/index-DBwmtEpB.js +0 -91
  39. figpack/figpack-figure-dist/assets/index-DHWczh-Q.css +0 -1
  40. figpack-0.2.17.dist-info/RECORD +0 -43
  41. {figpack-0.2.17.dist-info → figpack-0.2.40.dist-info}/WHEEL +0 -0
  42. {figpack-0.2.17.dist-info → figpack-0.2.40.dist-info}/entry_points.txt +0 -0
  43. {figpack-0.2.17.dist-info → figpack-0.2.40.dist-info}/licenses/LICENSE +0 -0
  44. {figpack-0.2.17.dist-info → figpack-0.2.40.dist-info}/top_level.txt +0 -0
@@ -3,7 +3,7 @@ Views module for figpack - contains visualization components
3
3
  """
4
4
 
5
5
  import math
6
- from typing import Any, Dict, List, Optional, Union
6
+ from typing import Any, Dict, List, Optional, Tuple, Union
7
7
 
8
8
  import numpy as np
9
9
 
@@ -26,7 +26,7 @@ class TimeseriesGraph(FigpackView):
26
26
  hide_nav_toolbar: bool = False,
27
27
  hide_time_axis_labels: bool = False,
28
28
  y_label: str = "",
29
- ):
29
+ ) -> None:
30
30
  """
31
31
  Initialize a TimeseriesGraph
32
32
 
@@ -54,8 +54,8 @@ class TimeseriesGraph(FigpackView):
54
54
  self,
55
55
  *,
56
56
  name: str,
57
- t: np.ndarray,
58
- y: np.ndarray,
57
+ t: Union[np.ndarray, List[float]],
58
+ y: Union[np.ndarray, List[float]],
59
59
  color: str = "blue",
60
60
  width: float = 1.0,
61
61
  dash: Optional[List[float]] = None,
@@ -71,6 +71,13 @@ class TimeseriesGraph(FigpackView):
71
71
  width: Line width
72
72
  dash: Dash pattern as [dash_length, gap_length]
73
73
  """
74
+ if isinstance(t, list):
75
+ t = np.array(t)
76
+ if isinstance(y, list):
77
+ y = np.array(y)
78
+ assert t.ndim == 1, "Time array must be 1-dimensional"
79
+ assert y.ndim == 1, "Y array must be 1-dimensional"
80
+ assert len(t) == len(y), "Time and Y arrays must have the same length"
74
81
  self._series.append(
75
82
  TGLineSeries(name=name, t=t, y=y, color=color, width=width, dash=dash)
76
83
  )
@@ -96,6 +103,13 @@ class TimeseriesGraph(FigpackView):
96
103
  radius: Marker radius
97
104
  shape: Marker shape ("circle", "square", etc.)
98
105
  """
106
+ if isinstance(t, list):
107
+ t = np.array(t)
108
+ if isinstance(y, list):
109
+ y = np.array(y)
110
+ assert t.ndim == 1, "Time array must be 1-dimensional"
111
+ assert y.ndim == 1, "Y array must be 1-dimensional"
112
+ assert len(t) == len(y), "Time and Y arrays must have the same length"
99
113
  self._series.append(
100
114
  TGMarkerSeries(name=name, t=t, y=y, color=color, radius=radius, shape=shape)
101
115
  )
@@ -119,6 +133,18 @@ class TimeseriesGraph(FigpackView):
119
133
  color: Fill color
120
134
  alpha: Transparency (0-1)
121
135
  """
136
+ if isinstance(t_start, list):
137
+ t_start = np.array(t_start)
138
+ if isinstance(t_end, list):
139
+ t_end = np.array(t_end)
140
+ assert t_start.ndim == 1, "Start time array must be 1-dimensional"
141
+ assert t_end.ndim == 1, "End time array must be 1-dimensional"
142
+ assert len(t_start) == len(
143
+ t_end
144
+ ), "Start and end time arrays must have the same length"
145
+ assert np.all(
146
+ t_start <= t_end
147
+ ), "Start times must be less than or equal to end times"
122
148
  self._series.append(
123
149
  TGIntervalSeries(
124
150
  name=name, t_start=t_start, t_end=t_end, color=color, alpha=alpha
@@ -135,6 +161,9 @@ class TimeseriesGraph(FigpackView):
135
161
  channel_names: Optional[List[str]] = None,
136
162
  colors: Optional[List[str]] = None,
137
163
  width: float = 1.0,
164
+ channel_spacing: Optional[float] = None,
165
+ auto_channel_spacing: Optional[float] = None,
166
+ timestamps_for_inserting_nans: Optional[np.ndarray] = None,
138
167
  ) -> None:
139
168
  """
140
169
  Add a uniform timeseries to the graph with optional multi-channel support
@@ -147,7 +176,12 @@ class TimeseriesGraph(FigpackView):
147
176
  channel_names: Optional list of channel names
148
177
  colors: Optional list of colors for each channel
149
178
  width: Line width
179
+ channel_spacing: Vertical spacing between channels
180
+ auto_channel_spacing: sets channel spacing to this multiple of the estimated RMS noise level
181
+ timestamps_for_inserting_nans: Optional array of timestamps used to determine where to insert NaNs in the data
150
182
  """
183
+ if isinstance(data, list):
184
+ data = np.array(data)
151
185
  self._series.append(
152
186
  TGUniformSeries(
153
187
  name=name,
@@ -157,10 +191,13 @@ class TimeseriesGraph(FigpackView):
157
191
  channel_names=channel_names,
158
192
  colors=colors,
159
193
  width=width,
194
+ channel_spacing=channel_spacing,
195
+ auto_channel_spacing=auto_channel_spacing,
196
+ timestamps_for_inserting_nans=timestamps_for_inserting_nans,
160
197
  )
161
198
  )
162
199
 
163
- def _write_to_zarr_group(self, group: Group) -> None:
200
+ def write_to_zarr_group(self, group: Group) -> None:
164
201
  """
165
202
  Write the graph data to a Zarr group
166
203
 
@@ -170,13 +207,13 @@ class TimeseriesGraph(FigpackView):
170
207
  for series in self._series:
171
208
  series_group = group.create_group(series.name)
172
209
  if isinstance(series, TGLineSeries):
173
- series._write_to_zarr_group(series_group)
210
+ series.write_to_zarr_group(series_group)
174
211
  elif isinstance(series, TGMarkerSeries):
175
- series._write_to_zarr_group(series_group)
212
+ series.write_to_zarr_group(series_group)
176
213
  elif isinstance(series, TGIntervalSeries):
177
- series._write_to_zarr_group(series_group)
214
+ series.write_to_zarr_group(series_group)
178
215
  elif isinstance(series, TGUniformSeries):
179
- series._write_to_zarr_group(series_group)
216
+ series.write_to_zarr_group(series_group)
180
217
  else:
181
218
  raise ValueError(f"Unknown series type: {type(series)}")
182
219
 
@@ -204,7 +241,7 @@ class TGLineSeries:
204
241
  color: str,
205
242
  width: float,
206
243
  dash: Optional[List[float]],
207
- ):
244
+ ) -> None:
208
245
  assert t.ndim == 1, "Time array must be 1-dimensional"
209
246
  assert y.ndim == 1, "Y array must be 1-dimensional"
210
247
  assert len(t) == len(y), "Time and Y arrays must have the same length"
@@ -215,7 +252,7 @@ class TGLineSeries:
215
252
  self.width = width
216
253
  self.dash = dash
217
254
 
218
- def _write_to_zarr_group(
255
+ def write_to_zarr_group(
219
256
  self,
220
257
  group: Group,
221
258
  ) -> None:
@@ -237,7 +274,7 @@ class TGMarkerSeries:
237
274
  color: str,
238
275
  radius: float,
239
276
  shape: str,
240
- ):
277
+ ) -> None:
241
278
  assert t.ndim == 1, "Time array must be 1-dimensional"
242
279
  assert y.ndim == 1, "Y array must be 1-dimensional"
243
280
  assert len(t) == len(y), "Time and Y arrays must have the same length"
@@ -248,7 +285,7 @@ class TGMarkerSeries:
248
285
  self.radius = radius
249
286
  self.shape = shape
250
287
 
251
- def _write_to_zarr_group(self, group: Group) -> None:
288
+ def write_to_zarr_group(self, group: Group) -> None:
252
289
  """
253
290
  Write the marker series data to a Zarr dataset
254
291
 
@@ -272,7 +309,7 @@ class TGIntervalSeries:
272
309
  t_end: np.ndarray,
273
310
  color: str,
274
311
  alpha: float,
275
- ):
312
+ ) -> None:
276
313
  assert t_start.ndim == 1, "Start time array must be 1-dimensional"
277
314
  assert t_end.ndim == 1, "End time array must be 1-dimensional"
278
315
  assert len(t_start) == len(
@@ -287,7 +324,7 @@ class TGIntervalSeries:
287
324
  self.color = color
288
325
  self.alpha = alpha
289
326
 
290
- def _write_to_zarr_group(self, group: Group) -> None:
327
+ def write_to_zarr_group(self, group: Group) -> None:
291
328
  """
292
329
  Write the interval series data to a Zarr dataset
293
330
 
@@ -312,7 +349,10 @@ class TGUniformSeries:
312
349
  channel_names: Optional[List[str]] = None,
313
350
  colors: Optional[List[str]] = None,
314
351
  width: float = 1.0,
315
- ):
352
+ channel_spacing: Optional[float] = None,
353
+ auto_channel_spacing: Optional[float] = None,
354
+ timestamps_for_inserting_nans: Optional[np.ndarray] = None,
355
+ ) -> None:
316
356
  assert sampling_frequency_hz > 0, "Sampling frequency must be positive"
317
357
 
318
358
  # Handle both 1D and 2D data
@@ -332,6 +372,34 @@ class TGUniformSeries:
332
372
  self.sampling_frequency_hz = sampling_frequency_hz
333
373
  self.data = data.astype(np.float32) # Ensure float32 for efficiency
334
374
 
375
+ if timestamps_for_inserting_nans is not None:
376
+ self.data = insert_nans_based_on_timestamps(
377
+ self.data,
378
+ start_time_sec=start_time_sec,
379
+ sampling_frequency_hz=sampling_frequency_hz,
380
+ timestamps=timestamps_for_inserting_nans,
381
+ )
382
+
383
+ if auto_channel_spacing is not None:
384
+ if channel_spacing is not None:
385
+ raise ValueError(
386
+ "Specify either channel_spacing or auto_channel_spacing, not both."
387
+ )
388
+ # Estimate RMS noise level across all channels using median absolute deviation
389
+ # Use nanmedian to handle NaN values properly
390
+ mad = np.nanmedian(
391
+ np.abs(self.data - np.nanmedian(self.data, axis=0)), axis=0
392
+ )
393
+ rms_estimate = mad / 0.6745 # Convert MAD to RMS estimate
394
+ channel_spacing = auto_channel_spacing * np.nanmedian(rms_estimate)
395
+ if (
396
+ channel_spacing is None
397
+ or (channel_spacing <= 0)
398
+ or np.isnan(channel_spacing)
399
+ ):
400
+ channel_spacing = 1.0 # Fallback to default spacing if estimate fails
401
+ self.channel_spacing = channel_spacing
402
+
335
403
  # Set channel names
336
404
  if channel_names is None:
337
405
  if n_channels == 1:
@@ -373,7 +441,7 @@ class TGUniformSeries:
373
441
  # Prepare downsampled arrays for efficient rendering
374
442
  self.downsampled_data = self._compute_downsampled_data()
375
443
 
376
- def _compute_downsampled_data(self) -> dict:
444
+ def _compute_downsampled_data(self) -> Dict[int, np.ndarray]:
377
445
  """
378
446
  Compute downsampled arrays at power-of-4 factors using a vectorized
379
447
  min/max pyramid with NaN padding for partial bins.
@@ -448,8 +516,8 @@ class TGUniformSeries:
448
516
  return downsampled
449
517
 
450
518
  def _calculate_optimal_chunk_size(
451
- self, shape: tuple, target_size_mb: float = 5.0
452
- ) -> tuple:
519
+ self, shape: Tuple[int, ...], target_size_mb: float = 5.0
520
+ ) -> Tuple[int, ...]:
453
521
  """
454
522
  Calculate optimal chunk size for Zarr storage targeting ~5MB per chunk
455
523
 
@@ -492,7 +560,7 @@ class TGUniformSeries:
492
560
  else: # len(shape) == 3
493
561
  return (chunk_timepoints, 2, n_channels)
494
562
 
495
- def _write_to_zarr_group(self, group: Group) -> None:
563
+ def write_to_zarr_group(self, group: Group) -> None:
496
564
  """
497
565
  Write the uniform series data to a Zarr group
498
566
 
@@ -512,6 +580,9 @@ class TGUniformSeries:
512
580
  group.attrs["n_timepoints"] = n_timepoints
513
581
  group.attrs["n_channels"] = n_channels
514
582
 
583
+ if self.channel_spacing is not None:
584
+ group.attrs["channel_spacing"] = float(self.channel_spacing)
585
+
515
586
  # Store original data with optimal chunking
516
587
  original_chunks = self._calculate_optimal_chunk_size(self.data.shape)
517
588
  group.create_dataset(
@@ -535,3 +606,25 @@ class TGUniformSeries:
535
606
  data=downsampled_array,
536
607
  chunks=ds_chunks,
537
608
  )
609
+
610
+
611
+ def insert_nans_based_on_timestamps(
612
+ x: np.ndarray,
613
+ *,
614
+ start_time_sec: float,
615
+ sampling_frequency_hz: float,
616
+ timestamps: np.ndarray,
617
+ ) -> np.ndarray:
618
+ end_timestamps = timestamps[-1]
619
+ ret_length = int((end_timestamps - start_time_sec) * sampling_frequency_hz) + 1
620
+
621
+ # Handle both 1D and 2D (multi-channel) data
622
+ if x.ndim == 1:
623
+ ret = np.nan * np.ones((ret_length,), dtype=x.dtype)
624
+ else: # x.ndim == 2
625
+ n_channels = x.shape[1]
626
+ ret = np.nan * np.ones((ret_length, n_channels), dtype=x.dtype)
627
+
628
+ indices = ((timestamps - start_time_sec) * sampling_frequency_hz).astype(int)
629
+ ret[indices] = x
630
+ return ret
figpack/views/__init__.py CHANGED
@@ -1,11 +1,15 @@
1
1
  from .Box import Box
2
+ from .CaptionedView import CaptionedView
2
3
  from .DataFrame import DataFrame
3
4
  from .Gallery import Gallery
4
5
  from .GalleryItem import GalleryItem
6
+ from .Iframe import Iframe
5
7
  from .Image import Image
6
8
  from .LayoutItem import LayoutItem
7
9
  from .Markdown import Markdown
8
10
  from .MatplotlibFigure import MatplotlibFigure
11
+ from .MountainLayout import MountainLayout
12
+ from .MountainLayoutItem import MountainLayoutItem
9
13
  from .MultiChannelTimeseries import MultiChannelTimeseries
10
14
  from .Spectrogram import Spectrogram
11
15
  from .Splitter import Splitter
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: figpack
3
- Version: 0.2.17
3
+ Version: 0.2.40
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
@@ -69,6 +69,9 @@ Requires-Dist: sphinx-rtd-theme>=2.0; extra == "docs"
69
69
  Requires-Dist: sphinx-autobuild>=2021.3.14; extra == "docs"
70
70
  Requires-Dist: linkify-it-py>=2.0; extra == "docs"
71
71
  Requires-Dist: sphinx-copybutton>=0.5; extra == "docs"
72
+ Requires-Dist: lindi; extra == "docs"
73
+ Requires-Dist: nibabel; extra == "docs"
74
+ Requires-Dist: Pillow; extra == "docs"
72
75
  Dynamic: license-file
73
76
 
74
77
  # figpack
@@ -111,6 +114,27 @@ graph.show(open_in_browser=True, title="Quick Start Example")
111
114
 
112
115
  Apache-2.0
113
116
 
117
+ ## Citation
118
+
119
+ If you use figpack in your research, please cite it:
120
+
121
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.17419621.svg)](https://doi.org/10.5281/zenodo.17419621)
122
+
123
+ ```bibtex
124
+ @software{magland_figpack_2025,
125
+ author = {Magland, Jeremy},
126
+ title = {figpack},
127
+ year = 2025,
128
+ publisher = {Zenodo},
129
+ doi = {10.5281/zenodo.17419621},
130
+ url = {https://doi.org/10.5281/zenodo.17419621}
131
+ }
132
+ ```
133
+
134
+ Or in APA format:
135
+
136
+ > Magland, J. (2025). figpack (Version 0.2.40) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.17419621
137
+
114
138
  ## Contributing
115
139
 
116
140
  Visit the [GitHub repository](https://github.com/flatironinstitute/figpack) for issues, contributions, and the latest updates.
@@ -0,0 +1,50 @@
1
+ figpack/__init__.py,sha256=skZ1R6k19F5UFsi2LdLti5jyUb4LzRtZT1VVaXWy0cE,358
2
+ figpack/cli.py,sha256=TfSGSw2YUlO0JPlNb4DYko636rk7vV91tqL6QHBSgoQ,18464
3
+ figpack/extensions.py,sha256=mILB4_F1RHkca4I7t88zh74IX8VCmfT7XFZZT4XYdNw,13009
4
+ figpack/core/__init__.py,sha256=7zU6O1piTk07aeCfbU81QqTgSHIO2n5MZ4LFNmsrtfs,192
5
+ figpack/core/_bundle_utils.py,sha256=a0oPsqRsaQbrNcUKXHZTfE5uPtgmtqLJdQQPE1jS4_0,9299
6
+ figpack/core/_file_handler.py,sha256=T_Yq3aGcgfqbGCW31Ge9MseApH3zoZ8iZ2wTyb9cYuw,7113
7
+ figpack/core/_save_figure.py,sha256=ZboTlu5N609GmBlQ7rni5p7AP1mvCelEjHBHWeLWGOM,1166
8
+ figpack/core/_server_manager.py,sha256=2F1fo1aEcbbmQXiZ5wjJ1SpV4BqgtwAqq8KvQFrFVPo,16262
9
+ figpack/core/_show_view.py,sha256=nLsVOuuy5-NLSAK8qMjxmRart3TAL1wH1duTcIH_mGA,5187
10
+ figpack/core/_upload_bundle.py,sha256=cNoLSbsulmZ8R8BzohZLACDmwxdDN9f8TwO_fpDeSHc,15020
11
+ figpack/core/_view_figure.py,sha256=FVPvSOa1hW2Th-X778VwKytfNpudoFNb1LK7eY43p44,5568
12
+ figpack/core/_zarr_consolidate.py,sha256=uKcSq_ml0pBVztJJZwinXAiyyk2P28Ao12IbEA3niSU,6052
13
+ figpack/core/config.py,sha256=oOR7SlP192vuFhYlS-h14HnG-kd_3gaz0vshXch2RNc,173
14
+ figpack/core/extension_view.py,sha256=qh1g7H_YfOF0eLAl-c7uZlv7A8Ssm8VbrhRfGsjtHto,1322
15
+ figpack/core/figpack_extension.py,sha256=F4q6poPihwVnjWQtasZjvzB0IkqFfgJuv8Xb9N4eNOA,2260
16
+ figpack/core/figpack_view.py,sha256=LCwydF_M03gvlAGjU9CMWFMyXGlV0EkfhzgAU9gxPWc,7292
17
+ figpack/core/zarr.py,sha256=wKi8G2MksdTbZUA3Yc-huhIplrOWCgkmYnn8NMftA7k,1666
18
+ figpack/figpack-figure-dist/index.html,sha256=hclmcIxQE4wsyJhUGc_VEn_mOIIwYNlPxMYiu-5Rl0Q,721
19
+ figpack/figpack-figure-dist/assets/index-ST_DU17U.js,sha256=mW0CJUOVNkAq41pYztt4p-stkSXMyG3Jv295_YHLd28,1116532
20
+ figpack/figpack-figure-dist/assets/index-V5m_wCvw.css,sha256=WRtQLW6SNlTlLtepSOt89t1z41SD7XzYUyRldqowjMM,7286
21
+ figpack/figpack-figure-dist/assets/neurosift-logo-CLsuwLMO.png,sha256=g5m-TwrGh5f6-9rXtWV-znH4B0nHgc__0GWclRDLUHs,9307
22
+ figpack/views/Box.py,sha256=WTp69JiytmcocdkKR4k-qLKMB9soiu_8uOKHeO6mtUQ,2416
23
+ figpack/views/CaptionedView.py,sha256=Lgv4ZMs0LqHuzLIjEGVZhq2zzv-Ufa9pqUCyky8DuCY,1908
24
+ figpack/views/DataFrame.py,sha256=VGspmfWtnZ4Gvea5zd-ODpiJPQEp8gVv-ScDhVVCeyA,3400
25
+ figpack/views/Gallery.py,sha256=15ukt9CmgkbT8q_okEYYDESW1E7vOJkVPombSlrEWKw,3324
26
+ figpack/views/GalleryItem.py,sha256=b_upJno5P3ANSulbG-h3t6Xj56tPGJ7iVxqyiZu3zaQ,1244
27
+ figpack/views/Iframe.py,sha256=F7q46W2UO1oDcG0IpAWgIxbMtRo9dPORJY8Msu3Tm6Y,1050
28
+ figpack/views/Image.py,sha256=z9PEnaGk470Zy5q06e2hIoHV53XSGpouMGT4bZf4ixA,3737
29
+ figpack/views/LayoutItem.py,sha256=wy8DggkIzZpU0F1zFIBceS7HpBb6lu-A3hpYINQzedk,1595
30
+ figpack/views/Markdown.py,sha256=yKMnWpxT0o9tRsPHjbcdZCgXpE67WNV-R66EAHdE2nA,1301
31
+ figpack/views/MatplotlibFigure.py,sha256=697xTOkNxcwYZrLoYOzh4CuME4NDUpIYzX-ckLE5aWU,2422
32
+ figpack/views/MountainLayout.py,sha256=JGvrhzqLR2im5d-m0TsZNy06KOR5iGfDlinrRqHpQsQ,2680
33
+ figpack/views/MountainLayoutItem.py,sha256=arYO1pD9RpXfHQKxtFagl66bjqSzEdafIf8ldDEMTD0,1451
34
+ figpack/views/MultiChannelTimeseries.py,sha256=6AkEbAsdM6fvZVsa3jakIjEcx6LNWhF0fbS00e33heM,8291
35
+ figpack/views/Spectrogram.py,sha256=YuxEbqDJhhD6R4z6aIR8zzPtk6Wcszjq5V5NtY_1s8w,9502
36
+ figpack/views/Splitter.py,sha256=BR2L-8aqicTubS1rSzsQ3XnhoJcX5GcfEnVWtEWEs0w,2016
37
+ figpack/views/TabLayout.py,sha256=AqdHPLcP2-caWjxbkC8r8m60z8n_eyZrIBGOOPSVNCs,1908
38
+ figpack/views/TabLayoutItem.py,sha256=xmHA0JsW_6naJze4_mQuP_Fy0Nm17p2N7w_AsmVRp8k,880
39
+ figpack/views/TimeseriesGraph.py,sha256=0s0Uc-4iuvnoosAh5-yJDYe0UyvWDMIJOqlNqb_dZdA,21931
40
+ figpack/views/__init__.py,sha256=eZVhNCRRUIYtXou__k2tfNjPKyrc576whfZsVFagofY,709
41
+ figpack/views/PlotlyExtension/PlotlyExtension.py,sha256=MehIrw3ZMjHc4LjKd6ZYKnMi0828bX2ehi68KcW4_P8,2125
42
+ figpack/views/PlotlyExtension/__init__.py,sha256=80Wy1mDMWyagjuR99ECxJePIYpRQ6TSyHkB0uZoBZ_0,70
43
+ figpack/views/PlotlyExtension/_plotly_extension.py,sha256=yZjG1NMGlQedeeLdV6TQWpi_NTm5Wfk5eWbXEdZbbFE,1455
44
+ figpack/views/PlotlyExtension/plotly_view.js,sha256=9BjgOPkqGl87SSonnb48nFeQV3UTIi1trpSPxd9qlKo,3055
45
+ figpack-0.2.40.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
46
+ figpack-0.2.40.dist-info/METADATA,sha256=QFIwOS4GN3o3vfLxr4OdSIEvdOGlJQyI1mNAojlQKcE,5196
47
+ figpack-0.2.40.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
48
+ figpack-0.2.40.dist-info/entry_points.txt,sha256=l6d3siH2LxXa8qJGbjAqpIZtI5AkMSyDeoRDCzdrUto,45
49
+ figpack-0.2.40.dist-info/top_level.txt,sha256=lMKGaC5xWmAYBx9Ac1iMokm42KFnJFjmkP2ldyvOo-c,8
50
+ figpack-0.2.40.dist-info/RECORD,,