Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python, Matplotlib: Drawing vertical lines in 3d plot, when data is independent

I have a random walker in the (x,y) plane and a -log(bivariate gaussian) in the (x,y,z) plane. These two datasets are essentially independent.

I want to sample, say 5 (x,y) pairs of the random walker and draw vertical lines up the z-axis and terminate the vertical line when it "meets" the bivariate gaussian.

This is my code so far:

import matplotlib as mpl
import matplotlib.pyplot as plt
import random
import numpy as np
import seaborn as sns
import scipy
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.mlab import bivariate_normal

%matplotlib inline

    # Data for random walk

def randomwalk():

    mpl.rcParams['legend.fontsize'] = 10

    xyz = []
    cur = [0, 0]

    for _ in range(40):
        axis = random.randrange(0, 2)
        cur[axis] += random.choice([-1, 1])
        xyz.append(cur[:])

    # Get density

    x, y = zip(*xyz)
    data = np.vstack([x,y])
    kde = scipy.stats.gaussian_kde(data)
    density = kde(data)


    # Data for bivariate gaussian 

    a = np.linspace(-7.5, 7.5, 40)
    b = a
    X,Y = np.meshgrid(a, b)
    Z = bivariate_normal(X, Y)
    surprise_Z = -np.log(Z)

    # Get random points from walker and plot up z-axis to the gaussian

    M = data[:,np.random.choice(20,5)].T

    # Plot figure

    fig = plt.figure(figsize=(10, 7))

    ax = fig.gca(projection='3d')
    ax.plot(x, y, 'grey', label='Random walk') # Walker
    ax.scatter(x[-1], y[-1], c='k', marker='o') # End point

    ax.legend()

    surf = ax.plot_surface(X, Y, surprise_Z, rstride=1, cstride=1, 
        cmap = plt.cm.gist_heat_r, alpha=0.1, linewidth=0.1)

    #fig.colorbar(surf, shrink=0.5, aspect=7, cmap=plt.cm.gray_r)

    for i in range(5):
        ax.plot([M[i,0], M[i,0]],[M[i,1], M[i,1]], [0,10],'k--',alpha=0.8, linewidth=0.5)

    ax.set_zlim(0, 50)
    ax.set_xlim(-10, 10)
    ax.set_ylim(-10, 10)

Which produces

enter image description here

As you can see the only thing I'm struggling with is how to terminate the vertical lines when they meet the appropriate Z-value. Any ideas are welcome!

like image 596
tmo Avatar asked Oct 16 '25 04:10

tmo


1 Answers

You're currently only letting those lines get to a height of 10 by using [0,10] as the z coordinates. You can change your loop to the following:

for i in range(5):
    x = [M[i,0], M[i,0]]
    y = [M[i,1], M[i,1]]
    z = [0,-np.log(bivariate_normal(M[i,0],M[i,1]))]
    ax.plot(x,y,z,'k--',alpha=0.8, linewidth=0.5)

This takes the x and y coordinates for each point you loop over and calculates the height of overlying Gaussian for that point and plots to there. Here is a plot with the linestyle changed to emphasize the lines relevant to the question:

enter image description here

like image 169
Ianhi Avatar answered Oct 17 '25 18:10

Ianhi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!