Plotting two objects using a 4-item list - python

I have this simulator (gravitation) I've been working on, and I've dissected the equations, math, etc. and it's totally legitimate. However, when I animate the thing I get weird behavior. I'd rather not bore everyone with the entire script because it's sorta lengthy, but the method I'm calling in line.set under the animate(i) function returns a list of four values, which are the positions of my two particles in Cartesian (x,y) coordinates. For example my list looks like:
[1.2, 3.2, 4.5, 5.1]
where the first index is the x-position of the first particle, the second index is the y-position and likewise for the the last two elements corresponding to the second particle (indices 2 and 3).
My question is whether the line.set_data(force.updatePosition(dt)) should be working the way I think it does, i.e. plotting the first particle with indices 0 and 1 and particle two with indices 2 and 3, or am I missing the point? The plotting works, the particles show up, but they get weird, non-sensical movement.
If it's completely necessary here is the script in its entirety...again it's long-ish that's why I didn't post it directly. Also, it's pretty messy as I'm still fighting with it and haven't cleaned it up yet.
Tl;DR Should line.set_data() be able to plot two separate objects if it is fed a list with 4 items?
def init():
line.set_data([], [])
return line,
def animate(i):
line.set_data(force.updatePosition(dt))
return line,

The docs say:
Definition: l.set_data(self, *args)
Docstring:
Set the x and y data
ACCEPTS: 2D array (rows are x, y) or two 1D arrays
So I imagine you want to give it two lists:
line.set_data([x1, x2], [y1, y2])
But it seems that force.updatePosition already returns a list of two lists([pos1]+[pos2]), so you can maybe try:
line.set_data(np.transpose(force.updatePosition(dt)))
My opinion is you might be better off keeping all this info in arrays and remove half the lines of your code, since you write every line two or four times for each element.

Related

Differentiate some points in a python plot

I have a plot in Python of the following
a = (1,2,3,4,5)
b = (1,2,3,4,5)
plot(a,b)
I want to differentiate some of the x axis points in the plot with a dots of unique colors
for examples this points
c = (2,4)
I tried the following:
a = (1,2,3,4,5)
b = (1,2,3,4,5)
plot(a,b)
matplotlib.pyplot.scatter(a, c)
But I got the error "x and y must be the same size"
If you google "matplotlib scatter" or something like that, one of the first links will be this one, which says that the function gives "a scatter plot of y vs. x". So, the error message you shared makes sense, since the length of a is greater than the length of c. I hope it makes sense to you why what your original code gives that error.
Your problem is specific enough that there isn't an out-of-the-box solution in matplotlib that I'm aware of, so this will require the use of your own custom functions. I'll give one approach that might be helpful to you. I'm structuring my answer here so you can see how to solve the issue to your own specifications, instead of relying too heavily on copying & pasting other people's code, since the latter makes it harder for you to do exactly what you want to do.
To restate the problem in more concise terms: How can a matplotlib user plot a line, and then put markers on a subset of the line's points, specified by their x-values?
To begin, here is what your program might look like currently:
import matplotlib.pyplot as plt
x_coords = [ ] # fill in x_coords here
y_coords = [ ] # fill in y_coords here
marker_x_coords = [ ] # fill in with x coordinates of points you want to have markers
plt.plot(x_coords, y_coords) # plots the line
#### TODO: plot the markers ####
Now, you have the x-values of the points you want to put markers on. How might you get their corresponding y-values? Well, you can make a function that searches for the index of the x-value in x_coords, and then gives the corresponding value at the same index of y_coords:
def getYVals(x_coords_lst, y_coords_lst, marker_x_coords_lst):
marker_y_coords = [] # start with an empty list
for x_point in marker_x_coords_lst:
point_index = x_coords_lst.index(x_point) # get the index of a point in the x list
marker_y_coords.append(y_coords_lst[point_index]) # add the value of the y list at that index to the list that will be returned
return marker_y_coords
This isn't the fastest method, but it is the clearest on what is happening. Here's an alternative that would give the same results but would likely perform faster computationally (it uses something called "list comprehension"):
def getYVals(x_coords_lst, y_coords_lst, marker_x_coords_lst):
return [y_coords_lst[x_coords_lst.index(x_val)] for x_val in marker_x_coords_lst]
The output of either of the getYVals function above will work as the y values of the markers. This can be put in the y argument of plt.scatter, and you already have the x values of it, so from there you should be good to go!

python - mpltPath.Path(polygon).contains_points(points)

I have a list of polygon's corners points (polygon) and a list of x,y points (points).
when I do mpltPath.Path(polygon).contains_points(points) I get a list of True/False on the index if each point in the points list.
my problem is that I don't know how to directly extract these specific points in a fast way.
I tried too do for loop and get all the indexes of the "True" but the problem is that it takes too long (its a list of 100M points) and I wondered if there is a faster way to get it directly from mpltPath package.
here is what I tried to get the indexes but it took too long:
list(locate(mpltPath.Path(polygon).contains_points(points), lambda x: x == 'True'))

