I'm working from the following example and failing miserably
# initialize the attractor
n = 1500
dt = 0.02
σ, ρ, β = 10., 28., 8/3
x, y, z = 1., 1., 1.
# initialize a 3D plot with 1 empty series
plt = path3d(1, xlim=(-25,25), ylim=(-25,25), zlim=(0,50),
xlab = "x", ylab = "y", zlab = "z",
title = "Lorenz Attractor", marker = 1)
# build an animated gif, saving every 10th frame
#gif for i=1:n
dx = σ*(y - x) ; x += dt * dx
dy = x*(ρ - z) - y ; y += dt * dy
dz = x*y - β*z ; z += dt * dz
push!(plt, x, y, z)
end every 10
I have simulations in which I want to calculate and plot a histogram every so often, and then animate all those histograms. This is what I have so far as a toy example:
using Distributions
using Plots
Plots.gr()
p = rand(Normal(0,1), 10000)
myplot = Plots. histogram(p)
savefig("initial.png")
anim = #animate for i=1:10
p = rand(Normal(0,1), 10000)
push!(myplot, Plots.histogram(p))
end
gif(anim, "mygif.gif", fps = 1)
As you can probably tell, I don't really get how this #animate thing works and am just guessing at the syntax here. I know that I could save a bunch of PNGs and later animate, but I want to try it this way.
anim = #animate for i=1:10
p = rand(Normal(0,1), 10000)
histogram(p)
end
gif(anim, "mygif.gif", fps = 1)
should work.
Related
I am attempting to map a panoramic image into polar coordinates using imageR, but get strange results.
As an example, I would like to take a square panorama like this one (courtesy of Flickr user gadl (Alexandre Duret-Lutz) under CC BY-NC-SA and edited into a square):
And remap it to something like this (which I've done in GIMP):
I've gotten pretty close in imageR with this code:
library(imager)
pano <- mirror(load.image("pano_image.jpg"), "y") # mirroring the image to map to center
map.shift <- function(x,y) list(x = y*cos(x), y = y*sin(x)) # Here, y is the radius and x is theta
polar_pano <- imwarp(pano, map = map.shift)
plot(polar_pano)
But I get the strange result:
I'm not sure why it is only mapping into one quadrant? (Note: I realize that the interpolation will be strange in this example--that is not the issue).
To confirm that this should work, here is a toy example:
library(ggplot)
test <- data.frame("val" = rep(100:1, each = 99), theta = rep(1:100, 99), r = rep(1:100, each = 99))
ggplot(test, aes(x = theta, y = r, col = val)) + geom_point()
# Now converting from polar to cartesian
test$x <- test$r*cos(test$theta)
test$y <- test$r*sin(teast$theta)
ggplot(test_p2c, aes(x = x, y = y, col = val)) + geom_point()
Your result only has one quadrant because the resulting transformation has both negative and positive values.
In your function, the result's top left is (-400, -400) and the bottom right is (400, 400). Halve and add 200 to make it (0, 0) and (400, 400).
Scale the trig parameters to go from -pi to pi.
For the bottom of the original image to become the center of the resulting circle, x needs to be the variable inside the trig functions.
library(imager)
pano <- load.image("pano_image.jpg")
pano <- mirror(load.image("pano_image.jpg"), "y")
map_shift <- function(x, y) {
list(
x = y * cos((x - 200) / 400 * 2 * pi) / 2 + 200,
y = y * sin((x - 200) / 400 * 2 * pi) / 2 + 200
)
}
polar_pano <- imwarp(pano, map = map_shift)
plot(polar_pano)
I want to model what it might look like to have the day length change smoothly over time (but remain sinusoidal). The formula for a "chirp", to change the instantaneous frequency is given at https://en.wikipedia.org/wiki/Chirp but it doesn't look right when coded for a 24h period over 5 days and then a transition to 12h over another 5 days:
period = list( c(24,24,5), c(24,12,5) )
alpha = list( c(0,5), c(0,5) )
s_samples = 100
A=50
O=50
simulatedData = data.frame(t=numeric(), v=numeric()) #initialise the output
daySteps = c(0, cumsum(unlist(period)[seq(3,length(unlist(period)), by=3)])) #set up the period starts and ends to set over, starting at 0
##Cycle over each of the items in the list
for(set in seq(period) ){
t_points = s_samples*period[[set]][3]
t = seq(daySteps[set], daySteps[set+1], length.out=t_points) #make the time
slope = (24/period[[set]][2]-24/period[[set]][1])/(max(t)-min(t)) # get the slope
f0 = 24/period[[set]][1] - slope*(min(t)) # find the freq when t0
c = (24/period[[set]][2]-f0)/(max(t)) #calculate the chirp see https://en.wikipedia.org/wiki/Chirp and https://dsp.stackexchange.com/questions/57904/chirp-after-t-seconds
wt = ((c*(t^2))/2) + f0*(t) # calc the freq
a = alpha[[set]][1]
v = A * cos(2*pi*wt - a) + O
simulatedData = rbind(simulatedData, data.frame(t, v) )
}
plot(simulatedData, type="l", lwd=2)
t = seq(0,sum(unlist(period)[seq(3,length(unlist(period)), by=3)]), by=1/24)
points(t, A*cos(2*pi*t)+O, col=3, type="l", lty=2)
points(t, A*cos(2*(24/12)*pi*t)+O, col=4, type="l", lty=2)
The first 24 are perfect, as expected, and the last part of the second 5 days matches a 12h cycled, but the first part of that period looks 180deg out of phase. What's wrong?
I think you're making this a lot more complex than it needs to be. Remember that many R functions are already vectorized. The following function will produce a linear chirp between frequencies f0 and f1 between t0 and t1, with an optional phi parameter to specify at what point on the cycle you want your sequence to begin:
chirp <- function(f0, f1, t0, t1, phi = 0, n_steps = 1000)
{
C <- (f1 - f0)/(t1 - t0)
x <- seq(t0, t1, length.out = n_steps)
y <- sin(2 * pi * (C / 2 * (x - t0)^2 + f0 * (x - t0)) + phi) # Ref Wikipedia
data.frame(x, y)
}
Of course, it can also produce the static first half of your plot by "chirping" between two identical frequencies, so we can get a data frame of x, y points on the plot by doing
df <- rbind(chirp(1, 1, 0, 5), chirp(1, 2, 5, 10))
Which results in:
plot(df$x, df$y, type = "l")
Note that between 5 and 10 days there are 7.5 cycles, so if you wanted to smoothly continue frequency 2, you would need to set the phi parameter to a half cycle (i.e. to pi):
df <- rbind(df, chirp(2, 2, 10, 15, phi = pi))
plot(df$x, df$y, type = "l")
Note that the phases of the chirped signal and a 2 Hz signal will only match after n seconds if the chirp occurs over an even number of periods of the original signal. For an odd number, the phase will be out by 180 degrees. This is a mathematical consequence of a linear chirp. To see this, let's use our function to chirp over 6 seconds so the phases match at 10 seconds:
plot(df$x, df$y, type = "l")
lines(df2$x, df2$y, lty = 2, col = "green")
lines(df3$x, df3$y, lty = 2, col = "blue")
lines(df$x, df$y)
I am currently working with B-splines using R's function bs from the package splines and as a graphic example I would like to provide a figure showing the differences between set of splines with different degrees.
The problem is that bs only supports degrees bigger than 0.
A spline of degree zero, is nothing more than an indicator function for the given region defined by the knots, but I don't really know how to generate it.
This is what I've done so far
x<-seq(0,1,length.out =1000)
par(mfrow=c(3,1))
B1<-bs(x,knots = seq(0,1,length.out = 11)[-c(1,11)],Boundary.knots = c(0,1),intercept = T,degree = 1)
matplot(x,B1,type="l",lty=1,ylim = c(-0.1,1.2),xlab = "",ylab = "")
abline(v=seq(0,1,length.out = 11),lty=2)
legend("top", legend ="B-splines of order 2")
B2<-bs(x,knots = seq(0,1,length.out = 11)[-c(1,11)],Boundary.knots = c(0,1),intercept = T,degree = 2)
matplot(x,B2,type="l",lty=1,ylim = c(-0.1,1.2),xlab = "",ylab = "")
abline(v=seq(0,1,length.out = 11),lty=2)
legend("top", legend ="B-splines of order 3")
B3<-bs(x,knots = seq(0,1,length.out = 11)[-c(1,11)],Boundary.knots = c(0,1),intercept = T,degree = 3)
matplot(x,B3,type="l",lty=1,ylim = c(-0.1,1.2),xlab = "",ylab = "")
abline(v=seq(0,1,length.out = 11),lty=2)
legend("top", legend ="B-splines of order 4")
This image taken from Hastie et.al (2017) is basically what I am missing.
Thanks in advance
As I understand from the comments, you want a function that given an input vector x of n points returns a series of n-1 "splines"; where the ith spline is defined as having the value 1 in the range x[i] < x < x[i+1] or 0 elsewhere.
We can do this so:
x <- seq(0,1,length.out =10)
zero_spline = function(x, xout, n=1000) {
if (missing(xout)) xout = seq(min(x), max(x), length.out = n)
zs = data.frame()
y = numeric(length(xout))
for (i in 1:(length(x)-1L)) {
yi = y
yi[(xout > x[i]) & (xout < x[i+1])] = 1
zs = rbind(zs, data.frame(xout, yi, interval=i))
}
zs
}
zs = zero_spline(x, n=100)
library(ggplot2)
ggplot(zs, aes(xout, yi, color=factor(interval))) +
geom_line()
I am trying to plot an EM wave (propagating in the z-direction) vector field in Julia. I looked around and it looks like quiver is what I need to use and I have tried that with unsuccessful results. As far as I understand (x, y, z) are the origins of the vectors and (u, v, w) are the vectors themselves originating at the (x, y, z) points. Here is what I have so far but this doesn't seem to produce the correct plot. How can I get this to work? I'm open to try other plotting libs as well. Thanks in advance.
using Plots; gr()
t = 0; n = 100; k = 1; ω = 1; φ = π/4
x = y = w = zeros(n)
z = range(0, stop=10, length=n)
u = #. cos(k*z - ω*t)
v = #. sin(k*z - ω*t)
quiver(x, y, z, quiver=(u, v, w), projection="3d")
I'm not exactly sure this is the result you want but I've managed to make your code work in Julia v1.1 :
using PyPlot
pygui(true)
fig = figure()
ax = fig.gca(projection="3d")
t = 0; n = 100; k = 1; ω = 1; φ = π/4
x = y = w = zeros(n)
z = range(0, stop=10, length=n)
u = cos.(k*z .- ω*t)
v = sin.(k*z .- ω*t)
ax.quiver(x,y,z, u,v,w)
Or, with colors :
using PyPlot
using Random
function main()
pygui(true)
fig = figure()
ax = fig.gca(projection="3d")
t = 0; n = 100; k = 1; ω = 1; φ = π/4
x = y = w = zeros(n)
z = range(0, stop=10, length=n)
u = cos.(k*z .- ω*t)
v = sin.(k*z .- ω*t)
a = ((u[1], 0.8, 0.5), (u[2], 0.8, 0.5))
for i in 3:length(u)-2
a = (a..., (abs(u[i]), 0.8, 0.5))
end
c = ((0.4, 0.5, 0.4), (0.4, 0.9, 0.4), (0.1, 0.1, 0.1))
q = ax.quiver(x,y,z, u,v,w, color = a)
end
main()
Given family of functions f(x;q) (x is argument and q is parameter) I'd like to visulaize this function family on x taking from the interval [0,1] for 9 values of q (from 0.1 to 0.9). So far my solution is:
f = function(p,q=0.9) {1-(1-(p*q)^3)^1024}
x = seq(0.0,0.99,by=0.01)
q = seq(0.1,0.9,by=0.1)
qplot(rep(x,9), f(rep(x,9),rep(q,each=100)), colour=factor(rep(q,each=100)),
geom="line", size=I(0.9), xlab="x", ylab=expression("y=f(x)"))
I get quick and easy visual with qplot:
My concern is that this method is rather memory hungry as I need to duplicate x for each parameter and duplicate each parameter value for whole x range. What would be alternative way to produce same graph without these duplications?
At some point ggplot will need to have the data available to plot it and the way that package works prohibits simply doing what you want. I suppose you could set up a blank plot if you know the x and y axis limits, and then loop over the 9 values of q, generating the data for that q, and adding a geom_line layer to the existing plot object. However, you'll have to produce the colours for each layer yourself.
If this is representative of the size of problem you have, I wouldn't worry too much about the memory footprint. We're only talking about a two vectors of length 900
> object.size(rnorm(900))
7240 bytes
and the 100 values over the range of x appears sufficient to give a smooth plot.
for loop to add layers to ggplot
require("ggplot2")
## something to replicate ggplot's colour palette, sure there is something
## to do this already in **ggplot** now...
ggHueColours <- function(n, h = c(0, 360) + 15, l = 65, c = 100,
direction = 1, h.start = 0) {
turn <- function(x, h.start, direction) {
(x + h.start) %% 360 * direction
}
if ((diff(h) %% 360) < 1) {
h[2] <- h[2] - 360 / n
}
hcl(h = turn(seq(h[1], h[2], length = n), h.start = h.start,
direction = direction), c = c, l = l)
}
f = function(p,q=0.9) {1-(1-(p*q)^3)^1024}
x = seq(0.0,0.99,by=0.01)
q = seq(0.1,0.9,by=0.1)
cols <- ggHueColours(n = length(q))
for(i in seq_along(q)) {
df <- data.frame(y = f(x, q[i]), x = x)
if(i == 1) {
plt <- ggplot(df, aes(x = x, y = y)) + geom_line(colour = cols[i])
} else {
plt <- plt + geom_line(data = df, colour = cols[i])
}
}
plt
which gives:
I'll leave the rest to you - I'm not familiar enough with ggplot to draw a legend manually.