mathplotlib is not updating animation - python

I would like to animate points that are changing position in a 3D scatterplot.
At the first timepoint the points in the scatterplot have the coordinates from the entry scatter[0][1] and then at the next timepoint the coordinates are scatter[1][2] and so on.
I have already set up the animation function from mathplotlib but it doesn't update.
Any help with this issue would be greatly appreciated.
from matplotlib import pyplot as plt
import numpy as np
import mpl_toolkits.mplot3d.axes3d as p3
from matplotlib import animation
fig = plt.figure()
ax = p3.Axes3D(fig)
ax.set_xlim3d([0, 100])
ax.set_xlabel('X')
ax.set_ylim3d([0, 100])
ax.set_ylabel('Y')
ax.set_zlim3d([0, 100])
ax.set_zlabel('Z')
scatter=[
np.array([9.956433493781429,
np.array([[50, 50, 50],
[53, 54, 55],
[50, 51, 50],
[52, 52, 52],
[50, 50, 52]])]),
np.array([10.189591392765704,
np.array([[50, 50, 50],
[73, 74, 75],
[70, 71, 70],
[72, 72, 72],
[70, 70, 72]])]),
np.array([10.40490011215984,
np.array([[80, 80, 80],
[83, 84, 75],
[80, 81, 60],
[82, 82, 42],
[88, 80, 52],
[89, 81, 29]])])
]
x=scatter[0][1][:,0]
y=scatter[0][1][:,1]
z=scatter[0][1][:,2]
points, = ax.plot(x, y, z, '*')
txt = fig.suptitle('')
def update_points(num,x, y, z, points):
for i in np.arange(0,len(scatter)):
txt.set_text('time={:f}'.format(scatter[i][0]))
new_x = scatter[i][1][:,0]
new_y = scatter[i][1][:,1]
new_z = scatter[i][1][:,2]
points.set_data(new_x,new_y)
points.set_3d_properties(new_z, 'z')
return points,txt
ani=animation.FuncAnimation(fig, update_points, frames=len(scatter), fargs=(x, y, z, points))
plt.show()

I found the solution. The code needs to be like this:
from matplotlib import pyplot as plt
import numpy as np
import mpl_toolkits.mplot3d.axes3d as p3
from matplotlib import animation
fig = plt.figure()
ax = p3.Axes3D(fig)
ax.set_xlim3d([0, 100])
ax.set_xlabel('X')
ax.set_ylim3d([0, 100])
ax.set_ylabel('Y')
ax.set_zlim3d([0, 100])
ax.set_zlabel('Z')
scatter=[
np.array([9.956433493781429,
np.array([[50, 50, 50],
[53, 54, 55],
[50, 51, 50],
[52, 52, 52],
[50, 50, 52]])]),
np.array([10.189591392765704,
np.array([[50, 50, 50],
[73, 74, 75],
[70, 71, 70],
[72, 72, 72],
[70, 70, 72]])]),
np.array([10.40490011215984,
np.array([[80, 80, 80],
[83, 84, 75],
[80, 81, 60],
[82, 82, 42],
[88, 80, 52],
[89, 81, 29]])])
]
x=scatter[0][1][:,0]
y=scatter[0][1][:,1]
z=scatter[0][1][:,2]
points, = ax.plot(x, y, z, '*')
txt = fig.suptitle('')
def update_points(num,x, y, z, points):
#for i in range(len(scatter)):
print(num,range(len(scatter)))
txt.set_text('time={:f}'.format(scatter[num][0]))
new_x = scatter[num][1][:,0]
new_y = scatter[num][1][:,1]
new_z = scatter[num][1][:,2]
print(new_x,new_y,new_z)
points.set_data(new_x,new_y)
points.set_3d_properties(new_z, 'z')
return points,txt
ani=animation.FuncAnimation(fig, update_points, frames=3, fargs=(x, y, z, points))
plt.show()

Related

Matplotlib plot spaces separated data array

