2

I would like to plot an orthogonal projection like this one:

orthogonal projection

using matplotlib, possibly including the 3D subplot. All the subplots should share common axes.

fig = plt.figure()
ax = fig.add_subplot(221, title="XZ")
bx = fig.add_subplot(222, title="YZ", sharey=ax)
cx = fig.add_subplot(223, title="XY", sharex=ax, sharey=[something like bx.Xaxis])
dx = fig.add_subplot(224, title="XYZ", projection="3d", sharex=ax, sharey=bx, sharez=[something like bx.Yaxis]

I can't figure out how to "link" the x-axis of one plot with the y-axis of another. Is there a way to accomplish this?

ali_m
74.5k28 gold badges230 silver badges313 bronze badges
asked Jan 30, 2015 at 15:23

3 Answers 3

0

Late to the party but...

You should be able to accomplish what you want by manually updating one subplot's axis data with the other subplots axis data.

Using the notation from your post, for example, you can match the ylim values of cx with the xlim values of bx using the get and set methods.

cx.set_ylim(bx.get_ylim())

Similarly, you can match tick labels and positions across subplots.

bx_xticks = bx.get_xticks()
bx_xticklabels = [label.get_text() for label in bx.get_xticklabels()]
cx.set_yticks(bx_xticks)
cx.set_yticklabels(bx_xticklabels)

You should be able to define any and all axis attributes and objects dynamically from an already instantiated subplot in this way.

answered May 17, 2016 at 1:22
0

Here is my approach to the problem, which is basically a condensed version of @elebards answer. I just add update limit methods to the axes class, so they get access to the set_xlim / set_ylim methods. Then I connect these functions to the callbacks of the axis I want to synchronize it. When these are called the event argument will be filled with

import types
import matplotlib.pyplot as plt
def sync_y_with_x(self, event):
 self.set_xlim(event.get_ylim(), emit=False)
def sync_x_with_y(self, event):
 self.set_ylim(event.get_xlim(), emit=False)
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
ax1.update_xlim = types.MethodType(sync_y_with_x, ax1)
ax2.update_ylim = types.MethodType(sync_x_with_y, ax2)
ax1.callbacks.connect("ylim_changed", ax2.update_ylim)
ax2.callbacks.connect("xlim_changed", ax1.update_xlim)
answered Mar 28, 2017 at 9:57
0

I solved1 the problem by exploiting event handlers. Listening for "*lim_changed" events and then properly get_*lim and set*_lim to synchronise the limits does the trick. Note you also have to reverse the x-axis in the upper right plot YZ.

Here is a sample function to sync the x-axis with the y-axis:

def sync_x_with_y(self, axis):
 # check whether the axes orientation is not coherent
 if (axis.get_ylim()[0] > axis.get_ylim()[1]) != (self.get_xlim()[0] > self.get_xlim()[1]):
 self.set_xlim(axis.get_ylim()[::-1], emit=False)
 else:
 self.set_xlim(axis.get_ylim(), emit=False)

I implemented a simple class Orthogonal Projection that make quite easy to make such kind of plots.

1 Starting from a hint that Benjamin Root gave me on matplotlib mailing list almost a year ago...sorry for not having posted the solution before

answered May 23, 2016 at 22:26

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.