rtime-seriessignal-processingtransformationdiscretization

non-linear 2d object transformation by horizontal axis


How can such a non-linear transformation be done? enter image description here

here is the code to draw it

my.sin <- function(ve,a,f,p)   a*sin(f*ve+p)

s1 <- my.sin(1:100, 15, 0.1, 0.5)
s2 <- my.sin(1:100, 21, 0.2, 1)
s <- s1+s2+10+1:100

par(mfrow=c(1,2),mar=rep(2,4))
plot(s,t="l",main = "input") ; abline(h=seq(10,120,by = 5),col=8)

plot(s*7,t="l",main = "output")
abline(h=cumsum(s)/10*2,col=8)

don't look at the vector, don't look at the values, only look at the horizontal grid, only the grid matters

####UPDATE####

I see that my question is not clear to many people, I apologize for that... Here are examples of transformations only along the vertical axis, maybe now it will be more clear to you what I want enter image description here enter image description here enter image description here

link Source

#### UPDATE 2 ####

Thanks for your answer, this looks like what I need, but I have a few more questions if I may.

  1. To clarify, I want to explain why I need this, I want to compare vectors with each other that are non-linearly distorted along the horizontal axis .. Maybe there are already ready-made tools for this?

  2. You mentioned that there are many ways to do such non-linear transformations, can you name a few of the best ones in my case?

  3. how to make the function f() more non-linear, so that it consists, for example, not of one sinusoid, but of 10 or more. Тhe figure shows that the distortion is quite simple, it corresponds to one sinusoid

and how to make the function f can be changed with different combinations of sinusoids.

set.seed(126)
par(mar = rep(2, 4),mfrow=c(1,3))
s <- cumsum(rnorm(100))
r <- range(s)
gridlines <- seq(r[1]*2, r[2]*2, by = 0.2)
plot(s, t = "l", main = "input")
abline(h = gridlines, col = 8)
f <- function(x) 2 * sin(x)/2 + x 
plot(s, t = "l", main = "input+new greed")
abline(h = f(gridlines), col = 8)
plot(f(s), t = "l", main = "output")
abline(h = f(gridlines), col = 8)

enter image description here


Solution

  • If I understand you correctly, you wish to map the vector s from the regular spacing defined in the first image to the irregular spacing implied by the second plot.

    Unfortunately, your mapping is not well-defined, since there is no clear correspondence between the horizontal lines in the first image and the second image. There are in fact an infinite number of ways to map the first space to the second.

    We can alter your example a bit to make it a bit more rigorous.

    If we start with your function and your data:

    my.sin <- function(ve, a, f, p) a * sin(f * ve + p)
    
    s1 <- my.sin(1:100, 15, 0.1, 0.5)
    s2 <- my.sin(1:100, 21, 0.2, 1)
    s  <- s1 + s2 + 10 + 1:100
    

    Let us also create a vector of gridlines that we will draw on the first plot:

    gridlines <- seq(10, 120, by = 2.5)
    

    Now we can recreate your first plot:

    par(mar = rep(2, 4))
    
    plot(s, t = "l", main = "input")
    abline(h = gridlines, col = 8)
    

    enter image description here

    Now, suppose we have a function that maps our y axis values to a different value:

    f <- function(x) 2 * sin(x/5) + x
    

    If we apply this to our gridlines, we have something similar to your second image:

    plot(s, t = "l", main = "input")
    abline(h = f(gridlines), col = 8)
    

    enter image description here

    Now, what we want to do here is effectively transform our curve so that it is stretched or compressed in such a way that it crosses the gridlines at the same points as the gridlines in the original image. To do this, we simply apply our mapping function to s. We can check the correspondence to the original gridlines by plotting our new curves with a transformed axis :

    plot(f(s), t = "l", main = "output", yaxt = "n")
    axis(2, at = f(20 * 1:6), labels = 20 * 1:6)
    abline(h = f(gridlines), col = 8)
    

    enter image description here

    It may be possible to create a mapping function using the cumsum(s)/10 * 2 that you have in your original example, but it is not clear how you want this to correspond to the original y axis values.


    Response to edits

    1. It's not clear what you mean by comparing two vectors. If one is a non-linear deformation of the other, then presumably you want to find the underlying function that produces the deformation. It is possible to create a function that applies the deformation empirically simply by doing f <- approxfun(untransformed_vector, transformed_vector).
    2. I didn't say there were many ways of doing non-linear transformations. What I meant is that in your original example, there is no correspondence between the grid lines in the original picture and the second picture, so there is an infinite choice for which gridines in the first picture correspond to which gridlines in the second picture. There is therefore an infinite choice of mapping functions that could be specified.
    3. The function f can be as complicated as you like, but in this scenario it should at least be everywhere non-decreasing, such that any value of the function's output can be mapped back to a single value of its input. For example, function(x) x + sin(x)/4 + cos(3*(x + 2))/5 would be a complex but ever-increasing sinusoidal function.