Skip to content

Commit dc71431

Browse files
committed
Now, plot_series gives a locked row window precedence over the row filter
1 parent 955abe8 commit dc71431

2 files changed

Lines changed: 45 additions & 9 deletions

File tree

src/blosc2/b2view/model.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -433,20 +433,29 @@ def plot_series(
433433
434434
Pass *row_start*/*row_stop* to zoom into a sub-range (always read
435435
exactly; ``x`` stays in absolute row coordinates). The series is a
436-
CTable column (*column* is its name; an active row filter is honored) or
437-
an array (*column* is the global index along the column dimension of
438-
*layout*, or None for 1-D arrays).
436+
CTable column (*column* is its name; a locked row window takes
437+
precedence, otherwise an active row filter is honored) or an array
438+
(*column* is the global index along the column dimension of *layout*,
439+
or None for 1-D arrays).
439440
"""
440441
path = self.normalize_path(path)
441442
obj = self._get_object(path)
442443
kind = object_kind(obj)
443444

444445
if kind == "ctable":
445-
filtered = path in self._filter_views
446-
view = self._filter_views.get(path, obj)
446+
# A locked row window (set by 'v') takes precedence over any row
447+
# filter, mirroring preview()/read_cell(): a plot shows exactly the
448+
# rows the grid is showing. The SUMMARY fast-path spans the whole
449+
# column, so it is only valid when neither narrows the series.
450+
if path in self._window_views:
451+
view = self._window_views[path]
452+
narrowed = True
453+
else:
454+
view = self._filter_views.get(path, obj)
455+
narrowed = path in self._filter_views
447456
n = len(view)
448457
start, stop = self._clamp_range(row_start, row_stop, n)
449-
if start == 0 and stop == n and not filtered:
458+
if start == 0 and stop == n and not narrowed:
450459
env = self._column_summary_envelope(obj, column, n, max_points)
451460
if env is not None:
452461
return {**env, "n": n, "row_start": start, "row_stop": stop, "method": "summary"}
@@ -514,8 +523,9 @@ def read_series(
514523
) -> dict[str, Any]:
515524
"""Return the *raw* values of one series over ``[row_start, row_stop)``.
516525
517-
Same series selection as :meth:`plot_series` (CTable column honoring an
518-
active filter, or an array column via *layout*) but with no bucketing —
526+
Same series selection as :meth:`plot_series` (CTable column honoring a
527+
locked row window then an active filter, or an array column via
528+
*layout*) but with no bucketing —
519529
every value is read exactly, for the high-res ``h`` view. The result is
520530
``{"x", "y", "n", "row_start", "row_stop"}`` with ``x`` in absolute row
521531
coordinates. This reads exactly what is asked, so callers must bound the
@@ -526,7 +536,12 @@ def read_series(
526536
kind = object_kind(obj)
527537

528538
if kind == "ctable":
529-
view = self._filter_views.get(path, obj)
539+
# Honor a locked row window first, then any row filter, matching
540+
# preview()/read_cell() so the hi-res view tracks the visible grid.
541+
if path in self._window_views:
542+
view = self._window_views[path]
543+
else:
544+
view = self._filter_views.get(path, obj)
530545
n = len(view)
531546
start, stop = self._clamp_range(row_start, row_stop, n)
532547
y = safe_asarray(view[column][start:stop])

tests/b2view/test_plot_model.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,27 @@ def test_read_series_clamps_range(plot_store):
193193
assert clamped["y"].shape == (N,)
194194

195195

196+
def test_locked_row_window_confines_plot_and_read_series(plot_store):
197+
"""A locked row window (the 'v' action) takes precedence over the full
198+
series in both plot_series and read_series, matching preview()/read_cell()
199+
(PR #663 review): a plot/hi-res of a windowed CTable shows only its rows."""
200+
path, vals = plot_store
201+
lo, hi = 1000, 1500
202+
with StoreBrowser(path) as browser:
203+
browser.set_row_window("/ctable", lo, hi)
204+
205+
env = browser.plot_series("/ctable", column="x", max_points=MAX_POINTS)
206+
assert env["n"] == hi - lo # window length, not the full series
207+
assert env["method"] != "summary" # whole-column fast-path disabled
208+
expected = _reduce_envelope(vals[lo:hi], hi - lo, MAX_POINTS)
209+
np.testing.assert_allclose(env["ymin"], expected["ymin"], equal_nan=True)
210+
np.testing.assert_allclose(env["ymax"], expected["ymax"], equal_nan=True)
211+
212+
raw = browser.read_series("/ctable", column="x")
213+
assert raw["n"] == hi - lo
214+
np.testing.assert_array_equal(raw["y"], vals[lo:hi])
215+
216+
196217
def test_streaming_reducer_integer_dtype():
197218
vals = np.arange(1000, dtype=np.int64)
198219
env = _minmax_buckets_streaming(lambda s, e: vals[s:e], 1000, 100, span=33)

0 commit comments

Comments
 (0)