-
Notifications
You must be signed in to change notification settings - Fork 28
add support for percent in taper and coord select #522
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds percent-based value handling and a non-extending coord_range mode, centralizes window functions into a new signal utils module and updates taper to use it (including percent/uneven coords), introduces an approximate Patch.equals option, small import tweaks, and corresponding tests. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Caller
participant Coord as BaseCoord
note over Coord: coord_range(extend=True|False)
Caller->>Coord: coord_range(extend=True)
alt extend=True
Coord->>Coord: validate evenly sampled
Coord-->>Caller: (max - min) + step
else extend=False
Coord-->>Caller: (max - min)
end
rect rgba(200,230,255,0.25)
note right of Caller: Percent handling in value conversion
Caller->>Coord: _get_compatible_value(value = x * percent)
Coord->>Coord: coord_range(extend=False)
Coord-->>Caller: absolute = (x/100) * range (marked relative)
end
sequenceDiagram
autonumber
actor User
participant Taper as proc.taper
participant Signal as utils.signal
participant Registry as WINDOW_FUNCTIONS
participant Coord as BaseCoord
User->>Taper: taper(patch, window_type, ...)
Taper->>Signal: _get_window_function(window_type)
Signal->>Registry: lookup window_type
alt known
Registry-->>Signal: window_fn
Signal-->>Taper: window_fn
else unknown
Signal-->>User: raise ParameterError (list options)
end
Taper->>Coord: coord_range(extend=False)
Coord-->>Taper: duration
Taper-->>User: return tapered Patch
sequenceDiagram
autonumber
actor Caller
participant Patch as Patch.equals
participant Other as Other Patch
Caller->>Patch: equals(Other, close)
Patch->>Patch: compare coords & attrs
alt close=True
Patch->>Patch: np.allclose(self.data, other.data)
else close=False
Patch->>Patch: (self.data == other.data).all()
end
Patch-->>Caller: bool
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested labels
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ 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). (15)
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
dascore/proc/taper.py (2)
25-27: Don’t use assert for runtime validation.assert can be stripped with -O, turning bad input into silent misbehavior. Raise ParameterError instead.
- if isinstance(value, Sequence | np.ndarray): - assert len(value) == 2, "Length 2 sequence required." + if isinstance(value, Sequence | np.ndarray): + if len(value) != 2: + raise ParameterError("Length-2 sequence required for taper start/stop.")
76-77: Docstring typos and style.Fix capitalization and a typo to keep user-facing docs clean.
- The type of window to use For tapering. Supported Options are: + The type of window to use for tapering. Supported options are: - If True, the values specified in kwargs are relateive to the + If True, the values specified in kwargs are relative to the - >>> # Apply an Hanning taper to 5% of each end for time dimension. + >>> # Apply a Hann taper to 5% of each end for time dimension.Also applies to: 211-213, 220-222, 97-99
🧹 Nitpick comments (9)
dascore/proc/basic.py (1)
111-125: Consider configurable tolerance and NaN handling for equals(close=True)Optional, but adds control and aligns NaN treatment with attrs. Also safely falls back for non-numeric dtypes.
Apply:
-def equals(self: PatchType, other: Any, only_required_attrs=True, close=False) -> bool: +def equals( + self: PatchType, + other: Any, + only_required_attrs=True, + close=False, + *, + rtol: float = 1e-08, + atol: float = 1e-08, + equal_nan: bool = False, +) -> bool: @@ - close - If True, the data can be "close" using np.allclose, otherwise - all data must be equal. + close + If True, use a tolerance-based comparison for data. + rtol, atol + Relative and absolute tolerances passed to numpy.allclose. + equal_nan + If True, NaNs compare equal when close=True. @@ - if close and not np.allclose(self.data, other.data): - return False - elif not close and not np.equal(self.data, other.data).all(): - return False + if close: + # Guard for non-numeric dtypes. + if np.issubdtype(self.data.dtype, np.number) and np.issubdtype(other.data.dtype, np.number): + if not np.allclose(self.data, other.data, rtol=rtol, atol=atol, equal_nan=equal_nan): + return False + else: + if not np.array_equal(self.data, other.data): + return False + else: + if not np.equal(self.data, other.data).all(): + return FalseAlso applies to: 151-156
tests/test_core/test_coords.py (1)
752-757: Tighten the percentage-length assertionUse an absolute tolerance of ~1 sample for evenly sampled coords.
- if coord.evenly_sampled: - assert abs((len(out) / len(coord)) - 0.70) < len(coord) / 100.0 + if coord.evenly_sampled: + import pytest + assert len(out) == pytest.approx(0.70 * len(coord), rel=0, abs=1)tests/test_proc/test_taper.py (2)
43-49: Minor: preserve original time range when crafting uneven timesOptional: derive uneven, sorted times from the existing time coord to keep range/units comparable across tests.
Example (conceptual):
- take orig = patch.get_coord("time").values
- add small, cumulative jitter to orig in its native units
- sort, then update_coords(time=new_values)
143-147: Uneven-time taper smoke testCovers the non-even sampling path; consider also asserting shape equality for completeness.
dascore/proc/taper.py (2)
30-35: Percent length calc now correct for uneven coords; one nit.Using coord.coord_range(exact=False) fixes off-by-one for evenly sampled coords and enables percent semantics on irregular coords. Minor: consider including np.datetime64 in clses to avoid accidental scaling if absolute datetimes are ever passed.
- clses = (Quantity, np.timedelta64) + clses = (Quantity, np.timedelta64, np.datetime64)
114-126: Micro: reuse window indexer.window_inds is identical in both branches; compute once.
- if samps[0] is not None: + window_inds = broadcast_for_index(n_dims, axis, slice(None), fill=None) + if samps[0] is not None: ... - window_inds = broadcast_for_index(n_dims, axis, slice(None), fill=None) out[data_inds] = out[data_inds] * window[window_inds] if samps[1] is not None: ... - window_inds = broadcast_for_index(n_dims, axis, slice(None), fill=None) out[data_inds] = out[data_inds] * window[window_inds]dascore/utils/signal.py (2)
9-22: Window registry looks solid; consider making it immutable.Freezing the mapping prevents accidental mutation at runtime.
+from types import MappingProxyType ... -WINDOW_FUNCTIONS = dict( +_WINDOW_FUNCTIONS = dict( barthann=windows.barthann, bartlett=windows.bartlett, blackman=windows.blackman, blackmanharris=windows.blackmanharris, bohman=windows.bohman, hamming=windows.hamming, hann=windows.hann, cos=windows.hann, nuttall=windows.nuttall, parzen=windows.parzen, triang=windows.triang, ramp=windows.triang, ) +WINDOW_FUNCTIONS = MappingProxyType(_WINDOW_FUNCTIONS)
25-35: Add type hints and tighten error message.Minor ergonomics: hint the callable signature and list options as a comma-separated string.
-from dascore.exceptions import ParameterError +from dascore.exceptions import ParameterError +from collections.abc import Callable +import numpy as np ... -def _get_window_function(window_type): +def _get_window_function(window_type: str) -> Callable[[int], np.ndarray]: @@ - msg = ( - f"'{window_type}' is not a known window type. " - f"Options are: {sorted(WINDOW_FUNCTIONS)}" - ) + opts = ", ".join(sorted(WINDOW_FUNCTIONS)) + msg = f"'{window_type}' is not a known window type. Options are: {opts}"dascore/core/coords.py (1)
618-624: Percent handling looks right; one edge-case to confirm.If self.units is None and a non-percent Quantity is passed, convert_units will raise. Is that desired? If not, consider interpreting it as “set units” or raising ParameterError with a clearer message.
- else: - value = convert_units(value.magnitude, self.units, value.units) + else: + if self.units is None: + raise ParameterError("Coordinate has no units; cannot convert input.") + value = convert_units(mag, self.units, unit)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (8)
dascore/compat.py(1 hunks)dascore/core/coords.py(3 hunks)dascore/proc/basic.py(3 hunks)dascore/proc/taper.py(4 hunks)dascore/utils/signal.py(1 hunks)tests/test_core/test_coords.py(3 hunks)tests/test_core/test_patch.py(1 hunks)tests/test_proc/test_taper.py(4 hunks)
🧰 Additional context used
🧬 Code graph analysis (7)
tests/test_core/test_patch.py (3)
tests/conftest.py (1)
random_patch(282-284)dascore/core/coordmanager.py (1)
equals(729-739)dascore/proc/basic.py (1)
equals(111-156)
dascore/utils/signal.py (1)
dascore/exceptions.py (1)
ParameterError(26-27)
dascore/proc/basic.py (3)
dascore/core/coordmanager.py (1)
equals(729-739)dascore/core/coords.py (1)
data(605-607)dascore/core/patch.py (1)
data(213-215)
tests/test_proc/test_taper.py (3)
dascore/utils/misc.py (1)
broadcast_for_index(136-157)dascore/core/coords.py (8)
sorted(483-485)sorted(1239-1241)sorted(1460-1462)get_coord(1471-1659)sort(531-532)sort(930-932)sort(1132-1145)sort(1304-1310)dascore/proc/coords.py (2)
get_coord(87-139)update_coords(218-243)
dascore/proc/taper.py (2)
dascore/utils/signal.py (1)
_get_window_function(25-35)dascore/core/coords.py (4)
coord_range(509-528)sorted(483-485)sorted(1239-1241)sorted(1460-1462)
tests/test_core/test_coords.py (2)
dascore/units.py (1)
get_quantity(70-94)dascore/core/coords.py (9)
coord_range(509-528)max(443-445)min(438-440)select(323-329)select(953-973)select(1105-1130)select(1276-1302)select(1387-1412)evenly_sampled(478-480)
dascore/core/coords.py (2)
dascore/core/coordmanager.py (2)
coord_range(1031-1033)convert_units(795-803)dascore/units.py (1)
convert_units(120-155)
⏰ 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). (15)
- GitHub Check: test_code (windows-latest, 3.10)
- GitHub Check: test_code (macos-latest, 3.11)
- GitHub Check: test_code (macos-latest, 3.10)
- GitHub Check: test_code (windows-latest, 3.12)
- GitHub Check: test_code (macos-latest, 3.12)
- GitHub Check: test_code (windows-latest, 3.11)
- GitHub Check: test_code_min_deps (windows-latest, 3.13)
- GitHub Check: test_code_min_deps (windows-latest, 3.12)
- GitHub Check: test_code (ubuntu-latest, 3.10)
- GitHub Check: test_code (ubuntu-latest, 3.11)
- GitHub Check: test_code (ubuntu-latest, 3.12)
- 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 (ubuntu-latest, 3.13)
- GitHub Check: test_code_min_deps (macos-latest, 3.13)
🔇 Additional comments (11)
dascore/compat.py (1)
13-13: Importing numpy.ndarray via compat looks goodThis cleanly exposes ndarray alongside floor and interp with no functional side effects.
tests/test_core/test_patch.py (1)
404-409: Nice addition validating equals(close=...) behaviorThe test robustly exercises both strict and tolerance-based equality.
tests/test_core/test_coords.py (1)
360-367: LGTM: coord_range(exact=False) expectation on uneven coordsThis correctly asserts max - min when step is undefined.
tests/test_proc/test_taper.py (3)
10-14: Imports updated to new window registry and units: goodSwitch to taper, WINDOW_FUNCTIONS, and percent aligns with implementation changes.
25-31: Deterministic parametrization over window functionsUsing sorted(WINDOW_FUNCTIONS) ensures stable test ordering.
137-142: Good parity check for percent vs fraction inputsValidates new percent handling without over-constraining numerical tolerance.
dascore/proc/taper.py (2)
17-17: Good move: centralize window resolution.Importing WINDOW_FUNCTIONS/_get_window_function from a shared utility avoids drift and duplication across modules.
158-173: Half-window sizing differs from taper(); confirm intent.here: func(samps2+1) vs taper() using func(2val). The +1 shifts symmetry/peak by one sample. If unintentional, align both.
Would you like me to align the two implementations and update tests accordingly?
dascore/utils/signal.py (2)
1-3: Module docstring LGTM.Clear purpose and scope.
25-35: No stale TAPER_FUNCTIONS references remain — grep confirms zero occurrences ofTAPER_FUNCTIONS, and_get_window_functionis defined solely in utils/signal.py (its calls in proc/taper.py are expected).dascore/core/coords.py (1)
33-34: Public percent import: nice.Exposes clear semantics for percentage-based inputs.
dascore/core/coords.py
Outdated
| def coord_range(self, exact: bool = True): | ||
| """ | ||
| Return a scaler value for the coordinate range (e.g., number of seconds). | ||
| Parameters | ||
| ---------- | ||
| exact | ||
| If true, only exact ranges are returned. This accounts for | ||
| spacing at the end of each sample. Consequently, exact is only | ||
| possible for evenly sampled coords. If false, just disregard | ||
| this if coord isnt't evenly sampled. | ||
| """ | ||
| if not self.evenly_sampled and exact: | ||
| raise CoordError("coord_range has to be called on an evenly sampled data.") | ||
| return self.max() - self.min() + self.step | ||
| step = getattr(self, "step", None) | ||
| coord_range = self.max() - self.min() | ||
| if step is not None: | ||
| coord_range += step | ||
| return coord_range | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: coord_range adds signed step; should add absolute step.
For reverse-sorted evenly sampled coords, adding a negative step shrinks the range (eg, 9 + (-1) -> 8). Use abs(step) so the inclusive range is correct. Also fix doc typos.
- """
- Return a scaler value for the coordinate range (e.g., number of seconds).
+ """
+ Return a scalar value for the coordinate range (e.g., number of seconds).
@@
- possible for evenly sampled coords. If false, just disregard
- this if coord isnt't evenly sampled.
+ possible for evenly sampled coords. If False, disregard this
+ when the coordinate isn't evenly sampled.
@@
- step = getattr(self, "step", None)
+ step = getattr(self, "step", None)
coord_range = self.max() - self.min()
- if step is not None:
- coord_range += step
+ if step is not None:
+ coord_range += np.abs(step)
return coord_range📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def coord_range(self, exact: bool = True): | |
| """ | |
| Return a scaler value for the coordinate range (e.g., number of seconds). | |
| Parameters | |
| ---------- | |
| exact | |
| If true, only exact ranges are returned. This accounts for | |
| spacing at the end of each sample. Consequently, exact is only | |
| possible for evenly sampled coords. If false, just disregard | |
| this if coord isnt't evenly sampled. | |
| """ | |
| if not self.evenly_sampled and exact: | |
| raise CoordError("coord_range has to be called on an evenly sampled data.") | |
| return self.max() - self.min() + self.step | |
| step = getattr(self, "step", None) | |
| coord_range = self.max() - self.min() | |
| if step is not None: | |
| coord_range += step | |
| return coord_range | |
| def coord_range(self, exact: bool = True): | |
| """ | |
| Return a scalar value for the coordinate range (e.g., number of seconds). | |
| Parameters | |
| ---------- | |
| exact | |
| If True, only exact ranges are returned. This accounts for | |
| spacing at the end of each sample. Consequently, exact is only | |
| possible for evenly sampled coords. If False, disregard this | |
| when the coordinate isn't evenly sampled. | |
| """ | |
| if not self.evenly_sampled and exact: | |
| raise CoordError("coord_range has to be called on an evenly sampled data.") | |
| step = getattr(self, "step", None) | |
| coord_range = self.max() - self.min() | |
| if step is not None: | |
| coord_range += np.abs(step) | |
| return coord_range |
🤖 Prompt for AI Agents
In dascore/core/coords.py around lines 509 to 529, coord_range currently adds
the signed step which shrinks the range for reverse-sorted coords; change the
code to add abs(step) instead of step so the inclusive range uses the magnitude
of the spacing regardless of direction, and correct the docstring typos
("scaler" -> "scalar", "coord isnt't" -> "coord isn't"); keep the even-sampled
guard and behavior otherwise unchanged.
| ) | ||
| from dascore.exceptions import CoordError, ParameterError | ||
| from dascore.units import get_quantity | ||
| from dascore.units import get_quantity, percent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify percent is exported from dascore.units
Ensure percent is a public symbol to avoid import errors.
🏁 Script executed:
#!/bin/bash
# Confirm 'percent' is defined/exported.
rg -nP 'percent' dascore/units.py
rg -nP 'from .*dascore\.units.* import .*percent' -SLength of output: 240
Export percent in dascore/units.py: add an import or definition of percent (and include it in __all__ if used) so that from dascore.units import percent in tests doesn’t error.
🤖 Prompt for AI Agents
In dascore/units.py (top-level exports), tests import percent but it is not
exported; add a definition or import for percent (e.g., import or alias the
existing percent quantity/function from wherever it's defined) and ensure
percent is included in the module's __all__ so that from dascore.units import
percent works without error.
There was a problem hiding this 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 (2)
dascore/proc/taper.py (2)
30-38: Regression: coord_range(exact=False) inflates duration by one step → overlapping tapers.coord_range currently adds the final step regardless of exact, so using it here makes the left+right taper lengths exceed the dimension on some inputs, tripping “Taper windows cannot overlap” (seen in CI). For percent/decimal inputs, the duration should be the geometric span (max − min), not the step-inclusive range.
Fix:
- dur = coord.coord_range(exact=False) + # Use geometric span (max - min) so two fractional tapers that sum to 1.0 + # meet but do not overlap. coord_range includes the final step, which + # causes off-by-one overlaps in small arrays and fails CI. + dur = coord.max() - coord.min()This restores previous non-overlapping behavior and keeps uneven-coord support (selection still happens via coord.select). If you want to keep using coord_range later, it likely needs an option to exclude the terminal step.
76-77: Fix user-facing doc typos/wording (critical polish).A few small text issues in public docs/examples.
Apply:
@@ - window_type - The type of window to use For tapering. Supported Options are: + window_type + The type of window to use for tapering. Supported options are: @@ - Used to specify the dimension along which to taper and the percentage - of total length of the dimension (if a decimal or percente, see examples), - or absolute units. If a single value is passed, the taper will be applied - to both ends. A length two tuple can specify different values for each - end, or no taper on one end. + Used to specify the dimension along which to taper and the percentage + of the dimension’s total length (if a decimal or percent; see examples), + or absolute units. If a single value is passed, the taper is applied + to both ends. A length-2 tuple can specify different values for each + end, or no taper on one end. @@ - >>> # Apply an Hanning taper to 5% of each end for time dimension. + >>> # Apply a Hann taper to 5% of each end of the time dimension. @@ - >>> # Apply a triangular taper to 10% of the start of the distance dimension. + >>> # Apply a triangular taper to 10% at the start of the distance dimension. @@ - window_type - The type of window to use For tapering. Supported Options are: + window_type + The type of window to use for tapering. Supported options are: @@ - If True, the values specified in kwargs are relateive to the + If True, the values specified in kwargs are relative to the @@ - # [2] and [3] are tapered and values inside [1] and [2] are - # not effected. + # [2] and [3] are tapered and values inside [1] and [2] are + # not affected.Also applies to: 80-83, 98-103, 104-107, 110-111, 216-218, 225-227, 263-266
🧹 Nitpick comments (1)
dascore/proc/taper.py (1)
32-35: Percent Quantity handling may bypass scaling; confirm intended behavior.20percent is a Quantity and will skip the dur scaling path here, relying on coord.select(relative=True) to interpret percent. Please confirm tests cover both float fractions (e.g., 0.1) and Quantity percents (e.g., 10percent) yielding identical indices. If not, normalize percent Quantities to absolute via the same dur used for floats.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
dascore/proc/correlate.py(1 hunks)dascore/proc/taper.py(6 hunks)
✅ Files skipped from review due to trivial changes (1)
- dascore/proc/correlate.py
🧰 Additional context used
🧬 Code graph analysis (1)
dascore/proc/taper.py (2)
dascore/utils/signal.py (1)
_get_window_function(25-35)dascore/core/coords.py (4)
coord_range(509-528)sorted(483-485)sorted(1239-1241)sorted(1460-1462)
🪛 GitHub Actions: TestCode
dascore/proc/taper.py
[error] 58-58: ParameterError: Taper windows cannot overlap (in _validate_windows) during taper() call in tests/test_proc/test_correlate.py::TestCorrelateInternal::test_basic_correlation
[error] 58-58: ParameterError: Taper windows cannot overlap (in _validate_windows) during taper() call in tests/test_proc/test_correlate.py::TestCorrelateInternal::test_transpose_independent
[error] 58-58: ParameterError: Taper windows cannot overlap (in _validate_windows) during taper() call in tests/test_proc/test_correlate.py::TestCorrelateInternal::test_correlation_freq_domain_patch
[error] 58-58: ParameterError: Taper windows cannot overlap (in _validate_windows) during taper() call in tests/test_proc/test_correlate.py::TestCorrelateInternal::test_correlate_decimated_patch
[error] 58-58: ParameterError: Taper windows cannot overlap (in _validate_windows) during taper() call in tests/test_proc/test_correlate.py::TestCorrelateInternal::test_correlate_units_raises
[error] 58-58: ParameterError: Taper windows cannot overlap (in _validate_windows) during taper() call in tests/test_proc/test_correlate.py::TestCorrelateInternal::test_correlate_units
[error] 58-58: ParameterError: Taper windows cannot overlap (in _validate_windows) during taper() call in tests/test_proc/test_correlate.py::TestCorrelateInternal::test_lag_deprecated
🪛 GitHub Actions: TestCodeMinDeps
dascore/proc/taper.py
[error] 58-58: Taper windows cannot overlap.
🔇 Additional comments (3)
dascore/proc/taper.py (3)
17-17: Good call: centralize window lookup via utils.signal.Importing WINDOW_FUNCTIONS and _get_window_function removes duplication and keeps the registry in one place.
62-62: Doc options now sourced from WINDOW_FUNCTIONS — LGTM.Keeps docs in sync with the centralized registry.
199-200: Doc list source update mirrors taper() — LGTM.Keeps both entry points consistent.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #522 +/- ##
=======================================
Coverage 99.87% 99.87%
=======================================
Files 121 122 +1
Lines 9912 9926 +14
=======================================
+ Hits 9900 9914 +14
Misses 12 12
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this 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/core/coords.py (1)
509-525: Fix inclusive range for reverse-sorted coords; tighten docs; improve error message.
- Use the magnitude of the step when extending the range so reverse-sorted coords don’t shrink the range.
- Correct “scaler” → “scalar”; “If true” → “If True”; grammar in the error message.
Apply this diff:
def coord_range(self, extend: bool = True): """ - Return a scaler value for the coordinate range (e.g., number of seconds). + Return a scalar value for the coordinate range (e.g., number of seconds). Parameters ---------- extend - If true, count the end of the range as max() + sample step. This - can only work for evenly sampled coordinates. + If True, count the end of the range as max() + |step|. + This only works for evenly sampled coordinates. """ - if not self.evenly_sampled and extend: - raise CoordError("coord_range has to be called on an evenly sampled data.") + if not self.evenly_sampled and extend: + raise CoordError("coord_range(extend=True) requires an evenly sampled coordinate.") coord_range = self.max() - self.min() if extend: - coord_range += self.step + coord_range += np.abs(self.step) return coord_range
🧹 Nitpick comments (1)
tests/test_proc/test_correlate.py (1)
73-77: Typo in comment.“autocorrection” → “autocorrelation”.
- # normalize energy so autocorrection is 1 + # normalize energy so autocorrelation is 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
dascore/core/coords.py(3 hunks)dascore/proc/taper.py(6 hunks)tests/test_core/test_coords.py(3 hunks)tests/test_proc/test_correlate.py(1 hunks)tests/test_proc/test_taper.py(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- tests/test_core/test_coords.py
- dascore/proc/taper.py
- tests/test_proc/test_taper.py
🧰 Additional context used
🧬 Code graph analysis (2)
tests/test_proc/test_correlate.py (1)
dascore/proc/taper.py (1)
taper(63-132)
dascore/core/coords.py (2)
dascore/core/coordmanager.py (1)
coord_range(1031-1033)dascore/exceptions.py (1)
CoordError(38-39)
⏰ 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). (15)
- GitHub Check: test_code (windows-latest, 3.12)
- GitHub Check: test_code (macos-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 (windows-latest, 3.10)
- GitHub Check: test_code (windows-latest, 3.11)
- GitHub Check: test_code (ubuntu-latest, 3.10)
- GitHub Check: test_code (ubuntu-latest, 3.11)
- 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 (macos-latest, 3.12)
- GitHub Check: test_code_min_deps (ubuntu-latest, 3.12)
- GitHub Check: test_code_min_deps (ubuntu-latest, 3.13)
- GitHub Check: test_code_min_deps (windows-latest, 3.12)
🔇 Additional comments (3)
tests/test_proc/test_correlate.py (1)
66-73: Audit and standardize taper unit usage
Multiple.taper(time=<float>)calls with ambiguous units (e.g.time=0.05) exist in tests, docs, examples, and src. Replace intended percentage tapers withtime=5 * percent(and explicit seconds withtime=0.5 * s) and update imports (from dascore.units import percent, s). Runrg -nP '\.taper\([^)]*time\s*=\s*\d+(\.\d+)?(?!\s*\*)'to locate and update all occurrences.
dascore/core/coords.py (2)
33-34: LGTM: percent import is appropriate for new percent-handling logic.
509-525: No changes needed for coord_range call sites
Verified that the only callers using the defaultextend=True—theCoordManager.coord_rangeconvenience method and its use inpatch.py—operate on evenly sampled coordinates, and all other consumers explicitly passextend=Falsewhere required.
| if hasattr(value, "units"): | ||
| value = convert_units(value.magnitude, self.units, value.units) | ||
| mag, unit = value.magnitude, value.units | ||
| if unit == percent: | ||
| value = (mag / 100.0) * self.coord_range(extend=False) | ||
| relative = True | ||
| else: | ||
| value = convert_units(value.magnitude, self.units, value.units) | ||
| # if null or ... just return None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Percent × timedelta64 can raise; convert range to float first.
Multiplying a float by numpy timedelta64 throws a TypeError. Convert the range to a numeric (via to_float) before scaling by percent, then let the existing relative/datetime path convert back as needed.
Apply this diff:
- if hasattr(value, "units"):
- mag, unit = value.magnitude, value.units
- if unit == percent:
- value = (mag / 100.0) * self.coord_range(extend=False)
- relative = True
- else:
- value = convert_units(value.magnitude, self.units, value.units)
+ if hasattr(value, "units"):
+ mag, unit = value.magnitude, value.units
+ if unit == percent:
+ base = to_float(self.coord_range(extend=False))
+ value = (mag / 100.0) * base
+ relative = True
+ else:
+ value = convert_units(mag, self.units, unit)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if hasattr(value, "units"): | |
| value = convert_units(value.magnitude, self.units, value.units) | |
| mag, unit = value.magnitude, value.units | |
| if unit == percent: | |
| value = (mag / 100.0) * self.coord_range(extend=False) | |
| relative = True | |
| else: | |
| value = convert_units(value.magnitude, self.units, value.units) | |
| # if null or ... just return None | |
| if hasattr(value, "units"): | |
| mag, unit = value.magnitude, value.units | |
| if unit == percent: | |
| base = to_float(self.coord_range(extend=False)) | |
| value = (mag / 100.0) * base | |
| relative = True | |
| else: | |
| value = convert_units(mag, self.units, unit) | |
| # if null or ... just return None |
🤖 Prompt for AI Agents
In dascore/core/coords.py around lines 613 to 620, multiplying a float percent
by a numpy timedelta64 can raise a TypeError; convert the coord range to a
numeric first before scaling. Replace the percent branch so it calls
to_float(self.coord_range(extend=False)) (or an equivalent numeric conversion)
and uses that numeric value for the (mag / 100.0) * range calculation, then set
relative = True so the existing relative/datetime conversion path handles
converting back as needed.
Description
This PR adds support for using percent (as in from dascore.units) in coord select and taper. It is interpreted as % of the coord range in these contexts.
Also added close option for
Patch.equalssonp.allcloseis used for data comparison rather than strict equality.Checklist
I have (if applicable):
Summary by CodeRabbit
New Features
Changes
Tests