question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Aliasing everywhere

See original GitHub issue

x_complex[::stride] can be lossless while abs(x_complex)[::stride] isn’t; modulus expands the spectrum. Stride and modulus commute, hence we lose information.

This yielded max 25% relative absolute difference on a simple example I tried, in second order:

sc.oversampling = 0
o0 = sc(x)
sc.oversampling = 999
o1 = sc(x)[:, ::sc.T]
adiff = np.abs(o0 - o1) / (np.abs(o0) + 1e7)

However, I noticed 1) difference in first order was <.01%, as expected; 2) second-order coeffs matched within a scalar multiple of 1.27.

This is tricky to interpret. Lossless subsampling preserves all information, yet a nonlinearity (abs) on this “identical” data produces a different result. From point of view of abs, we do lose information - obvious if we take abs first and then subsample. Yet, we can fully invert the complex subsampling and then take abs to produce the exact same abs.

However, consider if the nonlinearity instead mapped the first FFT bin to Nyquist, for any input length - e.g. (-1)**floor(x / factor). Then, no matter how much we FFT upsample, there’s always content at Nyquist. Hence I think the correct answer is, the perspective that matters is that of the intended operators; if our transform relied on the original 1Hz becoming Nyquist, this’ll be impossible post-subsampling. Similarly, scattering relies on modulus, and modulus isn’t same post-subsampling: the continuous-time math is distorted.

Thus, allclose(o0, o1) must pass - namely, o0 must agree with o1. This suggests potential need for a normalizing factor dependent upon k’s. Outstanding:

  • Is there exact math for this?
  • Is the difference always a constant scaling?
code
import numpy as np
from scipy.fft import fft, ifft
from kymatio.numpy import Scattering1D
from kymatio.visuals import plot

sc = Scattering1D(8, 2048, Q=8, T=256, max_pad_factor=None)
x = np.random.randn(sc.N)

#%%
def adiff(x0, x1):
    return np.abs(x0 - x1) / (np.abs(x0) + 1e-7)
    
def padiff(x0, x1):
    d = adiff(x0, x1)
    print(d.min(), d.max(), d.mean(), [n[0] for n in np.where(d == d.max())])

#%%
sc.oversampling = 0
o0 = sc(x)
sc.oversampling = 999
o1 = sc(x)[:, ::sc.T]

ord1_idxs, ord2_idxs = (sc.meta()['order'] == 1), (sc.meta()['order'] == 2)
o0_1, o1_1 = o0[ord1_idxs], o1[ord1_idxs]
o0_2, o1_2 = o0[ord2_idxs], o1[ord2_idxs]

padiff(o0_1, o1_1)
padiff(o0_2, o1_2)

#%% compute for one specific coefficient
n1 = 42
n2 = -1
pf1 = sc.psi1_f[n1][0]
j1 = sc.psi1_f[n1]['j']
j2 = sc.psi1_f[n2]['j']
pf20 = sc.psi2_f[n2][j1]
pf21 = sc.psi2_f[n2][0]

np.random.seed(0)
xp = np.pad(x, (len(pf1) - len(x))//2, mode='reflect')
xf = fft(xp)

o0, o1 = {}, {}

o0['0']  = xf * pf1
o0['1']  = o0['0'].reshape(2**j1, -1).mean(axis=0)
o0['2']  = ifft(o0['1'])
o0['3']  = np.abs(o0['2'])

o0['4']  = fft(o0['3'])
o0['5']  = o0['4'] * pf20
o0['6']  = o0['5'].reshape(2**int(j2 - j1), -1).mean(axis=0)
o0['7']  = ifft(o0['6'])
o0['8']  = np.abs(o0['7'])

o0['9']  = fft(o0['8'])
o0['10'] = o0['9'] * sc.phi_f[j2]
o0['11'] = o0['10'].reshape(sc.T//2**j2, -1).mean(axis=0)
o0['12'] = ifft(o0['11']).real


o1['0']  = xf * pf1
o1['2']  = ifft(o1['0'])
o1['3']  = np.abs(o1['2'])

o1['4']  = fft(o1['3'])
o1['5']  = o1['4'] * pf21
o1['7']  = ifft(o1['5'])
o1['8']  = np.abs(o1['7'])

o1['9']  = fft(o1['8'])
o1['10'] = o1['9'] * sc.phi_f[0]
o1['11'] = o1['10'].reshape(sc.T, -1).mean(axis=0)
o1['12'] = ifft(o1['11']).real

O0, O1 = o0['12'], o1['12']
s, e = sc.ind_start[sc.log2_T], sc.ind_end[sc.log2_T]
O0u, O1u = O0[s:e], O1[s:e]
padiff(O0, O1)
padiff(O0u, O1u)
print()

#%%
for i in (0, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12):
    if i in (3, 8):
        print()
    i = str(i)
    c0, c1 = o0[i], o1[i]
    c0 = c0[1:len(c0)//2]
    c1 = c1[1:len(c1)//2]
    # c0 = c0 / np.abs(c0).max()
    # c1 = c1 / np.abs(c1).max()
       
    mx = max(np.abs(c0).max(), np.abs(c1).max()) * 1.05
    pkw = dict(abs=1, show=1, ylims=(0, mx))
    
    plot(c0, title=f"o0-{i}", **pkw)
    plot(c1, title=f"o1-{i}", **pkw)

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5

github_iconTop GitHub Comments

1reaction
lostanlencommented, Mar 5, 2022

Excellent troubleshooting work !!

1reaction
OverLordGoldDragoncommented, Mar 4, 2022

Also >1% at first order is possible but is much rarer, I guess since aliasing the aliased compounds.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Troubleshooting help with aliasing everywhere.. : r/Monitors
Hey everyone, here is my problem So i had a computer, who had jaggy lines and aliasing everywhere, even if i used something...
Read more >
Aliasing, everywhere :: Between the Stars General - Steam Community
Aliasing, everywhere. The title is pleasant but is visually spoiled by this aliasing much too present. The DSR is not allowed and go...
Read more >
Aliasing and Shadow Zones
These artifacts are stronger in the shallow area and tend to decrease in amplitudes with depth, but they are present everywhere. Antialiasing successfully ......
Read more >
Shimmering and jaggies everywhere! - General Discussion
Prepar3D, DCS World, XPlane 11 all exhibit the same behaviors with anti-aliasing! Please fix this asap! Picture is from Prepar3D V5.
Read more >
Using anti-aliasing for text universally? #218 - GitHub
Based on the comment here #152, I was wondering if there's a global UI parameter to use anti-aliasing everywhere. I have FlatLaf side...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found