Skip to content

Conversation

@d-chambers
Copy link
Contributor

@d-chambers d-chambers commented Nov 19, 2025

Description

This PR changes align_to_coord (see #561 and #578) so that it has more validation checks and only works in a "relative" mode, which makes more sense as the mixing usage of relative and absolute didn't quite fit. This is a breaking change, but since align_to_coord is only in master it doesn't matter.

This also modifies the new waterfall plot (#574) such that timedelta64 y axis are not formatted to look like datetime64 axis.

Checklist

I have (if applicable):

  • referenced the GitHub issue this PR closes.
  • documented the new feature with docstrings and/or appropriate doc page.
  • included tests. See testing guidelines.
  • added the "ready_for_review" tag once the PR is ready to be reviewed.

Summary by CodeRabbit

  • Bug Fixes

    • Improved validation and clearer errors for alignment coordinates and sample handling; more consistent time-axis formatting.
  • Refactor

    • Alignment logic simplified to operate uniformly on coordinate values, removing legacy relative/absolute branching and reducing edge-case complexity.
  • New Features

    • Waterfall visualization: added interpolation option and improved image resampling behavior.
  • Tests

    • Alignment tests reorganized: added new validations and round‑trip checks; removed/renamed outdated cases to match new coordinate semantics.
  • Documentation

    • Clarified docstrings and examples for alignment and mute APIs.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 19, 2025

Walkthrough

Removed legacy relative-based alignment behavior and switched alignment functions to operate on explicit coordinate values; added coordinate-value validation helper, simplified shift-index/aligned-coords logic, normalized shift_time in fixtures/benchmarks, adjusted viz/mute docs, and reorganized/added alignment tests including new validation cases.

Changes

Cohort / File(s) Summary
Benchmarks
benchmarks/test_align_benchmarks.py, benchmarks/test_patch_benchmarks.py
Removed module header and from __future__ import in test_align_benchmarks.py. test_patch_benchmarks.py converts absolute shift_time_absolute to relative shift_time (subtracts min), updates fixtures/tests to use shift_time, and drops legacy 4D absolute-shift fixtures/tests.
Alignment logic
dascore/proc/align.py
Removed relative parameter from align_to_coord public API; added _get_coord_values to validate/convert coordinate values (uses get_compatible_values, dtype_time_like); refactored _get_shift_indices and _get_aligned_coords to accept/operate on coord values, simplified indexing and new_min computation; updated error messages and docstrings.
Supporting modules
dascore/proc/mute.py, dascore/viz/waterfall.py
mute.py: updated docstring references to Patch.mute.line_mute. waterfall.py: added interpolation parameter, imported matplotlib as mpl and is_datetime64, use is_datetime64 for time-format detection, enable image resampling via mpl.rc_context, pass interpolation to imshow, and adjust color-limit application.
Tests — small fixes & reorg
tests/test_core/test_attrs.py, tests/test_core/test_coords.py
Renamed test_can_roundriptest_can_roundtrip. Moved test_select_end_end_time into TestSelect without changing behavior.
Tests — alignment suite
tests/test_integrations/test_misc_integrations.py, tests/test_proc/test_align.py
Added TestAlignCoordCorrelation with fixtures and test_correlation_equivalent. Updated test_proc/test_align.py fixtures to use shift_time_1d/2d/3d and normalized relative shifts; added validation tests (test_samples_non_int_raises, test_bad_alignment_dim); removed several legacy absolute-shift, reverse-mode, and explicit-start tests; updated round-trip/reverse assertions.

Possibly related PRs

  • fix align_coords bug #578: Makes related changes to alignment index computation and reverse/destination index logic; overlaps on indexing/refactor areas.
  • Align to coord #561: Prior refactor adding align_to_coord helpers and signatures; directly related to the current signature and helper changes.

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is vague and overly broad. It mentions 'align_to_coord and plot' without specifying what the fixes are, making it unclear what changes were made. Provide a more specific title that describes the main changes, such as 'Refactor align_to_coord to relative-only mode and fix timedelta64 plotting' to give reviewers clear context.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed The description explains the changes (relative-only mode for align_to_coord and timedelta64 plotting fix) and references related issues, but the checklist items are incomplete: issue reference is missing, and documentation/tests/review tag status are unchecked.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix_align_and_plot

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai bot added bug Something isn't working proc Related to processing module labels Nov 19, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
dascore/proc/align.py (1)

179-189: LGTM - Simplified function signature.

The _get_aligned_coords function has been simplified by removing the shift_coord, samples, and relative parameters. The function now derives the new coordinate bounds purely from the shift metadata (start_shift, end_shift), which is cleaner and more maintainable.

Consider adding a docstring to explain how start_shift and end_shift are interpreted:

 def _get_aligned_coords(patch, dim_name, meta):
     """
     Get the aligned coordinate manager.
+    
+    Parameters
+    ----------
+    patch : Patch
+        The input patch.
+    dim_name : str
+        The dimension being aligned.
+    meta : _ShiftInfo
+        Shift metadata containing start_shift and end_shift which define
+        the new coordinate bounds in sample space.
     """
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2804631 and 7e4ec01.

📒 Files selected for processing (9)
  • benchmarks/test_align_benchmarks.py (0 hunks)
  • benchmarks/test_patch_benchmarks.py (1 hunks)
  • dascore/proc/align.py (7 hunks)
  • dascore/proc/mute.py (2 hunks)
  • dascore/viz/waterfall.py (2 hunks)
  • tests/test_core/test_attrs.py (1 hunks)
  • tests/test_core/test_coords.py (1 hunks)
  • tests/test_integrations/test_misc_integrations.py (2 hunks)
  • tests/test_proc/test_align.py (8 hunks)
💤 Files with no reviewable changes (1)
  • benchmarks/test_align_benchmarks.py
🧰 Additional context used
🧬 Code graph analysis (5)
benchmarks/test_patch_benchmarks.py (2)
dascore/proc/coords.py (1)
  • update_coords (228-253)
dascore/proc/align.py (1)
  • align_to_coord (246-378)
dascore/proc/align.py (2)
dascore/core/coords.py (7)
  • get_compatible_values (170-188)
  • get_coord (1533-1724)
  • min (438-440)
  • get_next_index (795-873)
  • values (1000-1004)
  • values (1259-1274)
  • index (702-721)
dascore/utils/time.py (1)
  • dtype_time_like (419-429)
tests/test_integrations/test_misc_integrations.py (5)
dascore/examples.py (1)
  • get_example_patch (659-706)
dascore/proc/coords.py (1)
  • update_coords (228-253)
dascore/proc/correlate.py (1)
  • correlate (88-225)
dascore/proc/align.py (1)
  • align_to_coord (246-378)
dascore/proc/basic.py (1)
  • dropna (438-494)
dascore/viz/waterfall.py (2)
dascore/utils/time.py (2)
  • dtype_time_like (419-429)
  • is_datetime64 (409-411)
dascore/utils/plotting.py (1)
  • _format_time_axis (84-103)
tests/test_proc/test_align.py (4)
dascore/utils/time.py (1)
  • to_datetime64 (22-55)
dascore/proc/coords.py (1)
  • update_coords (228-253)
dascore/exceptions.py (1)
  • ParameterError (26-27)
dascore/proc/align.py (1)
  • align_to_coord (246-378)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: test_code (macos-latest, 3.13)
  • GitHub Check: test_code (windows-latest, 3.13)
  • GitHub Check: test_code (windows-latest, 3.11)
  • GitHub Check: Run benchmarks
  • GitHub Check: test_code (macos-latest, 3.10)
  • GitHub Check: test_code (windows-latest, 3.12)
  • GitHub Check: test_code (ubuntu-latest, 3.13)
  • GitHub Check: test_code (ubuntu-latest, 3.11)
  • GitHub Check: test_code (windows-latest, 3.10)
  • GitHub Check: test_code (macos-latest, 3.11)
  • GitHub Check: test_code (ubuntu-latest, 3.12)
  • GitHub Check: test_code (ubuntu-latest, 3.10)
  • GitHub Check: test_code_min_deps (windows-latest, 3.13)
  • GitHub Check: test_code_min_deps (windows-latest, 3.12)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.12)
  • GitHub Check: test_code_min_deps (macos-latest, 3.13)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.13)
  • GitHub Check: test_code_min_deps (macos-latest, 3.12)
