Cartopy plotting unwanted lines on map - python

I'm very (very very) new at this game of mapping/carto in Python, and am finding a drought of resources available for CartoPy, so I thought someone here may be able to help.
I have thousands of lat/long coordinates to plot, distributed across 4 parallel lines.
My code so far is:
import pandas as pd
import numpy as np
import os
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from cartopy import config
import cartopy.feature as cf
latcol = [2]
loncol = [3]
df_lat = pd.read_csv(r'G:\Documents\Thesis\Outputs\concat_Xenos_combineds.csv', usecols = latcol)
df_lon = pd.read_csv(r'G:\Documents\Thesis\Outputs\concat_Xenos_combineds.csv', usecols = loncol)
map = plt.figure(figsize=(15,15))
ax = plt.axes(projection=ccrs.EuroPP())
ax.coastlines(resolution='10m')
ax.add_feature(cf.LAND)
ax.add_feature(cf.OCEAN)
ax.add_feature(cf.COASTLINE)
ax.add_feature(cf.BORDERS, linestyle=':')
ax.add_feature(cf.LAKES, alpha=0.5)
ax.add_feature(cf.RIVERS)
ax.plot(df_lon, df_lat, markersize=2, marker='o', color='red', transform=ccrs.PlateCarree())
ax.stock_img()
As I said, the coordinates are distributed accross 4 parallel lines. but the plot produced is messy as anything with lines going all over the place:
How do I correct this pls?
Also, I have a third column with a numerical value representing the value_count of a specific feature type at each coordinate point, and would eventually like to incorperate this into the map some way (whether as different sized or coloured markers or different colours). whats the best way to achieve this? Is it worth trying to do a heatmap-style plot instead/
Any clarification needed don't hesitate to ask!
Thanks,
R

To get rid of red lines between the markers, pass linestyle='none' to plot().
Regarding your second question, you should probably use ax.scatter() and use
the value_count variable for color.

Related

Plot closer lines in foreground with pyplot

I am trying to project some 3D paths with pyplot. I am running into the issue that pyplot will doesn't plot overlapping lines correctly. If i run the following code:
import numpy as np
import matplotlib.pyplot as plt
# make figure
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_xlim([-1,1])
ax.set_ylim([-1,1])
ax.set_zlim([-1,1])
# define 2 easily distiguishable paths
path1 = np.array( [np.zeros(100),
np.linspace(0.5,-0.5,100),
np.ones(100)*0.5])
path2 = np.array( [np.linspace(0.5,-0.5,100),
np.ones(100)*0.5,
np.zeros(100)])
#plot paths in order
ax.plot(path1[0], path1[1], path1[2], 'r')
ax.plot(path2[0], path2[1], path2[2], 'b')
plt.show()
I get the image below. You can see that, even though the blue line should be behind the red one, it is projected in front since it was plotted later. For more complicated paths this behaviour becomes quite unpredictable. Is there a way (either in pyplot or another library) to change the behaviour such that the closest line is always in the foreground?
I ended up finding a reasonable solution. If the observer position is set at the start, you can you the 'zorder' parameter of the plot function to get correct behaviour. It's a bit of a pain but it works.

Seaborn showing x-tick labels overlapping

