Search code examples
rsignal-processinginterpolationtransformationscaling

non-linearly compression decompression "x" and "y" axis in vector/time series


For example, I have a vector y that I want to change not linearly along the "x" "y" axis and get convert vector back

set.seed(123)
y <- cumsum(rnorm(50))
par(mar=c(0,2,0,0))
plot(y,t="l",lwd=2) ; abline(v=seq(1,length(y),3),col=8)

enter image description here

I found a function that does a non-linear transformation on the "x" axis

one_dimensional_fish_eye <- function (x1, x2, y, method="natural"){
  n <- length(y)
  x <- seq(min(x1), max(x1), length=n)
  x3 <- splinefun(x1, x2, method = method)(x)
  if (! all(x3 == sort(x3))) {
    warning("Non monotonic transformation!")
  }
  d <- cbind(x=x3, y=y)
  op1 <- par(mar=c(.1,.1,.1,.1))
  plot(d, type="l", lwd=3, axes = FALSE)
  box()
  abline(v=d[seq(0,length(y),by=ceiling(length(y)/50)),1],col=8)
  op2 <- par(fig=c(.02,.2,.8,.98), mar=c(0,0,0,0), new=TRUE)
  plot(x, x3, type = "l", lwd = 3, axes = FALSE)
  polygon(rep(par("usr")[1:2], 2)[c(1,2,4,3)], 
          rep(par("usr")[3:4], each=2), 
          border = NA, col = "white")
  lines(x, x3, type = "l", lwd = 3, col="blue")
  box(lwd=3, col="blue")
  par(op2)
  par(op1)
  return(d)
}

run func

one_dimensional_fish_eye(y = y,
  c(0, .33, .67, 1),
  c(0, .6, .9, 1))

result

            x          y
 [1,] 0.00000000 -0.5604756
 [2,] 0.04132695 -0.7906531
 [3,] 0.08255667  0.7680552
 [4,] 0.12359192  0.8385636
 [5,] 0.16433545  0.9678513
 [6,] 0.20469003  2.6829163
 [7,] 0.24455843  3.1438325
 [8,] 0.28384341  1.8787713
 [9,] 0.32244773  1.1919184
[10,] 0.36027415  0.7462564
[11,] 0.39722544  1.9703382

enter image description here

Can I do the same for the horizontal axis ? something like this

hrz <- sin(1:10)*4
plot(y,t="l",lwd=2) ; abline(h=hrz,col=8)

enter image description here

Maybe there is a package that does such conversions? Thank you UPD======================================================= enter image description here

I need a function that takes two deformation vectors and an initial time series as input, and at the output a deformed time series

X = some ts
verical_def = vector
horizontal_def = vector

deform_func = (X , verical_def ,  horizontal_def )
out = deformed X

UPD2=============================================== I do not know if this will help, but I will try to explain more globally what I am going to do.

How I see my function for finding distance between two time series

  1. there are two time series "A" and "B"

  2. there is a function that accepts a time series ("B") and two distortion vectors as input (a question about this function is here)

  3. the optimization algorithm uses the function from point 2 to find the distortion vectors to achieve the maximum similarity of ts "B" with ts "A"

All I need is a function that can distort the horizontal and vertical axis.


Solution

  • After some reflexion, I think it's better to use the function you found, and to modify it a little in order to achieve your goal ..

    Something like this perhaps :

    
    
    set.seed(123)
    y <- cumsum(rnorm(50))
    par(mar=c(0,2,0,0))
    plot(y,t="l",lwd=2) ; abline(v=seq(1,length(y),3),col=8)
    
    two_dimensional_fish_eye <- function (x1, x2, y1, y2, y, method="natural"){
      n <- length(y)
      x <- seq(min(x1), max(x1), length=n)
      x3 <- splinefun(x1, x2, method = method)(x)
      if (! all(x3 == sort(x3))) {
        warning("Non monotonic transformation on x axis!")
      }
      y3 <- splinefun(y1, y2, method = method)(y)
      y4 <- splinefun(y1, y2, method = method)(seq(min(y),max(y),by=ceiling(length(y)/50)))
      if (! all(y4 == sort(y4))) {
        warning("Non monotonic transformation on y axis!")
      }
      d <- cbind(x=x3, y=y3)
      print(y4)
      op1 <- par(mar=c(.1,.1,.1,.1))
      plot(d, type="l", lwd=3, axes = FALSE)
      box()
      abline(v=d[seq(0,length(y),by=ceiling(length(y)/50)),1],col=8)
      abline(h=y4,col=8)
      par(op1)
      return(d)
    }
    
    
    a <- two_dimensional_fish_eye(y = y,  
                                  y1 =  c(-1, -0.67, -0.33, 0, .33, .67, 1),
                                  y2 = c(-1, -0.9, -0.6, 0, .6, .9, 1),
                            x1 =  c(0, .33, .67, 1),
                            x2 = c(0, .6, .9, 1))