🔇 Additional comments (22)
dascore/proc/mute.py (2)

544-544: LGTM - Documentation improvement.

The reference has been corrected to point to the more specific Patch.mute.line_mute instead of the generic Patch.mute.


596-596: LGTM - Consistent documentation update.

This matches the documentation correction on line 544, ensuring consistency across the docstrings.

tests/test_core/test_coords.py (1)

503-507: LGTM - Test reorganization.

The test_select_end_end_time test has been moved but its logic remains unchanged. This appears to be a minor organizational improvement.

tests/test_core/test_attrs.py (1)

215-215: LGTM - Typo fix.

The method name has been corrected from test_can_roundrip to test_can_roundtrip.

dascore/viz/waterfall.py (2)

22-22: LGTM - Import added for refined time-type checking.

The is_datetime64 import enables more precise differentiation between datetime64 and timedelta64 types in axis formatting logic.


116-123: LGTM - Improved axis formatting logic.

This change correctly separates two concerns:

  1. Time-axis formatting (line 118): Now uses is_datetime64 to apply date formatting only to datetime64 axes, not timedelta64 axes
  2. Y-axis inversion (line 122): Still uses dtype_time_like to invert both datetime64 and timedelta64 axes

This addresses the PR objective of preventing timedelta64 y-axes from being incorrectly formatted as datetime64 axes.

benchmarks/test_patch_benchmarks.py (3)

340-343: LGTM - Coordinate naming updated for new alignment API.

The benchmark now computes relative shifts explicitly (shift_relative = shift_time_absolute - shift_time_absolute.min()) and assigns them as the shift_time coordinate. This aligns with the refactored align_to_coord API where coordinate values drive the shift behavior rather than a separate relative parameter.


349-349: LGTM - Benchmark updated to use new coordinate name.

The test now references shift_time instead of shift_time_absolute, consistent with the fixture changes above.


355-355: LGTM - Consistent benchmark update.

Matches the coordinate naming update on line 349.

tests/test_integrations/test_misc_integrations.py (2)

5-5: LGTM - Import added for test assertions.

The numpy import is used for np.allclose assertion in the new correlation test.


50-95: LGTM - Comprehensive integration test for alignment and correlation.

This new test class validates an important property: that shifting can be reversed correctly by performing forward alignment before correlation and reverse alignment after. The test:

  1. Creates a ricker patch with known velocity-based shifts
  2. Compares correlation without shifts vs. correlation with forward+reverse alignment
  3. Verifies data equivalence using np.allclose

This provides valuable regression protection for the alignment refactoring.

dascore/proc/align.py (6)

14-14: LGTM - Import added for coordinate value validation.

The get_compatible_values function is used in the new _get_coord_values helper to ensure dtype compatibility between dimensions and shift coordinates.


18-18: LGTM - Import added for time-type validation.

The dtype_time_like function is used in _get_coord_values to handle datetime/timedelta coordinate validation.


165-165: LGTM - Improved error message.

The error message now shows tuple(patch.coords.coord_map) which provides a clearer view of available coordinates.


214-242: LGTM - Well-designed validation helper.