What's the easiest way to format this array data so that I can connect the points on the graph iterating, assuming each line contains x and y coordinates of a single point?
import matplotlib.pyplot as plt
(...)
<class 'numpy.ndarray'>
[-22.58343371 7.97162262]
[-49.08400669 -28.64111278]
[-71.47754547 -25.78248676]
[-46.27120899 -21.72541444]
[ 43.6158669 109.61815799]
[-22.58343371 7.97162262]
(...)
plt.plot(x, y, color='orange')
Sorry, below is almost complete code (order is calculated by another alghoritm) corrected thanks to Quang Hoang's comment. This is obviously part of the solution to the well known tsp problem. The point, of course, is to connect the points according to the correct order in the list which in this case is: (0, 2, 1, 3, 4, 0).
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import numpy as np
n = 5
order = (0, 2, 1, 3, 4, 0)
distances = [[0, 39, 22, 59, 54, 33, 57, 32, 89, 73, 29, 46],
[39, 0, 20, 20, 81, 8, 49, 64, 63, 84, 10, 61],
[22, 20, 0, 39, 74, 18, 60, 44, 71, 73, 11, 46],
[59, 20, 39, 0, 93, 27, 51, 81, 48, 80, 30, 69],
[54, 81, 74, 93, 0, 73, 43, 56, 104, 76, 76, 77],
[33, 8, 18, 27, 73, 0, 45, 61, 71, 88, 8, 63],
[57, 49, 60, 51, 43, 45, 0, 85, 88, 115, 52, 103],
[32, 64, 44, 81, 56, 61, 85, 0, 74, 43, 55, 23],
[89, 63, 71, 48, 104, 71, 88, 74, 0, 38, 69, 51],
[73, 84, 73, 80, 76, 88, 115, 43, 38, 0, 81, 28],
[29, 10, 11, 30, 76, 8, 52, 55, 69, 81, 0, 55],
[46, 61, 46, 69, 77, 63, 103, 23, 51, 28, 55, 0]]
pca = PCA(n_components=2)
coord = pca.fit_transform(distances[:n])
plt.scatter(coord[:,0], coord[:,1])
for i in coord:
x = np.where(coord == i)
plt.annotate((x[0][0]) ,i, color='red')
for j in order:
print(coord[j])
plt.plot(coord[:,0], coord[:,1], color='orange')
plt.show()
Sometimes, after many hours, things feel more difficult than they are:) Thank's a lot Kapocsi! Working solution below:
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import numpy as np
n = 5
order = [0, 2, 1, 3, 4, 0]
distances = [[0, 39, 22, 59, 54, 33, 57, 32, 89, 73, 29, 46],
[39, 0, 20, 20, 81, 8, 49, 64, 63, 84, 10, 61],
[22, 20, 0, 39, 74, 18, 60, 44, 71, 73, 11, 46],
[59, 20, 39, 0, 93, 27, 51, 81, 48, 80, 30, 69],
[54, 81, 74, 93, 0, 73, 43, 56, 104, 76, 76, 77],
[33, 8, 18, 27, 73, 0, 45, 61, 71, 88, 8, 63]]
pca = PCA(n_components=2)
coord = pca.fit_transform(distances[:n])
plt.scatter(coord[:,0], coord[:,1])
for i in coord:
x = np.where(coord == i)
plt.annotate((x[0][0]) ,i, color='red')
x = coord[order]
print(x)
plt.plot(x[:, 0], x[:, 1], color='orange', marker='o', linestyle='-')
plt.show()
You likely need to sort the data to get the visualization you want:
import numpy as np
import matplotlib.pyplot as plt
a = np.array([[-22.58343371, 7.97162262],
[-49.08400669, -28.64111278],
[-71.47754547, -25.78248676],
[-46.27120899, -21.72541444],
[ 43.6158669 , 109.61815799],
[-22.58343371, 7.97162262]])
order = a[:, 0].argsort()
plt.plot(a[order, 0], a[order, 1], color='orange', marker='o', linestyle='-')
plt.show()
If you don't sort it, you will end up with something like this:
import numpy as np
import matplotlib.pyplot as plt
a = np.array([[-22.58343371, 7.97162262],
[-49.08400669, -28.64111278],
[-71.47754547, -25.78248676],
[-46.27120899, -21.72541444],
[ 43.6158669 , 109.61815799],
[-22.58343371, 7.97162262]])
plt.plot(a[:, 0], a[:, 1], color='orange', marker='o', linestyle='-')
plt.show()

