Related
I am importing CSV data in the format x,y,z,p to plot a trisurface which has the scatter plots displayed on top.
The trisurface script works (ax.plot_trisurf), however, I would like to colour the scatter points (ax.scatter) according to either the 1 or -1 assigned in the fourth column of the CSV file.
enter image description here
The x,y,z data is complicated and can't be coloured, hence trying to assign it as simply as possible in the fourth column.
I have attached a basic image, essentially I just want to be able to have a selection of the red dots a different colour without affecting the trisurface they are on.
Any comments or suggestions are be very welcome!
My most recent error is:
ax.scatter(X, Y, np.log10(Z), c= (not p <= (0)({True: 'g', False: 'r'})), marker='o')
TypeError: 'int' object is not callable
enter code here
from typing import Any
import matplotlib
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import sys
import csv
import bbox
import matplotlib.ticker as mticker
# Import CSV data
from numpy import ndarray
csvFileName = sys.argv[0]
csvData = []
with open('ParvaluesMESS.csv', 'r') as csvfile:
csvReader = csv.reader(csvfile, delimiter=',')
for csvRow in csvReader:
csvData.append(csvRow)
csvData = np.array(csvData)
csvData = csvData.astype(float)
X, Y, Z, p = csvData[:,0], csvData[:,1], csvData[:,2], csvData[:,3]
# Plot management: note Z is logged
# Change vmin and vmax values for colorbar range if needed
# Alpha value is transparency
# 111 means 1x1 grid, first subplot
fig = plt.figure(figsize=(5,5))
ax = fig.add_subplot(111, projection='3d')
cb = ax.plot_trisurf(X, Y, np.log10(Z), cmap='coolwarm', alpha=0.75)
#cb = ax.plot_trisurf(X, Y, np.log10(Z), cmap='coolwarm', alpha=0.75, vmin=0, vmax=1)
ax.scatter(X, Y, np.log10(Z), col==(p > 0({True: 'g', False: 'r'})), marker='o')
#ax.zaxis._set_scale('log')
def log_tick_formatter(val, pos=None):
"""Reformat log ticks for display"""
return f"$10^{{{int(val)}}}$"
# Set Z axis to log
ax.zaxis.set_major_formatter(mticker.FuncFormatter(log_tick_formatter))
# ax.zaxis.set_major_locator(mticker.MaxNLocator(integer=True))
def ticklabels(ticks):
ticks_labels = []
for i in ticks:
ticks_labels.append(f'2^{np.log2(i)}')
return ticks_labels
fig.colorbar(cb, shrink=0.5)
ax.set_title("First-year sea ice PAR")
ax.set_xlabel("Ice Thickness m")
ax.set_ylabel("Snow thickness m")
ax.set_zlabel("µmol $^{m-2}$ $^{s-1}$")
ax.view_init(azim=70, elev=30)
ax.set_xlim3d(20, 350)
image_format = 'png' # e.g .png, .svg, etc.
image_name = 'test.eps'
plt.show()
fig.savefig(image_name, format=image_format, dpi=1200)
it was resolved by rearranging into arrays:
from typing import Any
import matplotlib
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import sys
import matplotlib.ticker as mticker
from numpy import ndarray
data=pd.read_csv('ParvaluesMESS.csv',header=None,sep=',',names=.
['Ice','Snow','umol','P'])
x=data[['Ice']].to_numpy()
y=data[['Snow']].to_numpy()
z=data[['umol']].to_numpy()
p=data[['P']].to_numpy()
x=(x.astype(float)).flatten()
y=(y.astype(float)).flatten()
z=(z.astype(float)).flatten()
p=(p.astype(float)).flatten()
fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(111, projection='3d')
cb = ax.plot_trisurf(x, y, np.log10(z), cmap='coolwarm', alpha=0.75)
ax.scatter(x, y, np.log10(z),c=p,cmap='RdYlGn')
#your formats
def log_tick_formatter(val, pos=None):
"""Reformat log ticks for display"""
return f"$10^{{{int(val)}}}$"
# Set Z axis to log
ax.zaxis.set_major_formatter(mticker.FuncFormatter(log_tick_formatter))
# ax.zaxis.set_major_locator(mticker.MaxNLocator(integer=True))
def ticklabels(ticks):
ticks_labels = []
for i in ticks:
ticks_labels.append(f'2^{np.log2(i)}')
return ticks_labels
fig.colorbar(cb, shrink=0.5)
ax.set_title("First-year sea ice PAR")
ax.set_xlabel("Ice Thickness m")
ax.set_ylabel("Snow thickness m")
ax.set_zlabel("µmol $^{m-2}$ $^{s-1}$")
ax.view_init(azim=70, elev=30)
ax.set_xlim3d(20, 350)
image_name = 'BenImag'
image_format = 'png' # e.g .png, .svg, etc.
plt.show()
fig.savefig(image_name, format=image_format, dpi=1200)
I am trying to do a basic plot of the world map using Python and the Matplotlib library. However, when I plot the polygons the plot shows many straight lines that do not seem to be part of the polygon. I am relatively new at working with shapefiles but the code I'm using has worked for a previous shapefile I used, so I'm confused and wondering what might be missing in the code.
The code I'm using is:
import numpy as np
import pandas as pd
import shapefile as shp
import matplotlib.pyplot as plt
import seaborn as sns
import os
sns.set(style='whitegrid', palette='ocean', color_codes=True)
sns.mpl.rc('figure', figsize=(10,6))
sf = shp.Reader(shp_path)
def plot_map(sf, x_lim = None, y_lim = None, figsize = (11,9)):
'''
Plot map with lim coordinates
'''
plt.figure(figsize = figsize)
id=0
for shape in sf.shapeRecords():
x = [i[0] for i in shape.shape.points[:]]
y = [i[1] for i in shape.shape.points[:]]
plt.plot(x, y, 'k')
if (x_lim == None) & (y_lim == None):
x0 = np.mean(x)
y0 = np.mean(y)
plt.text(x0, y0, id, fontsize=10)
id = id+1
if (x_lim != None) & (y_lim != None):
plt.xlim(x_lim)
plt.ylim(y_lim)
plot_map(sf)
plt.show()
The following link shows resulting graph (I'm not allowed to post pictures yet?):
Any help is appreciated, thank you all!
pls use 'k.', or use scatter instead of plot
import numpy as np
import pandas as pd
import shapefile as shp
import matplotlib.pyplot as plt
import seaborn as sns
import os
sns.set(style='whitegrid', palette='ocean', color_codes=True)
sns.mpl.rc('figure', figsize=(10,6))
sf = shp.Reader(shp_path)
def plot_map(sf, x_lim = None, y_lim = None, figsize = (11,9)):
'''
Plot map with lim coordinates
'''
plt.figure(figsize = figsize)
id=0
for shape in sf.shapeRecords():
x = [i[0] for i in shape.shape.points[:]]
y = [i[1] for i in shape.shape.points[:]]
## change here
plt.plot(x, y, 'k.')
if (x_lim == None) & (y_lim == None):
x0 = np.mean(x)
y0 = np.mean(y)
plt.text(x0, y0, id, fontsize=10)
id = id+1
if (x_lim != None) & (y_lim != None):
plt.xlim(x_lim)
plt.ylim(y_lim)
plot_map(sf)
plt.show()
I am trying to generate a figure to visualize the entire covariance matrix.
However, I am not able to include the entire list of labels. See the working example below:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import cm as cm
numberYears=len(range(2002,2018+1))
covMatrix=np.ones([numberYears,numberYears])
for count1,year1 in enumerate(range(2002,2018+1)) :
for count2,year2 in enumerate(range(2002,2018+1)) :
covMatrix[count1,count2]=1-(abs(count1-count2)/numberYears)
fig = plt.figure()
ax1 = fig.add_subplot(111)
cmap = cm.get_cmap('rainbow', 30)
cax = ax1.imshow(covMatrix, interpolation="nearest", cmap=cmap)
labels=[]
for year in range(2002,2018+1):
labels.append(str(year))
ax1.set_xticklabels(labels,fontsize=10,rotation=90)
ax1.set_yticklabels(labels,fontsize=10)
fig.colorbar(cax, ticks=[.1,.2,.3,.4,.5,.6,.7,.8,.9,1.0])
fig.savefig('map.png')
Note that my labels are [2002,2003,...,2017,2018] and the entire list is not included as a label of the figure. How can I deal with this?
Considering #ImportanceOfBeingErnest comment, I was able to find the solution. I include the argument "extent" in the function "imshow" and I also "set.xticks":
from matplotlib import pyplot as plt
from matplotlib import cm as cm
numberYears=len(range(2002,2018+1))
covMatrix=np.ones([numberYears,numberYears])
for count1,year1 in enumerate(range(2002,2018+1)) :
for count2,year2 in enumerate(range(2002,2018+1)) :
covMatrix[count1,count2]=1-(abs(count1-count2)/numberYears)
fig = plt.figure()
ax1 = fig.add_subplot(111)
cmap = cm.get_cmap('rainbow', 30)
cax = ax1.imshow(covMatrix, interpolation="nearest", cmap=cmap,extent=[2002,2018,2002,2018])
labels=[]
for year in range(2002,2018+1):
labels.append(str(year))
ax1.set_xticks(listYears)
ax1.set_yticks(listYears)
ax1.set_xticklabels(labels,fontsize=10,rotation=90)
ax1.set_yticklabels(labels,fontsize=10)
fig.colorbar(cax, ticks=[.1,.2,.3,.4,.5,.6,.7,.8,.9,1.0])
fig.savefig('mapTeste.png')
Can the delimited part below (the part between comments) be encapsulated in a function?
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
def f(t):
x=np.random.rand(1)
y=np.random.rand(1)
return x,y
# From here
fig, ax = plt.subplots()
ax.set_xlim(0,1)
ax.set_ylim(0,1)
# To here
def update(t):
x,y = f(t)
ax.plot(x, y, marker="s")
ax.set_title(str(t))
ani = matplotlib.animation.FuncAnimation(fig, update, frames=100)
plt.show()
Thank you
Not sure what the problem is. But the answer is of course yes, anything can be put into a function.
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
def f(t):
x=np.random.rand(1)
y=np.random.rand(1)
return x,y
def function():
fig, ax = plt.subplots()
ax.set_xlim(0,1)
ax.set_ylim(0,1)
return fig,ax
def update(t):
x,y = f(t)
ax.plot(x, y, marker="s")
ax.set_title(str(t))
fig, ax = function()
ani = matplotlib.animation.FuncAnimation(fig, update, frames=100)
plt.show()
I'm trying to open up multiple plots but I ran into a few problems. When I tried to create plots using threading, python would first open a number of windows, then close all but the first.
In another question it was recommended that I use multiprocessing which I have tried. The code runs without error, it just doesn't show any plot.
I'm trying to get something very simple to work before moving on to my main project.
# Import the necessary packages and modules
import matplotlib.pyplot as plt
import numpy as np
#from threading import Thread
import multiprocessing
def plot(datax, datay, name):
# Prepare the data
x = datax
y = datay**2
# Plot the data
plt.scatter(x, y, label=name)
# Add a legend
plt.legend()
# Show the plot
plt.show()
#plot(3,3,)
'''
for i in range(10):
t = Thread(target=plot, args=(i,i+1,i,))
t.start()
'''
for i in range(2):
p = multiprocessing.Process(target=plot, args=(i, i, i))
p.start()
update:
for some reason, multiprocessing stopped working again. I tried creating a function multiP() only to open the processes but it didn't work when I added the input('value: '). scine I can't figure out how to send data to a specific thread I'm going to save data like this: dat = [[x,y0,y1,...yn],[x,y0,y1,...yn],...] and each plot process with check the if something was added to dat.
import matplotlib.pyplot as plt
import numpy as np
import multiprocessing
#multiprocessing.freeze_support() # <- may be required on windows
def plot(datax, datay, name):
x = datax
y = datay**2
plt.scatter(x, y, label=name)
plt.legend()
plt.show()
def multiP():
if __name__ == "__main__":
for i in range(2):
p = multiprocessing.Process(target=plot, args=(i, i, i))
p.start()
if True:
#input('Vlaue: ') # while commented plots are shown
multiP()
The following code produces two figures as desired.
import matplotlib.pyplot as plt
import numpy as np
import multiprocessing
#multiprocessing.freeze_support() # <- may be required on windows
def plot(datax, datay, name):
x = datax
y = datay**2
plt.scatter(x, y, label=name)
plt.legend()
plt.show()
def multiP():
for i in range(2):
p = multiprocessing.Process(target=plot, args=(i, i, i))
p.start()
if __name__ == "__main__":
input('Value: ')
multiP()
Taking ImportanceOfBeingErnest answer, I leave below an implementation which only shows one window and waits for the window to close, which can be very handy. Every time it is called, it displays a new window with the corresponding image (a new pocess will be started for each image). I used a lot to view images when stopped at some breakpoint during debug.
# Library packages needed
import numpy as np
import datetime
import sys
import queue
import multiprocessing
# Plot related packages
import matplotlib.pyplot as plt
def showImage(img: np.ndarray, title: str = str(datetime.datetime.today())):
"""Show an image in a new process without blocking. Usefull for debugging.
Args:
img (np.ndarray): Image to be shown
title (str, optional): Title to be shown. Defaults to
str(datetime.datetime.today()).
"""
def plot(q, title):
fig = plt.figure()
fig.suptitle(title)
try:
q.get(True, 2.0) # Wait a couple of seconds
except queue.Empty:
print('Not image received to plot...quitting')
sys.exit()
plt.imshow(img)
plt.show()
sys.exit()
# Create a queue to share data between process
q = multiprocessing.Queue()
# Create and start the process
proc = multiprocessing.Process(None, plot, args=(q, title))
proc.start()
q.put(img)
To run it, just save this to a show_image.py file and call
from show_image.py import showImage
show_image(img, title)