The new _get_coord_values function provides thorough validation of coordinate values:

  1. Samples mode validation (lines 220-226): Ensures coordinates are integer-type when using samples=True
  2. Dtype compatibility validation (lines 229-242): Converts coordinate values to be compatible with the dimension's dtype, with special handling for time-like types

The error messages are clear and helpful. The use of get_compatible_values for datetime conversions is appropriate.


245-378: Breaking change properly implemented and all usages updated.

Verification confirms the relative parameter removal has been consistently applied:

  • Zero residual usages of old relative parameter anywhere in codebase (test files, integrations, benchmarks all updated)
  • Master-only feature: align_to_coord introduced in commit d1cc5a9; no released version tags contain this commit
  • All callsites migrated: Tests, integrations, and benchmarks use new API with samples, mode, and reverse parameters
  • API consistency: Docstring examples match implemented signature

The breaking change is acceptable and properly scoped.


192-212: Shift index calculation logic is correct — no changes needed.

The refactored _get_shift_indices function correctly decomposes coordinate values into magnitude and sign, applies the reverse modifier appropriately, and the logic aligns with the docstring. Tests validate the behavior through magnitude checking (_test_mode_same asserts nan_count == shift) and round-trip validation (forward + reverse alignment approximately restores data). Both samples=True and coordinate-value modes are tested and functioning as expected.

tests/test_proc/test_align.py (5)

24-30: LGTM - Test fixture updated for new coordinate naming.

The fixture now creates a bad_type_shift coordinate using dc.to_datetime64(distance) instead of the previous bad_type_coord. This aligns with the new validation logic that checks dtype compatibility between shift coordinates and the target dimension.


57-62: LGTM - 4D fixture updated with new coordinate naming.

The shift coordinates have been renamed from shift_time_absolute_1d/2d/3d to shift_time_1d/2d/3d, and the values are now explicitly made relative by subtracting the minimum (e.g., shift_time_2d - shift_time_2d.min()). This aligns with the new API where coordinate values drive the shift behavior.


94-94: LGTM - Explicit dtype for zero shifts.

Adding dtype=np.int64 to the zero_shifts array ensures consistency with the samples mode requirements where integer types are expected.


171-183: LGTM - New validation tests added.

Two new test methods have been added:

  1. test_samples_non_int_raises (lines 171-176): Validates that using samples=True with non-integer coordinates raises an appropriate error
  2. test_bad_alignment_dim (lines 178-183): Validates that incompatible dtypes between shift coordinate and target dimension raise an error

These tests provide good coverage for the new validation logic in _get_coord_values.


337-358: LGTM - Updated round-trip test for new API.

The test_align_round_trip test has been updated to work with the new API:

  1. Creates relative shifts explicitly by subtracting the minimum (line 344)
  2. Uses the coordinate name rel_shifts instead of relying on a relative parameter (lines 342, 348, 352)
  3. Validates that forward and reverse alignment with mode="full" produces a round-trip (line 357)

This test effectively validates the core functionality of the refactored alignment system.

@codspeed-hq
Copy link

codspeed-hq bot commented Nov 19, 2025

CodSpeed Performance Report

Merging #582 will not alter performance

Comparing fix_align_and_plot (958b27c) with master (2804631)

Summary

✅ 54 untouched
⏩ 2 skipped1

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@d-chambers d-chambers added the documentation Improvements or additions to documentation label Nov 19, 2025
@codecov
Copy link

codecov bot commented Nov 19, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.92%. Comparing base (2804631) to head (958b27c).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #582   +/-   ##
=======================================
  Coverage   99.92%   99.92%           
=======================================
  Files         129      129           
  Lines       11207    11225   +18     
=======================================
+ Hits        11199    11217   +18     
  Misses          8        8           
Flag Coverage Δ
unittests 99.92% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
dascore/proc/align.py (1)

255-333: Docstring still references removed relative parameter and old semantics

The align_to_coord docstring has been updated, but a few bits are now inconsistent with the implementation:

  • Under samples:

    “If False and relative is False (absolute mode) ...”

    There is no relative parameter anymore and the implementation only supports relative shifts. This sentence is misleading and should be rewritten to describe the current behavior (samples=False always interprets values as relative offsets in the dimension’s units).

  • The initial description:

    “The specified coordinate must indicate a shift relative to the current positions.”

    This matches the new behavior and is good; it just conflicts with the leftover mention of “absolute mode”.

  • Example variable naming (aligned_abs) still suggests an “absolute” alignment mode, even though only relative shifts are now supported. Renaming the variable (e.g., aligned_full) would reduce confusion.

Recommend updating the parameter doc and examples so that they no longer mention absolute mode or a relative flag and clearly describe that all non-sample shifts are relative to the dimension.

🧹 Nitpick comments (3)
dascore/proc/align.py (3)

179-189: Check assumptions around coord.step in _get_aligned_coords

_get_aligned_coords now computes

new_min = coord.min() + coord.step * start_shift
new_coord = coord.update(min=new_min).change_length(len(coord) - start_shift + end_shift)

This assumes coord.step is meaningful and non-None for the aligned dimension in all modes. However, align_to_coord only enforces require_evenly_sampled=True when mode == "full"; for "same"/"valid" an uneven or array-based coordinate may be returned, where coord.step may not represent a fixed sampling interval.

If uneven coordinates are allowed for "same"/"valid" today, this change can break them or subtly misplace the new min.

Two possible directions:

  • Enforce require_evenly_sampled=True for all modes, or
  • Make _get_aligned_coords robust to non-uniform coords (e.g., derive the new coordinate from existing coord.values rather than min + step * ...).

Please double-check existing usage/tests for non-evenly-sampled dims and adjust either the requirement or this helper accordingly.


336-341: Note section wording can drop legacy “relative” terminology

In the notes:

