i've got a problem using MatlobLib with "Custom" Shapes from a shapereader. Importing and viewing inserted faces works fine, but i'm not able to place a colorbar on my figure.
I already tried several ways from the tutorial, but im quite sure there is a smart solution for this problem.
maybe somebody can help me, my current code is attached below:
from formencode.national import pycountry
import itertools
from matplotlib import cm, pyplot
from matplotlib import
from mpl_toolkits.basemap import Basemap
from numpy.dual import norm
import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader
import matplotlib as mpl
import matplotlib.colors as colors
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import numpy as np
def draw_map_for_non_normalized_data_with_alpha2_counrty_description(data, title=None):
m = Basemap()
ax = plt.axes(projection=ccrs.PlateCarree())
list = []
sum = 0
for key in data:
sum += data[key]
for key in data.keys():
new_val = (data[key]+0.00)/sum
list.append(new_val)
data[key] = new_val
#===========================================================================
# print str(min(list))
# print str(max(list))
#===========================================================================
cmap = mpl.cm.cool
colors = matplotlib.colors.Normalize(min(list)+0.0, max(list)+0.0)
labels = []
features = []
for country in shpreader.Reader(shapename).records():
a3_code = country.attributes["gu_a3"]
try :
a2_code = pycountry.countries.get(alpha3=a3_code).alpha2
except:
a2_code = ""
if a2_code in data:
val = data[a2_code]
color = cm.jet(norm(val))
print str(val) + " value for color: " + str(color)
labels.append(country.attributes['name_long'])
feat = ax.add_geometries(country.geometry, ccrs.PlateCarree(), facecolor=color, label=country.attributes['name_long'])
features.append(feat)
#ax.legend(features, labels, loc='upper right')
#===========================================================================
# fig = pyplot.figure(figsize=(8,3))
# ax1 = fig.add_axes([0.05, 0.80, 0.9, 0.15])
#===========================================================================
#cbar = m.colorbar(location='bottom')
cb1 = mpl.colorbar.ColorbarBase(ax, cmap=cmap,norm=colors,orientation='horizontal')
cb1.set_label('foo')
m.drawcoastlines()
m.drawcountries()
if title:
plt.title(title)
plt.show()
as you can see inside the code, i already tried several ways, but none of them worked for me.
maybe somebody has "the" hint for me.
thanks for help,
kind regards
As mentioned in the comments above, i would think twice about mixing Basemap and Cartopy, is there a specific reason to do so? Both are basically doing the same thing, extending Matplotlib with geographical plotting capabilities. Both are valid to use, they both have their pro's and con's.
In your example you have a Basemap axes m, a Cartopy axes ax and you are using the Pylab interface by using plt. which operates on the currently active axes. Perhaps it theoretically possible, but it seems prone to errors to me.
I cant modify your example to make it work, since the data is missing and your code is not valid Python, the indentation for the function is incorrect for example. But here is a Cartopy-only example showing how you can plot a Shapefile and use the same cmap/norm combination to add a colorbar to the axes.
One difference with your code is that you provide the axes containing the map to the ColorbarBase function, this should be a seperate axes specifically for the colorbar.
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import matplotlib as mpl
import cartopy.io.shapereader as shpreader
fig, ax = plt.subplots(figsize=(12,6),
subplot_kw={'projection': ccrs.PlateCarree()})
norm = mpl.colors.Normalize(vmin=0, vmax=1000000)
cmap = plt.cm.RdYlBu_r
for n, country in enumerate(shpreader.Reader(r'D:\ne_50m_admin_0_countries_lakes.shp').records()):
ax.add_geometries(country.geometry, ccrs.PlateCarree(),
facecolor=cmap(norm(country.attributes['gdp_md_est'])),
label=country.attributes['name'])
ax.set_title('gdp_md_est')
cax = fig.add_axes([0.95, 0.2, 0.02, 0.6])
cb = mpl.colorbar.ColorbarBase(cax, cmap=cmap, norm=norm, spacing='proportional')
cb.set_label('gdp_md_est')
Related
I want to set the formatting of the y-axis offset in my plot to non-scientific notation, but I can't find a setting to do this. Other questions and their solutions describe how to either remove the offset altogether, or set the y-ticks to scientific/plain notation; I haven't found an answer for setting the notation of the offset itself.
I've already tried using these two options, but I think they're meant for the y-ticks, not the offsets:
ax.ticklabel_format(axis='y', style='plain', useOffset=6378.1)
and
ax.get_yaxis().get_major_formatter().set_scientific(False)
So, the actual result is +6.3781e3, when I want +6378.1
Any way to do this?
Edit: Added example code and figure:
#!/usr/bin/env python
from matplotlib import pyplot as plt
from matplotlib import ticker
plt.rcParams['font.family'] = 'monospace'
import random
Date = range(10)
R = [6373.1+10*random.random() for i in range(10)]
fig, ax = plt.subplots(figsize=(9,6))
ax.plot(Date,R,'-D',zorder=2,markersize=3)
ax.ticklabel_format(axis='y', style='plain', useOffset=6378.1)
ax.set_ylabel('Mean R (km)',fontsize='small',labelpad=1)
plt.show()
You can subclass the default ScalarFormatter and replace the get_offset method, such that it would simply return the offset as it is. Note that if you wanted to make this compatible with the multiplicative "offset", this solution would need to be adapted (currently it just prints a warning).
from matplotlib import pyplot as plt
import matplotlib.ticker
import random
class PlainOffsetScalarFormatter(matplotlib.ticker.ScalarFormatter):
def get_offset(self):
if len(self.locs) == 0:
return ''
if self.orderOfMagnitude:
print("Your plot will likely be labelled incorrectly")
return self.offset
Date = range(10)
R = [6373.1+10*random.random() for i in range(10)]
fig, ax = plt.subplots(figsize=(9,6))
ax.plot(Date,R,'-D',zorder=2,markersize=3)
ax.yaxis.set_major_formatter(PlainOffsetScalarFormatter())
ax.ticklabel_format(axis='y', style='plain', useOffset=6378.1)
ax.set_ylabel('Mean R (km)',fontsize='small',labelpad=1)
plt.show()
A way to do this is to disable the offset text itself and add your custom ax.text there as follows
from matplotlib import pyplot as plt
import random
plt.rcParams['font.family'] = 'monospace'
offset = 6378.1
Date = range(10)
R = [offset+10*random.random() for i in range(10)]
fig, ax = plt.subplots(figsize=(9,6))
ax.plot(Date,R,'-D',zorder=2,markersize=3)
ax.ticklabel_format(axis='y', style='plain', useOffset=offset)
ax.set_ylabel('Mean R (km)',fontsize='small',labelpad=1)
ax.yaxis.offsetText.set_visible(False)
ax.text(x = 0.0, y = 1.01, s = str(offset), transform=ax.transAxes)
plt.show()
I'm trying to make my swarmplot easier to read in black&white and for people that are color-blind, by having the hue affect not just the color but also another geometrical aspect of the marker.
MWE
import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="whitegrid")
tips = sns.load_dataset("tips")
fig, ax = plt.subplots(1,1)
ax = sns.swarmplot(x="day", y="total_bill", hue="sex",data=tips,size=8,ax=ax)
plt.show()
Result
Desired Result (the left one)
I actually had thought of the same problem a while ago. I did not come up with the greatest of solutions, but I have a hack that works OK. Unfortunately, it's much easier to implement if you use dodge=True.
The idea is to collect the PathCollections objects created by swarmplot. If dodge=True then you'll get N_cat*N_hues+N_hues collections (the N_hues extras are used to create the legend). You can simply iterate through that list. Since we want all hues to be the same, we use a N_hues stride to get all the collections corresponding to each of the hues. After that, you are free to update the paths of that collection to whatever Path object you choose. Refer to the documentation for Path to learn how to create paths.
To simplify things, I created some dummy scatter plots before hands to get some premade Paths that I can use. Of course, any Path should be able to work.
import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="whitegrid")
tips = sns.load_dataset("tips")
fig, ax = plt.subplots(1,1)
# dummy plots, just to get the Path objects
a = ax.scatter([1,2],[3,4], marker='s')
b = ax.scatter([1,2],[3,4], marker='^')
square_mk, = a.get_paths()
triangle_up_mk, = b.get_paths()
a.remove()
b.remove()
ax = sns.swarmplot(x="day", y="total_bill", hue="sex",data=tips,size=8,ax=ax, dodge=True)
N_hues = len(pd.unique(tips.sex))
c = ax.collections
for a in c[::N_hues]:
a.set_paths([triangle_up_mk])
for a in c[1::N_hues]:
a.set_paths([square_mk])
#update legend
ax.legend(c[-2:],pd.unique(tips.sex))
plt.show()
UPDATE A solution that "works" with dodge=False.
If you use dodge=False, then you'll get N+2 collections, one for each category, +2 for the legend. The problem is that all the different marker colors are jumbled up in these collections.
A possible, but ugly, solution is to loop through each element of the collection, and create an array of Path objects based one the color of each element.
import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="whitegrid")
tips = sns.load_dataset("tips")
fig, ax = plt.subplots(1,1)
ax = sns.swarmplot(x="day", y="total_bill", hue="sex",data=tips,size=8,ax=ax, dodge=False)
collections = ax.collections
unique_colors = np.unique(collections[0].get_facecolors(), axis=0)
markers = [triangle_up_mk, square_mk] # this array must be at least as large as the number of unique colors
for collection in collections:
paths = []
for current_color in collection.get_facecolors():
for possible_marker,possible_color in zip(markers, unique_colors):
if np.array_equal(current_color,possible_color):
paths.append(possible_marker)
break
collection.set_paths(paths)
#update legend
ax.legend(collections[-2:],pd.unique(tips.sex))
plt.show()
The following would provide a hack which allows to easily achieve the desired different markers for swarmplots (or more generally any categorical scatter plots). It can be used as is, just copy it on top of existing plot scripts.
The idea is to link the color of a scatter point with a marker. E.g. any scatter point would get a marker from a specified list automatically. As a consequence this only works for plots with different colors.
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
############## Begin hack ##############
class CM():
def __init__(self, markers=["o"]):
self.marker = np.array(markers)
self.colors = []
def get_markers_for_colors(self, c):
for _co in c:
if not any((_co == x).all() for x in self.colors):
self.colors.append(_co)
ind = np.array([np.where((self.colors == row).all(axis=1)) \
for row in c]).flatten()
return self.marker[ind % len(self.marker)]
def get_legend_handles(self, **kwargs):
return [plt.Line2D([0],[0], ls="none", marker=m, color=c, mec="none", **kwargs) \
for m,c in zip(self.marker, self.colors)]
from matplotlib.axes._axes import Axes
import matplotlib.markers as mmarkers
cm = CM(plt.Line2D.filled_markers)
old_scatter = Axes.scatter
def new_scatter(self, *args, **kwargs):
sc = old_scatter(self, *args, **kwargs)
c = kwargs.get("c", None)
if isinstance(c, np.ndarray):
m = cm.get_markers_for_colors(c)
paths = []
for _m in m:
marker_obj = mmarkers.MarkerStyle(_m)
paths.append(marker_obj.get_path().transformed(
marker_obj.get_transform()))
sc.set_paths(paths)
return sc
Axes.scatter = new_scatter
############## End hack. ##############
# Copy and past to your file ##########
## Code ###
sns.set(style="whitegrid")
tips = sns.load_dataset("tips")
fig, ax = plt.subplots(1,1)
## Optionally specify own markers:
#cm.marker = np.array(["^", "s"])
ax = sns.swarmplot(x="day", y="total_bill", hue="sex",data=tips,size=8,ax=ax)
## Optionally adjust legend:
_,l = ax.get_legend_handles_labels()
ax.legend(cm.get_legend_handles(markersize=8),l)
plt.show()
Thank you to #ImportanceOfBeingErnest for the solution. I tried to edit his/her solution to fix some minor issues but in the end he/she suggested that I post my own answer.
This solution is the same as his/hers but it doesn't change the behavior of normal scatter when the marker array is not specified. It is also simpler to apply and it fixes the error where the legend loses the title.
The following figure is produced by the code below:
import seaborn as sns
import matplotlib.pyplot as plt
############## Begin hack ##############
from matplotlib.axes._axes import Axes
from matplotlib.markers import MarkerStyle
from seaborn import color_palette
from numpy import ndarray
def GetColor2Marker(markers):
palette = color_palette()
mkcolors = [(palette[i]) for i in range(len(markers))]
return dict(zip(mkcolors,markers))
def fixlegend(ax,markers,markersize=8,**kwargs):
# Fix Legend
legtitle = ax.get_legend().get_title().get_text()
_,l = ax.get_legend_handles_labels()
palette = color_palette()
mkcolors = [(palette[i]) for i in range(len(markers))]
newHandles = [plt.Line2D([0],[0], ls="none", marker=m, color=c, mec="none", markersize=markersize,**kwargs) \
for m,c in zip(markers, mkcolors)]
ax.legend(newHandles,l)
leg = ax.get_legend()
leg.set_title(legtitle)
old_scatter = Axes.scatter
def new_scatter(self, *args, **kwargs):
colors = kwargs.get("c", None)
co2mk = kwargs.pop("co2mk",None)
FinalCollection = old_scatter(self, *args, **kwargs)
if co2mk is not None and isinstance(colors, ndarray):
Color2Marker = GetColor2Marker(co2mk)
paths=[]
for col in colors:
mk=Color2Marker[tuple(col)]
marker_obj = MarkerStyle(mk)
paths.append(marker_obj.get_path().transformed(marker_obj.get_transform()))
FinalCollection.set_paths(paths)
return FinalCollection
Axes.scatter = new_scatter
############## End hack. ##############
# Example Test
sns.set(style="whitegrid")
tips = sns.load_dataset("tips")
# To test robustness
tips.loc[(tips['sex']=="Male") & (tips['day']=="Fri"),'sex']='Female'
tips.loc[(tips['sex']=="Female") & (tips['day']=="Sat"),'sex']='Male'
Markers = ["o","P"]
fig, axs = plt.subplots(1,2,figsize=(14,5))
axs[0] = sns.swarmplot(x="day", y="total_bill", hue="sex",data=tips,size=8,ax=axs[0])
axs[0].set_title("Original")
axs[1] = sns.swarmplot(x="day", y="total_bill", hue="sex",data=tips,size=8,ax=axs[1],co2mk=Markers)
axs[1].set_title("Hacked")
fixlegend(axs[1],Markers)
plt.show()
I'm trying to create a heatmap in seaborn (python) with certain squares colored with a different color, (these squares contain insignificant data - in my case it will be squares with values less than 1.3, which is -log of p-values >0.05). I couldn't find such function. Masking these squares also didn't work.
Here is my code:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
import seaborn as sns; sns.set()
data = [[1.3531363408, 3.339479161, 0.0760855365], [5.1167382617, 3.2890920405, 2.4764601828], [0.0025058257, 2.3165128345, 1.6532714962], [0.2600549869, 5.8427407219, 6.6627226609], [3.0828581725, 16.3825494439, 12.6722666929], [2.3386307357, 13.7275065772, 12.5760972276], [1.224683813, 2.2213656372, 0.6300876451], [0.4163788387, 1.8128374089, 0.0013106046], [0.0277592882, 2.9286203949, 0.810978992], [0.0086613622, 0.6181261247, 1.8287878837], [1.0174519889, 0.2621290291, 0.1922637697], [3.4687429571, 4.0061981716, 0.5507951444], [7.4201304939, 3.881457516, 0.1294141768], [2.5227546319, 6.0526491816, 0.3814362442], [8.147538027, 14.0975727815, 7.9755706939]]
cmap2 = mpl.colors.ListedColormap(sns.cubehelix_palette(n_colors=20, start=0, rot=0.4, gamma=1, hue=0.8, light=0.85, dark=0.15, reverse=False))
ax = sns.heatmap(data, cmap=cmap2, vmin=0)
plt.show()
I want to add that I'm not very advanced programmer.
OK, so I can answer my question myself now :) Here is the code that solved the problem:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
import seaborn as sns; sns.set()
data = np.array([[1.3531363408, 3.339479161, 0.0760855365],
[5.1167382617, 3.2890920405, 2.4764601828],
[0.0025058257, 2.3165128345, 1.6532714962],
[0.2600549869, 5.8427407219, 6.6627226609],
[3.0828581725, 16.3825494439, 12.6722666929],
[2.3386307357, 13.7275065772, 12.5760972276],
[1.224683813, 2.2213656372, 0.6300876451],
[0.4163788387, 1.8128374089, 0.0013106046],
[0.0277592882, 2.9286203949, 0.810978992],
[0.0086613622, 0.6181261247, 1.8287878837],
[1.0174519889, 0.2621290291, 0.1922637697],
[3.4687429571, 4.0061981716, 0.5507951444],
[7.4201304939, 3.881457516, 0.1294141768],
[2.5227546319, 6.0526491816, 0.3814362442],
[8.147538027, 14.0975727815, 7.9755706939]])
cmap1 = mpl.colors.ListedColormap(['c'])
fig, ax = plt.subplots(figsize=(8, 8))
sns.heatmap(data, ax=ax)
sns.heatmap(data, mask=data > 1.3, cmap=cmap1, cbar=False, ax=ax)
plt.show()
So the problem with masking which didn't work before was that it works only on arrays not on lists.
And another thing is just plotting the heatmap twice -second time with masking.
The only thing I still don't understand is that it masks opposite fields from what is written.. I want to mask values below 1.3, but then it colored values above 1.3.. So I wrote mask=data >1.3 and now it works...
as the title suggests, this is a straightforward question: ticklabel_format simply has no effect whatsoever on my figure.
here's the script:
import sys
import math
import yaml
import numpy as np
import matplotlib.pyplot as plt
dwarf = sys.argv[1]
pts = np.empty([100,100])
fig = plt.figure()
fig.suptitle('J value - %s'%dwarf,fontsize=18)
m = plt.imshow(pts,cmap='rainbow',extent=[-2,2,5,9])
plt.xlabel(r'$r_s [kpc]$',fontsize=18)
plt.ylabel(r'$\rho_s [M_{sun} kpc^{-3}]$',fontsize=18)
plt.ticklabel_format(style='sci',axis='x',scilimits=(-2,2))
plt.ticklabel_format(style='sci',axis='y',scilimits=(5,9))
plt.grid()
cx = plt.colorbar(m,pad=0)
cx.set_label(r'$log_{10}(J(\rho_s,r_s))$',fontsize=18)
plt.savefig('output/gridJ_%s.png'%dwarf,dpi=100,format='png')
plt.show()
on the produced plot, the ticks on the axes are simply the values dictated by extent kwarg in plt.imshow and not the nice scientific notation 10**n I would like it to have.
Any idea why it's misbehaving? Thank you
Just use matplotlib.pyplot.ylim or matplotlib.pyplot.xlim to set the limits.
How does one set the color of a line in matplotlib with scalar values provided at run time using a colormap (say jet)? I tried a couple of different approaches here and I think I'm stumped. values[] is a storted array of scalars. curves are a set of 1-d arrays, and labels are an array of text strings. Each of the arrays have the same length.
fig = plt.figure()
ax = fig.add_subplot(111)
jet = colors.Colormap('jet')
cNorm = colors.Normalize(vmin=0, vmax=values[-1])
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=jet)
lines = []
for idx in range(len(curves)):
line = curves[idx]
colorVal = scalarMap.to_rgba(values[idx])
retLine, = ax.plot(line, color=colorVal)
#retLine.set_color()
lines.append(retLine)
ax.legend(lines, labels, loc='upper right')
ax.grid()
plt.show()
The error you are receiving is due to how you define jet. You are creating the base class Colormap with the name 'jet', but this is very different from getting the default definition of the 'jet' colormap. This base class should never be created directly, and only the subclasses should be instantiated.
What you've found with your example is a buggy behavior in Matplotlib. There should be a clearer error message generated when this code is run.
This is an updated version of your example:
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.cm as cmx
import numpy as np
# define some random data that emulates your indeded code:
NCURVES = 10
np.random.seed(101)
curves = [np.random.random(20) for i in range(NCURVES)]
values = range(NCURVES)
fig = plt.figure()
ax = fig.add_subplot(111)
# replace the next line
#jet = colors.Colormap('jet')
# with
jet = cm = plt.get_cmap('jet')
cNorm = colors.Normalize(vmin=0, vmax=values[-1])
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=jet)
print scalarMap.get_clim()
lines = []
for idx in range(len(curves)):
line = curves[idx]
colorVal = scalarMap.to_rgba(values[idx])
colorText = (
'color: (%4.2f,%4.2f,%4.2f)'%(colorVal[0],colorVal[1],colorVal[2])
)
retLine, = ax.plot(line,
color=colorVal,
label=colorText)
lines.append(retLine)
#added this to get the legend to work
handles,labels = ax.get_legend_handles_labels()
ax.legend(handles, labels, loc='upper right')
ax.grid()
plt.show()
Resulting in:
Using a ScalarMappable is an improvement over the approach presented in my related answer:
creating over 20 unique legend colors using matplotlib
I thought it would be beneficial to include what I consider to be a more simple method using numpy's linspace coupled with matplotlib's cm-type object. It's possible that the above solution is for an older version. I am using the python 3.4.3, matplotlib 1.4.3, and numpy 1.9.3., and my solution is as follows.
import matplotlib.pyplot as plt
from matplotlib import cm
from numpy import linspace
start = 0.0
stop = 1.0
number_of_lines= 1000
cm_subsection = linspace(start, stop, number_of_lines)
colors = [ cm.jet(x) for x in cm_subsection ]
for i, color in enumerate(colors):
plt.axhline(i, color=color)
plt.ylabel('Line Number')
plt.show()
This results in 1000 uniquely-colored lines that span the entire cm.jet colormap as pictured below. If you run this script you'll find that you can zoom in on the individual lines.
Now say I want my 1000 line colors to just span the greenish portion between lines 400 to 600. I simply change my start and stop values to 0.4 and 0.6 and this results in using only 20% of the cm.jet color map between 0.4 and 0.6.
So in a one line summary you can create a list of rgba colors from a matplotlib.cm colormap accordingly:
colors = [ cm.jet(x) for x in linspace(start, stop, number_of_lines) ]
In this case I use the commonly invoked map named jet but you can find the complete list of colormaps available in your matplotlib version by invoking:
>>> from matplotlib import cm
>>> dir(cm)
A combination of line styles, markers, and qualitative colors from matplotlib:
import itertools
import matplotlib as mpl
import matplotlib.pyplot as plt
N = 8*4+10
l_styles = ['-','--','-.',':']
m_styles = ['','.','o','^','*']
colormap = mpl.cm.Dark2.colors # Qualitative colormap
for i,(marker,linestyle,color) in zip(range(N),itertools.product(m_styles,l_styles, colormap)):
plt.plot([0,1,2],[0,2*i,2*i], color=color, linestyle=linestyle,marker=marker,label=i)
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.,ncol=4);
UPDATE: Supporting not only ListedColormap, but also LinearSegmentedColormap
import itertools
import matplotlib.pyplot as plt
Ncolors = 8
#colormap = plt.cm.Dark2# ListedColormap
colormap = plt.cm.viridis# LinearSegmentedColormap
Ncolors = min(colormap.N,Ncolors)
mapcolors = [colormap(int(x*colormap.N/Ncolors)) for x in range(Ncolors)]
N = Ncolors*4+10
l_styles = ['-','--','-.',':']
m_styles = ['','.','o','^','*']
fig,ax = plt.subplots(gridspec_kw=dict(right=0.6))
for i,(marker,linestyle,color) in zip(range(N),itertools.product(m_styles,l_styles, mapcolors)):
ax.plot([0,1,2],[0,2*i,2*i], color=color, linestyle=linestyle,marker=marker,label=i)
ax.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.,ncol=3,prop={'size': 8})
U may do as I have written from my deleted account (ban for new posts :( there was). Its rather simple and nice looking.
Im using 3-rd one of these 3 ones usually, also I wasny checking 1 and 2 version.
from matplotlib.pyplot import cm
import numpy as np
#variable n should be number of curves to plot (I skipped this earlier thinking that it is obvious when looking at picture - sorry my bad mistake xD): n=len(array_of_curves_to_plot)
#version 1:
color=cm.rainbow(np.linspace(0,1,n))
for i,c in zip(range(n),color):
ax1.plot(x, y,c=c)
#or version 2: - faster and better:
color=iter(cm.rainbow(np.linspace(0,1,n)))
c=next(color)
plt.plot(x,y,c=c)
#or version 3:
color=iter(cm.rainbow(np.linspace(0,1,n)))
for i in range(n):
c=next(color)
ax1.plot(x, y,c=c)
example of 3:
Ship RAO of Roll vs Ikeda damping in function of Roll amplitude A44