I am trying to make a box plot that looks like this.
Now, there are a lot of tickmarks that I do not need and truly do not show any additional information.
The code I am using is the following:
plot=sns.boxplot(y=MSE, x=Sim,
width=0.5,
palette='colorblind')
plot=sns.stripplot(y=MSE, x=Sim,
jitter=True,
marker='o',
alpha=0.15,
color='black')
plt.xlabel('xlabel')
plt.ylabel('ylabel')
plt.gca().invert_xaxis()
Where MSE and SIM are two numpy arrays of 400 elements each.
I reviewed some solutions that use locator_params and set_xticklabels. However, I want to know:
why this happen and,
is there a simple transformation in the MSE and SIM arrays to solve this?
I hope my questions are clear enough.
Thanks in advance.
Not very sure what you have as Sim, if it is an array of floats, then they are converted to categorical before plotting. The thing you can do, since the labels are not useful, is to use a range of values thats as long as the y-values.
With that, it still overlaps a lot because you are trying to fit 400 x ticks onto the x-axis, and the font size are set by default to be something readable. For example:
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
fig,ax = plt.subplots(figsize=(15,6))
MSE = [np.random.normal(0,1,10) for i in range(100)]
Sim = np.arange(len(MSE))
g = sns.boxplot(y=MSE, x=Sim, width=0.5,palette='colorblind',ax=ax)
You can set the font size to be smaller and they don't overlap but I guess its hardly readable:
So like you said in your case, they are not useful, you can do:
ax.set(xticks=Sim[0::10])

Pyplot errorbar cannot be passed an array of colours