“alignment dimension length of 10, and a relative shift of 5 samples.”

Given the API now only supports relative shifts, this can be phrased more simply as “a shift of 5 samples” without referencing relative vs absolute modes. Not a correctness issue, just a small clarity improvement to fully align with the new API.


360-361: Validation call into _get_coord_values is a good centralization (typo nit)

Routing all dtype and “samples vs. values” checking through _get_coord_values prior to computing shift indices is a solid simplification and will make the behavior easier to reason about.

Very minor nit: the comment reads # Ensure valide dim and coordinate.; consider fixing the typo (valid) when you next touch this area.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7e4ec01 and 101038d.

📒 Files selected for processing (1)
  • dascore/proc/align.py (7 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
dascore/proc/align.py (2)
dascore/core/coords.py (7)
  • get_compatible_values (170-188)
  • get_coord (1533-1724)
  • min (438-440)
  • get_next_index (795-873)
  • values (1000-1004)
  • values (1259-1274)
  • index (702-721)
dascore/utils/time.py (1)
  • dtype_time_like (419-429)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: test_build_docs
  • GitHub Check: test_code (windows-latest, 3.12)
  • GitHub Check: test_code (windows-latest, 3.13)
  • GitHub Check: test_code (windows-latest, 3.11)
  • GitHub Check: test_code (windows-latest, 3.10)
  • GitHub Check: test_code (macos-latest, 3.13)
  • GitHub Check: test_code (ubuntu-latest, 3.12)
  • GitHub Check: test_code (macos-latest, 3.10)
  • GitHub Check: test_code (macos-latest, 3.12)
  • GitHub Check: test_code (ubuntu-latest, 3.11)
  • GitHub Check: test_code (ubuntu-latest, 3.13)
  • GitHub Check: test_code (ubuntu-latest, 3.10)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.13)
  • GitHub Check: test_code_min_deps (macos-latest, 3.13)
  • GitHub Check: test_code_min_deps (windows-latest, 3.13)
  • GitHub Check: test_code_min_deps (macos-latest, 3.12)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.12)
  • GitHub Check: test_code_min_deps (windows-latest, 3.12)
  • GitHub Check: Run benchmarks
🔇 Additional comments (4)
dascore/proc/align.py (4)

14-19: New imports for coord/value handling look appropriate

Bringing in get_compatible_values and dtype_time_like is consistent with the new _get_coord_values helper and centralizes dtype coercion logic instead of rolling custom conversions here. No issues with these imports.


160-167: Improved error message for invalid coord name

Using tuple(patch.coords.coord_map) produces a clearer, more readable list of available coordinate names in the error, which should help users debug mis-specified align_to_coord calls.


214-242: ---

Consider using np.can_cast instead of np.issubdtype for dtype compatibility validation

The dtype validation logic is sound and prevents misuse, but the tool choice can be clarified. NumPy best practices recommend:

  • np.issubdtype: for type hierarchy checks only (e.g., "is integer" or "is floating"); does NOT imply safe/value-preserving casts.
  • np.can_cast: for validating dtype conversion compatibility with explicit casting semantics (safe, same_kind, etc.).

The current line at 236:

if not np.issubdtype(expected_dtype, coord_values.dtype):

Is a hierarchy check rather than a casting validation. If the intent is to ensure coordinate values can be safely used in alignment, consider:

if not np.can_cast(coord_values.dtype, expected_dtype, casting="safe"):

This more explicitly expresses the intent and aligns with NumPy conventions for dtype compatibility checks.


367-378: Code review verification complete — no fixes required

The code at lines 367-378 is correct and well-tested. Verification confirms:

  1. Time-like coordinate support: test_shift_2d_relative directly exercises the code path with timedelta64 coordinates and samples=False, confirming alignment works with relative time shifts across all modes ("full", "same", "valid").

  2. Round-trip alignment with reverse=True: test_round_trip_with_reverse (line 299) verifies that forward and reverse alignments work correctly, including the specific scenario mentioned in the docstring example (lines 312-325).

  3. Sign handling is valid: np.sign() correctly handles timedelta64 values in NumPy, preserving the sign while converting to indices. The multiplication at line 210 (sign_vals * (-1 if reverse else 1)) properly inverts shifts when reverse=True.

The refactored pipeline is clearer and behaves as documented. All concerns raised in the original review have been addressed by the current implementation.

@github-actions
Copy link

github-actions bot commented Nov 19, 2025

✅ Documentation built:
👉 Download
Note: You must be logged in to github and a DASDAE member to access the link.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
dascore/proc/align.py (1)

192-210: Critical bug: np.sign on timedelta64 still produces incorrect shift indices.

The issue flagged in the previous review remains: when coord_vals is timedelta64, np.sign(coord_vals) returns timedelta64 values (not integers -1, 0, 1). Although line 209 adds .astype(np.int64), this interprets the timedelta as nanoseconds, producing shifts with completely wrong magnitudes. This breaks alignment for timedelta64 coordinates—a primary use case shown in the docstring at line 306.

Apply this fix to compute sign explicitly as integers:

 def _get_shift_indices(coord_vals, dim, reverse, samples):
     """
     Get the indices  for shifting.
 
     Positive values indicate a shift to the right, negative to left.
     """
-    # Relative means something slightly different here. It only means
-    # move backwards, rather than implying a reference from the end of the trace.
-    # Therefore, we need to insure positive values go into get_next_index.
     abs_vals = np.abs(coord_vals)
-    sign_vals = np.sign(coord_vals)
+    # Compute sign as integers so it works for both numeric and time-like dtypes.
+    sign_vals = np.zeros_like(abs_vals, dtype=np.int64)
+    sign_vals[coord_vals > 0] = 1
+    sign_vals[coord_vals < 0] = -1
     inds_abs = dim.get_next_index(
         abs_vals,
         samples=samples,
         relative=False if samples else True,
     )
