0

I have a plot in a Jupyter Notebook that maps annual population data against percentages. It looks like this:

Atheists and Believers in Hackney and London

The plot has the dimensions 800*400:

       plt.figure(figsize=(8,4));
       plt.ylim([0,100])
       ...
 IN[]: fig.get_size_inches()*fig.dpi
OUT[]: array([800., 400.])

Now that it's done I want to set an image in the background. If I now load in the image I want to use completely separately from the plot:

fig = plt.figure(figsize=(8,4));
plt.style.use('seaborn-muted')
img = mpimg.imread('london_skyline.png')
plt.imshow(img, cmap=cm.gray, alpha=0.2)

The code produces this:

London SKyline

I note that the y axis of the image is mapped in reverse, from 100-0 rather than 0-100, and the x axis is sized at 250. The image shape is (100, 250):

 IN[]: img.shape
OUT[]: (100, 250)

If I try to combine the background with the original plot everything is horribly resized and reshaped. Presumably what I need to do is reshape and resize the image so that it fits the shape, dimensions and orientation of the original plot (800, 400). I see, eg., that skimage.transform has the functions rescale and resize that may be of use.

Basically I want to keep the image as it is, but reshape it so that it slots into the original plot frame. So I would want to manipulate the image so that I could just add it to the original plot without it distorting anything, or itself being distorted.

Can anyone help?


Looking at Paul Brodersen's response below I used the extent keyword to resize my image, which solves my original problem. So my code now looks like this:


plt.figure(figsize=(8,4));
plt.ylim([0,100])
plt.plot(df1, color=col, linewidth=1.0, zorder=2);
plt.plot(df2, color=col, ls='-.',alpha=0.5, linewidth=1.0, zorder=2);
plt.gca().fill_between(df1.keys(), df1, df2,facecolor=col, alpha=0.05, zorder=2)
plt.imshow(img, cmap=cm.gray, alpha=0.1, zorder=1, extent=[0, 400, 0, 100])

which produces this:

enter image description here

However, as you'll notice, the plots don't appear on top of the image even though I have set the zorder arguments appropriately, and the whole image / plot is shrunk in the y dimension, so I feel I still have a few things to understand here.

Any more clues? tia.

Perhaps of interest - if I set the alpha of the image to 0.0 the plot lines still don't appear. I've also tried suggestions made elsewhere such as using larger zorder values (10, 15...), or using values such as 2.5. I have also tried setting the image to a negative order value, -1. None of them have helped so far.


Setting the extent to [2004, 2018, 0 , 100], as suggested in the comments below, produces this:

    plt.style.use('seaborn-muted')
    plt.ylim([0,100])
    plt.ylabel('% of population', fontsize=8)
    plt.rcParams['xtick.labelsize']=8    
    plt.rcParams['ytick.labelsize']=8

    plt.plot(hackney_df['Christian'], color='k', linewidth=1.0, zorder=2.5);
    plt.plot(london_df['Christian'], color='k', ls='-.',alpha=0.5, linewidth=1.0, zorder=2.5);
    plt.gca().fill_between(hackney_df['Christian'].keys(), hackney_df['Christian'], london_df['Christian'],facecolor='k', alpha=0.1, zorder=2.5)

    plt.imshow(img, cmap=cm.gray, alpha=0.1, extent=[2004, 2018, 0, 100])
    plt.title ('Hackney Christians compared to London', fontsize=9)
    plt.tight_layout()

enter image description here

So now I just need somehow to stretch the x axis out to a reasonable size.

Andy Wilson
  • 145
  • 2
  • 8
  • 1
    Does [this](https://stackoverflow.com/a/15160269/2912349) answer your question? – Paul Brodersen May 18 '20 at 10:27
  • That's definitely got me a lot closer to understanding. I knew this question must be basically FAQ as most people must face this issue on importing an image. I still need to flip the image on the horizontal axis and resize the whole thing appropriately. – Andy Wilson May 18 '20 at 10:42
  • If you show your progress, then people can help you figure out the details. ;-) – Paul Brodersen May 18 '20 at 10:43
  • Cheers, Paul - I've edited the post above to reflect the remaining issues. – Andy Wilson May 18 '20 at 11:06
  • The lines are there, but I think you are looking at the wrong part of the plot. Set `extent=[2004, 2018, 0, 100]`. – Paul Brodersen May 18 '20 at 11:33
  • that produces a plot just a few pixels wide (I'll add it in the post so you can see it). My feeling is that the extent settings are correct, but that the result just needs some tweaking to get the y scale and z order right. But I think I see what you mean. Isn't there a way to set the values passed to extent to equal the actually existing scaling / dimensions of the plot, rather than setting them manually? – Andy Wilson May 18 '20 at 12:18
  • The x axis is not set manually but autosizes according to the index of the data passed to the plot function, which has one row for each year from 2004-2018, with the year as the index. – Andy Wilson May 18 '20 at 12:25
  • Actually, you are right, of course. The truncated plot now at the end of my post, made by setting `extent=[2004, 2018, 0, 100]` is right - it's just that the x axis is now squeezed into too small a space, so I need to expand it somehow. – Andy Wilson May 18 '20 at 12:58

1 Answers1

0

Got it... after setting extent=[2004, 2018, 0, 100] I also needed to set the image aspect='auto'.

plt.imshow(img, cmap=cm.gray, alpha=0.1, extent=[2004, 2018, 0, 100], aspect='auto')
Andy Wilson
  • 145
  • 2
  • 8