Python Visualisations

The Perfect Valentine with Python

Last year, The New York Times published the article “The Perfect Valentine? A Math Formula” featuring a widget which allows you to visualise the equation

$(x^2 + (1+b)^2y^2 +z^2 -1)^3 -(x^2 +ay^2 )z^3 $

where both a and b are parameters. At first, this equation may not seem romantic at all. But as soon as we plot it we cannot help but agreeing with the article’s first sentence:

Nothing says I love you like an algebraic equation

You can customise your equation within the Süss — German for “sweet” — widget created for Valentine’s Day by Imaginary, a nonprofit organisation in Berlin that designs open-source mathematics programs and exhibitions. But if you are a true romantic, go ahead and make your very own 3D-heart (in your favourite colour palette) in Python using only numpy, pandas, and plotly. Code below ⬇️

Take a look at the interactive version (takes a bit to load!) in Chart Studio.

Python Code

# Author: @Quant_Girl
# Title: Perfect Valentine
# Type: 3d Scatter

import plotly.graph_objects as go
import numpy as np
import plotly.express as px
import pandas as pd
import chart_studio.plotly as py

def get_zvalue(a, b, x, y):
    """
    Finds the roots of the polynomial in z
    for given values of
    a, b, x, y.
    """
    constant = x ** 2 + ((1 + b) * y) ** 2 - 1
    c0 = constant ** 3
    c1 = 0.0
    c2 = 3 * (constant ** 2)
    c3 = -(a * (y ** 2) + x ** 2)
    c4 = 3 * constant
    c5 = 0.0
    c6 = 1.0

    coefficients = [c6, c5, c4, c3, c2, c1, c0]
    rts = np.roots(coefficients)
    z = rts[~np.iscomplex(rts)]

    if len(z) > 0:
        zreal = z.real
        return zreal
    else:
        return []


def draw_heart(a=9/200, b=0.01, grid=0.10, palette='viridis'):
    """
    Draws the figure
    @param a: a>0
    @param b:
    @param grid: sparsity of the scatter
    @param palette: palette
    """
    x = np.arange(-2, 2, grid)
    y = x

    all_triplets = []
    for i in x:
        for j in y:
            zaxis = get_zvalue(a, b, i, j)
            for k in zaxis:
                triplet = [i, j, k]
                all_triplets.append(triplet)
    results = np.array(all_triplets).transpose()

    # Save the triplets in a data frame
    xaxis = results[0]
    yaxis = results[1]
    zaxis = results[2]
    df = pd.DataFrame({'x': xaxis, 'y': yaxis, 'z': zaxis})

    # Draw
    fig = go.Figure(data=px.scatter_3d(df, x='x', y='y', z='z',
                                       color='z',
                                       color_continuous_scale=palette,
                                       height=800, width=800,
                                       template="plotly_white"))

    fig.update(layout_coloraxis_showscale=False)

    fig.update_layout(
        title='$\hbox{A Perfect Valentine: } (x^2 + (1+b)^2y^2 +z^2 -1)^3 -(x^2 +ay^2 )z^3$',
        scene=dict(
            xaxis=dict(showticklabels=False, showgrid=False),
            yaxis=dict(showticklabels=False, showgrid=False),
            zaxis=dict(showticklabels=False, showgrid=False),
            bgcolor='white'))
    fig.show()

draw_heart(palette='twilight')

Happy Valentine’s Day!