-    # Reverse index if needed. This way the reference stays the same.
-    inds = inds_abs * (sign_vals.astype(np.int64) * (-1 if reverse else 1))
+    factor = -1 if reverse else 1
+    inds = inds_abs * (sign_vals * factor)
     return inds

Based on learnings

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 101038d and e8c6c08.

📒 Files selected for processing (2)
  • dascore/proc/align.py (7 hunks)
  • dascore/viz/waterfall.py (6 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
dascore/viz/waterfall.py (2)
dascore/utils/time.py (2)
  • dtype_time_like (419-429)
  • is_datetime64 (409-411)
dascore/utils/plotting.py (1)
  • _format_time_axis (84-103)
dascore/proc/align.py (3)
dascore/core/patch.py (2)
  • coords (255-269)
  • dtype (318-320)
dascore/core/coords.py (7)
  • get_compatible_values (170-188)
  • get_coord (1533-1724)
  • min (438-440)
  • get_next_index (795-873)
  • values (1000-1004)
  • values (1259-1274)
  • index (702-721)
dascore/utils/time.py (1)
  • dtype_time_like (419-429)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.12)
  • GitHub Check: test_code_min_deps (windows-latest, 3.13)
  • GitHub Check: test_code_min_deps (macos-latest, 3.13)
  • GitHub Check: test_code_min_deps (windows-latest, 3.12)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.13)
  • GitHub Check: test_code (windows-latest, 3.13)
  • GitHub Check: test_build_docs
  • GitHub Check: test_code (windows-latest, 3.12)
  • GitHub Check: test_code (macos-latest, 3.13)
  • GitHub Check: test_code (windows-latest, 3.11)
  • GitHub Check: test_code (macos-latest, 3.12)
  • GitHub Check: test_code (windows-latest, 3.10)
  • GitHub Check: test_code (ubuntu-latest, 3.10)
  • GitHub Check: test_code (macos-latest, 3.10)
  • GitHub Check: test_code (ubuntu-latest, 3.12)
  • GitHub Check: test_code (ubuntu-latest, 3.13)
  • GitHub Check: test_code (ubuntu-latest, 3.11)
  • GitHub Check: test_code (macos-latest, 3.11)
  • GitHub Check: Run benchmarks
🔇 Additional comments (9)
dascore/viz/waterfall.py (4)

8-8: LGTM: Imports are appropriate.

The new imports support the datetime handling improvements and rcParams configuration.

Also applies to: 23-23


123-130: LGTM: Datetime/timedelta distinction correctly implemented.

The use of is_datetime64 for formatting (line 125) and dtype_time_like for y-axis inversion (line 129) is intentional. This ensures that only datetime64 axes receive datetime formatting, while both datetime64 and timedelta64 axes are inverted. This aligns with the PR objective to prevent timedelta64 axes from being formatted as datetime64 axes.


269-269: LGTM: Interpolation parameter correctly passed to imshow.

The interpolation parameter is properly threaded through to matplotlib's imshow, giving users control over downsampling behavior for large arrays.


272-273: LGTM: Defensive color scale handling with robustness improvements.

The updated guard adds an np.isfinite check to prevent setting invalid color limits (NaN or inf). The np.asarray wrapper is defensive but harmless since _get_scale already returns numpy arrays. The scale is not None check appears unnecessary based on _get_scale always returning an array, but adds defensive robustness.

dascore/proc/align.py (5)

14-14: LGTM! Appropriate imports for new validation logic.

The new imports get_compatible_values and dtype_time_like support the enhanced dtype validation and coordinate value handling introduced in this refactor.

Also applies to: 18-18


165-165: LGTM! Improved error message clarity.

Explicit tuple conversion ensures consistent formatting in the error message.


179-189: LGTM! Simplified and correct coordinate alignment logic.

The direct computation new_min = coord.min() + coord.step * start_shift works correctly for both numeric and time-like coordinates, and the simplified signature improves maintainability.


213-241: LGTM! Well-structured validation logic.

The new _get_coord_values helper properly validates dtype compatibility between the dimension and coordinate, with clear error messages for incompatible cases. The handling of time-like dtypes and samples mode is correct.


245-377: Simplified API and improved clarity.

The removal of the relative parameter and the introduction of explicit validation via _get_coord_values makes the alignment logic clearer and more maintainable. The updated docstring examples effectively illustrate the new coordinate-based shifting semantics.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
dascore/proc/align.py (1)

254-283: Update docstring to match new “relative-only” semantics (remove stale relative references).

The align_to_coord docstring still references the old relative parameter and “absolute mode”:

  • The samples description mentions “If False and relative is False (absolute mode)…”, but relative is no longer a parameter and absolute-position alignment is no longer supported.
  • The “Mode Parameter” notes talk about “a relative shift of 5 samples” without clarifying that all non-sample alignments are now interpreted as relative offsets.

Please rewrite these sections so they describe the current behavior: coordinate values are always interpreted as relative shifts (or sample offsets when samples=True), with no absolute-position mode exposed in the API.

Also applies to: 335-350

♻️ Duplicate comments (2)
dascore/viz/waterfall.py (1)

176-180: Docstring still has a typo (“relavent”).

The interpolation parameter docstring still reads “relavent for DAS”; this should be “relevant for DAS” to fully address the earlier doc typo comment.

dascore/proc/align.py (1)

192-210: Critical: np.sign on timedelta64 still produces invalid shift indices.

For time-like alignment coordinates (timedelta64), np.sign(coord_vals) returns timedelta64, so inds_abs * sign_vals yields timedelta-valued shifts that are later coerced to int64 in _calculate_shift_info, effectively scaling shifts by the time unit (e.g., nanoseconds). This matches the earlier critical issue and will badly break time-based alignments.

