Question Details

No question body available.

Tags

python numpy signal-processing fft

Answers (2)

Accepted Answer Available
Accepted Answer
August 5, 2025 Score: 20 Rep: 15,176 Quality: Expert Completeness: 80%

Answer to your question

(initial version of my answer)

You are doing the computation of D and N wrong (and therefore, no, it's not a signal processing question. More an array shaping question ;-))

See what happens if stretchfactor is 2. Then Dold (my naming, but you get it) is 1000. So Nold is 2D+1 = 2001. Now you stretch N by a factor 2, so you have Nnew=2002 which isn't even odd. So Dnew=(Nnew-1)//2 ends up being 1000, and so the rule N=2D+1 on which you count isn't true.

Plus, the resulting fk array having a non-odd size, that means that it desn't even have a middle. And you expect the middle value to be the "constant" part, right? So, all your stretched frequencies are not really stretched: they are shifted an stretched (since middle value is the freq 0, and it ends up else where in the "stretched and shifted" array...

With an even strechfactor what I say is obvious because there isn't even a middle part.

But even with an odd stretchfactor.

With your example 5 what you got is

fk.shape # (10005,) # ok it has a middle 5002 values before, 5002 after.
ak.shape # 2001
fk[::5] = ak*0.2
print(fk[5002]) # 0 !! when you expected to find there the middle ak[1000] value (times 0.2)
print(fk[5000]) # there is your 0.2*ak[1000]. 

So you see, your frequency 0 in ak (index 1000) ends up at frequency -2 in fk (index 5000) (Well -2 units, but you get what I mean)

So, solution => stretch D, not N

    D=(N-1)//2
    Dnew = stretchfactorD
    N_new = 2Dnew+1
    fk = np.zeros(Nnew , dtype=complex)
    fk[::stretchfactor] = ak/stretchfactor

Another error

(well, it is almost the same one: it is D that you stretch, not N. So, if you multiply the range by 5, the factors fullrange should also be multiplied by 5. Said otherwise: fullrange in the Fourier computation should be 2D, not 2D+1 (but still, the size of the array is 2D+1)

So fourier code becomes

def fourierseriestransform(data, posrange, inverse=False):
    fullrange=2pos_range
    # Allocate result array
    result = np.zeros(full_range+1, dtype=complex)

if inverse: # Inverse transform: reconstruct time-domain signal from bk for n in range(-pos_range, pos_range+ 1): for k in range(-pos_range, pos_range+ 1): result[n + pos_range] += data[k + pos_range] cmath.exp(j 2 pi k n / fullrange) else: # Forward transform: compute bk from b[n] for k in range(-posrange, posrange+ 1): for n in range(-posrange, posrange+ 1): result[k + posrange] += (1 / fullrange) * data[n + posrange] cmath.exp(-j 2 pi k * n / fullrange)

return result

see how I use fullrange+1 when it is about number of element in array, but fullrange when it is about the scale of frequencies. So, roughly the same error as before: the middle element (0) doesn't cound when it comes to counting the strech, or frequency scale

Figure once corrected

Which is way closer to what you expected (and no more bunny ears. Which I find sad, even if it is probably better)

Vectorization (not strictly needed, but I can't resist)

Your code is not using numpy right. The whole point of numpy is to avoid iterating on arrays with for loops, as you do. I don't need to explain that too much, since you are probably aware of it: your cleancomplex is already using numpy correctly, by computing batches of operations (doing those

August 5, 2025 Score: 7 Rep: 106,102 Quality: High Completeness: 80%

I think you were applying 5x upsampling before converting the signal from frequency domain back to time domain.

In this case, you should have 4 consecutive zeros between the raw ak series, and also the tail 4 zeros should not be added. You can cross check your fk with the sequence generated by sp.signal.upfirdn()

Below is an example that should fit your objective

import scipy as sp

u = 5 fk = sp.signal.upfirdn([1], ak, u) fn = 0.2*sp.fft.ifft(fk, norm = 'forward') Dnew = (len(fn)-1)/2 x = np.arange(-Dnew,Dnew+1)

plt.title(f'time domain fn (after {u}x upsampling)') plt.plot(x, np.abs(fn), label = 'abs') plt.legend() plt.grid(True)

which should give a plot like below

enter image description here