RGB TIF to GeoTIF and Removing the Background Color

I have created tif image using matplotlib python trigulation function, Now tif need to be change to goetiff with epsg4326 projection with removing the background only the patch need to be there.
What difficulty i am facing :-
1- projection change is not happening correct.
2- pixel value should be z parameter value.
3- only the clip of lat lon i want not the whole lat lon area.
CODES:-
1- For creating matplotlib trigulation tiff code below
#MAKING TIFF FILE USING TRIANGULARION MATPLOTLIB.
import matplotlib.tri as mtri
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
def plot():
x=np.random.uniform(70,94,74)
y=np.random.uniform(8,22,74)
# A selected triangulation of the points.
triangles = np.asarray([
[67, 66, 1], [65, 2, 66], [1, 66, 2], [64, 2, 65], [63, 3, 64],
[60, 59, 57], [2, 64, 3], [3, 63, 4], [0, 67, 1], [62, 4, 63],
[57, 59, 56], [59, 58, 56], [61, 60, 69], [57, 69, 60], [4, 62, 68],
[6, 5, 9], [61, 68, 62], [69, 68, 61], [9, 5, 70], [6, 8, 7],
[4, 70, 5], [8, 6, 9], [56, 69, 57], [69, 56, 52], [70, 10, 9],
[54, 53, 55], [56, 55, 53], [68, 70, 4], [52, 56, 53], [11, 10, 12],
[69, 71, 68], [68, 13, 70], [10, 70, 13], [51, 50, 52], [13, 68, 71],
[52, 71, 69], [12, 10, 13], [71, 52, 50], [71, 14, 13], [50, 49, 71],
[49, 48, 71], [14, 16, 15], [14, 71, 48], [17, 19, 18], [17, 20, 19],
[48, 16, 14], [48, 47, 16], [47, 46, 16], [16, 46, 45], [23, 22, 24],
[21, 24, 22], [17, 16, 45], [20, 17, 45], [21, 25, 24], [27, 26, 28],
[20, 72, 21], [25, 21, 72], [45, 72, 20], [25, 28, 26], [44, 73, 45],
[72, 45, 73], [28, 25, 29], [29, 25, 31], [43, 73, 44], [73, 43, 40],
[72, 73, 39], [72, 31, 25], [42, 40, 43], [31, 30, 29], [39, 73, 40],
[42, 41, 40], [72, 33, 31], [32, 31, 33], [39, 38, 72], [33, 72, 38],
[33, 38, 34], [37, 35, 38], [34, 38, 35], [35, 37, 36]])
z = np.random.uniform(0.5, 8, 74)
triang = mtri.Triangulation(x, y, triangles=triangles)
print("type(triang):", triang)
print("type(z):", type(z))
ax=plt.tripcolor(triang,z,vmin=0,vmax=2)
ax
plt.savefig("ax.tif")
plt.show(ax)
plot()
2- making geotiff with projection from tif
from osgeo import gdal, osr
import numpy, gdal
ds = gdal.Open('ax.tif')
band = ds.GetRasterBand(1)
myarray = numpy.array(band.ReadAsArray())
convert=lambda x:x*(0.0124796)
myarray=convert(myarray)
#print("myarray:",myarray)
selection = numpy.logical_or(myarray >= 3.5, myarray <= 7)
new_array = [ [0 for i in range(band.XSize)] for j in range(band.YSize)]
for i, item in enumerate(myarray):
for j, element in enumerate(item):
if selection[i][j] == True:
new_array[i][j] = myarray[i][j]
else:
new_array[i][j] = -999
if new_array[i][j]==3.182298:
new_array[i][j] = -999
geotransform = ds.GetGeoTransform()
wkt = ds.GetProjection()
# Create gtif file
driver = gdal.GetDriverByName("GTiff")
output_file = "ax_geotiff.tif"
dst_ds = driver.Create(output_file,
band.XSize,
band.YSize,
1,
gdal.GDT_Float64)
new_array = numpy.array(new_array)
print(type(new_array[i]))
#new_array[i]=new_array.max())
#transformed_arr = np.where(arr<5, arr*10, 0)
#new_array=numpy.where(new_array[i]==new_array.max(),-999,new_array)
print("new_array:",new_array)
#writting output raster
dst_ds.GetRasterBand(1).WriteArray( new_array )
#setting nodata value
dst_ds.GetRasterBand(1).SetNoDataValue(-999)
#setting extension of output raster
# top left x, w-e pixel resolution, rotation, top left y, rotation, n-s pixel resolution
dst_ds.SetGeoTransform(geotransform)
# setting spatial reference of output raster
srs = osr.SpatialReference()
srs.ImportFromEPSG(4326)
#srs = osr.SpatialReference()
#srs.ImportFromWkt(wkt)
dst_ds.SetProjection( srs.ExportToWkt() )
#Close output raster dataset
ds = None
dst_ds = None
print(numpy.unique(new_array))
3- To plot the geotiff
#CHECKING THE TIFF FILE / ANALYSING THE TIFF FILE DATA AND PLOT.
#tttraster_geotiff
import gdal
%matplotlib inline
import rasterio
from matplotlib import pyplot
import numpy
ds = gdal.Open('ax_geotiff.tif')
band = ds.GetRasterBand(1)
myarray = numpy.array(band.ReadAsArray())
print(myarray)
pyplot.imshow(myarray, cmap='pink')
pyplot.show()
##Above is the sample data and codes i am using but i am not getting correct epsg 4326 projection and my background color in geottiff blue color is coming if i select cmap='jet' i.e blue color large part of geotiff plot indicate the mav value of z parameter , those blue color if i change to np.nan then i a not able to see the other,
so what all modification i have to do-
1- correct projection
2- remove only the blue color as nan color.enter image description here
enter image description here
3- want to remove that drak red color(max value of z variable) , only the map plot i want.
enter image description here