Replace np.sign with an explicit integer sign array so shifts stay integer for both numeric and time-like dtypes:

-def _get_shift_indices(coord_vals, dim, reverse, samples):
+def _get_shift_indices(coord_vals, dim, reverse, samples):
@@
-    abs_vals = np.abs(coord_vals)
-    sign_vals = np.sign(coord_vals)
+    abs_vals = np.abs(coord_vals)
+    # Compute sign as integers so it works for both numeric and time-like dtypes.
+    sign_vals = np.zeros_like(abs_vals, dtype=np.int64)
+    sign_vals[coord_vals > 0] = 1
+    sign_vals[coord_vals < 0] = -1
@@
-    inds_abs = dim.get_next_index(
+    inds_abs = dim.get_next_index(
         abs_vals,
         samples=samples,
         relative=False if samples else True,
     )
-    # Reverse index if needed. This way the reference stays the same.
-    inds = inds_abs * (sign_vals.astype(np.int64) * (-1 if reverse else 1))
+    # Reverse index if needed. This way the reference stays the same.
+    factor = -1 if reverse else 1
+    inds = inds_abs * (sign_vals * factor)
     return inds
#!/bin/bash
# Minimal check: search for uses of np.sign in align.py to ensure all shift-sign paths are updated.
rg -n "np\.sign" dascore/proc/align.py -n -C2
🧹 Nitpick comments (2)
dascore/proc/align.py (2)

179-189: Guard use of coord.step when mode ≠ "full".

_get_aligned_coords always uses coord.step to compute new_min, but align_to_coord only enforces require_evenly_sampled=True when mode == "full". For "same" and "valid" modes, coord.step may be None or not well-defined for irregular coordinates, which would cause failures or misleading coordinate updates.

Consider either:

  • requiring require_evenly_sampled=True for all modes if coord.step is relied on, or
  • handling the coord.step is None / irregular case explicitly (e.g., falling back to using the existing coord without recomputing min).

Based on learnings.

Also applies to: 352-357


213-241: Relax dtype compatibility check using np.can_cast in _get_coord_values.

The check at line 237 (np.issubdtype(expected_dtype, coord_values.dtype)) is overly strict and backwards. NumPy's np.can_cast is the recommended function to check whether values of one dtype can be safely cast to another, while np.issubdtype only checks type hierarchy and does not consider casting compatibility. This causes false rejections of safe conversions (e.g., int32 → float64).

Replace with:

if not np.can_cast(coord_values.dtype, expected_dtype, casting="safe"):
    ...

This maintains validation while accepting safely-castable numeric types.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e8c6c08 and 0d6eabe.

📒 Files selected for processing (2)
  • dascore/proc/align.py (6 hunks)
  • dascore/viz/waterfall.py (6 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-02T16:22:22.879Z
Learnt from: d-chambers
Repo: DASDAE/dascore PR: 523
File: dascore/transform/fourier.py:433-434
Timestamp: 2025-09-02T16:22:22.879Z
Learning: In dascore STFT implementation, use `require_evenly_sampled=True` on `get_coord` calls instead of manual validation for coord.step to ensure sampling rate calculations are safe.

Applied to files:

  • dascore/proc/align.py
🧬 Code graph analysis (2)
dascore/proc/align.py (3)
dascore/core/patch.py (4)
  • coords (255-269)
  • dtype (318-320)
  • shape (286-299)
  • data (272-283)
dascore/core/coords.py (8)
  • get_compatible_values (170-188)
  • get_coord (1533-1724)
  • min (438-440)
  • get_next_index (795-873)
  • values (1000-1004)
  • values (1259-1274)
  • index (702-721)
  • data (606-608)
dascore/utils/time.py (1)
  • dtype_time_like (419-429)
dascore/viz/waterfall.py (2)
dascore/utils/time.py (2)
  • dtype_time_like (419-429)
  • is_datetime64 (409-411)
dascore/utils/plotting.py (1)
  • _format_time_axis (84-103)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.12)
  • GitHub Check: test_code_min_deps (windows-latest, 3.12)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.13)
  • GitHub Check: test_code_min_deps (windows-latest, 3.13)
  • GitHub Check: test_code_min_deps (macos-latest, 3.13)
  • GitHub Check: test_build_docs
  • GitHub Check: test_code (ubuntu-latest, 3.13)
  • GitHub Check: Run benchmarks
  • GitHub Check: test_code (windows-latest, 3.11)
  • GitHub Check: test_code (macos-latest, 3.13)
  • GitHub Check: test_code (windows-latest, 3.13)
  • GitHub Check: test_code (macos-latest, 3.11)
  • GitHub Check: test_code (macos-latest, 3.10)
  • GitHub Check: test_code (ubuntu-latest, 3.10)
  • GitHub Check: test_code (macos-latest, 3.12)
  • GitHub Check: test_code (windows-latest, 3.10)
  • GitHub Check: test_code (ubuntu-latest, 3.12)
  • GitHub Check: test_code (ubuntu-latest, 3.11)
  • GitHub Check: test_code (windows-latest, 3.12)
🔇 Additional comments (2)
dascore/viz/waterfall.py (1)

111-124: Axis time-handling and rc_context usage look correct.

Using is_datetime64 for formatter setup while still using dtype_time_like only for y-axis inversion cleanly separates datetime from timedelta axes, which should fix the timedelta y-axis formatting issue without changing the seismic-style inversion behavior. Wrapping imshow in mpl.rc_context({"image.resample": True}) and threading the interpolation parameter into the imshow call is also a good, locally-scoped way to control resampling and interpolation behavior for waterfall plots only.

Also applies to: 253-268

dascore/proc/align.py (1)

165-176: Input validation and high-level flow look sound.

