Matplotlib Colormaps – Choosing a different color for each graph/line/subject

I created a script that reads and plots .txt files and their content (numbers/values). Each .txt file is located in a different folder. Each folder, in turn, represents one subject from which the data stems.

This code works fine. Python reads each single .txt. file and plots 23 individual graphs/lines into one single plot. Python uses some standard colors here, i.e., each graph is automatically presented in a different color.

What I would like to do is the following: Instead of using the standard colors that are assigned by python automatically without adding any color related code, I would like to use a specific colormap (for example "plasma") from matplotlib.

The problem: no matter what code from the internet I use, all graphs/lines/subjects always receive the same color (e.g. the first color or last color from the plasma colormap).

How do I specify the code so that every line gets one distinct color from a colormap of choice?

Here is my code:

# Initialize import numpy as np import matplotlib.pyplot as plt from scipy import signal from matplotlib.pyplot import cm # Numpy.loadtxt – Loads data from a textfile. Scipy.signal.welch – Creation of the FFT/power-spectrum. f, Pxx_den creates the ideal frequencies/FFT (f, Welch = Power Spectrum or Power Spectral Density) Subjects = ["Subject1", "Subject2", "Subject3", "Subject4", "Subject5", "Subject7", "Subject8", "Subject9", "Subject10", "Subject11", "Subject12", "Subject13", "Subject14", "Subject15", "Subject16", "Subject17", "Subject18", "Subject19", "Subject20", "Subject22", "Subject23", "Subject24", "Subject25"] for Subject in Subjects: Subject = np.loadtxt("/volumes/SanDisk2/fmri/dataset/processed/extracted_timeseriespython/restingstate/{0}/TimeSeries.SPC.Core_ROI.{0}.txt".format(Subject), comments="#", delimiter=None, converters=None, skiprows=0, usecols=0, unpack=False, ndmin=0, encoding=None, max_rows=None, like=None) f, Welch = signal.welch(Subject, fs=1.0, window="hann", nperseg=None, noverlap=None, nfft=1024, detrend="constant", return_onesided=True, scaling="density", axis=-1, average="mean") cmap = plt.get_cmap("inferno") slicedCM = cmap(np.linspace(0, 1, len(Subjects))) plt.plot(f, Welch, c=slicedCM[Subjects.index(Subject)]) # Grid labels plt.title("Power Spectrum for all subjects", fontsize=12, fontweight="bold") plt.xlabel("Log Frequency [Hz]", fontsize=11, fontweight="bold") plt.ylabel("Log Power [Hz]", fontsize=11, fontweight="bold") # Grid dimenions and style plt.xlim([0.005, 0.2]) # x-axis range plt.ylim([0, 100]) # y-axis range plt.xticks(np.arange(0, 0.21, 0.025)) # x ticks range (start, end, step) plt.yticks(np.arange(0, 101, 10)) # y ticks range (start, end, step) plt.grid(True) # Show grid plt.rc("axes", axisbelow=True) # Grid behind figures plt.rc("grid", linestyle="-", color="black") # Grid look # Show result plt.show() 

Here is the resulting screenshot, showing that the standard colors are used instead of the desired plasma colormap:

screenshot

I'm running matplotlib 3.5.0 with MacOSX as backend.

3

3 Answers

enter image description here

You want to give to the colormap instance an argument varying between 0 and 1, this requires a minimum of planning, e.g.,

x = np.linspace(0,355/113, 101) p = plt.get_cmap('plasma') n = 23 for i in range(n): plt.plot(x, np.sin(x-i/2/n), color=p(i/(n-1))) 
1

One way to achieve your goal is to slice-up a colormap and then plot each line with one of the resulting colors. See the lines below that can be integrated in your code in appropriate places.

import numpy as np import matplotlib.pyplot as plt # 1. Choose your desired colormap cmap = plt.get_cmap('plasma') # 2. Segmenting the whole range (from 0 to 1) of the color map into multiple segments slicedCM = cmap(np.linspace(0, 1, len(Subjects))) # 3. Color the i-th line with the i-th color, i.e. slicedCM[i] plt.plot(f, Welch, c=slicedCM[Subjects.index(Subject)]) 

(The first two lines can be put in the beginning and you can replace the line plotting curves in your code with the third line of code suggested above.)

Alternatively, and perhaps a neater approach, is using the below lines inside your main loop through Subjects:

cmap = plt.get_cmap('inferno') plt.plot(f, Welch, c=cmap(Subjects.index(Subject)/len(Subjects))) 

(I see in your question that you are changing Subject when you load the file again into Subject. Just use another variable name, say, data = np.loadtxt... and then f, Welch = signal.welch(data, ..... Keep the codes for plotting with different colors as suggested above and you won't have any problem.)

11

My CMasher has the function take_cmap_colors() (), which was written to handle exactly this case. Simply provide it with a colormap, the number of colors and optionally a range that you want, and it will return you with a list of colors (in a format that MPL understands) taken uniformly from the provided colormap.

So, in your particular case, you could do this with:

# Import CMasher import cmasher as cmr # Obtain colors from a colormap colors = cmr.take_cmap_colors('inferno', len(Subjects)) # YOUR FOR-LOOP for Subject, color in zip(Subjects, colors): Subject = np.loadtxt("/volumes/SanDisk2/fmri/dataset/processed/extracted_timeseriespython/restingstate/{0}/TimeSeries.SPC.Core_ROI.{0}.txt".format(Subject), comments="#", delimiter=None, converters=None, skiprows=0, usecols=0, unpack=False, ndmin=0, encoding=None, max_rows=None, like=None) f, Welch = signal.welch(Subject, fs=1.0, window="hann", nperseg=None, noverlap=None, nfft=1024, detrend="constant", return_onesided=True, scaling="density", axis=-1, average="mean") plt.plot(f, Welch, c=color) 

You can provide the function with the name of any registered colormap in MPL, or with a Colormap object if you use custom, non-registered colormaps.

Also take a look at the colormaps that CMasher provides to you as well (). You might find a better candidate for your plot in there.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like