Reading images from adjacent folders

I have 4 different path to folders, but each folder are adjacent to each other and they're called faces 1, faces 2, faces 3 and faces 4. I'm using that path to read the faces images from inside and extract features from them and put them inside a feature_vector.
What i need to do is: read each face images folder and store them inside a feature vector, therefore, for each folder faces 1, faces 2, faces 3, i want to store them inside vec1, vec2, vec 3.
Here's what i am doing:
from os import listdir
from PIL import Image as PImage
def loadImages(path):
imagesList = listdir(path)
loadedImages = []
for image in imagesList:
img = PImage.open(path + image)
arr = np.array(img)
loadedImages.append(arr)
return loadedImages #function that loads all images inside the path given loadimages('path')
Thats my function for loading a path.
imgs = loadImages('C:/Dataset/face1')
coord_list = [[45, 100], [80, 45], [65, 50] , [110, 50], [110, 40], [90, 35], [90, 25], [100, 25], [89, 64], [60, 65], [65, 25], [65, 40], [120, 65], [75, 82], [105, 82], [88, 78], [90, 110], [89, 90], [65, 110], [110, 100]]
vec_1 = []
for img in imgs:
img_feats = []
for coords in coord_list:
img_feats.append(img[coords[0], coords[1]])
vec_1.append(img_feats)
Then i grab my array of coordinates and append each pixel from 50 images inside faces 1 to vec_1, which gives me a 50x22 array
What i want to do is to read inside faces 2 and store in vec_2, faces 3 inside vec_3 and faces 4 inside vec_4
I tried it like this, but it doesn't and also it does not look optmized.
imgs2 = loadImages('C:/Dataset/face2')
coord_list = [[45, 100], [80, 45], [65, 50] , [110, 50], [110, 40], [90, 35], [90, 25], [100, 25], [89, 64], [60, 65], [65, 25], [65, 40], [120, 65], [75, 82], [105, 82], [88, 78], [90, 110], [89, 90], [65, 110], [110, 100]]
vec_2 = []
for imgs2 in imgs:
img_feats = []
for coords in coord_list:
img_feats.append(img[coords[0], coords[1]])
feat_vec_2.append(img_feats)
imgs3 = loadImages('C:/Dataset/face3')
coord_list = [[45, 100], [80, 45], [65, 50] , [110, 50], [110, 40], [90, 35], [90, 25], [100, 25], [89, 64], [60, 65], [65, 25], [65, 40], [120, 65], [75, 82], [105, 82], [88, 78], [90, 110], [89, 90], [65, 110], [110, 100]]
vec_3 = []
for imgs3 in imgs:
img_feats = []
for coords in coord_list:
img_feats.append(img[coords[0], coords[1]])
vec_3.append(img_feats)
imgs4 = loadImages('C:/Dataset/face4')
coord_list = [[45, 100], [80, 45], [65, 50] , [110, 50], [110, 40], [90, 35], [90, 25], [100, 25], [89, 64], [60, 65], [65, 25], [65, 40], [120, 65], [75, 82], [105, 82], [88, 78], [90, 110], [89, 90], [65, 110], [110, 100]]
vec_4 = []
for imgs4 in imgs:
img_feats = []
for coords in coord_list:
img_feats.append(img[coords[0], coords[1]])
vec_4.append(img_feats)
The features from vec_1 kept appending to vec_2 and vec_1, vec_2 to vec_3....
For what I see, coord_list is always the same for every set of images, so you could condensate the assignation of all the four vec_n lists into one single for loop, by performing the appropriate string interpolation.
This solution will substitute the four vec_n variables for a dictionary (named vec_dict)containing the feature lists for each image set, under a vec_n key.
import os
base_path = os.path.join('C:', os.sep, 'Dataset')
vec_dict = {}
coord_list = [[45, 100], [80, 45], [65, 50] , [110, 50], [110, 40], [90, 35], [90, 25], [100, 25], [89, 64], [60, 65], [65, 25], [65, 40], [120, 65], [75, 82], [105, 82], [88, 78], [90, 110], [89, 90], [65, 110], [110, 100]]
for i in range(1, 5):
folder_path = os.path.join(base_path, f'face{i}')
images = loadImages(folder_path)
for img in images:
vec_dict.setdefault(f'vec_{i}', []).append([img[coords[0], coords[1]] for coords in coord_list])

