Selective patterns with Matplotlib imshow
Asked Answered
C

1

4

Is there a way to place custom patterns into selected areas on an imshow graph? To be precise, I need to make it so that, in addition to the numerical-data-carrying colored squares, I also have different patterns in other squares indicate different failure modes for the experiment (and also generate a key explaining the meaning of these different patterns). An example of a pattern that would be useful would be various types of crosshatches. i need to be able to do this without disrupting the main color-numerical data relationship on the graph.

Below is code from my attempt to use what was suggested in the answers. If I comment the error section the imshow shows up fine with white space wherever there is no data from the masking. I am not even attempting to do different kinds of crosshatching for different failure types or deal with cases where either the simulation or the experiment worked but the other didn't yet.

EDIT3: I am receiving error massages from the multiprocessing package about how it 'can't pickle' the object. Due to the program this is a part of it goes through the multiprocessing package. Any way to fix this or do it without add_patches (the plot method suggested below doesn't work, as the plotting happens on a completely different coordinate system and draws connecting lines)?

import numpy as np
import matplotlib.patches as patches
...
grid = np.ma.array(grid, mask=np.isnan(grid))
plot.imshow(grid, interpolation='nearest', aspect='equal', vmax = private.vmax, vmin = private.vmin)
if show_fail and faildat != []:
    faildat = faildat[np.lexsort((faildat[:,yind],faildat[:,xind]))]
    fails = []
    for i in range(len(faildat)):
        fails.append((faildat[i,1],faildat[i,0]))
    for F in fails:
        p = patches.Rectangle(F,1,1,hatch='/',fill=False)
        plot.add_patch(p)
plot.minorticks_off()
plot.set_xticks(range(len(placex)))        
plot.set_yticks(range(len(placey)))
plot.set_xticklabels(placex)        
plot.set_yticklabels(placey, rotation = 0)
plot.colorbar()
plot.show()
Crank answered 26/12, 2012 at 20:12 Comment(10)
Sorry, skimmed your code too fast. The problem is you are setting ax as the object that is returned by imshow, you need to add the patch objects to an axes object.Demetrademetre
also, importing matplotlib.pyplot as plot makes your code a little odd to read.Demetrademetre
Sorry I fixed the ax issue but forgot to update it here (I copied too quickly from what you wrote). matplotlib is not imported as plot, it's just that higher up in the code the axes was assigned to plot (it made the code easier to read in context). You'll notice when I go to call patch that it's imported as mpl.Crank
Did you get this working? I amend my statement about plot to be using it as a variable name at all confuses me.Demetrademetre
what version of matplotlib are you using?Demetrademetre
Can you past the exact error you are getting?Demetrademetre
File "C:\Python27\lib\multiprocessing\managers.py", line 758, in _callmethod conn.send((self._id, methodname, args, kwds)) PicklingError: Can't pickle <type 'function'>: attribute lookup builtin.function failedCrank
where did pickle and multiprocessing come into this?Demetrademetre
The graphing is part of a program made under the PYTHICS GUI environment, which does a lot of cross process passing.Crank
not to beat a dead horse, but patch objects appear to pickle fine.. p = mpl.patches.Rectangle((1,1),1,1,hatch='/',fill=False); pickle.dumps(p) does not raise any errors on my system...Demetrademetre
D
12

There are several ways to do this, which is better will depend on if you need to mark large regions or scattered individual pixels.

If you need to mark large regions, you can do this by added rectangles over the image:

import matplotlib as mpl
import matplotlib.pyplot as plt
from numpy.random import rand

ax = plt.gca()
ax.imshow(rand(50,50))
ax.add_patch(mpl.patches.Rectangle((2,2),20,20,hatch='//////////',fill=False,snap=False))
plt.draw()

Rectangle (doc) a variety of hash options. This is just adding additional artists on top of the image, they will not affect the data-color mapping in any way. The large number of / increases the density of the hash marks, which may be necessary to acctually see the hashing with small boxes.

ex:

from numpy.random import rand
import matplotlib as mpl
import matplotlib.pyplot as plt
     
ax = plt.gca()
ax.imshow(rand(50,50),interpolation='nearest')
for i,j in np.floor(50*rand(10,2)).astype('int'):
    ax.add_patch(mpl.patches.Rectangle((i-.5, j-.5), 1, 1, hatch='///////', fill=False, snap=False))

plt.draw()

image with some pixel hatched If you just need to mark a few pixels here and you might be able to get away with just plotting (using plot([x],[y],marker='x') and maybe playing with the marker size).

Demetrademetre answered 27/12, 2012 at 4:48 Comment(1)
This method works in general but is blocked by the specific packages that I am using. I am thus accepting it as an answer as it is generally useful for other users.Crank

© 2022 - 2024 — McMap. All rights reserved.