figpack 0.2.27__py3-none-any.whl → 0.2.28__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 CHANGED
@@ -2,7 +2,7 @@
2
2
  figpack - A Python package for creating shareable, interactive visualizations in the browser
3
3
  """
4
4
 
5
- __version__ = "0.2.27"
5
+ __version__ = "0.2.28"
6
6
 
7
7
  from .cli import view_figure
8
8
  from .core import FigpackView, FigpackExtension, ExtensionView
@@ -137,6 +137,7 @@ class TimeseriesGraph(FigpackView):
137
137
  width: float = 1.0,
138
138
  channel_spacing: Optional[float] = None,
139
139
  auto_channel_spacing: Optional[float] = None,
140
+ timestamps_for_inserting_nans: Optional[np.ndarray] = None,
140
141
  ) -> None:
141
142
  """
142
143
  Add a uniform timeseries to the graph with optional multi-channel support
@@ -151,6 +152,7 @@ class TimeseriesGraph(FigpackView):
151
152
  width: Line width
152
153
  channel_spacing: Vertical spacing between channels
153
154
  auto_channel_spacing: sets channel spacing to this multiple of the estimated RMS noise level
155
+ timestamps_for_inserting_nans: Optional array of timestamps used to determine where to insert NaNs in the data
154
156
  """
155
157
  self._series.append(
156
158
  TGUniformSeries(
@@ -163,6 +165,7 @@ class TimeseriesGraph(FigpackView):
163
165
  width=width,
164
166
  channel_spacing=channel_spacing,
165
167
  auto_channel_spacing=auto_channel_spacing,
168
+ timestamps_for_inserting_nans=timestamps_for_inserting_nans,
166
169
  )
167
170
  )
168
171
 
@@ -320,6 +323,7 @@ class TGUniformSeries:
320
323
  width: float = 1.0,
321
324
  channel_spacing: Optional[float] = None,
322
325
  auto_channel_spacing: Optional[float] = None,
326
+ timestamps_for_inserting_nans: Optional[np.ndarray] = None,
323
327
  ):
324
328
  assert sampling_frequency_hz > 0, "Sampling frequency must be positive"
325
329
 
@@ -340,16 +344,27 @@ class TGUniformSeries:
340
344
  self.sampling_frequency_hz = sampling_frequency_hz
341
345
  self.data = data.astype(np.float32) # Ensure float32 for efficiency
342
346
 
347
+ if timestamps_for_inserting_nans is not None:
348
+ self.data = insert_nans_based_on_timestamps(
349
+ self.data,
350
+ start_time_sec=start_time_sec,
351
+ sampling_frequency_hz=sampling_frequency_hz,
352
+ timestamps=timestamps_for_inserting_nans,
353
+ )
354
+
343
355
  if auto_channel_spacing is not None:
344
356
  if channel_spacing is not None:
345
357
  raise ValueError(
346
358
  "Specify either channel_spacing or auto_channel_spacing, not both."
347
359
  )
348
360
  # Estimate RMS noise level across all channels using median absolute deviation
349
- mad = np.median(np.abs(self.data - np.median(self.data, axis=0)), axis=0)
361
+ # Use nanmedian to handle NaN values properly
362
+ mad = np.nanmedian(
363
+ np.abs(self.data - np.nanmedian(self.data, axis=0)), axis=0
364
+ )
350
365
  rms_estimate = mad / 0.6745 # Convert MAD to RMS estimate
351
- channel_spacing = auto_channel_spacing * np.median(rms_estimate)
352
- if channel_spacing <= 0:
366
+ channel_spacing = auto_channel_spacing * np.nanmedian(rms_estimate)
367
+ if channel_spacing <= 0 or np.isnan(channel_spacing):
353
368
  channel_spacing = 1.0 # Fallback to default spacing if estimate fails
354
369
  self.channel_spacing = channel_spacing
355
370
 
@@ -559,3 +574,25 @@ class TGUniformSeries:
559
574
  data=downsampled_array,
560
575
  chunks=ds_chunks,
561
576
  )
577
+
578
+
579
+ def insert_nans_based_on_timestamps(
580
+ x: np.ndarray,
581
+ *,
582
+ start_time_sec: float,
583
+ sampling_frequency_hz: float,
584
+ timestamps: np.ndarray,
585
+ ):
586
+ end_timestamps = timestamps[-1]
587
+ ret_length = int((end_timestamps - start_time_sec) * sampling_frequency_hz) + 1
588
+
589
+ # Handle both 1D and 2D (multi-channel) data
590
+ if x.ndim == 1:
591
+ ret = np.nan * np.ones((ret_length,), dtype=x.dtype)
592
+ else: # x.ndim == 2
593
+ n_channels = x.shape[1]
594
+ ret = np.nan * np.ones((ret_length, n_channels), dtype=x.dtype)
595
+
596
+ indices = ((timestamps - start_time_sec) * sampling_frequency_hz).astype(int)
597
+ ret[indices] = x
598
+ return ret
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: figpack
3
- Version: 0.2.27
3
+ Version: 0.2.28
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=zxhqr0lde2J_mnAi73-7r4CZptcqrtGZIZB7Tj5AJos,358
1
+ figpack/__init__.py,sha256=ZIM-xRn0YXJHMil7YxRrnjEResxKD-UXM9PQN8sBLOg,358
2
2
  figpack/cli.py,sha256=s1mGQuFSntxiIvU6OWwHVlM9Cj-l1zMQ3OzFFe1-5ZE,11089
3
3
  figpack/extensions.py,sha256=mILB4_F1RHkca4I7t88zh74IX8VCmfT7XFZZT4XYdNw,13009
4
4
  figpack/core/__init__.py,sha256=7zU6O1piTk07aeCfbU81QqTgSHIO2n5MZ4LFNmsrtfs,192
@@ -33,15 +33,15 @@ figpack/views/Spectrogram.py,sha256=jcm26ucHedKDnBA5xnAUu9tW-g-ZutT-kw1EIhYm66E,
33
33
  figpack/views/Splitter.py,sha256=BR2L-8aqicTubS1rSzsQ3XnhoJcX5GcfEnVWtEWEs0w,2016
34
34
  figpack/views/TabLayout.py,sha256=AqdHPLcP2-caWjxbkC8r8m60z8n_eyZrIBGOOPSVNCs,1908
35
35
  figpack/views/TabLayoutItem.py,sha256=xmHA0JsW_6naJze4_mQuP_Fy0Nm17p2N7w_AsmVRp8k,880
36
- figpack/views/TimeseriesGraph.py,sha256=ygbgB83CIc5z_FN6gedWB_KIGh9Zo6LwrCafJqWckfU,19011
36
+ figpack/views/TimeseriesGraph.py,sha256=hhHhtbgaYMldWeSg76M8WRf9ZkI7-1xc3bLWX3c4Acg,20448
37
37
  figpack/views/__init__.py,sha256=V09R6vFRzhY7ANevWomM7muFfUieXZEjGimPiMHpey4,641
38
38
  figpack/views/PlotlyExtension/PlotlyExtension.py,sha256=LOFSqbm46UZ7HsHTDxUPnNB33ydYQvEkRVK-TSKkzK4,2149
39
39
  figpack/views/PlotlyExtension/__init__.py,sha256=80Wy1mDMWyagjuR99ECxJePIYpRQ6TSyHkB0uZoBZ_0,70
40
40
  figpack/views/PlotlyExtension/_plotly_extension.py,sha256=yZjG1NMGlQedeeLdV6TQWpi_NTm5Wfk5eWbXEdZbbFE,1455
41
41
  figpack/views/PlotlyExtension/plotly_view.js,sha256=9BjgOPkqGl87SSonnb48nFeQV3UTIi1trpSPxd9qlKo,3055
42
- figpack-0.2.27.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
43
- figpack-0.2.27.dist-info/METADATA,sha256=1_RNdRpyaQQaJD0ZoqyWjWNAn2WcgrIdlfDLfFGYtes,4618
44
- figpack-0.2.27.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
- figpack-0.2.27.dist-info/entry_points.txt,sha256=l6d3siH2LxXa8qJGbjAqpIZtI5AkMSyDeoRDCzdrUto,45
46
- figpack-0.2.27.dist-info/top_level.txt,sha256=lMKGaC5xWmAYBx9Ac1iMokm42KFnJFjmkP2ldyvOo-c,8
47
- figpack-0.2.27.dist-info/RECORD,,
42
+ figpack-0.2.28.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
43
+ figpack-0.2.28.dist-info/METADATA,sha256=SexqCXW831vYDik27uUYBKr2EokWoXCYpgL0mgG3EbM,4618
44
+ figpack-0.2.28.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
+ figpack-0.2.28.dist-info/entry_points.txt,sha256=l6d3siH2LxXa8qJGbjAqpIZtI5AkMSyDeoRDCzdrUto,45
46
+ figpack-0.2.28.dist-info/top_level.txt,sha256=lMKGaC5xWmAYBx9Ac1iMokm42KFnJFjmkP2ldyvOo-c,8
47
+ figpack-0.2.28.dist-info/RECORD,,