Python 2d array

I want to make 2D array, which is 50X75.
Computer has to make random coordinates inside the array, about 15 to 20 coordinates.
What should I do TT
I stopped with the first step, making 50X75 2D array, so help meTT
You can generate 2D array using random runmbers
from random import randint
coordinates = [[randint(1, 100), randint(1, 100)] for i in range(20)]
Output: [[81, 52], [12, 79], [24, 90], [93, 53], [98, 17], [40, 44], [31, 1], [1, 40], [8, 34], [81, 31], [87, 50], [45, 72], [86, 70], [43, 78], [64, 80], [85, 76], [28, 43], [81, 78], [80, 55], [82, 58]]
A 50 x 75 2D array can be made using a np.reshape function. Here is an example, hope this helps.
import numpy as np
np.arange(3750).reshape(50, 75) # the array has 50 rows and 75 cols
array([[ 0, 1, 2, ..., 72, 73, 74],
[ 75, 76, 77, ..., 147, 148, 149],
[ 150, 151, 152, ..., 222, 223, 224],
...,
[3525, 3526, 3527, ..., 3597, 3598, 3599],
[3600, 3601, 3602, ..., 3672, 3673, 3674],
[3675, 3676, 3677, ..., 3747, 3748, 3749]])

Python and Matplotlib: reduce number of x tick marks and remove zero-padding

I am new to matplotlib and pyplot and trying to plot a large data set. The below is a small snippet.
The plot works, but the xtick marks are crowded.
How can I reduce the number of tick marks?
Using plt.locator_params(nbins=4) returned an error:
AttributeError: 'FixedLocator' object has no attribute 'set_params'
And is there a way to remove the 0 padding from the date labels within pyplot?
import matplotlib.pyplot as plt
x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
xticks = ['01/01', '01/02', '01/03', '01/04', '01/05', '01/06', '01/07', '01/08', '01/09', '01/10', '01/11', '01/12', '01/13', '01/14', '01/15', '01/16', '01/17', '01/18', '01/19', '01/20', '01/21', '01/22', '01/23', '01/24', '01/25', '01/26', '01/27', '01/28', '01/29', '01/30']
y = [80, 80, 60, 30, 90, 50, 200, 300, 200, 150, 10, 80, 20, 30, 40, 150, 160, 170, 180, 190, 20, 210, 220, 20, 20, 20, 200, 270, 280, 90, 00]
y2 = [100, 100, 200, 300, 40, 50, 60, 70, 80, 90, 100, 110, 12, 13, 10, 110, 16, 170, 80, 90, 20, 89, 28, 20, 20, 28, 60, 70, 80, 90, 30]
plt.plot(x, y)
plt.plot(x, y2)
plt.xticks(x, xticks, rotation=90)
plt.show()
Since matplotlib has some really nice tools for dates I think it makes sense to convert your date strings to datetime.datetime objects.
Then you can use one of the handy date-locators; in this case DayLocator makes the most sense. To get that to skip some of the labels you use the interval kwarg.
Then to drop the leading zero from your xticklabels you need a custom formatting function.
import datetime as dt
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as tkr
def xfmt(x,pos=None):
''' custom date formatting '''
x = mdates.num2date(x)
label = x.strftime('%m/%d')
label = label.lstrip('0')
return label
x = ['01/01', '01/02', '01/03', '01/04', '01/05', '01/06', '01/07', '01/08', '01/09', '01/10', '01/11', '01/12', '01/13', '01/14', '01/15', '01/16', '01/17', '01/18', '01/19', '01/20', '01/21', '01/22', '01/23', '01/24', '01/25', '01/26', '01/27', '01/28', '01/29', '01/30', '01/31']
xdates = [dt.datetime.strptime(i,'%m/%d') for i in x]
y = [80, 80, 60, 30, 90, 50, 200, 300, 200, 150, 10, 80, 20, 30, 40, 150, 160, 170, 180, 190, 20, 210, 220, 20, 20, 20, 200, 270, 280, 90, 00]
y2 = [100, 100, 200, 300, 40, 50, 60, 70, 80, 90, 100, 110, 12, 13, 10, 110, 16, 170, 80, 90, 20, 89, 28, 20, 20, 28, 60, 70, 80, 90, 30]
plt.plot(xdates,y)
plt.plot(xdates,y2)
plt.setp(plt.gca().xaxis.get_majorticklabels(),rotation=90)
plt.gca().xaxis.set_major_formatter(tkr.FuncFormatter(xfmt))
plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=4))
plt.gca().xaxis.set_minor_locator(mdates.DayLocator())
plt.show()
The code above produces the following plot:
you use the maxNLocator
fig, ax = plt.subplots()
locator = MaxNLocator(nbins=3) # with 3 bins you will have 4 ticks
ax.xaxis.set_major_locator(locator)
alternatively see https://stackoverflow.com/a/13418954/541038

Categories