Plot your brain MRI

How to plot OBJ files in Plotly

To see the results of this code click here

To convert .nii files quickly to .obj without Freesurfer processing

import plotly.graph_objects as go
import numpy as np
brain = "/content/drive/MyDrive/Data Science/MRI/brain.obj"
# Function to read the .obj file
def read_obj(filename):
    vertices = []
    faces = []

    with open(filename, 'r') as file:
        for line in file:
            if line.startswith('v '):
                vertices.append(list(map(float, line.strip().split()[1:])))
            elif line.startswith('f'):
                face = [int(i.split('/')[0]) for i in line.strip().split()[1:]]
                faces.append(face)

    return np.array(vertices), np.array(faces)
vertices, faces = read_obj(brain)
vertices
array([[  50.666779,  -28.194384,  -21.338442],
       [  50.121082,  -27.810968,  -20.198452],
       [   3.378802, -100.455139,    4.870674],
       ...,
       [ -12.782207,   66.600349,   16.896309],
       [ -13.962158,   66.610062,   17.925493],
       [ -10.211386,   31.746548,   -1.28224 ]])
faces
array([[34663, 28109, 28500],
       [ 3049, 15445, 37208],
       [ 1154,     1,     2],
       ...,
       [50243, 51376, 44998],
       [70636, 50891, 69542],
       [49939, 70369, 74995]])
# Create a mesh object
pl_mygrey=[0, 'rgb(153, 153, 153)'], [1., 'rgb(255,255,255)']

mesh = go.Mesh3d(
    x=vertices[:,0],
    y=vertices[:,1],
    z=vertices[:,2],
    intensity=vertices[:,2],
    i=faces[:,0]-1,
    j=faces[:,1]-1,
    k=faces[:,2]-1,
    colorscale=pl_mygrey,
    showscale=False
)
mesh.update(cmin=-7,
               lighting=dict(ambient=0.18,
                             diffuse=1,
                             fresnel=0.1,
                             specular=1,
                             roughness=0.05,
                             facenormalsepsilon=1e-15,
                             vertexnormalsepsilon=1e-15),
               lightposition=dict(x=100,
                                  y=200,
                                  z=0
                                 )
                      );

# Create a figure and add the mesh object to it
fig = go.Figure(data=[mesh])
camera = dict(
    eye=dict(x=5, y=1.5, z=0)  # Adjust these values as needed
)
fig.update_layout(
    scene=dict(
        xaxis=dict(
            showbackground=False,
            showgrid=False,
            zeroline=False,
            showticklabels=False,
            showline=False,
            title=''  # Remove the x-axis label
        ),
        yaxis=dict(
            showbackground=False,
            showgrid=False,
            zeroline=False,
            showticklabels=False,
            showline=False,
            title=''
        ),
        zaxis=dict(
            showbackground=False,
            showgrid=False,
            zeroline=False,
            showticklabels=False,
            showline=False,
            title=''
        ),
        camera=camera
    ),
    margin=dict(r=0, l=0, b=0, t=0),  # Removes white margins around the plot
    paper_bgcolor='rgba(0,0,0,0)',  # Set the background color of the paper to transparent
    plot_bgcolor='rgba(0,0,0,0)'    # Set the background color of the plot to transparent
)
fig.show()
fig.write_html('/content/drive/MyDrive/Data Science/MRI/brain.html')

Subplots containing a variety of different views of the .nii to .obj conversion.

import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
face = "/content/drive/MyDrive/Data Science/MRI/nii2mesh_sub-009_T1w.obj"
T7_raw = "/content/drive/MyDrive/Data Science/MRI/nii2mesh_7T.obj"
T7_white = "/content/drive/MyDrive/Data Science/MRI/nii2mesh_c2_KP_anatomical.obj"
T7_gray = "/content/drive/MyDrive/Data Science/MRI/nii2mesh_c1_KP_anatomical.obj"
T7_csf = "/content/drive/MyDrive/Data Science/MRI/nii2mesh_c3_KP_anatomical.obj"

# Default camera settings
camera = dict(
    eye=dict(x=3, y=1.5, z=0)  # Adjust these values as needed
)
# Function to read the .obj file
def read_obj(filename):
    vertices = []
    faces = []

    with open(filename, 'r') as file:
        for line in file:
            if line.startswith('v '):
                vertices.append(list(map(float, line.strip().split()[1:])))
            elif line.startswith('f'):
                face = [int(i.split('/')[0]) for i in line.strip().split()[1:]]
                faces.append(face)

    return np.array(vertices), np.array(faces)

3T Face and 7T raw

face_vertices, face_faces = read_obj(face)
T7_raw_vertices, T7_raw_faces = read_obj(T7_raw)
# Create a mesh object
pl_mygrey=[0, 'rgb(153, 153, 153)'], [1., 'rgb(255,255,255)']

face_mesh = go.Mesh3d(
    x=face_vertices[:,0],
    y=face_vertices[:,1],
    z=face_vertices[:,2],
    intensity=face_vertices[:,2],
    i=face_faces[:,0]-1,
    j=face_faces[:,1]-1,
    k=face_faces[:,2]-1,
    colorscale=pl_mygrey,
    showscale=False
)
T7_raw_mesh = go.Mesh3d(
    x=T7_raw_vertices[:,0],
    y=T7_raw_vertices[:,1],
    z=T7_raw_vertices[:,2],
    intensity=T7_raw_vertices[:,2],
    i=T7_raw_faces[:,0]-1,
    j=T7_raw_faces[:,1]-1,
    k=T7_raw_faces[:,2]-1,
    colorscale=pl_mygrey,
    showscale=False
)

face_mesh.update(cmin=-3.3109,
               lighting=dict(ambient=0.18,
                             diffuse=1,
                             fresnel=0.1,
                             specular=1,
                             roughness=0.05,
                             facenormalsepsilon=1e-15,
                             vertexnormalsepsilon=1e-15),
               lightposition=dict(x=100,
                                  y=200,
                                  z=0
                                 )
                      );
T7_raw_mesh.update(cmin=-3.31909,
               lighting=dict(ambient=0.18,
                             diffuse=1,
                             fresnel=0.1,
                             specular=1,
                             roughness=0.05,
                             facenormalsepsilon=1e-15,
                             vertexnormalsepsilon=1e-15),
               lightposition=dict(x=100,
                                  y=200,
                                  z=0
                                 )
                      );
# Create a figure and add the mesh object to it
fig = make_subplots(
    rows=1, cols=2,
    specs=[[{'type': 'mesh3d'}, {'type': 'mesh3d'}]],
    horizontal_spacing=0.02  # Adjust the spacing as needed
)

fig.add_trace(face_mesh, row=1, col=1)
fig.add_trace(T7_raw_mesh, row=1, col=2)


axis_settings = dict(
    showbackground=False,
    showgrid=False,
    zeroline=False,
    showticklabels=False,
    showline=False,
    title=""
)

# Add titles as 3D text
fig.add_trace(go.Scatter3d(
    x=[np.mean(face_vertices[:,0])],
    y=[np.mean(face_vertices[:,1])],
    z=[np.max(face_vertices[:,2]) * 1.2],  # Position above the highest point of the mesh
    text=["Face (from separate 3T)"],
    mode="text",
), row=1, col=1)

fig.add_trace(go.Scatter3d(
    x=[np.mean(T7_raw_vertices[:,0])],
    y=[np.mean(T7_raw_vertices[:,1])],
    z=[np.max(T7_raw_vertices[:,2]) * 1.2],  # Position above the highest point of the mesh
    text=["Skulled stripped (7T)"],
    mode="text",
), row=1, col=2)

fig.update_layout(
    scene=dict(
        xaxis=axis_settings,
        yaxis=axis_settings,
        zaxis=axis_settings,
        camera=camera
    ),
    scene2=dict(
        xaxis=axis_settings,
        yaxis=axis_settings,
        zaxis=axis_settings,
        camera=camera
    ),
    margin=dict(r=0, l=0, b=0, t=0),
    paper_bgcolor='rgba(0,0,0,0)',
    plot_bgcolor='rgba(0,0,0,0)',
    showlegend=False
)

fig.show()
fig.write_html('/content/drive/MyDrive/Data Science/MRI/face_raw.html')

7T white and gray matter, and CSF

white_vertices, white_faces = read_obj(T7_white)
gray_vertices, gray_faces = read_obj(T7_gray)
csf_vertices, csf_faces = read_obj(T7_csf)

# Create a mesh object
pl_mygrey=[0, 'rgb(153, 153, 153)'], [1., 'rgb(255,255,255)']

white_mesh = go.Mesh3d(
    x=white_vertices[:,0],
    y=white_vertices[:,1],
    z=white_vertices[:,2],
    intensity=white_vertices[:,2],
    i=white_faces[:,0]-1,
    j=white_faces[:,1]-1,
    k=white_faces[:,2]-1,
    colorscale=pl_mygrey,
    showscale=False
)
gray_mesh = go.Mesh3d(
    x=gray_vertices[:,0],
    y=gray_vertices[:,1],
    z=gray_vertices[:,2],
    intensity=gray_vertices[:,2],
    i=gray_faces[:,0]-1,
    j=gray_faces[:,1]-1,
    k=gray_faces[:,2]-1,
    colorscale=pl_mygrey,
    showscale=False
)
csf_mesh = go.Mesh3d(
    x=csf_vertices[:,0],
    y=csf_vertices[:,1],
    z=csf_vertices[:,2],
    intensity=csf_vertices[:,2],
    i=csf_faces[:,0]-1,
    j=csf_faces[:,1]-1,
    k=csf_faces[:,2]-1,
    colorscale=pl_mygrey,
    showscale=False
)

white_mesh.update(cmin=-3.3109,
               lighting=dict(ambient=0.18,
                             diffuse=1,
                             fresnel=0.1,
                             specular=1,
                             roughness=0.05,
                             facenormalsepsilon=1e-15,
                             vertexnormalsepsilon=1e-15),
               lightposition=dict(x=100,
                                  y=200,
                                  z=0
                                 )
                      );
gray_mesh.update(cmin=-3.31909,
               lighting=dict(ambient=0.18,
                             diffuse=1,
                             fresnel=0.1,
                             specular=1,
                             roughness=0.05,
                             facenormalsepsilon=1e-15,
                             vertexnormalsepsilon=1e-15),
               lightposition=dict(x=100,
                                  y=200,
                                  z=0
                                 )
                      );
csf_mesh.update(cmin=-3.31909,
               lighting=dict(ambient=0.18,
                             diffuse=1,
                             fresnel=0.1,
                             specular=1,
                             roughness=0.05,
                             facenormalsepsilon=1e-15,
                             vertexnormalsepsilon=1e-15),
               lightposition=dict(x=100,
                                  y=200,
                                  z=0
                                 )
                      );
# Create a figure and add the mesh object to it
fig = make_subplots(
    rows=1, cols=3,
    specs=[[{'type': 'mesh3d'}, {'type': 'mesh3d'}, {'type': 'mesh3d'}]],
    horizontal_spacing=0.02  # Adjust the spacing as needed
)

fig.add_trace(white_mesh, row=1, col=1)
fig.add_trace(gray_mesh, row=1, col=2)
fig.add_trace(csf_mesh, row=1, col=3)


axis_settings = dict(
    showbackground=False,
    showgrid=False,
    zeroline=False,
    showticklabels=False,
    showline=False,
    title=""
)

# Add titles as 3D text
fig.add_trace(go.Scatter3d(
    x=[np.mean(white_vertices[:,0])],
    y=[np.mean(white_vertices[:,1])],
    z=[np.max(white_vertices[:,2]) * 1.2],  # Position above the highest point of the mesh
    text=["White matter (7T)"],
    mode="text",
), row=1, col=1)

fig.add_trace(go.Scatter3d(
    x=[np.mean(gray_vertices[:,0])],
    y=[np.mean(gray_vertices[:,1])],
    z=[np.max(gray_vertices[:,2]) * 1.2],  # Position above the highest point of the mesh
    text=["Gray matter (7T)"],
    mode="text",
), row=1, col=2)

fig.add_trace(go.Scatter3d(
    x=[np.mean(csf_vertices[:,0])],
    y=[np.mean(csf_vertices[:,1])],
    z=[np.max(csf_vertices[:,2]) * 1.2],  # Position above the highest point of the mesh
    text=["CSF (7T)"],
    mode="text",
), row=1, col=3)

fig.update_layout(
    scene=dict(
        xaxis=axis_settings,
        yaxis=axis_settings,
        zaxis=axis_settings,
        camera=camera
    ),
    scene2=dict(
        xaxis=axis_settings,
        yaxis=axis_settings,
        zaxis=axis_settings,
        camera=camera
    ),
      scene3=dict(
        xaxis=axis_settings,
        yaxis=axis_settings,
        zaxis=axis_settings,
        camera=camera
    ),
    margin=dict(r=0, l=0, b=0, t=0),
    paper_bgcolor='rgba(0,0,0,0)',
    plot_bgcolor='rgba(0,0,0,0)',
    showlegend=False
)

fig.show()
fig.write_html('/content/drive/MyDrive/Data Science/MRI/white_gray_csf.html')