Two column data with multiple minimums

I am trying to read two column data and find all the minimums it has. Graph looks like this
x axis is time and y axis is flux. Data can be seen with this link
https://onedrive.live.com/redir?resid=1E870F010DBA8407!298&authkey=!ABdG6FJ_i3d9oWI&ithint=file%2ctxt
I couldn't find a cool algorithm. I also tried to fit a curve to define minimums easily but the result weren't correct. Which statical method is suitable for this job. I used python and C.
I ll be happy if you share your ideas.
The first thing to do is to sort the list of points along the x axis, otherwise it is going to be an absolute pain. Then you can use:
minima_indices=[i+1 for i,y in enumerate(y_list[1:-1]) if y_list[i-1]>=y<=y_list[i+1]]
This should give you the indices of the minima in the sorted list. Note that it omits the first and last point, if you want them to be included this can be done easily.
If you only want the deep minima in your graph then you can filter out all the small minima at the end (or during the original list comprehension by adding a condition):
def approx(a,b,tol):
if abs(a-b)<tol: return True
return False
minima_indices_filtered=[i for i in minima_indices if not approx(y_list[i],y_0,tol)]
y_0 is the value of the flat line at the top of your picture, and tol is how deep a minima has to be before it registers as being a minima.

Sort arrays by two criteria

My figure has a very large legend, and to make it easier to find each corresponding line, I want to sort the legend by the y value of the line at the last datapoint.
plots[] contains a list of Line2D objects,
labels[] is the corresponding labels to each Line2D object, generated through labels = [plot._label for plot in plots]
I want to sort each/both arrays by plots._y[-1], the value of y at the last point
Bonus points if I can also sort first by _linestyle (a string) and then by the y value.
I am unsure of how to do this well, I wouldn't think it would require a loop, but it might because I am sorting by 2 criteria, one of which will be tricky to deal with (':' and '-' are the values of linestyle). Is there a function that can help me out here?
edit: it just occurred to me that I can generate labels after I sort, so that uncomplicates things a bit. However, I still have to sort plots by each object's linestyle and y[-1] value.
I believe this may work:
sorted(plots, key = lambda plot :(plot._linestyle, plot._y[-1]))

Most Efficient Way to Automate Grouping of List Entries

Background:I have a very large list of 3D cartesian coordinates, I need to process this list to group the coordinates by their Z coordinate (ie all coordinates in that plane). Currently, I manually create groups from the list using a loop for each Z coordinate, but if there are now dozens of possible Z (was previously handling only 2-3 planes)coordinates this becomes impractical. I know how to group lists based on like elements of course, but I am looking for a method to automate this process for n possible values of Z.Question:What's the most efficient way to automate the process of grouping list elements of the same Z coordinate and then create a unique list for each plane?
Code Snippet:
I'm just using a simple list comprehension to group individual planes:
newlist=[x for x in coordinates_xyz if insert_possible_Z in x]
I'm looking for it to automatically make a new unique list for every Z plane in the data set.
Data Format:
((x1,y1,0), (x2, y2, 0), ... (xn, yn, 0), (xn+1,yn+1, 50),(xn+2,yn+2, 50), ... (x2n+1,y2n+1, 100), (x2n+2,y2n+2, 100)...)etc. I want to automatically get all coordinates where Z=0, Z=50, Z=100 etc. Note that the value of Z (increments of 50) is an example only, the actual data can have any value.Notes:My data is imported either from a file or generated by a separate module in lists. This is necessary for interface with another program (that I have not written).
The most efficient way to group elements by Z and make a list of them so grouped is to not make a list.
itertools.groupby does the grouping you want without the overhead of creating new lists.
Python generators take a little getting used to when you aren't familiar with the general mechanism. The official generator documentation is a good starting point for learning why they are useful.
If I am interpreting this correctly, you have a set of coordinates C = (X,Y,Z) with a discrete number of Z values. If this is the case, why not use a dictionary to associate a list of the coordinates with the associated Z value as a key?
You're data structure would look something like:
z_ordered = {}
z_ordered[3] = [(x1,y1,z1),(x2,y2,z2),(x3,y3,z3)]
Where each list associated with a key has the same Z-value.
Of course, if your Z-values are continuous, you may need to modify this, say by making the key only the whole number associated with a Z-value, so you are binning in increments of 1.
So this is the simple solution I came up with:
groups=[]
groups[:]=[]
No_Planes=#Number of planes
dz=#Z spacing variable here
for i in range(No_Planes):
newlist=[x for x in coordinates_xyz if i*dz in x]
groups.append(newlist)
This lets me manipulate any plane within my data set simply with groups[i]. I can also manipulate my spacing. This is also an extension of my existing code, as I realised after reading #msw's response about itertools, looping through my current method was staring me in the face, and far more simple than I imagined!

Categories

Resources