Skip to content

Conversation

ev-br
Copy link
Member

@ev-br ev-br commented Oct 30, 2024

Reference issue

supersedes #20668

What does this implement/fix?

Finish up gh-20688 : make signal.windows array api compatible.

Had to add several small shims:

  • acos / arccos renames in numpy 2.0; We'll be able to drop the shims when we drop numpy < 2 and cupy < 14
  • asarray accepting / not accepting the device= kwarg
  • To minimize the churn in tests, also added a small bit to xp_assert_* functions: if desired is a list, deduce its array namespace from array_namespace(actual).

The rest is fairly straightforward

cc @jakevdp : can push additional commits into your branch if you prefer.

Additional information

Needed to add delegation to several signal functions which only accepts scalars, not arrays; wanted to follow the prior art, found gh-20668; noticed that the CI is red and logs are gone; and here we are, several frustrating hours later.

@ev-br ev-br added scipy.signal array types Items related to array API support and input array validation (see gh-18286) labels Oct 30, 2024
@ev-br ev-br requested review from larsoner and ilayn as code owners October 30, 2024 19:58
@github-actions github-actions bot added scipy._lib enhancement A new feature or improvement labels Oct 30, 2024
@ev-br ev-br requested a review from andyfaff as a code owner October 30, 2024 20:27
@ev-br
Copy link
Member Author

ev-br commented Oct 30, 2024

The Array API CI job looks green, and I ran tests locally with CuPy (but not with torch GPU or jax GPU). The failures in "regular" CI jobs, I'm pretty sure I fixed those in #20772 or #21713.

@ev-br ev-br force-pushed the pr/20668 branch 2 times, most recently from 573eb55 to 65bdc5d Compare November 3, 2024 20:02
@ev-br ev-br force-pushed the pr/20668 branch 2 times, most recently from b27d82b to 7a6e164 Compare November 4, 2024 09:02
Comment on lines 2281 to 2193
dpss_rxx = _fftautocorr(xp.asarray(windows))
r = 4 * W * xp_sinc(xp.asarray(2 * W * nidx), xp=xp)
r[0] = 2 * W
ratios = np.dot(dpss_rxx, r)
ratios = xp.matmul(dpss_rxx, r)
if singleton:
ratios = ratios[0]
ratios = xp.asarray(ratios, device=device)
Copy link
Member

Choose a reason for hiding this comment

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

can we do all of this calculation on device rather than copying at the end?

Copy link
Member Author

Choose a reason for hiding this comment

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

There's not much point ATM because dpss is effectively CPU-only; it relies on eigh_triangular which is not available on CUDA anyhow.

@ev-br
Copy link
Member Author

ev-br commented Nov 6, 2024

Updated to address review comments.

@lucascolley lucascolley dismissed their stale review November 6, 2024 11:28

comments addressed

@ev-br ev-br force-pushed the pr/20668 branch 2 times, most recently from 68d2c37 to 775ab2d Compare November 23, 2024 19:51
@ev-br
Copy link
Member Author

ev-br commented Dec 6, 2024

CI failures are data-apis/array-api-extra#49

@ev-br
Copy link
Member Author

ev-br commented Dec 29, 2024

The general discussion on the default fp dtype seems to have completed reached a conclusion, https://discuss.scientific-python.org/t/should-scipy-tests-assume-float64-as-the-default-floating-point-dtype/1606/6

My summary of actionable items is #22210

To help move this PR forward, I rolled back the dtype changes and fixed the CI. Thus, the CI here is green with no sweeping changes to unrelated modules.

@ev-br
Copy link
Member Author

ev-br commented Jan 4, 2025

CI failures here are an interesting fallout from #22132

Here's a test which looks like this:

    def test_correctness(self, xp):
        ...
        w = windows.taylor(M_win, nbar=4, sll=35, norm=False, sym=False, xp=xp)
        f = fft(w, N_fft)    # f is an xp.array

        f_np = np.asarray(f)    # deliberate conversion to numpy!

       #.... manupulate `f_np`

        spec = 20 * np.log10(np.abs(f_np / np.max(f_np)))
        first_zero = np.argmax(np.diff(spec) > 0)
        PSLL = np.max(spec[first_zero:-first_zero])

        xp_assert_close(PSLL, -35.1672, atol=1)    # fails because PSSL is a numpy object

Thoughts @crusaderky ?

@lucascolley
Copy link
Member

If you're comparing to a python scalar then I think you can just use assert abs(PSSL - (-35.1672)) < 1. Or np.testing.assert_almost_equal.

@crusaderky
Copy link
Contributor

CI failures here are an interesting fallout from #22132

Here's a test which looks like this:

    def test_correctness(self, xp):
        ...
        w = windows.taylor(M_win, nbar=4, sll=35, norm=False, sym=False, xp=xp)
        f = fft(w, N_fft)    # f is an xp.array

        f_np = np.asarray(f)    # deliberate conversion to numpy!

       #.... manupulate `f_np`

        spec = 20 * np.log10(np.abs(f_np / np.max(f_np)))
        first_zero = np.argmax(np.diff(spec) > 0)
        PSLL = np.max(spec[first_zero:-first_zero])

        xp_assert_close(PSLL, -35.1672, atol=1)    # fails because PSSL is a numpy object

Thoughts @crusaderky ?

xp_assert_close(PSLL, -35.1672, atol=1, xp=np)

@ev-br
Copy link
Member Author

ev-br commented Jan 15, 2025

The CI is all green, all review comments are addressed either here or separately; I'm going to press the green button in about a week's time unless there are further comments.

Copy link
Member

@j-bowhay j-bowhay left a comment

Choose a reason for hiding this comment

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

I had a look through and other than a couple of non-blocking nit this seems good to go

One thing I wasn't quite sure on is how the xp arg interacts with the environment variable flag? Normally I'd just try it out but I'm on mobile

)

def test_correctness(self):
@skip_xp_backends(cpu_only=True)
Copy link
Member

Choose a reason for hiding this comment

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

Nit, it would be nice to have a reason

Copy link
Member Author

Choose a reason for hiding this comment

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

No fundamental reason, just that the rest of the test is using f_np = np.asarray(f) . Want me to flush the CI for it?

Copy link
Member

Choose a reason for hiding this comment

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

Probably not, maybe just add it in one of the subsequent prs if you remember

assert_allclose(PSLL, -35.1672, atol=1)
assert_allclose(BW_3dB, 1.1822, atol=0.1)
assert_allclose(BW_18dB, 2.6112, atol=0.1)
assert math.isclose(PSLL, -35.1672, abs_tol=1)
Copy link
Member

Choose a reason for hiding this comment

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

Did we need to change anything here since it looks like all the qualities being test come from f_np? It's just I imagine assert math.isclose(...) has a less informative error

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, this :-). Yes, since #22132 you cannot xp_assert_close(np_array, np_array) when xp is not numpy.
An alternative is, I believe, xp_assert_close(actual, desired, xp=array_namespace(np.empty(0))) or some such.

Copy link
Member

Choose a reason for hiding this comment

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

Can we not just leave it as assert_allclose?

Copy link
Member Author

Choose a reason for hiding this comment

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

FWIW I prefer to introduce math.isclose to reintroducing numpy.testing.assert_allclose, for python scalars.

@j-bowhay j-bowhay merged commit f454662 into scipy:main Jan 19, 2025
39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
array types Items related to array API support and input array validation (see gh-18286) enhancement A new feature or improvement scipy._lib scipy.signal
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants