9

I have a two dimensional array with 5 columns and some number of rows. The different columns have the following entriesx1 y1 x2 y2 z I want to plot an arrow from (x1,y1) to (x2,y2) and the color of the arrow should be taken from z column corresponding to some inbuilt colormap. How can I do this matplotlib/python?

1 Answer 1

18

You can do this:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.cm as cmx

DATA = np.random.rand(5,5)

cmap = plt.cm.jet

cNorm  = colors.Normalize(vmin=np.min(DATA[:,4]), vmax=np.max(DATA[:,4]))

scalarMap = cmx.ScalarMappable(norm=cNorm,cmap=cmap)

for idx in range(0,len(DATA[:,1])):
    colorVal = scalarMap.to_rgba(DATA[idx,4])
    plt.arrow(DATA[idx,0],  #x1
              DATA[idx,1],  # y1
              DATA[idx,2]-DATA[idx,0], # x2 - x1
              DATA[idx,3]-DATA[idx,1], # y2 - y1
              color=colorVal)

plt.show()  

You want to use scalarMap.to_rgba to turn your z value into an argument to pass to the color option of the arrow command.
Your result should look something like this:

enter image description here

EDIT
If you want to see the colorbar, too, things are a little bit more tricky. Here's an updated minimal example:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.cm as cmx
import matplotlib as mpl

DATA = np.random.rand(5,5)

cmap = plt.cm.jet

cNorm  = colors.Normalize(vmin=np.min(DATA[:,4]), vmax=np.max(DATA[:,4]))

scalarMap = cmx.ScalarMappable(norm=cNorm,cmap=cmap)

fig = plt.figure()
ax  = fig.add_axes([0.1, 0.1, 0.7, 0.85]) # [left, bottom, width, height]
axc = fig.add_axes([0.85, 0.10, 0.05, 0.85])

for idx in range(0,len(DATA[:,1])):
    colorVal = scalarMap.to_rgba(DATA[idx,4])
    ax.arrow(DATA[idx,0],  # x1
             DATA[idx,1],  # y1
             DATA[idx,2]-DATA[idx,0], # x2 - x1
             DATA[idx,3]-DATA[idx,1], # y2 - y1
             color=colorVal)

cb1 = mpl.colorbar.ColorbarBase(axc, cmap=cmap,
                                norm=cNorm,orientation='vertical')

plt.show() 

Things to note:

  • The additional import matplotlib as mpl to have access to the ColorbarBase
  • Now, there is an explicit need to specify two axes, one for the arrows and one for the colorbar. This second set of axis should have a reasonable size for the colorbar.
    The add_axes command takes [left, botton, width, height] in relative units as input. So the right side is given by left + width.
  • Plot the arrows on the first set of axis, ax, your initial figure.
  • Plot the colobar on the second set of axis, axc. Pass the cmap, the normalization, cNorm and an orientation as arguments.

Your figure should look something like this:

enter image description here

EDIT 2

If you want a different colored edge on the arrows, change color to facecolor (or fc) and specify an edgecolor (ec). Additionally, you may now want to control the width of the arrow (default = 0.001) and the width of the head (default = 3x width).

plt.arrow(DATA[idx,0],  #x1
          DATA[idx,1],  # y1
          DATA[idx,2]-DATA[idx,0], # x2 - x1
          DATA[idx,3]-DATA[idx,1], # y2 - y1
          facecolor=colorVal,
          edgecolor='k',
          width=0.005,
          head_width=0.01)
Sign up to request clarification or add additional context in comments.

2 Comments

It will be helpful if you could show how to plot the colorbar along with it as well, thanks
Is there a way to put edgecolor around an arrow? For example, the yellow one is hard to see unless there is a dark color edge. Also, what about a white arrow?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.