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')