Plotting trajectories in python using matplotlib - python

I'm having some trouble using matplotlib to plot the path of something.
Here's a basic version of the type of thing I'm doing.
Essentially, I'm seeing if the value breaks a certain threshold (6 in this case) at any point during the path and then doing something with it later on.
Now, I have 3 lists set-up. The end_vector will be based on the other two lists. If the value breaks past 2 any time during a single simulation, I will add the last position of the object to my end_vector
trajectories_vect is something I want to keep track of my trajectories for all 5 simulations, by keeping a list of lists. I'll clarify this below. And, timestep_vect stores the path for a single simulation.
from random import gauss
from matplotlib import pyplot as plt
import numpy as np
starting_val = 5
T = 1 #1 year
delta_t = .1 #time-step
N = int(T/delta_t) #how many points on the path looked at
trials = 5 #number of simulations
#main iterative loop
end_vect = []
trajectories_vect = []
for k in xrange(trials):
s_j = starting_val
timestep_vect = []
for j in xrange(N-1):
xi = gauss(0,1.0)
s_j *= xi
timestep_vect.append(s_j)
trajectories_vect.append(timestep_vect)
if max(timestep_vect) > 5:
end_vect.append(timestep_vect[-1])
else:
end_vect.append(0)
Okay, at this part if I print my trajectories, I get something like this (I only posted two simulations, instead of the full 5):
[[ -3.61689976e+00 2.85839230e+00 -1.59673115e+00 6.22743522e-01
1.95127718e-02 -1.72827152e-02 1.79295788e-02 4.26807446e-02
-4.06175288e-02] [ 4.29119818e-01 4.50321728e-01 -7.62901016e-01
-8.31124346e-02 -6.40330554e-03 1.28172906e-02 -1.91664737e-02
-8.29173982e-03 4.03917926e-03]]
This is good and what I want to happen.
Now, my problem is that I don't know how to plot my path (y-axis) against my time (x-axis) properly.
First, I want to put my data into numpy arrays because I'll need to use them later on to compute some statistics and other things which from experience numpy makes very easy.
#creating numpy arrays from list
#might need to use this with matplotlib somehow
np_trajectories = np.array(trajectories_vect)
time_array = np.arange(1,10)
Here's the crux of the issue though. When i'm putting my trajectories (y-axis) into matplotlib, it's not treating each "list" (row in numpy) as one path. Instead of getting 5 paths for 5 simulations, I am getting 9 paths for 5 simulations. I believe I am inputing stuff wrong hence it is using the 9 time intervals in the wrong way.
#matplotlib stuff
plt.plot(np_trajectories)
plt.xlabel('timestep')
plt.ylabel('trajectories')
plt.show()
Here's the image produced:
Obviously, this is wrong for the aforementioned reason. Instead, I want to have 5 paths based on the 5 lists (rows) in my trajectories. I seem to understand what the problem is but don't know how to go about fixing it.
Thanks in advance for the help.

When you call np_trajectories = np.array(trajectories_vect), your list of trajectories is transformed into a 2d numpy array. The information about its dimensions is stored in np_trajectories.shape, and, in your case, is (5, 9). Therefore, when you pass np_trajectories to plt.plot(), the plotting library assumes that the y-values are stored in the first dimension, while the second dimension describes individual lines to plot.
In your case, all you need to do is to transpose your np_trajectories array. In numpy, it is as simple as
plt.plot(np_trajectories.T)
plt.xlabel('timestep')
plt.ylabel('trajectories')
plt.show()
If you want to plot the x-axis as time, instead of steps of one, you have to define your time progression as a list or an array. In numpy, you can do something like
times = np.linspace(0, T, N-1)
plt.plot(times, np_trajectories.T)
plt.xlabel('timestep')
plt.ylabel('trajectories')
plt.show()
which produces the following figure:

Related

How to Order Coordinates in Matplotlib (xticks and yticks)