The expanded error message in _validate_alignment_inputs that includes the available coord names is helpful for debugging. The new flow in align_to_coord (validate → _get_coord_values for dtype compatibility → _get_shift_indices_calculate_shift_info_apply_shifts_to_data_get_aligned_coords) is cohesive and keeps validation and transformation concerns nicely separated.

Also applies to: 358-366, 373-374

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
dascore/proc/align.py (1)

192-210: Fix np.sign on time-like coordinates in _get_shift_indices (still broken for timedelta64)

When coord_vals is time-like (e.g. timedelta64), np.sign(coord_vals) returns a time-like array, and sign_vals.astype(np.int64) interprets those as underlying units (e.g. nanoseconds), not -1/0/1. This produces huge, incorrect integer shift values and breaks alignment for the timedelta-based example in the docstring and any time-like alignment coordinate. This is the same issue previously flagged and remains unresolved.

A safer implementation is to compute the sign explicitly as integers:

-def _get_shift_indices(coord_vals, dim, reverse, samples):
-    """
-    Get the indices  for shifting.
-
-    Positive values indicate a shift to the right, negative to left.
-    """
-    # Relative means something slightly different here. It only means
-    # move backwards, rather than implying a reference from the end of the trace.
-    # Therefore, we need to insure positive values go into get_next_index.
-    abs_vals = np.abs(coord_vals)
-    sign_vals = np.sign(coord_vals)
-    inds_abs = dim.get_next_index(
-        abs_vals,
-        samples=samples,
-        relative=False if samples else True,
-    )
-    # Reverse index if needed. This way the reference stays the same.
-    inds = inds_abs * (sign_vals.astype(np.int64) * (-1 if reverse else 1))
-    return inds
+def _get_shift_indices(coord_vals, dim, reverse, samples):
+    """
+    Get the indices for shifting.
+
+    Positive values indicate a shift to the right, negative to left.
+    """
+    abs_vals = np.abs(coord_vals)
+    # Compute integer sign so it works for numeric and time-like dtypes.
+    sign_vals = np.zeros_like(abs_vals, dtype=np.int64)
+    sign_vals[coord_vals > 0] = 1
+    sign_vals[coord_vals < 0] = -1
+    inds_abs = dim.get_next_index(
+        abs_vals,
+        samples=samples,
+        relative=False if samples else True,
+    )
+    factor = -1 if reverse else 1
+    inds = inds_abs * (sign_vals * factor)
+    return inds

If you want, you can double-check NumPy’s current behavior for np.sign on timedelta64 to confirm this reasoning.

What dtype and values does `numpy.sign` return when applied to a `numpy.timedelta64` array, and how does casting that result to `int64` behave?
🧹 Nitpick comments (1)
dascore/proc/align.py (1)

213-241: New _get_coord_values helper solidly centralizes dtype validation

This helper cleanly enforces that samples=True only works with integer, non-time-like coordinates and that non-sample alignment values are cast/validated against the dimension’s step dtype using get_compatible_values and np.can_cast. That should prevent many subtle dtype mismatches between alignment coords and the aligned dimension.

If you want to tighten it further, two small, optional tweaks:

  • Call dtype_time_like(dim.dtype) / dtype_time_like(coord.dtype) explicitly for readability.
  • Use cdtype in the samples=True error message instead of coord.dtype to guarantee consistency if those ever diverge.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0d6eabe and 3594ff0.

📒 Files selected for processing (2)
  • dascore/proc/align.py (6 hunks)
  • dascore/viz/waterfall.py (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • dascore/viz/waterfall.py
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-02T16:22:22.879Z
Learnt from: d-chambers
Repo: DASDAE/dascore PR: 523
File: dascore/transform/fourier.py:433-434
Timestamp: 2025-09-02T16:22:22.879Z
Learning: In dascore STFT implementation, use `require_evenly_sampled=True` on `get_coord` calls instead of manual validation for coord.step to ensure sampling rate calculations are safe.

Applied to files:

  • dascore/proc/align.py
🧬 Code graph analysis (1)
dascore/proc/align.py (3)
dascore/core/patch.py (5)
  • coords (255-269)
  • dtype (318-320)
  • shape (286-299)
  • data (272-283)
  • ndim (229-231)
dascore/core/coords.py (14)
  • get_compatible_values (170-188)
  • get_coord (1533-1724)
  • min (438-440)
  • update (742-755)
  • update (983-985)
  • change_length (893-908)
  • change_length (1048-1053)
  • change_length (1287-1298)
  • get_next_index (795-873)
  • values (1000-1004)
  • values (1259-1274)
  • index (702-721)
  • data (606-608)
  • ndim (468-470)
dascore/utils/time.py (1)
  • dtype_time_like (419-429)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.13)
  • GitHub Check: test_code_min_deps (windows-latest, 3.13)
  • GitHub Check: test_code (windows-latest, 3.13)
  • GitHub Check: test_code (windows-latest, 3.10)
  • GitHub Check: test_code (windows-latest, 3.12)
  • GitHub Check: test_code (macos-latest, 3.12)
  • GitHub Check: test_code_min_deps (windows-latest, 3.12)
  • GitHub Check: test_code_min_deps (macos-latest, 3.12)
  • GitHub Check: test_code_min_deps (macos-latest, 3.13)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.12)
  • GitHub Check: test_code (macos-latest, 3.10)
  • GitHub Check: test_code (ubuntu-latest, 3.12)
  • GitHub Check: test_code (macos-latest, 3.11)
  • GitHub Check: test_code (ubuntu-latest, 3.11)
  • GitHub Check: test_code (ubuntu-latest, 3.13)
  • GitHub Check: test_code (ubuntu-latest, 3.10)
  • GitHub Check: test_build_docs
  • GitHub Check: Run benchmarks
