Skip to main content

See your matplotlib plots in 3D by making stereograms and anaglyphs

Project description

Release Builds Tests codecov PyPI - Python Version

Matplotlib add-on to make stereograms and anaglyphs.

Stereographic images can significantly enhance the interpretability of 3D data by leveraging human binocular vision. Instead of looking at a flat projection on a page, stereograms give us "3D glasses" for 2D data with just our eyes.

It takes some practice to be able to view the stereoscopic effect for the first time, but the effort is well worth it!

Usage

Installation

pip install mpl_stereo

Setup

import numpy as np
from mpl_stereo import AxesStereo2D, AxesStereo3D, AxesAnaglyph
from mpl_stereo.example_data import trefoil
x, y, z = trefoil()  # trefoil knot

2D Stereogram plots

Currently, only a subset of matplotlib's 2D plots are officially supported. See the list in axstereo.known_methods.

axstereo = AxesStereo2D()
axstereo.plot(x, y, z, c='k', alpha=0.2)
axstereo.scatter(x, y, z, c=z, cmap='viridis', s=10)

When you are viewing the stereogram properly, you should see the knot weave in and out of the page!

Warning: Please note that for 2D plots the stereoscopic effect requires shifting data, so the data will not necessarily line up with the x-axis labels! Right now this is controlled with the eye_balance parameter. Calling AxesStereo2D(eye_balance=-1) (the default) will ensure that the left x-axis data is not shifted, whereas AxesStereo2D(eye_balance=1) will lock down the right x-axis data. The tick labels for x-axes where the data is not aligned will have transparency applied. So in the plot above, the right side labels being lighter gray indicates that you should not trust that x-axis data to be positioned correctly, but the left subplot with its black labeling is accurate.

3D Stereogram plots

The stereoscopic effect in 3D is made just by rotating the plot view, so all of matplotlib's 3D plot types are supported, and there are no concerns about data not lining up with the axis labels.

axstereo = AxesStereo3D()
axstereo.plot(x, y, z, c='k', alpha=0.2)
axstereo.scatter(x, y, z, c=z, cmap='viridis', s=10)

Red-Cyan Anaglyphs

Some 2D plots can also be made into anaglyphs, which are stereograms that can be viewed with red-cyan 3D glasses. While this allows for seeing the stereoscopic effect without training your eyes, it also means that the data cannot be otherwise colored.

The same warning as for the 2D stereo plots about shifting data applies here as well. If eye_balance is -1 or +1 such that the data for one of the colors is not shifted, then that color will be applied to the x-axis tick labels to show that they are accurate.

axstereo = AxesAnaglyph()
axstereo.plot(x, y, z)
axstereo.scatter(x, y, z, s=10)

Existing Stereo Images

Existing stereo image data can easily be plotted up side-by-side, or combined into an anaglyph. Here we plot up two images of the sun taken in July 2023 by the NASA STEREO-A and SDO spacecraft. This example was adapted from the SunPy documentation.

from mpl_stereo.example_data import sun_left_right
sun_left_data, sun_right_data = sun_left_right

axstereo = AxesStereo2D()
axstereo.ax_left.imshow(sun_left_data, cmap='gray')
axstereo.ax_right.imshow(sun_right_data, cmap='gray')

axstereo = AxesAnaglyph()
axstereo.imshow_stereo(sun_left_data, sun_right_data)

Here's another example, showing how this translates to full color data. This example is a pair of photos of St. Mary's Church in Colston Basset, Britain, taken by David Skinner and shared under a CC-BY2.0 license.

from mpl_stereo.example_data import church_left_right
chruch_left_data, church_right_data = church_left_right

axstereo = AxesStereo2D()
axstereo.ax_left.imshow(chruch_left_data)
axstereo.ax_right.imshow(church_right_data)

axstereo = AxesAnaglyph()
axstereo.imshow_stereo(church_left_data, church_right_data)

Working With Plots

The figure and subplot axes can be accessed with the following:

axstereo.fig
axstereo.axs  # (ax_left, ax_right), for AxesStereo2D and AxesStereo3D
axstereo.ax  # for AxesAnaglyph

Calling any method on axstereo will pass that method call onto all the subplot axes. In the 2D cases, the plotting methods which take in x and y arguments are intercepted and the additional z data is processed to obtain appropriate horizontal offsets.

# For example instead of:
for ax in axstereo.axs:
    ax.set_xlabel('X Label')

# You can do the equivalent:
axstereo.set_xlabel('X Label')

# When applicable, the return values from the two method calls are returned as a tuple
(line_left, line_right) = axstereo.plot(x, y, z)

The apparent depth of 2D stereograms can be adjusted with the zscale parameter. The default is 1/4th the x-axis range, i.e. zscale=(max(ax.get_xlim()) - ax.get_xlim()) / 4. Decrease this number to flatten the stereogram, or increase it to exaggerate the depth.

For 2D plots and anaglyphs, the focal plane can be set with the zzero parameter. This is the z value that will be "on the page" when viewing the stereogram.

axstereo = AxesAnaglyph(zzero=min(z))  # data will float above the page
axstereo = AxesAnaglyph(zzero=None)  # page will be at the midpoint of the data range (default)
axstereo = AxesAnaglyph(zzero=max(z))  # data will sink below the page

Animations

See an example of how to use this with matplotlib animations in docs/gen_graphics.py.

Viewing Stereograms

These are not autostereograms, like the "Magic Eye" books that were popular in the 1990's. However, they use the same viewing technique. Below is ChatGPT's how-to guide on viewing these, but I'll try to find a better beginner-friendly resource to put here.

  1. Position the Stereogram: Place it at arm's length and ensure it's level with your eyes.
  2. Relax Your Focus: Look through the image, as if focusing on something distant, rather than the stereogram itself.
  3. Parallel Viewing: Try to view the image with your eyes parallel, similar to how you would look at a distant object.
  4. Align and Overlap: Adjust the angle and distance of the stereogram until the two images begin to overlap.
  5. Perceive the 3D Image: As the images overlap, a 3D image should emerge. Keep your focus steady to maintain the illusion.
  6. Practice: If initially unsuccessful, take breaks and try again. It might require some practice to get used to this method.

Parallel vs Cross-Eyed Viewing

By default, the stereograms are set up for "parallel" viewing method as described above. For "cross-eyed" viewing, initialize with a negative ipd parameter. An ipd (Inter-Pupilary Distance) of 65 millimeters is the default, so call AxesStereo2D(ipd=-65) for the default cross-eyed viewing.

Derivation of Geometry

Two eyes with separation IPD are looking at a point a distance z offset from a focal plane at distance d, resulting in view angle θ. If this point were projected back to the focal plane, it would be offset by δ from where it visually appears on that plane. This offset δ is used to displace each point in the stereogram for each eye based on its z value to achieve the stereoscopic effect. The eye_balance parameter allocates the total relative displacement of between the two eyes.

θ = arctan((d - z) / (IPD / 2))
D / d = (IPD / 2) / (d - z)
δ = D - IPD / 2
  = IPD / 2 * (d / (d - z) - 1)
  = IPD / 2 * z / (d - z)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mpl_stereo-0.6.0.tar.gz (2.6 MB view details)

Uploaded Source

Built Distribution

mpl_stereo-0.6.0-py3-none-any.whl (2.6 MB view details)

Uploaded Python 3

File details

Details for the file mpl_stereo-0.6.0.tar.gz.

File metadata

  • Download URL: mpl_stereo-0.6.0.tar.gz
  • Upload date:
  • Size: 2.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.6.1 CPython/3.8.10 Linux/5.10.102.1-microsoft-standard-WSL2

File hashes

Hashes for mpl_stereo-0.6.0.tar.gz
Algorithm Hash digest
SHA256 cf43ac96441ed3685e8a22316dbd4dc7ef9624472e52c583e1f78bee005966c3
MD5 34184857fa97f57ce8d6ef501e83ec54
BLAKE2b-256 d551393f7e7e3b533961bd56963bc1854e8a3c6ac061f59d7ef5ec79cd76fc61

See more details on using hashes here.

Provenance

File details

Details for the file mpl_stereo-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: mpl_stereo-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 2.6 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.6.1 CPython/3.8.10 Linux/5.10.102.1-microsoft-standard-WSL2

File hashes

Hashes for mpl_stereo-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 228b496417b238e8944cf7e5ba4ed0131a9f8d0ce4e5bb49d6c56474d710f44b
MD5 92bcb8b8f36e14a63b6b0fad7cddad3c
BLAKE2b-256 e70d20fee4b1b1387e3650fc60ddce3c3809f6b4eb443b3bac502c08d101e30b

See more details on using hashes here.

Provenance

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page