Alright, so I was working on a simple program to just pull coordinates out of a text pad and then graph what was in the text pad on a graph. I thought it would be pretty simple, but I am VERY new to matplotlib, so I still don't fully understand. I got most of the code done correctly, but the only thing that is not working is that when I put the values in the graph, they come all out of order. I want to order the xticks and yticks so that it actually looks like a real line graph you'd see in math, so you can see how the lower coordinates lower than the higher coordinates, and vice versa. Here is my code:
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
def split(word):
return list(word)
fileIWant = open('C:/Users/JustA/Desktop/Python Shenanigans/Converting Coordinates in a .txt to a Graph/Coordinates.txt', 'r');
stopwords = ['\n']
array = fileIWant.readlines()
array = [array.replace('\n', '') for array in array if array not in stopwords]
fileIWant.close()
editFile = open('C:/Users/JustA/Desktop/Python Shenanigans/Converting Coordinates in a .txt to a Graph/Coordinates.txt', 'w')
array_length = len(array)
x = []
y = []
for i in range(array_length):
dataSplit = array[i].split()
getCoordinateX = dataSplit[1]
getCoordinateY = dataSplit[3]
x.append(getCoordinateX)
y.append(getCoordinateY)
plt.scatter(x, y)
plt.plot(x, y) #Add this line in if you want to show lines.
plt.title('Your Coordinate Graph')
plt.xlabel('X Coordinates')
plt.ylabel('Y Coordinates')
#plt.xticks([-100,-80,-60,-40,-20,0,20,40,60,80,100])
#plt.yticks([-100,-80,-60,-40,-20,0,20,40,60,80,100])
plt.show()
editFile.close()
I commented out what I put for the ticks, because it was not working at all. With those commented out, it looks okay, but it is very confusing. I think it just puts them in the order they are at in the .txt, when I want them to order themselves in the code. Here is what it is outputting right now:
Sorry if this is so simple that it has never been asked before, like I said, very new to matplotlib, and numpy if I have to use that at all. I imported it because I thought I may have to, but I don't think I really used it as of yet. Also, I am going to rewrite the coordinates into the graph in order, but I think I can do that myself later.
The problem is that your coordinates are strings, which means matplotlib is just plotting strings against strings ("categorical" axis labels). To fix, you simply have to convert your strings to numbers, e.g. x.append(int(getCoordinateX)).
Note that you also don't have to put plt.scatter/plt.plot in the loop - you only have to call one of those once on the full array. That'll probably make things a little faster too.

Finding the zeroes of a position vector