🔇 Additional comments (3)
dascore/proc/align.py (3)

160-166: Error message clarification looks good

Using tuple(patch.coords.coord_map) makes the coords listing in the error message much clearer and avoids dumping the raw mapping representation. No issues here.


179-189: Aligned coordinate computation is consistent with shift metadata

Using coord.min() + coord.step * start_shift together with change_length(len(coord) - start_shift + end_shift) keeps the updated dimension length in sync with _ShiftInfo.output_length and preserves even sampling. This assumes the aligned dimension is evenly sampled, which is enforced by require_evenly_sampled=True, so this looks correct.


353-375: Core wiring of align_to_coord looks correct and aligns with prior best practices

Using _validate_alignment_inputs, patch.get_coord(dim_name, require_evenly_sampled=True), _get_coord_values, _get_shift_indices, and _get_aligned_coords gives a clear, linear pipeline: validate → normalize values → compute shifts → compute metadata → shift data → update coords. The evenly-sampled requirement is appropriate here, since both _get_coord_values and _get_aligned_coords rely on a well-defined step, and it matches the prior learning to prefer require_evenly_sampled=True over ad-hoc step checks.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3594ff0 and 958b27c.

📒 Files selected for processing (1)
  • dascore/proc/align.py (7 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-02T16:22:22.879Z
Learnt from: d-chambers
Repo: DASDAE/dascore PR: 523
File: dascore/transform/fourier.py:433-434
Timestamp: 2025-09-02T16:22:22.879Z
Learning: In dascore STFT implementation, use `require_evenly_sampled=True` on `get_coord` calls instead of manual validation for coord.step to ensure sampling rate calculations are safe.

Applied to files:

  • dascore/proc/align.py
🧬 Code graph analysis (1)
dascore/proc/align.py (2)
dascore/core/coords.py (14)
  • get_compatible_values (170-188)
  • get_coord (1533-1724)
  • min (438-440)
  • update (742-755)
  • update (983-985)
  • change_length (893-908)
  • change_length (1048-1053)
  • change_length (1287-1298)
  • get_next_index (795-873)
  • values (1000-1004)
  • values (1259-1274)
  • index (702-721)
  • data (606-608)
  • ndim (468-470)
dascore/utils/time.py (1)
  • dtype_time_like (419-429)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: test_code (windows-latest, 3.12)
  • GitHub Check: test_code (macos-latest, 3.13)
  • GitHub Check: test_code (ubuntu-latest, 3.12)
  • GitHub Check: test_code (macos-latest, 3.11)
  • GitHub Check: test_code (windows-latest, 3.13)
  • GitHub Check: test_code (ubuntu-latest, 3.13)
  • GitHub Check: test_code (windows-latest, 3.10)
  • GitHub Check: test_code (windows-latest, 3.11)
  • GitHub Check: test_code (macos-latest, 3.12)
  • GitHub Check: test_code (ubuntu-latest, 3.11)
  • GitHub Check: test_code (ubuntu-latest, 3.10)
  • GitHub Check: test_code_min_deps (windows-latest, 3.12)
  • GitHub Check: test_code_min_deps (macos-latest, 3.12)
  • GitHub Check: test_code_min_deps (windows-latest, 3.13)
  • GitHub Check: test_code_min_deps (macos-latest, 3.13)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.12)
  • GitHub Check: test_code_min_deps (ubuntu-latest, 3.13)
  • GitHub Check: test_build_docs
  • GitHub Check: Run benchmarks
🔇 Additional comments (5)
dascore/proc/align.py (5)

14-14: LGTM: New imports support coordinate validation.

The get_compatible_values and dtype_time_like imports are correctly added to support the new _get_coord_values validation function.

Also applies to: 18-18


179-189: LGTM: Simplified coordinate alignment logic.

The signature simplification and coordinate calculation correctly implement the new relative-only semantics. Computing new_min as coord.min() + coord.step * start_shift properly adjusts the coordinate range based on the shift metadata.


254-357: LGTM: Docstring correctly updated for relative-only semantics.

The docstring has been properly revised to reflect the new purely relative alignment behavior:

  • The samples parameter now clearly documents the two supported modes without referencing the removed relative parameter
  • Examples use neutral naming (e.g., aligned_offsets) instead of absolute/relative terminology
  • The new "Alignment Semantics" section (lines 352-357) explicitly clarifies the relative-only behavior

364-382: LGTM: Function calls correctly updated for refactored flow.

The integration of the refactored helper functions is correct:

  • Requiring evenly sampled dimensions (line 364) is necessary for the step-based shift calculations
  • The new validation step (line 367) ensures coordinate compatibility before computing shifts
  • Updated function calls pass the correct validated values and simplified parameters

The TODO comment (lines 362-363) about relaxing the evenly sampled requirement for certain modes is a reasonable future enhancement.


213-241: Code validation logic is correct—no issues found.

The dtype validation in _get_coord_values properly handles coordinate and dimension type checking. The function correctly:

  • Rejects non-integer coordinates when samples=True (line 219)
  • Computes expected_dtype as the result of dimension value differences (line 229), which converts datetime64 to timedelta64
  • Applies get_compatible_values conversion only when the dimension is time-like but the coordinate is not (line 233)
  • Validates that the final coordinate dtype can safely cast to the expected dtype (line 234)

The test cases confirm expected behavior: bad_type_shift (datetime64) raises an error because datetime64 cannot safely cast to the expected timedelta64, and shift_time_relative (timedelta64) correctly raises when used with samples=True.

@d-chambers d-chambers merged commit 21994a0 into master Nov 20, 2025
24 checks passed
@d-chambers d-chambers deleted the fix_align_and_plot branch November 20, 2025 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working documentation Improvements or additions to documentation proc Related to processing module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants