GithubHelp home page GithubHelp logo

Comments (5)

QhelDIV avatar QhelDIV commented on August 29, 2024 1

Thank you so much! I can directly render new point sets without any problem :)

image

from scientific-visualization-book.

rougier avatar rougier commented on August 29, 2024

Sorry for delay. This is actually a regular scatter plot but the trick is to render each point several times using the disc marker, from back to front. "Halo" is made of transparent black disc with larger radius and the highlight is made with a smaller shifted white disc. Quite slow and primite but it gives the illusion. I thought the code was available from https://github.com/rougier/matplotlib-3d but I did not find it. Where did you find the image ? I could give me some hints on where to search the code.

from scientific-visualization-book.

QhelDIV avatar QhelDIV commented on August 29, 2024

Hi, thank you for your reply!

The image comes from the gallery show cases in this repo's README.md, the url is: https://github.com/rougier/scientific-visualization-book/blob/master/images/scatter-3d.png

Thank you again!

from scientific-visualization-book.

rougier avatar rougier commented on August 29, 2024

Cannot find the original but here is another similar on with a different technique:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import PolyCollection, LineCollection


def frustum(left, right, bottom, top, znear, zfar):
    M = np.zeros((4, 4))
    M[0, 0] = +2.0 * znear / (right - left)
    M[2, 0] = (right + left) / (right - left)
    M[1, 1] = +2.0 * znear / (top - bottom)
    M[2, 1] = (top + bottom) / (top - bottom)
    M[2, 2] = -(zfar + znear) / (zfar - znear)
    M[3, 2] = -2.0 * znear * zfar / (zfar - znear)
    M[2, 3] = -1.0
    return M.T

def perspective(fovy, aspect, znear, zfar):
    h = np.tan(fovy / 360.0 * np.pi) * znear
    w = h * aspect
    return frustum(-w, w, -h, h, znear, zfar)

def scale(x, y, z):
    return np.array([[x, 0, 0, 0],
                     [0, y, 0, 0],
                     [0, 0, z, 0],
                     [0, 0, 0, 1]], dtype=float)
def zoom(z):
    return scale(z,z,z)

def translate(x, y, z):
    return np.array([[1, 0, 0, x],
                     [0, 1, 0, y],
                     [0, 0, 1, z],
                     [0, 0, 0, 1]], dtype=float)

def xrotate(theta):
    t = np.pi * theta / 180
    c, s = np.cos(t), np.sin(t)
    return np.array([[1, 0,  0, 0],
                     [0, c, -s, 0],
                     [0, s,  c, 0],
                     [0, 0,  0, 1]], dtype=float)

def yrotate(theta):
    t = np.pi * theta / 180
    c, s = np.cos(t), np.sin(t)
    return  np.array([[ c, 0, s, 0],
                      [ 0, 1, 0, 0],
                      [-s, 0, c, 0],
                      [ 0, 0, 0, 1]], dtype=float)

def zrotate(theta):
    t = np.pi * theta / 180
    c, s = np.cos(t), np.sin(t)
    return np.array([[ c, -s, 0, 0],
                     [ s,  c, 0, 0],
                     [ 0,  0, 1, 0],
                     [ 0,  0, 0, 1]], dtype=float)


n = 11
V = np.zeros((12,n,3))
V[0] = [(x,0,0) for x in np.linspace(0,1,n)] # (0,0,0) to (1,0,0)
V[1] = [(x,0,1) for x in np.linspace(0,1,n)] # (0,0,1) to (1,0,1)
V[2] = [(0,0,z) for z in np.linspace(0,1,n)] # (0,0,0) to (0,0,1)
V[3] = [(1,0,z) for z in np.linspace(0,1,n)] # (1,0,0) to (1,0,1)
V[4] = [(0,y,0) for y in np.linspace(0,1,n)] # (0,0,0) to (0,1,0)
V[5] = [(1,y,0) for y in np.linspace(0,1,n)] # (1,0,0) to (1,1,0)
V[6] = [(x,1,0) for x in np.linspace(0,1,n)] # (0,1,0) to (1,1,0)
V[7] = [(1,y,1) for y in np.linspace(0,1,n)] # (1,0,0) to (1,1,0)
V[8] = [(1,1,z) for z in np.linspace(0,1,n)] # (0,1,0) to (1,1,0)

V[9]  = [(x,0,1.025) for x in np.linspace(0,1,n)]
V[10] = [(-0.025,0,z) for z in np.linspace(0,1,n)]
V[11] = [(-0.025,y,0) for y in np.linspace(0,1,n)]

V = V - 0.5


model = xrotate(25) @ yrotate(45) 
view  = translate(0, 0,-3.5)
proj  = perspective(30, 1, 1, 100) 
MVP   = proj  @ view  @ model 

def transform(V, depth=False):
    V = np.asarray(V).reshape(-1,3)
    VH = np.c_[V, np.ones(len(V))]     # Homogenous coordinates
    VT = (VH @ MVP.T)                  # Transformed coordinates
    VN = VT/abs(VT[:,3].reshape(-1,1)) # Normalization
    if depth:
        return VN[:,:2], VN[:,2]
    else:
        return VN[:,:2]
    
V = transform(V).reshape((12,n,2))

# 3 axis + grid (at once)
segments, linewidths = [], []
for i in range(0,n):
    if 0 < i < (n-1): linewidth = 0.25
    else:             linewidth = 1.00
    for (j,k) in [(0,1), (2,3), (4,5), (6,0), (7,5), (8,3)]:
        triangle = [V[j,i], V[k,i]]
        segments.append(triangle)
        linewidths.append(linewidth)

# Ticks
for i in range(0,n):
    triangle = [V[1,i], V[9,i]]
    segments.append(triangle)
    linewidths.append(1.0)

    triangle = [V[2,i], V[10,i]]
    segments.append(triangle)
    linewidths.append(1.0)

    triangle = [V[4,i], V[11,i]]
    segments.append(triangle)
    linewidths.append(1.0)



    
fig = plt.figure(figsize=(6,6))
ax = fig.add_axes([0,0,1,1], xlim=[-1,1], ylim=[-1,1], aspect=1)
ax.axis("off")
collection = PolyCollection(segments, linewidths=linewidths, 
                            facecolors="None", edgecolor="black")
ax.add_collection(collection)

# Tick labels
P = [(x, -0.5,+0.55) for x in np.linspace(-0.5,0.5,n)]
for i,pos in enumerate(transform(P)):
    ax.text(pos[0], pos[1], "%d" % (i-10),
            ha="center", va="center", size="x-small")

P = [(-0.55, -0.5, z) for z in np.linspace(-0.5,0.5,n)]
for i,pos in enumerate(transform(P)):
    ax.text(pos[0], pos[1], "%d" % i,
            ha="center", va="center", size="x-small")

P = [(-0.55, y, -0.50) for y in np.linspace(-0.5,0.5,n)]
for i,pos in enumerate(transform(P)):
    ax.text(pos[0], pos[1], "%d" % i,
            ha="center", va="center", size="x-small")


normalize = lambda x: np.asarray(x)/np.linalg.norm(x)
n = 256
I = np.zeros((n,n,4))
X,Y = np.linspace(-1,1,n), np.linspace(-1,1,n)
color = np.array([1,0,0])
white = np.array([1,1,1])
direction = normalize([1,1,1])
for i,x in enumerate(X):
    for j,y in enumerate(Y):
        z = 1 - np.sqrt(x*x+y*y)
        if z < 0: continue
        normal = normalize([x,y,z])
        diffuse = max(0,(direction*normal).sum())
        specular = np.power(diffuse,24)
        I[j,i,:3] = np.maximum(diffuse*color, specular)
        I[j,i,3] = 1


from matplotlib.offsetbox import OffsetImage, AnnotationBbox


mol = np.load("protein.npy")
V = mol["position"]
Z = mol["radius"]
V = (2*(V-V.min())/(V.max()-V.min()) - 1 )*.75
V = np.random.normal(0, .2, (1500,3))


V,Z = transform(V, depth=True)
zmin,zmax = Z.min(), Z.max()
Z = (Z-zmin)/(zmax-zmin)
V = V[np.argsort(-Z)]
for i in range(len(V)):
    image = OffsetImage(I, zoom=0.05, #*Z[i],
                        origin="lower", interpolation="nearest")
    box = AnnotationBbox(image, V[i], frameon=False)
    ax.add_artist(box)

plt.show()

from scientific-visualization-book.

rougier avatar rougier commented on August 29, 2024

Found it: https://github.com/rougier/scientific-visualization-book/blob/master/code/unsorted/3d/scatter.py

from scientific-visualization-book.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.