For my dynamics course I am tasked with writing a python code that will plot the trajectory of a position vector from when it starts on the ground to when it lands on the ground. I currently have my code create a linear space from the two zero values that I calculated by hand, but I want to code that in. Because I also need to create velocity vectors on the trajectory, I have the position vector broken into its x and y components. I have looked into xlim and this thread, but couldn't figure out how to implement them. I'm fairly new to python and coding in general, so I'm still trying to learn how things work.
import numpy as np
import matplotlib.pyplot as plt
#creates a function that returns the x component
def re10(x):
r1 = 0.05*x
return r1
#creates a function that returns the y component
def re20(x):
r2 = -4.91*(x**2) + 30*x + 100
return r2
#Calculates the two zeroes of the trajectory
tmin = (-30 + np.sqrt(30**2 -4*-4.91*100))/(2*-4.91)
tmax = (-30 - np.sqrt(30**2 -4*-4.91*100))/(2*-4.91)
#Initializing time space
t = np.linspace(tmin, tmax, 100)
#Plot
plt.plot(re10(t), re20(t)) #(x, y)
You can easily find the zeroes of a funtion using numpy library.
First, install it. Open a cmd console and write pip install numpy.
Then, write this code in your script:
import numpy
re20 = [-4.91, 30, 100]
zeroes = numpy.roots(coeff)
print(zeroes[0])
print(zeroes[1])
As you will see when running the script from console (or you IDE), numpy.roots(function) will return you the zeroes of your function, as an array.
That is why you use the [] operator to access each one of them (take note that in programming, an array's first element will be at index 0).
To use it directly into your code, you can do:
tmin = zeroes[0]
tmax = zeroes[1]
Simpy is for symbolic operations, it is pretty powerful, but you don't need it for this, my mistake.
Hope you have fun with Python, it's a cool language !

How to chunk up an a step function array based on when x-values flatten out

I am running into a problem that I am having trouble figuring out in python (which I will currently blame on sever jetlag).
I have an array, let's call it x. The plot of x where y-axis is generic value, x-axis is index of array, looks like:
What I want to do is isolate the flat sections after the initial bump (see next picture that I am interested in):
I want to ignore the leading flat line and bump, and make an array of the five red boxes in the second image such that I have something like
x_chunk = [[box 0], [box 1], [box 2], [box 3], [box 4]]
I want to ignore all of the sloped transition line between the red chunks. I am having trouble figuring out the proper iterating procedure and setting the condition such that I get what I need.
So, this is probably not the cleanest solution, however it works:
import numpy as np
import matplotlib.pyplot as plt
# Create data
r=np.random.random(50)
y1 = np.array([50,40,30,20,10])
y=np.repeat(y1,10)
y[9]=y[9]+10
y=y+r
# Plot data
x=np.arange(len(y))
plt.plot(x,y)
plt.show()
Will give you something like this:
# Find maximum and start from there
idxStart=np.argmax(y)
y2=y[idxStart:]
# Grab jump indices
idxs=np.where(np.diff(y2)<-1)[0]+1
# Put into boxes
boxs=[]
for i in range(len(idxs)-1):
boxs.append(y2[idxs[i]:idxs[i+1]])
print boxs
Of course you will need to find the right threshold to distinguish the "jumps/drops" in the data, in my case -1 was good enough since random returns values between 0 and 1. Hope your jetlag gets better soon.
Not tested as I have no data, but something like this should work
def findSteps(arr, thr=.02, window=10, disc=np.std):
d = disc(np.lib.stride_tricks.as_strided(arr, strides = arr.strides*2, shape = (arr.size-window+1, window)), axis = 1)
m = np.minimum(np.abs(d[:-window]), np.abs(d[window:])) < thr
i = np.nonzero(np.diff(m))
return np.split(arr[window:-window], i)[::2]
May have to play around with the window and threshold value, and you may want to write a slope function for disc if np.std doesn't work, but the basic idea is looking forward and backward by window steps and seeing if the standard deviation (or slope) of the stride is close to 0.
You'll end up with blocks of True values, which you find the start and end of by np.nonzero(np.diff())
You then np.split the array into a list of arrays by the blocks and only take every other member of the list (since the other sub-arrays will be the transitions).

Discretize or bin LAB colorspace in 2 dimensions

I have a lab colorspace
And I want to "bin" the colorspace in a grid of 10x10 squares.
So the first bin might be (-110,-110) to (-100,-100) then the next one might be (-100,-110) to (-90,-100) and so on. These bins could be bin 1 and bin 2
I have seen np.digitize() but it appears that you have to pass it 1-dimensional bins.
A rudimentary approach that I have tried is this:
for fn in filenames:
image = color.rgb2lab(io.imread(fn))
ab = image[:,:,1:]
width,height,d = ab.shape
reshaped_ab = np.reshape(ab,(width*height,d))
print reshaped_ab.shape
images.append(reshaped_ab)
all_abs = np.vstack(images)
all_abs = shuffle(all_abs,random_state=0)
sns
df = pd.DataFrame(all_abs[:3000],columns=["a","b"])
top_a,top_b = df.max()
bottom_a,bottom_b = df.min()
range_a = top_a-bottom_a
range_b = top_b-bottom_b
corner_a = bottom_a
corner_b = bottom_b
bins = []
for i in xrange(int(range_a/10)):
for j in xrange(int(range_b/10)):
bins.append([corner_a,corner_b,corner_a+10,corner_b+10])
corner_b = bottom_b+10
corner_a = corner_a+10
but the "bins" that results seem kinda sketchy. For one thing there are many empty bins as the color space does have values in a square arrangement and that code pretty much just boxes off from the max and min values. Additionally, the rounding might cause issues. I am wondering if there is a better way to do this? I have heard of color histograms which count the values in each "bin". I don't need the values but the bins are I think what I am looking for here.
Ideally the bins would be an object that each have a label. So I could do bins.indices[0] and it would return the bounding box I gave it. Then also I could bin each observation, like if a new color was color = [15.342,-6.534], color.bin would return 15 or the 15th bin.
I realize this is a lot to ask for, but I think it must be a somewhat common need for people working with color spaces. So is there any python module or tool that can accomplish what I'm asking? How would you approach this? thanks!
Use the standard numpy 2D-histogram function: numpy.histogram2d:
import numpy as np
# a and b are arrays representing your color points
H, a_edges, b_edges = np.histogram2d(a, b, bins=10)
If you want to discard the empty bins, you'd have to do some work from here. But I don't see why you'd want that, because assigning future colors to existing nonempty bins will be much more work if they are not on a rectangular grid.
You are probably trying to repeat what Richard Zhang did in "Colorful Image Colorization" research: http://richzhang.github.io/colorization/
Here, author himself discuss this problem: https://github.com/richzhang/colorization/issues/23
Fortunately Zhang provides .npy file, that contains those quantized values. It is under: https://github.com/richzhang/colorization/blob/master/resources/pts_in_hull.npy
The only thing, you have to do now, is to load this file in your python script:
import numpy as np
pts_in_hull = np.load("pts_in_hull.npy")
It is numpy array of shape 313x2 containing values from your image.
I know this answer comes few years too late, but maybe it will help someone else.

Matplotlib Magnitude_spectrum Units in Python for Comparing Guitar Strings

I'm using matplotlib's magnitude_spectrum to compare the tonal characteristics of guitar strings. Magnitude_spectrum shows the y axis as having units of "Magnitude (energy)". I use two different 'processes' to compare the FFT. Process 2 (for lack of a better description) is much easier to interpret- code & graphs below
My questions are:
In terms of units, what does "Magnitude (energy)" mean and how does it relate to dB?
Using #Process 2 (see code & graphs below), what type of units am I looking at, dB?
If #Process 2 is not dB, then what is the best way to scale it to dB?
My code below (simplified) shows an example of what I'm talking about/looking at.
import numpy as np
from scipy.io.wavfile import read
from pylab import plot
from pylab import plot, psd, magnitude_spectrum
import matplotlib.pyplot as plt
#Hello Signal!!!
(fs, x) = read('C:\Desktop\Spectral Work\EB_AB_1_2.wav')
#Remove silence out of beginning of signal with threshold of 1000
def indices(a, func):
#This allows to use the lambda function for equivalent of find() in matlab
return [i for (i, val) in enumerate(a) if func(val)]
#Make the signal smaller so it uses less resources
x_tiny = x[0:100000]
#threshold is 1000, 0 is calling the first index greater than 1000
thresh = indices(x_tiny, lambda y: y > 1000)[1]
# backs signal up 20 bins, so to not ignore the initial pluck sound...
thresh_start = thresh-20
#starts at threshstart ends at end of signal (-1 is just a referencing thing)
analysis_signal = x[thresh_start-1:]
#Split signal so it is 1 second long
one_sec = 1*fs
onesec = x[thresh_start-1:one_sec+thresh_start-1]
#process 1
(spectrum, freqs, _) = magnitude_spectrum(onesec, Fs=fs)
#process 2
spectrum1 = spectrum/len(spectrum)
I don't know how to bulk process on multiple .wav files so I run this code separately on a whole bunch of different .wav files and i put them into excel to compare. But for the sake of not looking at ugly graphs, I graphed it in Python. Here's what #process1 and #process2 look like when graphed:
Process 1
Process 2
Magnetude is just the absolute value of the frequency spectrum. As you have labelled in Process 1 "Energy" is a good way to think about it.
Both Process 1 and Process 2 are in the same units. The only difference is that the values in Process 2 has been divided by the total length of the array (a scalar, hence no change of units). Normally this happens as part of the FFT, but sometimes it does not (e.g. numpy.FFT doesn't include the divide by length).
The easiest way to scale it to dB is:
(spectrum, freqs, _) = magnitude_spectrum(onesec, Fs=fs, scale='dB')
If you wanted to do this yourself then you would need to do something like:
spectrum2 = 20*numpy.log10(spectrum)
**It is worth noting that I'm not sure if you should be applying the /len(spectrum) or not. I would suggest using the scale='dB' !!
To convert to dB, take the log of any non-zero spectrum magnitudes, and scale (scale to match a calibrated mic and sound source if available, or use an arbitrarily scale to make the levels look familiar otherwise), before plotting.
For zero magnitude values, perhaps just replace or clamp the log with whatever you want to be on the bottom of your log plot (certainly not negative-infinity).

Categories