I am trying to change the appearance of a diagram created using plt.errorbar, but I can't get it to change in the ways I would like.
To demonstrate the problem, I have made up some example data:
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.axes as axes
import numpy as np
Temps=np.array([18000,15000,14000,12000,11750,11500,10000,5750,6000])
Powers=np.array([1.2,1.0,0.5,.35,0.4,0.2,.15,5.3,4.9])
Errors=100*np.array([2,2,2,2,2,2,2,3,3])
I have a function that turns the temperature values into colours:
def makecolour(t):
a=(t-min(Temps))/(max(Temps)-min(Temps))
return [[1-A,0,A] for A in a]
I have also changed some of the other properties of the diagram.
plt.axes(facecolor='black')
plt.yscale('log')
plt.xscale('log')
plt.xlim(2e4,5e3)
plt.errorbar(Temps,Powers,xerr=Errors,ecolor=makecolour(Temps),fmt='.')
I can't get the data points to change colour, only the error bars. When I try to change the colour of the actual points:
plt.errorbar(Temps,Powers,xerr=Errors,ecolor=makecolour(Temps),fmt='.',color=makecolour(Temps))
"Breaks because it fails to interpret the array of colours."
It doesn't work and I'm don't know how to fix it. The closest I have come to a solution is hiding the data points entirely:
plt.errorbar(Temps,Powers,xerr=Errors,ecolor=makecolour(Temps),fmt='.',markersize=0)
"Not showing where the data point is isn't acceptable."`
But this not good enough.
I have also been struggling with the way the axis ticks are displayed when using plt.xscale('log'). Ideally, I want to display the tick labels as a plain integer as opposed to scientific notation, but neither of the solutions I have tried worked. I have tried:
ticker.LogFormatter(base=1)
axes.ticklabel_format(style='plain')
I have searched around on here for previous answers, but I have not found any disussions of similar problems with plt.errorbar. Any help would be much appreciated.
Here is a partial answer. Just first plot without markers and on the same plot without the errorlines.
About the tickers, this post proposes:
ax=plt.gca()
ax.xaxis.set_minor_formatter(ticker.ScalarFormatter())
ax.xaxis.set_major_formatter(ticker.ScalarFormatter())
Demo code:
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.axes as axes
import numpy as np
Temps=np.array([18000,15000,14000,12000,11750,11500,10000,5750,6000])
Powers=np.array([1.2,1.0,0.5,.35,0.4,0.2,.15,5.3,4.9])
Errors=100*np.array([2,2,2,2,2,2,2,3,3])
def makecolour(t):
a=(t-min(Temps))/(max(Temps)-min(Temps))
return [[1-A,0,A] for A in a]
plt.axes(facecolor='black')
plt.yscale('log')
plt.xscale('log')
plt.xlim(2e4,5e3)
ax=plt.gca()
ax.xaxis.set_minor_formatter(ticker.ScalarFormatter())
ax.xaxis.set_major_formatter(ticker.ScalarFormatter())
plt.errorbar(Temps,Powers,xerr=Errors,ecolor=makecolour(Temps),fmt='.',markersize=0)
plt.errorbar(Temps,Powers,xerr=None,fmt='.')
plt.show()

matplotlib plotting multiple lines in 3D

I am trying to plot multiple lines in a 3D plot using matplotlib. I have 6 datasets with x and y values. What I've tried so far was, to give each point in the data sets a z-value. So all points in data set 1 have z=1 all points of data set 2 have z=2 and so on.
Then I exported them into three files. "X.txt" containing all x-values, "Y.txt" containing all y-values, same for "Z.txt".
Here's the code so far:
#!/usr/bin/python
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
import pylab
xdata = '/X.txt'
ydata = '/Y.txt'
zdata = '/Z.txt'
X = np.loadtxt(xdata)
Y = np.loadtxt(ydata)
Z = np.loadtxt(zdata)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_wireframe(X,Y,Z)
plt.show()
What I get looks pretty close to what I need. But when using wireframe, the first point and the last point of each dataset are connected. How can I change the colour of the line for each data set and how can I remove the connecting lines between the datasets?
Is there a better plotting style then wireframe?
Load the data sets individually, and then plot each one individually.
I don't know what formats you have, but you want something like this
from mpl_toolkits.mplot3d.axes3d import Axes3D
import matplotlib.pyplot as plt
fig, ax = plt.subplots(subplot_kw={'projection': '3d'})
datasets = [{"x":[1,2,3], "y":[1,4,9], "z":[0,0,0], "colour": "red"} for _ in range(6)]
for dataset in datasets:
ax.plot(dataset["x"], dataset["y"], dataset["z"], color=dataset["colour"])
plt.show()
Each time you call plot (or plot_wireframe but i don't know what you need that) on an axes object, it will add the data as a new series. If you leave out the color argument matplotlib will choose them for you, but it's not too smart and after you add too many series' it will loop around and start using the same colours again.
n.b. i haven't tested this - can't remember if color is the correct argument. Pretty sure it is though.

Python Pylab pcolor options for publication quality plots

I am trying to make DFT (discrete fourier transforms) plots using pcolor in python. I have previously been using Mathematica 8.0 to do this but I find that the colorbar in mathematica 8.0 has bad one-to-one correlation with the data I try to represent. For instance, here is the data that I am plotting:
[[0.,0.,0.10664,0.,0.,0.,0.0412719,0.,0.,0.],
[0.,0.351894,0.,0.17873,0.,0.,0.,0.,0.,0.],
[0.10663,0.,0.178183,0.,0.,0.,0.0405148,0.,0.,0.],
[0.,0.177586,0.,0.,0.,0.0500377,0.,0.,0.,0.],
[0.,0.,0.,0.,0.0588906,0.,0.,0.,0.,0.],
[0.,0.,0.,0.0493811,0.,0.,0.,0.,0.,0.],
[0.0397341,0.,0.0399249,0.,0.,0.,0.,0.,0.,0.],
[0.,0.,0.,0.,0.,0.,0.,0.,0.,0.],
[0.,0.,0.,0.,0.,0.,0.,0.,0.,0.],
[0.,0.,0.,0.,0.,0.,0.,0.,0.,0.]]
So, its a lot of zeros or small numbers in a DFT matrix or small quantity of high frequency energies.
When I plot this using mathematica, this is the result:
The color bar is off and I thought I'd like to plot this with python instead.
My python code (that I hijacked from here) is:
from numpy import corrcoef, sum, log, arange
from numpy.random import rand
#from pylab import pcolor, show, colorbar, xticks, yticks
from pylab import *
data = np.array([[0.,0.,0.10664,0.,0.,0.,0.0412719,0.,0.,0.],
[0.,0.351894,0.,0.17873,0.,0.,0.,0.,0.,0.],
[0.10663,0.,0.178183,0.,0.,0.,0.0405148,0.,0.,0.],
[0.,0.177586,0.,0.,0.,0.0500377,0.,0.,0.,0.],
[0.,0.,0.,0.,0.0588906,0.,0.,0.,0.,0.],
[0.,0.,0.,0.0493811,0.,0.,0.,0.,0.,0.],
[0.0397341,0.,0.0399249,0.,0.,0.,0.,0.,0.,0.],
[0.,0.,0.,0.,0.,0.,0.,0.,0.,0.],
[0.,0.,0.,0.,0.,0.,0.,0.,0.,0.],
[0.,0.,0.,0.,0.,0.,0.,0.,0.,0.]], np.float)
pcolor(data)
colorbar()
yticks(arange(0.5,10.5),range(0,10))
xticks(arange(0.5,10.5),range(0,10))
#show()
savefig('/home/mydir/foo.eps',figsize=(4,4),dpi=100)
And this python code plots as:
Now here is my question/list of questions:
I like how python plots this and would like to use this but...
How do I make all the "blue" which represents "0" go away like it does in my mathematica plot?
How do I rotate the plot to have the bright red spot in the top left corner?
The way I set the "dpi", is that correct?
Any useful references that I should use to strengthen my love for python?
I have looked through other questions on here and the user manual for numpy but found not much help.
I plan on publishing this data and it is rather important that I get all the bits and pieces right! :)
Edit:
Modified python code and resulting plot! What improvements would one suggest to this to make it publication worthy?
from numpy import corrcoef, sum, log, arange, save
from numpy.random import rand
from pylab import *
data = np.array([[0.,0.,0.10664,0.,0.,0.,0.0412719,0.,0.,0.],
[0.,0.351894,0.,0.17873,0.,0.,0.,0.,0.,0.],
[0.10663,0.,0.178183,0.,0.,0.,0.0405148,0.,0.,0.],
[0.,0.177586,0.,0.,0.,0.0500377,0.,0.,0.,0.],
[0.,0.,0.,0.,0.0588906,0.,0.,0.,0.,0.],
[0.,0.,0.,0.0493811,0.,0.,0.,0.,0.,0.],
[0.0397341,0.,0.0399249,0.,0.,0.,0.,0.,0.,0.],
[0.,0.,0.,0.,0.,0.,0.,0.,0.,0.],
[0.,0.,0.,0.,0.,0.,0.,0.,0.,0.],
[0.,0.,0.,0.,0.,0.,0.,0.,0.,0.]], np.float)
v1 = abs(data).max()
v2 = abs(data).min()
pcolor(data, cmap="binary")
colorbar()
#xlabel("X", fontsize=12, fontweight="bold")
#ylabel("Y", fontsize=12, fontweight="bold")
xticks(arange(0.5,10.5),range(0,10),fontsize=19)
yticks(arange(0.5,10.5),range(0,10),fontsize=19)
axis([0,7,0,7])
#show()
savefig('/home/mydir/Desktop/py_dft.eps',figsize=(4,4),dpi=600)
The following will get you closer to what you want:
import matplotlib.pyplot as plt
plt.pcolor(data, cmap=plt.cm.OrRd)
plt.yticks(np.arange(0.5,10.5),range(0,10))
plt.xticks(np.arange(0.5,10.5),range(0,10))
plt.colorbar()
plt.gca().invert_yaxis()
plt.gca().set_aspect('equal')
plt.show()
The list of available colormaps by default is here. You'll need one that starts out white.
If none of those suits your needs, you can try generating your own, start by looking at LinearSegmentedColormap.
Just for the record, in Mathematica 9.0:
GraphicsGrid#{{MatrixPlot[l,
ColorFunction -> (ColorData["TemperatureMap"][Rescale[#, {Min#l, Max#l}]] &),
ColorFunctionScaling -> False], BarLegend[{"TemperatureMap", {0, Max#l}}]}}

Categories