Subject: Re: [ot][spam][random][crazy][random][crazy]
From: ilsa <[email-masked]>
To: "Undescribed Horrific Abuse, One Victim & Survivor of Many" <[email-masked]>
Date: Wed, 16 Nov 2022 18:13:49 -0800

Thanks

On Wed, Nov 16, 2022, 5:38 PM Undescribed Horrific Abuse, One Victim &
Survivor of Many <[email-masked]> wrote:

> according to numpy my square wave matrix is singular.
>
> something for me to think about!
>
> i'm guessing a big issue is that my wavelet function doesn't have a
> way to shift phase.
>
> i don't really know much about wavelets; it's a word i remember from
> being a teenager, learning about these things in the resources i knew
> how to find.
>
> i don't know if it's the cause, but my wavelet will need a way to have
> phase.
>
> i could interpret the complex argument in terms of angle and
> magnitude, and simply phase shift the output. this seems like it would
> work fine, at first. but i'm not sure if it would survive the whole
> process, with no complex output.
>
> the trick with the sinusoids is that in frequency space, the phase is
> held as an angle in the complex plane.
> when the freq2time matrix is created, where does the complex output
> come from, and what meaning does it hold?
> it has only real-domain frequencies, and yet produces a matrix that
> converts from complex frequency.
>
> it takes the frequencies, and scales them by the offsets, and turns
> that into time parameters
> it passes the time parameters to the sinusoids.
> this produces a matrix that can process complex frequency data, and
> convert it to time data.
> each frequency is a magnitude and a phase.
>
> i can make a function that takes complex frequency data
> but the frequencies that are passed in are not complex: they are
> negative and positive.
> where the negative is the complex conjugate i.e. the angle iand hence
> phase is treated as negative.
>
> there are various things i could try but i'm trying to figure out
> what's going on in general.
>
> exp(2i pi x) produces a complex number rotated with an angle x
>
> how does this produce real-domain data? if i pass in a single
> frequency with a 0 angle, what does it do?
>
> i tried this:
> (Pdb) p np.array([0,1,0,1]) @ create_freq2time(4)
> array([ 5.00000000e-01+0.j,  3.06161700e-17+0.j, -5.00000000e-01+0.j,
>        -9.18485099e-17+0.j])
>
> so how does that work?
>
> (Pdb) p create_freq2time(4).round(2)
> array([[ 0.25+0.j  ,  0.25+0.j  ,  0.25+0.j  ,  0.25+0.j  ],
>        [ 0.25+0.j  ,  0.  +0.25j, -0.25+0.j  , -0.  -0.25j],
>        [ 0.25+0.j  , -0.25-0.j  ,  0.25+0.j  , -0.25-0.j  ],
>        [ 0.25+0.j  ,  0.  -0.25j, -0.25-0.j  , -0.  +0.25j]])
>
> columns are freq, rows are samps
> The first sample gets 0.25 + 0.25 = 0.5
> The second sample is the only one with complex domain stuff, and its
> 0.25 components cancel each other.
> The third has -0.25 at the two indices.
> The fourth cancels again.
>
> I'm going to paste it again.
> array([[ 0.25+0.j  ,  0.25+0.j  ,  0.25+0.j  ,  0.25+0.j  ],
>        [ 0.25+0.j  ,  0.  +0.25j, -0.25+0.j  , -0.  -0.25j],
>        [ 0.25+0.j  , -0.25-0.j  ,  0.25+0.j  , -0.25-0.j  ],
>        [ 0.25+0.j  ,  0.  -0.25j, -0.25-0.j  , -0.  +0.25j]])
>
> It's 4 complex sinusoids, but they oppose each other in the complex
> domain. Because a real-valued signal has both negative and complex
> frequencies equal, and because the complex component of the wavelet
> function is odd, the two cancel.
>
> That would work fine for phaseless square wave data. You'd provide an
> even function square wave for the real component, and an odd function
> square wave for the imaginary component.
>
> What about phase offset?
>
> (Pdb) p (np.array([0,1+1j,0,1+1j]) @ create_freq2time(4)).round(3)
> array([ 0.5+0.5j,  0. +0.j , -0.5-0.5j, -0. -0.j ])
> When I specify complex numbers for the frequencies, it actually
> produces a wave with the same phase, that has complex value, not a
> phased wave !
>
> I thought the angle of the frequency was the phase, but it isn't?
>
> (Pdb) p np.fft.ifft(np.array([0,1+1j,0,1+1j])).round(3)
> array([ 0.5+0.5j,  0. +0.j , -0.5-0.5j,  0. +0.j ])
>
> That appears to be so.
>
> That doesn't seem very useful to me, it seems it would be more useful
> if it were.
>
> Ohhhh I need to use the complex conjugate!
>
> (Pdb) p (np.array([0,1+1j,0,1-1j]) @ create_freq2time(4)).round(3)
> array([ 0.5+0.j, -0.5+0.j, -0.5+0.j,  0.5+0.j])
>
> There we go. I offset it by 45 degrees?
>
> (Pdb) p (np.array([0,1,0,1]) @ create_freq2time(4)).round(3)
> array([ 0.5+0.j,  0. +0.j, -0.5+0.j, -0. +0.j])
>
> I'm guessing the peaks for 45 degrees were between the samples. 90
> might be clearer.
>
> Yeah here's 90 degrees offset:
> (Pdb) p (np.array([0,1j,0,-1j]) @ create_freq2time(4)).round(3)
> array([ 0. +0.j, -0.5+0.j, -0. +0.j,  0.5+0.j])
>
> So how does that happen?
> (Pdb) p create_freq2time(4).round(3)
> array([[ 0.25+0.j  ,  0.25+0.j  ,  0.25+0.j  ,  0.25+0.j  ],
>        [ 0.25+0.j  ,  0.  +0.25j, -0.25+0.j  , -0.  -0.25j],
>        [ 0.25+0.j  , -0.25-0.j  ,  0.25+0.j  , -0.25-0.j  ],
>        [ 0.25+0.j  ,  0.  -0.25j, -0.25-0.j  , -0.  +0.25j]])
>
> Passing (0,1j,0,-1j) ...
> The first two frequencies have opposing components so they cancel.
> That would work with a 90 degree square wave.
> In the second .. it's 1j and -1j. the j's multiply to -1, and we get
> -.25 and -.25, which sum to 0.5 .
>
> the 90 degree case would work with square waves. but why does it work
> for sinusoids?
> cos(x) + sin(x)j = exp(2j pi x) is applied, not to the input data x,
> but rather to the frequency.
> then when the input data comes in, it is multiplied against that result.
> so if it's real, the sinusoid components cancel and the cosine is
> extracted. this then produces a real cosine wave.
> if it's imaginary and self-opposing, the cosines cancel from the
> self-opposingness, whereas the sines amplify, producing a wave that is
> 90 degrees off.
>
> how would a 45 degree wave be produced? what is that?
> it seems it would be a sum of the 0 degree and 90 degree waves, not sure.
>
> i looked at trigonometric identities and i found a relation that looked
> complex.
> let's see how it goes
>
> (Pdb) p create_freq2time(4).round(3)
> array([[ 0.25+0.j  ,  0.25+0.j  ,  0.25+0.j  ,  0.25+0.j  ],
>        [ 0.25+0.j  ,  0.  +0.25j, -0.25+0.j  , -0.  -0.25j],
>        [ 0.25+0.j  , -0.25-0.j  ,  0.25+0.j  , -0.25-0.j  ],
>        [ 0.25+0.j  ,  0.  -0.25j, -0.25-0.j  , -0.  +0.25j]])
> (Pdb) p (np.array([0,1+1j,0,1-1j]) @ create_freq2time(4)).round(3)
> array([ 0.5+0.j, -0.5+0.j, -0.5+0.j,  0.5+0.j])
>
> first sample: (1+1j)(0.25) + (1-1j)(0.25) = 0.5
> second sample: (1+1j)(0.25j) + (1-1j)(-0.25j) = -0.5
>
> so the first sample is just the real component
> then again the second sample is just the complex component
> it really is two waves, rising at different times, offset by 90 degrees,
> or such
>
> (Pdb) p (np.array([0,0.5+1j,0,0.5-1j]) @ create_freq2time(4)).round(3)
> array([ 0.25+0.j, -0.5 +0.j, -0.25+0.j,  0.5 +0.j])
>
> One could think of it as outputting the data in pairs.
> It outputs a real component, then a complex component, both in the real
> domain.
> Because one is offset by 90 degrees, this can provide for the
> construction of waves smoothly.
>
> It may work for the square wave.
>
> I guess I'll try it.
>
> 1600
>
> I made a complex square wave. Basically the real and imaginary parts
> are juts off by 1/4 .
> The forward matrix it produces has an inverse, and the pseudoinverse
> passes np.allclose() with it.
> The assertion still doesn't pass, but again it should now be a closed
> system.
>
> 1603 I'm looking a little at the real-domain matrix produced for the
> square wave, and I'm not yet sure about it.
>
> (Pdb) list
> 174         forward_mat = np.linalg.pinv(inverse_mat)
> 175         if not is_complex:
> 176             # todo: remove test data
> 177             time_data = np.random.random(inverse_mat.shape[1])
> 178             freq_data = time_data @ forward_mat
> 179  ->         forward_mat = np.concatenate([
> 180                 forward_mat[:,:tail_idx],
> 181                 forward_mat[:,tail_idx:neg_start_idx].conj()
> 182             ], axis=1)
> 183         return forward_mat
> 184
> (Pdb) normal_forward_mat = np.linalg.pinv(create_freq2time(time_count,
> freqs))
> (Pdb) p normal_forward_mat[6].round(3)
> array([ 1.   +0.j   , -0.707-0.707j, -0.   +1.j   ,  0.707-0.707j,
>        -1.   -0.j   ,  0.707+0.707j, -0.   -1.j   , -0.707+0.707j,
>         1.   -0.j   , -0.707-0.707j, -0.   +1.j   ,  0.707-0.707j,
>        -1.   -0.j   ,  0.707+0.707j,  0.   -1.j   , -0.707+0.707j])
> (Pdb) p forward_mat[6].round(3)
> array([-0.5+0.5j,  0.5+0.5j, -0.5-0.5j, -0.5+0.5j,  0.5-0.5j, -0.5-0.5j,
>         0.5+0.5j,  0.5-0.5j, -0.5+0.5j,  0.5+0.5j, -0.5-0.5j, -0.5+0.5j,
>         0.5-0.5j, -0.5-0.5j,  0.5+0.5j,  0.5-0.5j])
>
> In the normal dft matrix, the negative frequencies that occupy the
> second half, are the reverse-order complex conjugates of the positive
> frequencies that occupy the first half.
> In the forward_mat here, where the the square wave is being used, this
> complex conjugate situation does not hold. It's 1609.
>
> Basically, the even-numbered indices are conjugates, whereas the odds
> are opposites.
>
> It might be possible this could relate to the evaluation of the square
> wave at its discontinuous points.
>
> With real frequencies, the implication is that there are never
> frequencies equal to 0.125, for example. Looking a little further I'm
> not immediately discerning a pattern.
>
> 1640
>
> having trouble developing behaviors and energy and stuff around this next
> step.
>
> i'm looking at inverse_mat and it seems to have a similar issue.
>
> i'm thinking that the real component of the waveform is not an even
> function, and that that is the issue here.
>
> trying out numbers, it kind of looks like the wavelet is getting
> indexed in a way that is rounding negative, rather than toward zero.
> that's something i can look into!
>
> this is what I have:
>
> SINE = lambda x: np.sin(2 * np.pi * x)
> SQUARE = lambda x: np.floor(x * 2) * 2 - 1
>
> def complex_wavelet(wavelet, x):
>     return wavelet((x + 0.25) % 1) + wavelet(x % 1) * 1j
>
> and I'm getting this:
> >>> complex_wavelet(SQUARE, -.25)
> (-1+1j)
> >>> complex_wavelet(SQUARE, .25)
> (1-1j)
>
> the real component should have the same sign for correct behavior.
>
> other than the cutoff point, it is even:
> >>> complex_wavelet(SQUARE, .24)
> (-1-1j)
> >>> complex_wavelet(SQUARE, -.24)
> (-1+1j)
> >>> complex_wavelet(SQUARE, .26)
> (1-1j)
> >>> complex_wavelet(SQUARE, -.26)
> (1+1j)
>
> >>> SINE(0)
> 0.0
> >>> SINE(0.5)
> 1.2246467991473532e-16
> >>> SQUARE(0)
> -1.0
> >>> SQUARE(0.5)
> 1.0
>
> The sine function has 0 and 1/2 equal, whereas the square function
> does not. If the square function had 1.0 | x==0 or 1.0 | x > 0.5, it
> would work, but instead it has 1.0 | x >= 0.5 .
>
> The difference stems from floor(x * 2). With the floor function, lower
> values are included in the range, and upper values are not.
>
> I wonder if it would be appropriate to offset things by 0.125 simply
> to make the behavior look even when sampled at the points : but this
> wouldn't work for denser sampling, of course, which I imagine is
> needed.
>
> 1703
> I changed SQUARE to (x > 0.5) * 2 - 1, which kinda works because True
> is treated like 1 and False treated like 0. Assertion still failing.
>
> Note: if an even function is required for a wavelet to work, it would
> make sense to define them as even functions.
>
> 2036
> I ended up doing other things. The matrix did look better with the
> change. I would like to look at it more.
>