From 163dc48022cc9dae1347a397de04cf8b32b4ef17 Mon Sep 17 00:00:00 2001 From: milesmedina <44986194+milesmedina@users.noreply.github.com> Date: Fri, 6 Sep 2024 19:32:26 -0400 Subject: [PATCH] phase space embeddings for pyro & chl --- R/embed_chl_otb.R | 94 ++++++++++++++++++++++++++++++++++++ R/embed_chl_otb_ce.R | 94 ++++++++++++++++++++++++++++++++++++ R/embed_chl_otb_cw.R | 94 ++++++++++++++++++++++++++++++++++++ R/embed_chl_otb_ne.R | 94 ++++++++++++++++++++++++++++++++++++ R/embed_chl_otb_nw.R | 94 ++++++++++++++++++++++++++++++++++++ R/embed_chl_otb_se.R | 94 ++++++++++++++++++++++++++++++++++++ R/embed_chl_otb_sw.R | 94 ++++++++++++++++++++++++++++++++++++ R/embed_pyro_otb-ce.R | 94 ++++++++++++++++++++++++++++++++++++ R/embed_pyro_otb-cw.R | 94 ++++++++++++++++++++++++++++++++++++ R/embed_pyro_otb-ne.R | 94 ++++++++++++++++++++++++++++++++++++ R/embed_pyro_otb-nw.R | 94 ++++++++++++++++++++++++++++++++++++ R/embed_pyro_otb-se.R | 94 ++++++++++++++++++++++++++++++++++++ R/embed_pyro_otb-sw.R | 94 ++++++++++++++++++++++++++++++++++++ data/embed_chl_otb.RData | Bin 0 -> 5717 bytes data/embed_chl_otb_ce.RData | Bin 0 -> 5722 bytes data/embed_chl_otb_cw.RData | Bin 0 -> 5695 bytes data/embed_chl_otb_ne.RData | Bin 0 -> 5723 bytes data/embed_chl_otb_nw.RData | Bin 0 -> 5722 bytes data/embed_chl_otb_se.RData | Bin 0 -> 5716 bytes data/embed_chl_otb_sw.RData | Bin 0 -> 5729 bytes 20 files changed, 1222 insertions(+) create mode 100644 R/embed_chl_otb.R create mode 100644 R/embed_chl_otb_ce.R create mode 100644 R/embed_chl_otb_cw.R create mode 100644 R/embed_chl_otb_ne.R create mode 100644 R/embed_chl_otb_nw.R create mode 100644 R/embed_chl_otb_se.R create mode 100644 R/embed_chl_otb_sw.R create mode 100644 R/embed_pyro_otb-ce.R create mode 100644 R/embed_pyro_otb-cw.R create mode 100644 R/embed_pyro_otb-ne.R create mode 100644 R/embed_pyro_otb-nw.R create mode 100644 R/embed_pyro_otb-se.R create mode 100644 R/embed_pyro_otb-sw.R create mode 100644 data/embed_chl_otb.RData create mode 100644 data/embed_chl_otb_ce.RData create mode 100644 data/embed_chl_otb_cw.RData create mode 100644 data/embed_chl_otb_ne.RData create mode 100644 data/embed_chl_otb_nw.RData create mode 100644 data/embed_chl_otb_se.RData create mode 100644 data/embed_chl_otb_sw.RData diff --git a/R/embed_chl_otb.R b/R/embed_chl_otb.R new file mode 100644 index 0000000..3d3f2d8 --- /dev/null +++ b/R/embed_chl_otb.R @@ -0,0 +1,94 @@ +# Phase space reconstruction +# Miles Medina, ECCO Scientific, 2024 +# + +rm(list=ls(all=TRUE)) + +# Load libraries + if(!require(tseriesChaos)) { install.packages('tseriesChaos') }; library(tseriesChaos) + if(!require(zoo)) { install.packages('zoo') }; library(zoo) + if(!require(plotly)) { install.packages('plotly') }; library(plotly) + if(!require(rEDM)) { install.packages('rEDM') }; library(rEDM) + +# Load data and select column + load( "../data/ssa_chl_otb.RData" ) + dat <- ssa_chl_otb$dat + colnames( dat ) + var <- 'signal' + x <- dat[,var] |> na.omit() + x <- scale( x ) + t <- dat$month + +# Plot the time series + par(mfrow=c(2,1)) + plot( x, type = 'l', xlab = 'time', main = "Time series x" ) + abline( v = axTicks(1), col = rgb(0,0,0,0.2) ) + abline( h = axTicks(2), col = rgb(0,0,0,0.2) ) + +# Find embedding parameters + par(mfrow=c(3,1)) + # Set embedding delay (d) using AMI function + ami <- mutual( x, lag.max = 20 ) # average mutual information function + local.d.min <- rollapply( ami, 3, function (x) which.min(x)==2 ) # local minima + d <- as.numeric( which(local.d.min==TRUE)[1] ) # first local min + points( x = d, y = ami[d+1], cex = 2, col = rgb(1,0,0,0.7) ) + d + + # Set Theiler window (tw) using ACF + ac <- acf( x, lag.max = 20 ) # autocorrelation function + ac$acf_abs <- ac$acf |> abs() # absolute values of acf + local.tw.min <- rollapply(ac$acf_abs, 3, function (x) which.min(x)==2 ) # abs local minima + tw <- as.numeric( which(local.tw.min==TRUE)[1] ) # first abs local min + points( x = tw, y = ac$acf[tw+1], cex = 2, col = rgb(1,0,0,0.7) ) + tw + + # Set embedding dimension (m) using false nearest neighbors test + fnn <- false.nearest( series=x, m=6, d=d, t=tw, eps=sd(x), rt=10 ) + threshold <- 0.15 + plot( fnn[1,], type = 'b', main = "FNN", pch = 16, cex = 2, + xlab = 'dim', ylab = 'proportion of false neighbors' ) + abline( h = threshold, lty = 2, col = rgb(0,0,0,0.6) ) + m <- as.numeric( which( fnn[1,] <= threshold )[1] ) + if( m==2 ){ m <- 3 } + points( x = m, y = fnn[1,m], cex = 3, col = rgb(1,0,0,0.7) ) + + +# Time-delay embedding + Mx <- embedd( x, m = m, d = d ) |> as.data.frame() + +# Plot phase space reconstruction + # Rename columns + for(i in 1:m){ + if(i==1){ names(Mx)[i]<-'x(t)' + } else { + names(Mx)[i] <- paste0('x(t+',d*(i-1),')') + } + } # // end i + # Plotly + p1 <- plot_ly( Mx, x = ~Mx[,1], y = ~Mx[,2], z = ~Mx[,3], + type = 'scatter3d', mode = 'lines', + opacity = 0.75, line = list(width = 6, reverscale = FALSE) ) |> + layout( title = 'Reconstructed attractor', + scene = list( xaxis = list(title=names(Mx)[1]), + yaxis = list(title=names(Mx)[2]), + zaxis = list(title=names(Mx)[3]) + ) ) + p1 + + +# Test for nonlinear stationarity with space-time separation plots + par(mfrow=c(1,1)) + stp <- stplot( series = x, m = m, d = d, mdt = length(x) ) + + +# Export embedding outputs + embed_chl_otb <- list( x = x, + t = t, + Mx = Mx, + d = d, + tw = tw, + m = m, + plot = p1 + ) + save( embed_chl_otb, file = "../data/embed_chl_otb.RData" ) + \ No newline at end of file diff --git a/R/embed_chl_otb_ce.R b/R/embed_chl_otb_ce.R new file mode 100644 index 0000000..3340a9e --- /dev/null +++ b/R/embed_chl_otb_ce.R @@ -0,0 +1,94 @@ +# Phase space reconstruction +# Miles Medina, ECCO Scientific, 2024 +# + +rm(list=ls(all=TRUE)) + +# Load libraries + if(!require(tseriesChaos)) { install.packages('tseriesChaos') }; library(tseriesChaos) + if(!require(zoo)) { install.packages('zoo') }; library(zoo) + if(!require(plotly)) { install.packages('plotly') }; library(plotly) + if(!require(rEDM)) { install.packages('rEDM') }; library(rEDM) + +# Load data and select column + load( "../data/ssa_chl_otb_ce.RData" ) + dat <- ssa_chl_otb_ce$dat + colnames( dat ) + var <- 'signal' + x <- dat[,var] |> na.omit() + x <- scale( x ) + t <- dat$month + +# Plot the time series + par(mfrow=c(2,1)) + plot( x, type = 'l', xlab = 'time', main = "Time series x" ) + abline( v = axTicks(1), col = rgb(0,0,0,0.2) ) + abline( h = axTicks(2), col = rgb(0,0,0,0.2) ) + +# Find embedding parameters + par(mfrow=c(3,1)) + # Set embedding delay (d) using AMI function + ami <- mutual( x, lag.max = 20 ) # average mutual information function + local.d.min <- rollapply( ami, 3, function (x) which.min(x)==2 ) # local minima + d <- as.numeric( which(local.d.min==TRUE)[1] ) # first local min + points( x = d, y = ami[d+1], cex = 2, col = rgb(1,0,0,0.7) ) + d + + # Set Theiler window (tw) using ACF + ac <- acf( x, lag.max = 20 ) # autocorrelation function + ac$acf_abs <- ac$acf |> abs() # absolute values of acf + local.tw.min <- rollapply(ac$acf_abs, 3, function (x) which.min(x)==2 ) # abs local minima + tw <- as.numeric( which(local.tw.min==TRUE)[1] ) # first abs local min + points( x = tw, y = ac$acf[tw+1], cex = 2, col = rgb(1,0,0,0.7) ) + tw + + # Set embedding dimension (m) using false nearest neighbors test + fnn <- false.nearest( series=x, m=6, d=d, t=tw, eps=sd(x), rt=10 ) + threshold <- 0.15 + plot( fnn[1,], type = 'b', main = "FNN", pch = 16, cex = 2, + xlab = 'dim', ylab = 'proportion of false neighbors' ) + abline( h = threshold, lty = 2, col = rgb(0,0,0,0.6) ) + m <- as.numeric( which( fnn[1,] <= threshold )[1] ) + if( m==2 ){ m <- 3 } + points( x = m, y = fnn[1,m], cex = 3, col = rgb(1,0,0,0.7) ) + + +# Time-delay embedding + Mx <- embedd( x, m = m, d = d ) |> as.data.frame() + +# Plot phase space reconstruction + # Rename columns + for(i in 1:m){ + if(i==1){ names(Mx)[i]<-'x(t)' + } else { + names(Mx)[i] <- paste0('x(t+',d*(i-1),')') + } + } # // end i + # Plotly + p1 <- plot_ly( Mx, x = ~Mx[,1], y = ~Mx[,2], z = ~Mx[,3], + type = 'scatter3d', mode = 'lines', + opacity = 0.75, line = list(width = 6, reverscale = FALSE) ) |> + layout( title = 'Reconstructed attractor', + scene = list( xaxis = list(title=names(Mx)[1]), + yaxis = list(title=names(Mx)[2]), + zaxis = list(title=names(Mx)[3]) + ) ) + p1 + + +# Test for nonlinear stationarity with space-time separation plots + par(mfrow=c(1,1)) + stp <- stplot( series = x, m = m, d = d, mdt = length(x) ) + + +# Export embedding outputs + embed_chl_otb_ce <- list( x = x, + t = t, + Mx = Mx, + d = d, + tw = tw, + m = m, + plot = p1 + ) + save( embed_chl_otb_ce, file = "../data/embed_chl_otb_ce.RData" ) + \ No newline at end of file diff --git a/R/embed_chl_otb_cw.R b/R/embed_chl_otb_cw.R new file mode 100644 index 0000000..746e975 --- /dev/null +++ b/R/embed_chl_otb_cw.R @@ -0,0 +1,94 @@ +# Phase space reconstruction +# Miles Medina, ECCO Scientific, 2024 +# + +rm(list=ls(all=TRUE)) + +# Load libraries + if(!require(tseriesChaos)) { install.packages('tseriesChaos') }; library(tseriesChaos) + if(!require(zoo)) { install.packages('zoo') }; library(zoo) + if(!require(plotly)) { install.packages('plotly') }; library(plotly) + if(!require(rEDM)) { install.packages('rEDM') }; library(rEDM) + +# Load data and select column + load( "../data/ssa_chl_otb_cw.RData" ) + dat <- ssa_chl_otb_cw$dat + colnames( dat ) + var <- 'signal' + x <- dat[,var] |> na.omit() + x <- scale( x ) + t <- dat$month + +# Plot the time series + par(mfrow=c(2,1)) + plot( x, type = 'l', xlab = 'time', main = "Time series x" ) + abline( v = axTicks(1), col = rgb(0,0,0,0.2) ) + abline( h = axTicks(2), col = rgb(0,0,0,0.2) ) + +# Find embedding parameters + par(mfrow=c(3,1)) + # Set embedding delay (d) using AMI function + ami <- mutual( x, lag.max = 20 ) # average mutual information function + local.d.min <- rollapply( ami, 3, function (x) which.min(x)==2 ) # local minima + d <- as.numeric( which(local.d.min==TRUE)[1] ) # first local min + points( x = d, y = ami[d+1], cex = 2, col = rgb(1,0,0,0.7) ) + d + + # Set Theiler window (tw) using ACF + ac <- acf( x, lag.max = 20 ) # autocorrelation function + ac$acf_abs <- ac$acf |> abs() # absolute values of acf + local.tw.min <- rollapply(ac$acf_abs, 3, function (x) which.min(x)==2 ) # abs local minima + tw <- as.numeric( which(local.tw.min==TRUE)[1] ) # first abs local min + points( x = tw, y = ac$acf[tw+1], cex = 2, col = rgb(1,0,0,0.7) ) + tw + + # Set embedding dimension (m) using false nearest neighbors test + fnn <- false.nearest( series=x, m=6, d=d, t=tw, eps=sd(x), rt=10 ) + threshold <- 0.15 + plot( fnn[1,], type = 'b', main = "FNN", pch = 16, cex = 2, + xlab = 'dim', ylab = 'proportion of false neighbors' ) + abline( h = threshold, lty = 2, col = rgb(0,0,0,0.6) ) + m <- as.numeric( which( fnn[1,] <= threshold )[1] ) + if( m==2 ){ m <- 3 } + points( x = m, y = fnn[1,m], cex = 3, col = rgb(1,0,0,0.7) ) + + +# Time-delay embedding + Mx <- embedd( x, m = m, d = d ) |> as.data.frame() + +# Plot phase space reconstruction + # Rename columns + for(i in 1:m){ + if(i==1){ names(Mx)[i]<-'x(t)' + } else { + names(Mx)[i] <- paste0('x(t+',d*(i-1),')') + } + } # // end i + # Plotly + p1 <- plot_ly( Mx, x = ~Mx[,1], y = ~Mx[,2], z = ~Mx[,3], + type = 'scatter3d', mode = 'lines', + opacity = 0.75, line = list(width = 6, reverscale = FALSE) ) |> + layout( title = 'Reconstructed attractor', + scene = list( xaxis = list(title=names(Mx)[1]), + yaxis = list(title=names(Mx)[2]), + zaxis = list(title=names(Mx)[3]) + ) ) + p1 + + +# Test for nonlinear stationarity with space-time separation plots + par(mfrow=c(1,1)) + stp <- stplot( series = x, m = m, d = d, mdt = length(x) ) + + +# Export embedding outputs + embed_chl_otb_cw <- list( x = x, + t = t, + Mx = Mx, + d = d, + tw = tw, + m = m, + plot = p1 + ) + save( embed_chl_otb_cw, file = "../data/embed_chl_otb_cw.RData" ) + \ No newline at end of file diff --git a/R/embed_chl_otb_ne.R b/R/embed_chl_otb_ne.R new file mode 100644 index 0000000..e7c530a --- /dev/null +++ b/R/embed_chl_otb_ne.R @@ -0,0 +1,94 @@ +# Phase space reconstruction +# Miles Medina, ECCO Scientific, 2024 +# + +rm(list=ls(all=TRUE)) + +# Load libraries + if(!require(tseriesChaos)) { install.packages('tseriesChaos') }; library(tseriesChaos) + if(!require(zoo)) { install.packages('zoo') }; library(zoo) + if(!require(plotly)) { install.packages('plotly') }; library(plotly) + if(!require(rEDM)) { install.packages('rEDM') }; library(rEDM) + +# Load data and select column + load( "../data/ssa_chl_otb_ne.RData" ) + dat <- ssa_chl_otb_ne$dat + colnames( dat ) + var <- 'signal' + x <- dat[,var] |> na.omit() + x <- scale( x ) + t <- dat$month + +# Plot the time series + par(mfrow=c(2,1)) + plot( x, type = 'l', xlab = 'time', main = "Time series x" ) + abline( v = axTicks(1), col = rgb(0,0,0,0.2) ) + abline( h = axTicks(2), col = rgb(0,0,0,0.2) ) + +# Find embedding parameters + par(mfrow=c(3,1)) + # Set embedding delay (d) using AMI function + ami <- mutual( x, lag.max = 20 ) # average mutual information function + local.d.min <- rollapply( ami, 3, function (x) which.min(x)==2 ) # local minima + d <- as.numeric( which(local.d.min==TRUE)[1] ) # first local min + points( x = d, y = ami[d+1], cex = 2, col = rgb(1,0,0,0.7) ) + d + + # Set Theiler window (tw) using ACF + ac <- acf( x, lag.max = 20 ) # autocorrelation function + ac$acf_abs <- ac$acf |> abs() # absolute values of acf + local.tw.min <- rollapply(ac$acf_abs, 3, function (x) which.min(x)==2 ) # abs local minima + tw <- as.numeric( which(local.tw.min==TRUE)[1] ) # first abs local min + points( x = tw, y = ac$acf[tw+1], cex = 2, col = rgb(1,0,0,0.7) ) + tw + + # Set embedding dimension (m) using false nearest neighbors test + fnn <- false.nearest( series=x, m=6, d=d, t=tw, eps=sd(x), rt=10 ) + threshold <- 0.15 + plot( fnn[1,], type = 'b', main = "FNN", pch = 16, cex = 2, + xlab = 'dim', ylab = 'proportion of false neighbors' ) + abline( h = threshold, lty = 2, col = rgb(0,0,0,0.6) ) + m <- as.numeric( which( fnn[1,] <= threshold )[1] ) + if( m==2 ){ m <- 3 } + points( x = m, y = fnn[1,m], cex = 3, col = rgb(1,0,0,0.7) ) + + +# Time-delay embedding + Mx <- embedd( x, m = m, d = d ) |> as.data.frame() + +# Plot phase space reconstruction + # Rename columns + for(i in 1:m){ + if(i==1){ names(Mx)[i]<-'x(t)' + } else { + names(Mx)[i] <- paste0('x(t+',d*(i-1),')') + } + } # // end i + # Plotly + p1 <- plot_ly( Mx, x = ~Mx[,1], y = ~Mx[,2], z = ~Mx[,3], + type = 'scatter3d', mode = 'lines', + opacity = 0.75, line = list(width = 6, reverscale = FALSE) ) |> + layout( title = 'Reconstructed attractor', + scene = list( xaxis = list(title=names(Mx)[1]), + yaxis = list(title=names(Mx)[2]), + zaxis = list(title=names(Mx)[3]) + ) ) + p1 + + +# Test for nonlinear stationarity with space-time separation plots + par(mfrow=c(1,1)) + stp <- stplot( series = x, m = m, d = d, mdt = length(x) ) + + +# Export embedding outputs + embed_chl_otb_ne <- list( x = x, + t = t, + Mx = Mx, + d = d, + tw = tw, + m = m, + plot = p1 + ) + save( embed_chl_otb_ne, file = "../data/embed_chl_otb_ne.RData" ) + \ No newline at end of file diff --git a/R/embed_chl_otb_nw.R b/R/embed_chl_otb_nw.R new file mode 100644 index 0000000..1cbbf09 --- /dev/null +++ b/R/embed_chl_otb_nw.R @@ -0,0 +1,94 @@ +# Phase space reconstruction +# Miles Medina, ECCO Scientific, 2024 +# + +rm(list=ls(all=TRUE)) + +# Load libraries + if(!require(tseriesChaos)) { install.packages('tseriesChaos') }; library(tseriesChaos) + if(!require(zoo)) { install.packages('zoo') }; library(zoo) + if(!require(plotly)) { install.packages('plotly') }; library(plotly) + if(!require(rEDM)) { install.packages('rEDM') }; library(rEDM) + +# Load data and select column + load( "../data/ssa_chl_otb_nw.RData" ) + dat <- ssa_chl_otb_nw$dat + colnames( dat ) + var <- 'signal' + x <- dat[,var] |> na.omit() + x <- scale( x ) + t <- dat$month + +# Plot the time series + par(mfrow=c(2,1)) + plot( x, type = 'l', xlab = 'time', main = "Time series x" ) + abline( v = axTicks(1), col = rgb(0,0,0,0.2) ) + abline( h = axTicks(2), col = rgb(0,0,0,0.2) ) + +# Find embedding parameters + par(mfrow=c(3,1)) + # Set embedding delay (d) using AMI function + ami <- mutual( x, lag.max = 20 ) # average mutual information function + local.d.min <- rollapply( ami, 3, function (x) which.min(x)==2 ) # local minima + d <- as.numeric( which(local.d.min==TRUE)[1] ) # first local min + points( x = d, y = ami[d+1], cex = 2, col = rgb(1,0,0,0.7) ) + d + + # Set Theiler window (tw) using ACF + ac <- acf( x, lag.max = 20 ) # autocorrelation function + ac$acf_abs <- ac$acf |> abs() # absolute values of acf + local.tw.min <- rollapply(ac$acf_abs, 3, function (x) which.min(x)==2 ) # abs local minima + tw <- as.numeric( which(local.tw.min==TRUE)[1] ) # first abs local min + points( x = tw, y = ac$acf[tw+1], cex = 2, col = rgb(1,0,0,0.7) ) + tw + + # Set embedding dimension (m) using false nearest neighbors test + fnn <- false.nearest( series=x, m=6, d=d, t=tw, eps=sd(x), rt=10 ) + threshold <- 0.15 + plot( fnn[1,], type = 'b', main = "FNN", pch = 16, cex = 2, + xlab = 'dim', ylab = 'proportion of false neighbors' ) + abline( h = threshold, lty = 2, col = rgb(0,0,0,0.6) ) + m <- as.numeric( which( fnn[1,] <= threshold )[1] ) + if( m==2 ){ m <- 3 } + points( x = m, y = fnn[1,m], cex = 3, col = rgb(1,0,0,0.7) ) + + +# Time-delay embedding + Mx <- embedd( x, m = m, d = d ) |> as.data.frame() + +# Plot phase space reconstruction + # Rename columns + for(i in 1:m){ + if(i==1){ names(Mx)[i]<-'x(t)' + } else { + names(Mx)[i] <- paste0('x(t+',d*(i-1),')') + } + } # // end i + # Plotly + p1 <- plot_ly( Mx, x = ~Mx[,1], y = ~Mx[,2], z = ~Mx[,3], + type = 'scatter3d', mode = 'lines', + opacity = 0.75, line = list(width = 6, reverscale = FALSE) ) |> + layout( title = 'Reconstructed attractor', + scene = list( xaxis = list(title=names(Mx)[1]), + yaxis = list(title=names(Mx)[2]), + zaxis = list(title=names(Mx)[3]) + ) ) + p1 + + +# Test for nonlinear stationarity with space-time separation plots + par(mfrow=c(1,1)) + stp <- stplot( series = x, m = m, d = d, mdt = length(x) ) + + +# Export embedding outputs + embed_chl_otb_nw <- list( x = x, + t = t, + Mx = Mx, + d = d, + tw = tw, + m = m, + plot = p1 + ) + save( embed_chl_otb_nw, file = "../data/embed_chl_otb_nw.RData" ) + \ No newline at end of file diff --git a/R/embed_chl_otb_se.R b/R/embed_chl_otb_se.R new file mode 100644 index 0000000..deebd44 --- /dev/null +++ b/R/embed_chl_otb_se.R @@ -0,0 +1,94 @@ +# Phase space reconstruction +# Miles Medina, ECCO Scientific, 2024 +# + +rm(list=ls(all=TRUE)) + +# Load libraries + if(!require(tseriesChaos)) { install.packages('tseriesChaos') }; library(tseriesChaos) + if(!require(zoo)) { install.packages('zoo') }; library(zoo) + if(!require(plotly)) { install.packages('plotly') }; library(plotly) + if(!require(rEDM)) { install.packages('rEDM') }; library(rEDM) + +# Load data and select column + load( "../data/ssa_chl_otb_se.RData" ) + dat <- ssa_chl_otb_se$dat + colnames( dat ) + var <- 'signal' + x <- dat[,var] |> na.omit() + x <- scale( x ) + t <- dat$month + +# Plot the time series + par(mfrow=c(2,1)) + plot( x, type = 'l', xlab = 'time', main = "Time series x" ) + abline( v = axTicks(1), col = rgb(0,0,0,0.2) ) + abline( h = axTicks(2), col = rgb(0,0,0,0.2) ) + +# Find embedding parameters + par(mfrow=c(3,1)) + # Set embedding delay (d) using AMI function + ami <- mutual( x, lag.max = 20 ) # average mutual information function + local.d.min <- rollapply( ami, 3, function (x) which.min(x)==2 ) # local minima + d <- as.numeric( which(local.d.min==TRUE)[1] ) # first local min + points( x = d, y = ami[d+1], cex = 2, col = rgb(1,0,0,0.7) ) + d + + # Set Theiler window (tw) using ACF + ac <- acf( x, lag.max = 20 ) # autocorrelation function + ac$acf_abs <- ac$acf |> abs() # absolute values of acf + local.tw.min <- rollapply(ac$acf_abs, 3, function (x) which.min(x)==2 ) # abs local minima + tw <- as.numeric( which(local.tw.min==TRUE)[1] ) # first abs local min + points( x = tw, y = ac$acf[tw+1], cex = 2, col = rgb(1,0,0,0.7) ) + tw + + # Set embedding dimension (m) using false nearest neighbors test + fnn <- false.nearest( series=x, m=6, d=d, t=tw, eps=sd(x), rt=10 ) + threshold <- 0.15 + plot( fnn[1,], type = 'b', main = "FNN", pch = 16, cex = 2, + xlab = 'dim', ylab = 'proportion of false neighbors' ) + abline( h = threshold, lty = 2, col = rgb(0,0,0,0.6) ) + m <- as.numeric( which( fnn[1,] <= threshold )[1] ) + if( m==2 ){ m <- 3 } + points( x = m, y = fnn[1,m], cex = 3, col = rgb(1,0,0,0.7) ) + + +# Time-delay embedding + Mx <- embedd( x, m = m, d = d ) |> as.data.frame() + +# Plot phase space reconstruction + # Rename columns + for(i in 1:m){ + if(i==1){ names(Mx)[i]<-'x(t)' + } else { + names(Mx)[i] <- paste0('x(t+',d*(i-1),')') + } + } # // end i + # Plotly + p1 <- plot_ly( Mx, x = ~Mx[,1], y = ~Mx[,2], z = ~Mx[,3], + type = 'scatter3d', mode = 'lines', + opacity = 0.75, line = list(width = 6, reverscale = FALSE) ) |> + layout( title = 'Reconstructed attractor', + scene = list( xaxis = list(title=names(Mx)[1]), + yaxis = list(title=names(Mx)[2]), + zaxis = list(title=names(Mx)[3]) + ) ) + p1 + + +# Test for nonlinear stationarity with space-time separation plots + par(mfrow=c(1,1)) + stp <- stplot( series = x, m = m, d = d, mdt = length(x) ) + + +# Export embedding outputs + embed_chl_otb_se <- list( x = x, + t = t, + Mx = Mx, + d = d, + tw = tw, + m = m, + plot = p1 + ) + save( embed_chl_otb_se, file = "../data/embed_chl_otb_se.RData" ) + \ No newline at end of file diff --git a/R/embed_chl_otb_sw.R b/R/embed_chl_otb_sw.R new file mode 100644 index 0000000..006d5a9 --- /dev/null +++ b/R/embed_chl_otb_sw.R @@ -0,0 +1,94 @@ +# Phase space reconstruction +# Miles Medina, ECCO Scientific, 2024 +# + +rm(list=ls(all=TRUE)) + +# Load libraries + if(!require(tseriesChaos)) { install.packages('tseriesChaos') }; library(tseriesChaos) + if(!require(zoo)) { install.packages('zoo') }; library(zoo) + if(!require(plotly)) { install.packages('plotly') }; library(plotly) + if(!require(rEDM)) { install.packages('rEDM') }; library(rEDM) + +# Load data and select column + load( "../data/ssa_chl_otb_sw.RData" ) + dat <- ssa_chl_otb_sw$dat + colnames( dat ) + var <- 'signal' + x <- dat[,var] |> na.omit() + x <- scale( x ) + t <- dat$month + +# Plot the time series + par(mfrow=c(2,1)) + plot( x, type = 'l', xlab = 'time', main = "Time series x" ) + abline( v = axTicks(1), col = rgb(0,0,0,0.2) ) + abline( h = axTicks(2), col = rgb(0,0,0,0.2) ) + +# Find embedding parameters + par(mfrow=c(3,1)) + # Set embedding delay (d) using AMI function + ami <- mutual( x, lag.max = 20 ) # average mutual information function + local.d.min <- rollapply( ami, 3, function (x) which.min(x)==2 ) # local minima + d <- as.numeric( which(local.d.min==TRUE)[1] ) # first local min + points( x = d, y = ami[d+1], cex = 2, col = rgb(1,0,0,0.7) ) + d + + # Set Theiler window (tw) using ACF + ac <- acf( x, lag.max = 20 ) # autocorrelation function + ac$acf_abs <- ac$acf |> abs() # absolute values of acf + local.tw.min <- rollapply(ac$acf_abs, 3, function (x) which.min(x)==2 ) # abs local minima + tw <- as.numeric( which(local.tw.min==TRUE)[1] ) # first abs local min + points( x = tw, y = ac$acf[tw+1], cex = 2, col = rgb(1,0,0,0.7) ) + tw + + # Set embedding dimension (m) using false nearest neighbors test + fnn <- false.nearest( series=x, m=6, d=d, t=tw, eps=sd(x), rt=10 ) + threshold <- 0.15 + plot( fnn[1,], type = 'b', main = "FNN", pch = 16, cex = 2, + xlab = 'dim', ylab = 'proportion of false neighbors' ) + abline( h = threshold, lty = 2, col = rgb(0,0,0,0.6) ) + m <- as.numeric( which( fnn[1,] <= threshold )[1] ) + if( m==2 ){ m <- 3 } + points( x = m, y = fnn[1,m], cex = 3, col = rgb(1,0,0,0.7) ) + + +# Time-delay embedding + Mx <- embedd( x, m = m, d = d ) |> as.data.frame() + +# Plot phase space reconstruction + # Rename columns + for(i in 1:m){ + if(i==1){ names(Mx)[i]<-'x(t)' + } else { + names(Mx)[i] <- paste0('x(t+',d*(i-1),')') + } + } # // end i + # Plotly + p1 <- plot_ly( Mx, x = ~Mx[,1], y = ~Mx[,2], z = ~Mx[,3], + type = 'scatter3d', mode = 'lines', + opacity = 0.75, line = list(width = 6, reverscale = FALSE) ) |> + layout( title = 'Reconstructed attractor', + scene = list( xaxis = list(title=names(Mx)[1]), + yaxis = list(title=names(Mx)[2]), + zaxis = list(title=names(Mx)[3]) + ) ) + p1 + + +# Test for nonlinear stationarity with space-time separation plots + par(mfrow=c(1,1)) + stp <- stplot( series = x, m = m, d = d, mdt = length(x) ) + + +# Export embedding outputs + embed_chl_otb_sw <- list( x = x, + t = t, + Mx = Mx, + d = d, + tw = tw, + m = m, + plot = p1 + ) + save( embed_chl_otb_sw, file = "../data/embed_chl_otb_sw.RData" ) + \ No newline at end of file diff --git a/R/embed_pyro_otb-ce.R b/R/embed_pyro_otb-ce.R new file mode 100644 index 0000000..7d4e911 --- /dev/null +++ b/R/embed_pyro_otb-ce.R @@ -0,0 +1,94 @@ +# Phase space reconstruction +# Miles Medina, ECCO Scientific, 2024 +# + +rm(list=ls(all=TRUE)) + +# Load libraries + if(!require(tseriesChaos)) { install.packages('tseriesChaos') }; library(tseriesChaos) + if(!require(zoo)) { install.packages('zoo') }; library(zoo) + if(!require(plotly)) { install.packages('plotly') }; library(plotly) + if(!require(rEDM)) { install.packages('rEDM') }; library(rEDM) + +# Load data and select column + load( "../data/ssa_pyro_otb_ce.RData" ) + dat <- ssa_pyro_otb_ce$dat + colnames( dat ) + var <- 'signal' + x <- dat[,var] |> na.omit() + x <- scale( x ) + t <- dat$month + +# Plot the time series + par(mfrow=c(2,1)) + plot( x, type = 'l', xlab = 'time', main = "Time series x" ) + abline( v = axTicks(1), col = rgb(0,0,0,0.2) ) + abline( h = axTicks(2), col = rgb(0,0,0,0.2) ) + +# Find embedding parameters + par(mfrow=c(3,1)) + # Set embedding delay (d) using AMI function + ami <- mutual( x, lag.max = 20 ) # average mutual information function + local.d.min <- rollapply( ami, 3, function (x) which.min(x)==2 ) # local minima + d <- as.numeric( which(local.d.min==TRUE)[1] ) # first local min + points( x = d, y = ami[d+1], cex = 2, col = rgb(1,0,0,0.7) ) + d + + # Set Theiler window (tw) using ACF + ac <- acf( x, lag.max = 20 ) # autocorrelation function + ac$acf_abs <- ac$acf |> abs() # absolute values of acf + local.tw.min <- rollapply(ac$acf_abs, 3, function (x) which.min(x)==2 ) # abs local minima + tw <- as.numeric( which(local.tw.min==TRUE)[1] ) # first abs local min + points( x = tw, y = ac$acf[tw+1], cex = 2, col = rgb(1,0,0,0.7) ) + tw + + # Set embedding dimension (m) using false nearest neighbors test + fnn <- false.nearest( series=x, m=6, d=d, t=tw, eps=sd(x), rt=10 ) + threshold <- 0.15 + plot( fnn[1,], type = 'b', main = "FNN", pch = 16, cex = 2, + xlab = 'dim', ylab = 'proportion of false neighbors' ) + abline( h = threshold, lty = 2, col = rgb(0,0,0,0.6) ) + m <- as.numeric( which( fnn[1,] <= threshold )[1] ) + if( m==2 ){ m <- 3 } + points( x = m, y = fnn[1,m], cex = 3, col = rgb(1,0,0,0.7) ) + + +# Time-delay embedding + Mx <- embedd( x, m = m, d = d ) |> as.data.frame() + +# Plot phase space reconstruction + # Rename columns + for(i in 1:m){ + if(i==1){ names(Mx)[i]<-'x(t)' + } else { + names(Mx)[i] <- paste0('x(t+',d*(i-1),')') + } + } # // end i + # Plotly + p1 <- plot_ly( Mx, x = ~Mx[,1], y = ~Mx[,2], z = ~Mx[,3], + type = 'scatter3d', mode = 'lines', + opacity = 0.75, line = list(width = 6, reverscale = FALSE) ) |> + layout( title = 'Reconstructed attractor', + scene = list( xaxis = list(title=names(Mx)[1]), + yaxis = list(title=names(Mx)[2]), + zaxis = list(title=names(Mx)[3]) + ) ) + p1 + + +# Test for nonlinear stationarity with space-time separation plots + par(mfrow=c(1,1)) + stp <- stplot( series = x, m = m, d = d, mdt = length(x) ) + + +# Export embedding outputs + embed_pyro_otb_ce <- list( x = x, + t = t, + Mx = Mx, + d = d, + tw = tw, + m = m, + plot = p1 + ) + save( embed_pyro_otb_ce, file = "../data/embed_pyro_otb_ce.RData" ) + \ No newline at end of file diff --git a/R/embed_pyro_otb-cw.R b/R/embed_pyro_otb-cw.R new file mode 100644 index 0000000..498b0b1 --- /dev/null +++ b/R/embed_pyro_otb-cw.R @@ -0,0 +1,94 @@ +# Phase space reconstruction +# Miles Medina, ECCO Scientific, 2024 +# + +rm(list=ls(all=TRUE)) + +# Load libraries + if(!require(tseriesChaos)) { install.packages('tseriesChaos') }; library(tseriesChaos) + if(!require(zoo)) { install.packages('zoo') }; library(zoo) + if(!require(plotly)) { install.packages('plotly') }; library(plotly) + if(!require(rEDM)) { install.packages('rEDM') }; library(rEDM) + +# Load data and select column + load( "../data/ssa_pyro_otb_cw.RData" ) + dat <- ssa_pyro_otb_cw$dat + colnames( dat ) + var <- 'signal' + x <- dat[,var] |> na.omit() + x <- scale( x ) + t <- dat$month + +# Plot the time series + par(mfrow=c(2,1)) + plot( x, type = 'l', xlab = 'time', main = "Time series x" ) + abline( v = axTicks(1), col = rgb(0,0,0,0.2) ) + abline( h = axTicks(2), col = rgb(0,0,0,0.2) ) + +# Find embedding parameters + par(mfrow=c(3,1)) + # Set embedding delay (d) using AMI function + ami <- mutual( x, lag.max = 20 ) # average mutual information function + local.d.min <- rollapply( ami, 3, function (x) which.min(x)==2 ) # local minima + d <- as.numeric( which(local.d.min==TRUE)[1] ) # first local min + points( x = d, y = ami[d+1], cex = 2, col = rgb(1,0,0,0.7) ) + d + + # Set Theiler window (tw) using ACF + ac <- acf( x, lag.max = 20 ) # autocorrelation function + ac$acf_abs <- ac$acf |> abs() # absolute values of acf + local.tw.min <- rollapply(ac$acf_abs, 3, function (x) which.min(x)==2 ) # abs local minima + tw <- as.numeric( which(local.tw.min==TRUE)[1] ) # first abs local min + points( x = tw, y = ac$acf[tw+1], cex = 2, col = rgb(1,0,0,0.7) ) + tw + + # Set embedding dimension (m) using false nearest neighbors test + fnn <- false.nearest( series=x, m=6, d=d, t=tw, eps=sd(x), rt=10 ) + threshold <- 0.15 + plot( fnn[1,], type = 'b', main = "FNN", pch = 16, cex = 2, + xlab = 'dim', ylab = 'proportion of false neighbors' ) + abline( h = threshold, lty = 2, col = rgb(0,0,0,0.6) ) + m <- as.numeric( which( fnn[1,] <= threshold )[1] ) + if( m==2 ){ m <- 3 } + points( x = m, y = fnn[1,m], cex = 3, col = rgb(1,0,0,0.7) ) + + +# Time-delay embedding + Mx <- embedd( x, m = m, d = d ) |> as.data.frame() + +# Plot phase space reconstruction + # Rename columns + for(i in 1:m){ + if(i==1){ names(Mx)[i]<-'x(t)' + } else { + names(Mx)[i] <- paste0('x(t+',d*(i-1),')') + } + } # // end i + # Plotly + p1 <- plot_ly( Mx, x = ~Mx[,1], y = ~Mx[,2], z = ~Mx[,3], + type = 'scatter3d', mode = 'lines', + opacity = 0.75, line = list(width = 6, reverscale = FALSE) ) |> + layout( title = 'Reconstructed attractor', + scene = list( xaxis = list(title=names(Mx)[1]), + yaxis = list(title=names(Mx)[2]), + zaxis = list(title=names(Mx)[3]) + ) ) + p1 + + +# Test for nonlinear stationarity with space-time separation plots + par(mfrow=c(1,1)) + stp <- stplot( series = x, m = m, d = d, mdt = length(x) ) + + +# Export embedding outputs + embed_pyro_otb_cw <- list( x = x, + t = t, + Mx = Mx, + d = d, + tw = tw, + m = m, + plot = p1 + ) + save( embed_pyro_otb_cw, file = "../data/embed_pyro_otb_cw.RData" ) + \ No newline at end of file diff --git a/R/embed_pyro_otb-ne.R b/R/embed_pyro_otb-ne.R new file mode 100644 index 0000000..1b3d3c5 --- /dev/null +++ b/R/embed_pyro_otb-ne.R @@ -0,0 +1,94 @@ +# Phase space reconstruction +# Miles Medina, ECCO Scientific, 2024 +# + +rm(list=ls(all=TRUE)) + +# Load libraries + if(!require(tseriesChaos)) { install.packages('tseriesChaos') }; library(tseriesChaos) + if(!require(zoo)) { install.packages('zoo') }; library(zoo) + if(!require(plotly)) { install.packages('plotly') }; library(plotly) + if(!require(rEDM)) { install.packages('rEDM') }; library(rEDM) + +# Load data and select column + load( "../data/ssa_pyro_otb_ne.RData" ) + dat <- ssa_pyro_otb_ne$dat + colnames( dat ) + var <- 'signal' + x <- dat[,var] |> na.omit() + x <- scale( x ) + t <- dat$month + +# Plot the time series + par(mfrow=c(2,1)) + plot( x, type = 'l', xlab = 'time', main = "Time series x" ) + abline( v = axTicks(1), col = rgb(0,0,0,0.2) ) + abline( h = axTicks(2), col = rgb(0,0,0,0.2) ) + +# Find embedding parameters + par(mfrow=c(3,1)) + # Set embedding delay (d) using AMI function + ami <- mutual( x, lag.max = 20 ) # average mutual information function + local.d.min <- rollapply( ami, 3, function (x) which.min(x)==2 ) # local minima + d <- as.numeric( which(local.d.min==TRUE)[1] ) # first local min + points( x = d, y = ami[d+1], cex = 2, col = rgb(1,0,0,0.7) ) + d + + # Set Theiler window (tw) using ACF + ac <- acf( x, lag.max = 20 ) # autocorrelation function + ac$acf_abs <- ac$acf |> abs() # absolute values of acf + local.tw.min <- rollapply(ac$acf_abs, 3, function (x) which.min(x)==2 ) # abs local minima + tw <- as.numeric( which(local.tw.min==TRUE)[1] ) # first abs local min + points( x = tw, y = ac$acf[tw+1], cex = 2, col = rgb(1,0,0,0.7) ) + tw + + # Set embedding dimension (m) using false nearest neighbors test + fnn <- false.nearest( series=x, m=6, d=d, t=tw, eps=sd(x), rt=10 ) + threshold <- 0.15 + plot( fnn[1,], type = 'b', main = "FNN", pch = 16, cex = 2, + xlab = 'dim', ylab = 'proportion of false neighbors' ) + abline( h = threshold, lty = 2, col = rgb(0,0,0,0.6) ) + m <- as.numeric( which( fnn[1,] <= threshold )[1] ) + if( m==2 ){ m <- 3 } + points( x = m, y = fnn[1,m], cex = 3, col = rgb(1,0,0,0.7) ) + + +# Time-delay embedding + Mx <- embedd( x, m = m, d = d ) |> as.data.frame() + +# Plot phase space reconstruction + # Rename columns + for(i in 1:m){ + if(i==1){ names(Mx)[i]<-'x(t)' + } else { + names(Mx)[i] <- paste0('x(t+',d*(i-1),')') + } + } # // end i + # Plotly + p1 <- plot_ly( Mx, x = ~Mx[,1], y = ~Mx[,2], z = ~Mx[,3], + type = 'scatter3d', mode = 'lines', + opacity = 0.75, line = list(width = 6, reverscale = FALSE) ) |> + layout( title = 'Reconstructed attractor', + scene = list( xaxis = list(title=names(Mx)[1]), + yaxis = list(title=names(Mx)[2]), + zaxis = list(title=names(Mx)[3]) + ) ) + p1 + + +# Test for nonlinear stationarity with space-time separation plots + par(mfrow=c(1,1)) + stp <- stplot( series = x, m = m, d = d, mdt = length(x) ) + + +# Export embedding outputs + embed_pyro_otb_ne <- list( x = x, + t = t, + Mx = Mx, + d = d, + tw = tw, + m = m, + plot = p1 + ) + save( embed_pyro_otb_ne, file = "../data/embed_pyro_otb_ne.RData" ) + \ No newline at end of file diff --git a/R/embed_pyro_otb-nw.R b/R/embed_pyro_otb-nw.R new file mode 100644 index 0000000..e1d84f9 --- /dev/null +++ b/R/embed_pyro_otb-nw.R @@ -0,0 +1,94 @@ +# Phase space reconstruction +# Miles Medina, ECCO Scientific, 2024 +# + +rm(list=ls(all=TRUE)) + +# Load libraries + if(!require(tseriesChaos)) { install.packages('tseriesChaos') }; library(tseriesChaos) + if(!require(zoo)) { install.packages('zoo') }; library(zoo) + if(!require(plotly)) { install.packages('plotly') }; library(plotly) + if(!require(rEDM)) { install.packages('rEDM') }; library(rEDM) + +# Load data and select column + load( "../data/ssa_pyro_otb_nw.RData" ) + dat <- ssa_pyro_otb_nw$dat + colnames( dat ) + var <- 'signal' + x <- dat[,var] |> na.omit() + x <- scale( x ) + t <- dat$month + +# Plot the time series + par(mfrow=c(2,1)) + plot( x, type = 'l', xlab = 'time', main = "Time series x" ) + abline( v = axTicks(1), col = rgb(0,0,0,0.2) ) + abline( h = axTicks(2), col = rgb(0,0,0,0.2) ) + +# Find embedding parameters + par(mfrow=c(3,1)) + # Set embedding delay (d) using AMI function + ami <- mutual( x, lag.max = 20 ) # average mutual information function + local.d.min <- rollapply( ami, 3, function (x) which.min(x)==2 ) # local minima + d <- as.numeric( which(local.d.min==TRUE)[1] ) # first local min + points( x = d, y = ami[d+1], cex = 2, col = rgb(1,0,0,0.7) ) + d + + # Set Theiler window (tw) using ACF + ac <- acf( x, lag.max = 20 ) # autocorrelation function + ac$acf_abs <- ac$acf |> abs() # absolute values of acf + local.tw.min <- rollapply(ac$acf_abs, 3, function (x) which.min(x)==2 ) # abs local minima + tw <- as.numeric( which(local.tw.min==TRUE)[1] ) # first abs local min + points( x = tw, y = ac$acf[tw+1], cex = 2, col = rgb(1,0,0,0.7) ) + tw + + # Set embedding dimension (m) using false nearest neighbors test + fnn <- false.nearest( series=x, m=6, d=d, t=tw, eps=sd(x), rt=10 ) + threshold <- 0.15 + plot( fnn[1,], type = 'b', main = "FNN", pch = 16, cex = 2, + xlab = 'dim', ylab = 'proportion of false neighbors' ) + abline( h = threshold, lty = 2, col = rgb(0,0,0,0.6) ) + m <- as.numeric( which( fnn[1,] <= threshold )[1] ) + if( m==2 ){ m <- 3 } + points( x = m, y = fnn[1,m], cex = 3, col = rgb(1,0,0,0.7) ) + + +# Time-delay embedding + Mx <- embedd( x, m = m, d = d ) |> as.data.frame() + +# Plot phase space reconstruction + # Rename columns + for(i in 1:m){ + if(i==1){ names(Mx)[i]<-'x(t)' + } else { + names(Mx)[i] <- paste0('x(t+',d*(i-1),')') + } + } # // end i + # Plotly + p1 <- plot_ly( Mx, x = ~Mx[,1], y = ~Mx[,2], z = ~Mx[,3], + type = 'scatter3d', mode = 'lines', + opacity = 0.75, line = list(width = 6, reverscale = FALSE) ) |> + layout( title = 'Reconstructed attractor', + scene = list( xaxis = list(title=names(Mx)[1]), + yaxis = list(title=names(Mx)[2]), + zaxis = list(title=names(Mx)[3]) + ) ) + p1 + + +# Test for nonlinear stationarity with space-time separation plots + par(mfrow=c(1,1)) + stp <- stplot( series = x, m = m, d = d, mdt = length(x) ) + + +# Export embedding outputs + embed_pyro_otb_nw <- list( x = x, + t = t, + Mx = Mx, + d = d, + tw = tw, + m = m, + plot = p1 + ) + save( embed_pyro_otb_nw, file = "../data/embed_pyro_otb_nw.RData" ) + \ No newline at end of file diff --git a/R/embed_pyro_otb-se.R b/R/embed_pyro_otb-se.R new file mode 100644 index 0000000..c7e7c0f --- /dev/null +++ b/R/embed_pyro_otb-se.R @@ -0,0 +1,94 @@ +# Phase space reconstruction +# Miles Medina, ECCO Scientific, 2024 +# + +rm(list=ls(all=TRUE)) + +# Load libraries + if(!require(tseriesChaos)) { install.packages('tseriesChaos') }; library(tseriesChaos) + if(!require(zoo)) { install.packages('zoo') }; library(zoo) + if(!require(plotly)) { install.packages('plotly') }; library(plotly) + if(!require(rEDM)) { install.packages('rEDM') }; library(rEDM) + +# Load data and select column + load( "../data/ssa_pyro_otb_se.RData" ) + dat <- ssa_pyro_otb_se$dat + colnames( dat ) + var <- 'signal' + x <- dat[,var] |> na.omit() + x <- scale( x ) + t <- dat$month + +# Plot the time series + par(mfrow=c(2,1)) + plot( x, type = 'l', xlab = 'time', main = "Time series x" ) + abline( v = axTicks(1), col = rgb(0,0,0,0.2) ) + abline( h = axTicks(2), col = rgb(0,0,0,0.2) ) + +# Find embedding parameters + par(mfrow=c(3,1)) + # Set embedding delay (d) using AMI function + ami <- mutual( x, lag.max = 20 ) # average mutual information function + local.d.min <- rollapply( ami, 3, function (x) which.min(x)==2 ) # local minima + d <- as.numeric( which(local.d.min==TRUE)[1] ) # first local min + points( x = d, y = ami[d+1], cex = 2, col = rgb(1,0,0,0.7) ) + d + + # Set Theiler window (tw) using ACF + ac <- acf( x, lag.max = 20 ) # autocorrelation function + ac$acf_abs <- ac$acf |> abs() # absolute values of acf + local.tw.min <- rollapply(ac$acf_abs, 3, function (x) which.min(x)==2 ) # abs local minima + tw <- as.numeric( which(local.tw.min==TRUE)[1] ) # first abs local min + points( x = tw, y = ac$acf[tw+1], cex = 2, col = rgb(1,0,0,0.7) ) + tw + + # Set embedding dimension (m) using false nearest neighbors test + fnn <- false.nearest( series=x, m=6, d=d, t=tw, eps=sd(x), rt=10 ) + threshold <- 0.15 + plot( fnn[1,], type = 'b', main = "FNN", pch = 16, cex = 2, + xlab = 'dim', ylab = 'proportion of false neighbors' ) + abline( h = threshold, lty = 2, col = rgb(0,0,0,0.6) ) + m <- as.numeric( which( fnn[1,] <= threshold )[1] ) + if( m==2 ){ m <- 3 } + points( x = m, y = fnn[1,m], cex = 3, col = rgb(1,0,0,0.7) ) + + +# Time-delay embedding + Mx <- embedd( x, m = m, d = d ) |> as.data.frame() + +# Plot phase space reconstruction + # Rename columns + for(i in 1:m){ + if(i==1){ names(Mx)[i]<-'x(t)' + } else { + names(Mx)[i] <- paste0('x(t+',d*(i-1),')') + } + } # // end i + # Plotly + p1 <- plot_ly( Mx, x = ~Mx[,1], y = ~Mx[,2], z = ~Mx[,3], + type = 'scatter3d', mode = 'lines', + opacity = 0.75, line = list(width = 6, reverscale = FALSE) ) |> + layout( title = 'Reconstructed attractor', + scene = list( xaxis = list(title=names(Mx)[1]), + yaxis = list(title=names(Mx)[2]), + zaxis = list(title=names(Mx)[3]) + ) ) + p1 + + +# Test for nonlinear stationarity with space-time separation plots + par(mfrow=c(1,1)) + stp <- stplot( series = x, m = m, d = d, mdt = length(x) ) + + +# Export embedding outputs + embed_pyro_otb_se <- list( x = x, + t = t, + Mx = Mx, + d = d, + tw = tw, + m = m, + plot = p1 + ) + save( embed_pyro_otb_se, file = "../data/embed_pyro_otb_se.RData" ) + \ No newline at end of file diff --git a/R/embed_pyro_otb-sw.R b/R/embed_pyro_otb-sw.R new file mode 100644 index 0000000..1cdce21 --- /dev/null +++ b/R/embed_pyro_otb-sw.R @@ -0,0 +1,94 @@ +# Phase space reconstruction +# Miles Medina, ECCO Scientific, 2024 +# + +rm(list=ls(all=TRUE)) + +# Load libraries + if(!require(tseriesChaos)) { install.packages('tseriesChaos') }; library(tseriesChaos) + if(!require(zoo)) { install.packages('zoo') }; library(zoo) + if(!require(plotly)) { install.packages('plotly') }; library(plotly) + if(!require(rEDM)) { install.packages('rEDM') }; library(rEDM) + +# Load data and select column + load( "../data/ssa_pyro_otb_sw.RData" ) + dat <- ssa_pyro_otb_sw$dat + colnames( dat ) + var <- 'signal' + x <- dat[,var] |> na.omit() + x <- scale( x ) + t <- dat$month + +# Plot the time series + par(mfrow=c(2,1)) + plot( x, type = 'l', xlab = 'time', main = "Time series x" ) + abline( v = axTicks(1), col = rgb(0,0,0,0.2) ) + abline( h = axTicks(2), col = rgb(0,0,0,0.2) ) + +# Find embedding parameters + par(mfrow=c(3,1)) + # Set embedding delay (d) using AMI function + ami <- mutual( x, lag.max = 20 ) # average mutual information function + local.d.min <- rollapply( ami, 3, function (x) which.min(x)==2 ) # local minima + d <- as.numeric( which(local.d.min==TRUE)[1] ) # first local min + points( x = d, y = ami[d+1], cex = 2, col = rgb(1,0,0,0.7) ) + d + + # Set Theiler window (tw) using ACF + ac <- acf( x, lag.max = 20 ) # autocorrelation function + ac$acf_abs <- ac$acf |> abs() # absolute values of acf + local.tw.min <- rollapply(ac$acf_abs, 3, function (x) which.min(x)==2 ) # abs local minima + tw <- as.numeric( which(local.tw.min==TRUE)[1] ) # first abs local min + points( x = tw, y = ac$acf[tw+1], cex = 2, col = rgb(1,0,0,0.7) ) + tw + + # Set embedding dimension (m) using false nearest neighbors test + fnn <- false.nearest( series=x, m=6, d=d, t=tw, eps=sd(x), rt=10 ) + threshold <- 0.15 + plot( fnn[1,], type = 'b', main = "FNN", pch = 16, cex = 2, + xlab = 'dim', ylab = 'proportion of false neighbors' ) + abline( h = threshold, lty = 2, col = rgb(0,0,0,0.6) ) + m <- as.numeric( which( fnn[1,] <= threshold )[1] ) + if( m==2 ){ m <- 3 } + points( x = m, y = fnn[1,m], cex = 3, col = rgb(1,0,0,0.7) ) + + +# Time-delay embedding + Mx <- embedd( x, m = m, d = d ) |> as.data.frame() + +# Plot phase space reconstruction + # Rename columns + for(i in 1:m){ + if(i==1){ names(Mx)[i]<-'x(t)' + } else { + names(Mx)[i] <- paste0('x(t+',d*(i-1),')') + } + } # // end i + # Plotly + p1 <- plot_ly( Mx, x = ~Mx[,1], y = ~Mx[,2], z = ~Mx[,3], + type = 'scatter3d', mode = 'lines', + opacity = 0.75, line = list(width = 6, reverscale = FALSE) ) |> + layout( title = 'Reconstructed attractor', + scene = list( xaxis = list(title=names(Mx)[1]), + yaxis = list(title=names(Mx)[2]), + zaxis = list(title=names(Mx)[3]) + ) ) + p1 + + +# Test for nonlinear stationarity with space-time separation plots + par(mfrow=c(1,1)) + stp <- stplot( series = x, m = m, d = d, mdt = length(x) ) + + +# Export embedding outputs + embed_pyro_otb_sw <- list( x = x, + t = t, + Mx = Mx, + d = d, + tw = tw, + m = m, + plot = p1 + ) + save( embed_pyro_otb_sw, file = "../data/embed_pyro_otb_sw.RData" ) + \ No newline at end of file diff --git a/data/embed_chl_otb.RData b/data/embed_chl_otb.RData new file mode 100644 index 0000000000000000000000000000000000000000..0a0354e37100cbb72879b6f3aad55b490d5450f3 GIT binary patch literal 5717 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 literal 0 HcmV?d00001 diff --git a/data/embed_chl_otb_ce.RData b/data/embed_chl_otb_ce.RData new file mode 100644 index 0000000000000000000000000000000000000000..124d9dd59c62ef7c8ec060f4e6e5f3e534416d4e GIT binary patch literal 5722 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 P%)MUt%$;g79^QWeP-aUK literal 0 HcmV?d00001 diff --git a/data/embed_chl_otb_ne.RData b/data/embed_chl_otb_ne.RData new file mode 100644 index 0000000000000000000000000000000000000000..4f8b6fd897c9a66583f1e615043e60cb3b464874 GIT binary patch literal 5723 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 literal 0 HcmV?d00001 diff --git a/data/embed_chl_otb_nw.RData b/data/embed_chl_otb_nw.RData new file mode 100644 index 0000000000000000000000000000000000000000..45ee217bdbf2c42bf406c3e178b3a216a0b77986 GIT binary patch literal 5722 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 C>qzPV literal 0 HcmV?d00001 diff --git a/data/embed_chl_otb_se.RData b/data/embed_chl_otb_se.RData new file mode 100644 index 0000000000000000000000000000000000000000..779d25c6381fce29e50e97824993b48055bd8457 GIT binary patch literal 5716 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%0AHbqr9n>ye^>T#m#vm$5G-w1;ym;u z8Pv^`wDuqU{;z5OjC2F)u9K+!PdR)3xyh^R-x5haF5PFj1c~DU6S1oUE(;K46qAGx zakmcC960Vsb}G%v=ZYExDiMm6>-0oW7`*E3qk^ZZ=Les$$wvkEpOW_}{@=JEfqJo? zM4k-vuI#-ow#~^zu(Wjvk!7`=6L=b{)PT@`pTqy-Vbt~4@+a7(+xg$1p(cgrO)@dS z`Qk^wDb&+*T2Tj*s=?vcwOS*XU4P?tbhWae?^Z+-)bpLF&Ny}#d38wkz;$riK7TWN za9RNGcwux1pEd4nmRzE%$c`A>)#A2Udyts95}m(|WvI140sMyeFB=RiiO1C^cE-1> zX*Coe#_>s#KvXSpekRh^O{}QJQqu!@7jd8`SHKN^Nv$bUL@3*(%up0D@&y_o>}M+3 z9)bn`$=~(jDQH7yFO{~m_GHU}G)^QE{mb+fuQn5&P`WrH)w`Dy3re`~YSyTLUX5$S z4&-&@7i-EKLvHer=G#o$i_sCxt79rL3BbUcAY4yplC&(4&hw$urFaEMf8tnZ`qjR_UH`4U^A#ee^GRf< zKTyno3^+-={=A9en^B>p_^fU|{e!Z>qZ7NOplQau_m>YJ7>6S{y0urmM!GN0-pFA% zi~28DXl(Z55PcT$!3!qOqdw9!(^IW3{rqVS0%JC$%rXVEQCtQrQv{SzMtQUC4J}dQ zK+HzRbBpG8U;R0tz`BxzRhW3t`Zd|enY{opOt=tx$xa}Zd?)T@6hlDIwG4YucJH}7 z<71+q$gxbndu6B*>A>NTk4I#`$+DDdSq*L3*J+%vXNSX{k)_d$IF%;yr(}eh=$F)VQfMAX*K?| zH1rvaS~y^Qq9ix5vpR8PR&}P^E(-RW&Mn(L<91&%)#s9&SZ0|<{j&H}^XvMju2&yd zIAg4dSM>3L25)Z#QFe&|#`p7mq>Z1P7rOJraAu~b7)nSp3V$@sMcpa4hxc!YPj%(( zMIJzm_6dxH9})p4qfeHV8W4q@^Oq0y7kev9s`E$st@bc(FWzr|0dL)`Qw0Lg>4KOi z0*lRrcw6I$D55lG0Y54tnclE35Pj9CP~=D-%*}4{PgNQIPN`+|x}vFmqdFBS78UbhW#c)-ZAx)rU}?T__bf(Bn7t}4u!V7y~;@_e!4Mqp$J zjBZ6@R~8G>@O&|#7#4#!YBF(h8rh`Vl6eXP-z-!&#vI^9*&vy|wANCLkzl)YKAIz!MhXeB^$3TRJGPX46iCPt{=a(M2%N9jYw{bg9_ zgI=i<2RziNys-$uR9gefu0Cz)jB;Av-&vpBYj?6k9TZO!>BDV1pZ$$a6M+})KBl=T zFuY^SRlIxH7`>vFt&yfu=F!XG5r@5UtR!}pbshcl;ZPfyW&2&Fl+~g)3wkA!e<7Uj zJsbgV*&j=IaV9!v2@||4ZeCx_d9(dqTvhc0>#R+5+yvsh-WkWF7#Ax>ql695;bh(N z+O;Y-P5%wPM5|ztAS%Y8I$g!NdCe~x%x2pW{^vkO?d#o)qpGGxRj;~8WY;Uhf_O0B zHeR$1i71IOIMaRs*)LcPbIs9=kvFlI5|?;n*z6)k1m)i9`<7w$WiEr6x)nw2y$pe( Qk*5f^N^hIGWHhw@0x1I|cmMzZ literal 0 HcmV?d00001