dive-mri 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dive/Viz_UI.py +205 -0
- dive/__init__.py +1 -0
- dive/add.png +0 -0
- dive/csv_tocolors.py +79 -0
- dive/helper.py +155 -0
- dive/loading.py +101 -0
- dive/main.py +228 -0
- dive/mask.py +41 -0
- dive/minus.png +0 -0
- dive/showman.py +2010 -0
- dive/tract.py +45 -0
- dive_mri-1.0.0.dist-info/LICENSE +21 -0
- dive_mri-1.0.0.dist-info/METADATA +259 -0
- dive_mri-1.0.0.dist-info/RECORD +17 -0
- dive_mri-1.0.0.dist-info/WHEEL +5 -0
- dive_mri-1.0.0.dist-info/entry_points.txt +2 -0
- dive_mri-1.0.0.dist-info/top_level.txt +1 -0
dive/Viz_UI.py
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import tkinter as tk
|
|
2
|
+
from tkinter import ttk
|
|
3
|
+
from tkinter import filedialog
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
nifti_li, track_li,vtk_li = [], [], []
|
|
7
|
+
ouptput_file_name = []
|
|
8
|
+
width_value = 1
|
|
9
|
+
zoom_value = 0.5
|
|
10
|
+
command = ""
|
|
11
|
+
def nifti():
|
|
12
|
+
global nifti_li
|
|
13
|
+
filename = filedialog.askopenfilenames(initialdir = os.getcwd(),title = "Select Nifti Files",multiple=True, filetypes = (("Nifti files", "*.nii.*"),("Compressed","*.gz"),("all files","*.*")))
|
|
14
|
+
if filename:
|
|
15
|
+
nifti_li = list(filename)
|
|
16
|
+
else:
|
|
17
|
+
nifti_li = None
|
|
18
|
+
|
|
19
|
+
def track():
|
|
20
|
+
global track_li
|
|
21
|
+
filename = filedialog.askopenfilenames(initialdir = os.getcwd(),title = "Select Tracks Files",multiple=True, filetypes = (("Trk files", "*.trk"),("Tck files", "*.tck"),("Trx files", "*.trx"),("all files","*.*")))
|
|
22
|
+
if filename:
|
|
23
|
+
track_li = list(filename)
|
|
24
|
+
else:
|
|
25
|
+
return None
|
|
26
|
+
|
|
27
|
+
def vtk():
|
|
28
|
+
global vtk_li
|
|
29
|
+
filename = filedialog.askopenfilenames(initialdir = os.getcwd(),title = "Select Tracks Files",multiple=True, filetypes = (("Vtk files", "*.vtk"),("all files","*.*")))
|
|
30
|
+
if filename:
|
|
31
|
+
vtk_li = list(filename)
|
|
32
|
+
else:
|
|
33
|
+
return None
|
|
34
|
+
background_val = 0
|
|
35
|
+
def width_control(value2):
|
|
36
|
+
global width_value
|
|
37
|
+
value_label_track.config(text=f"Track Width: {value2}")
|
|
38
|
+
width_value = value2
|
|
39
|
+
|
|
40
|
+
def choose_output_path():
|
|
41
|
+
global ouptput_file_name
|
|
42
|
+
filename = filedialog.asksaveasfilename(defaultextension=".png",title="Save As" )
|
|
43
|
+
if filename:
|
|
44
|
+
ouptput_file_name = filename
|
|
45
|
+
else:
|
|
46
|
+
return None
|
|
47
|
+
|
|
48
|
+
mask_csv_val,tract_csv_val = [],[]
|
|
49
|
+
## CSV functions
|
|
50
|
+
def csv_mask():
|
|
51
|
+
global mask_csv_val
|
|
52
|
+
filename = filedialog.askopenfilenames(initialdir = "/",title = "Select CSV Files",multiple=True, filetypes = (("CSV files", "*.csv"),("all files","*.*")))
|
|
53
|
+
if filename:
|
|
54
|
+
mask_csv_val = list(filename)
|
|
55
|
+
else:
|
|
56
|
+
mask_csv_val = None
|
|
57
|
+
|
|
58
|
+
def csv_track():
|
|
59
|
+
global tract_csv_val
|
|
60
|
+
filename = filedialog.askopenfilenames(initialdir = "/",title = "Select CSV Files",multiple=True, filetypes = (("CSV files", "*.csv"),("all files","*.*")))
|
|
61
|
+
if filename:
|
|
62
|
+
tract_csv_val = list(filename)
|
|
63
|
+
else:
|
|
64
|
+
tract_csv_val = None
|
|
65
|
+
|
|
66
|
+
def p_val():
|
|
67
|
+
if var_log_pval.get() == 1:
|
|
68
|
+
label_pval.config(text="Do log for pval")
|
|
69
|
+
else:
|
|
70
|
+
label_pval.config(text="Don't apply")
|
|
71
|
+
def submit():
|
|
72
|
+
global command
|
|
73
|
+
global nifti_li,track_li,vtk_li,ouptput_file_name,mask_csv_val,tract_csv_val,threshold_tract
|
|
74
|
+
global threshold_mask,var_log_pval,zoom_value,width_value
|
|
75
|
+
global tvalue_range, pvalue_range, map_pval_value_val, map_tval_value_val
|
|
76
|
+
global color_mask_value_val,color_tract_value_val,color_vtk_value_val
|
|
77
|
+
global background_val
|
|
78
|
+
if len(vtk_li)>0:
|
|
79
|
+
command+= " --mesh " + " ".join(vtk_li)
|
|
80
|
+
if len(nifti_li)>0:
|
|
81
|
+
command+= " --mask " + " ".join(nifti_li)
|
|
82
|
+
if len(track_li)>0:
|
|
83
|
+
command+= " --tract " + " ".join(track_li)
|
|
84
|
+
if len(mask_csv_val)>0:
|
|
85
|
+
command+= " --stats_csv " + " ".join(mask_csv_val)
|
|
86
|
+
if threshold_mask.get():
|
|
87
|
+
command+= " --threshold " + str(threshold_mask.get())
|
|
88
|
+
if width_value:
|
|
89
|
+
command+= " --width_tract " + str(width_value)
|
|
90
|
+
if var_log_pval.get():
|
|
91
|
+
command+= " --log_p_value " + str(var_log_pval.get())
|
|
92
|
+
if str(pvalue_range.get())!="(Min,Max)":
|
|
93
|
+
command+= " --range_value "+ str(pvalue_range.get()).replace(",", " ")
|
|
94
|
+
if map_pval_value.get():
|
|
95
|
+
command+= " --map "+ str(map_pval_value_val.get())
|
|
96
|
+
if color_mask_value.get():
|
|
97
|
+
command+= " --color_mask "+ str(color_mask_value_val.get())
|
|
98
|
+
if color_vtk_value.get():
|
|
99
|
+
command+= " --color_mesh "+ str(color_vtk_value_val.get())
|
|
100
|
+
if color_tract_value.get():
|
|
101
|
+
command+= " --color_tract "+ str(color_tract_value_val.get())
|
|
102
|
+
|
|
103
|
+
# command
|
|
104
|
+
print(command)
|
|
105
|
+
window.destroy()
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
window = tk.Tk()
|
|
110
|
+
window.title("DiVE")
|
|
111
|
+
window.geometry('400x600')
|
|
112
|
+
|
|
113
|
+
title = ttk.Label(master = window, text="Input Files",font='Arial 15 bold')
|
|
114
|
+
title.pack()
|
|
115
|
+
|
|
116
|
+
input_frame = ttk.Frame(master=window)
|
|
117
|
+
mask = ttk.Button(input_frame,text='Add Mask',command=nifti)
|
|
118
|
+
track_button = ttk.Button(input_frame,text='Add Tract',command=track)
|
|
119
|
+
vtk_button = ttk.Button(input_frame,text="Add Mesh",command=vtk)
|
|
120
|
+
|
|
121
|
+
mask.grid(row=0, column=0)
|
|
122
|
+
track_button.grid(row=0, column=1)
|
|
123
|
+
vtk_button.grid(row=0, column=2)
|
|
124
|
+
input_frame.pack(pady=10)
|
|
125
|
+
|
|
126
|
+
input_frame2 = ttk.Frame(master=window)
|
|
127
|
+
|
|
128
|
+
value_label_track = tk.Label(input_frame2, text="Track Width: 1",fg="blue")
|
|
129
|
+
width_slider = tk.Scale(input_frame2, from_=1, to=15, orient="horizontal", command=width_control)
|
|
130
|
+
width_slider.set(1)
|
|
131
|
+
width_slider.grid(row=4, column=0, padx=1, pady=1)
|
|
132
|
+
value_label_track.grid(row=4, column=1, padx=1, pady=1)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
input_frame2.pack(pady=10)
|
|
136
|
+
|
|
137
|
+
title3 = ttk.Label(master = window, text="Visualize with Stats",font='Arial 15 bold')
|
|
138
|
+
title3.pack()
|
|
139
|
+
input_frame3 = ttk.Frame(master=window)
|
|
140
|
+
|
|
141
|
+
mask_csv = ttk.Button(input_frame3,text='Add CSV for Mask',command=csv_mask)
|
|
142
|
+
mask_csv.grid(row=0, column=0, padx=1, pady=1)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
threshold_label = ttk.Label(input_frame3, text="Threshold Value:")
|
|
146
|
+
threshold_label.grid(row=1, column=0, padx=1, pady=1, sticky="w")
|
|
147
|
+
threshold_mask=tk.DoubleVar()
|
|
148
|
+
threshold_entry = ttk.Entry(input_frame3,textvariable=threshold_mask)
|
|
149
|
+
threshold_entry.grid(row=1, column=1, padx=1, pady=1)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
var_log_pval = tk.IntVar()
|
|
153
|
+
checkbox_pval = tk.Checkbutton(input_frame3, text="Apply Log for P value", variable=var_log_pval, command=p_val)
|
|
154
|
+
label_pval = tk.Label(input_frame3, text=" Default Don't apply", fg="blue")
|
|
155
|
+
|
|
156
|
+
checkbox_pval.grid(row=3, column=0, padx=1, pady=1)
|
|
157
|
+
label_pval.grid(row=3, column=1, padx=1, pady=1)
|
|
158
|
+
|
|
159
|
+
pvalue_r = ttk.Label(input_frame3, text=" Pvalue Range(Min,Max):")
|
|
160
|
+
pvalue_r.grid(row=4, column=0, padx=1, pady=1, sticky="w")
|
|
161
|
+
pvalue_range=tk.StringVar()
|
|
162
|
+
pvalue_range_entry = ttk.Entry(input_frame3,textvariable=pvalue_range)
|
|
163
|
+
pvalue_range_entry.insert(0, "(Min,Max)")
|
|
164
|
+
pvalue_range_entry.grid(row=4, column=1, padx=1, pady=1)
|
|
165
|
+
|
|
166
|
+
map_pval = ttk.Label(input_frame3, text="Color Map for Value")
|
|
167
|
+
map_pval.grid(row=5, column=0, padx=1, pady=1, sticky="w")
|
|
168
|
+
map_pval_value_val=tk.StringVar()
|
|
169
|
+
map_pval_value = ttk.Entry(input_frame3,textvariable=map_pval_value_val)
|
|
170
|
+
map_pval_value.insert(0, "RdBu")
|
|
171
|
+
map_pval_value.grid(row=5, column=1, padx=1, pady=1)
|
|
172
|
+
|
|
173
|
+
input_frame3.pack(pady=10)
|
|
174
|
+
|
|
175
|
+
##Colors
|
|
176
|
+
title4 = ttk.Label(master = window, text="Add Colors",font='Arial 15 bold')
|
|
177
|
+
title4.pack()
|
|
178
|
+
input_frame4 = ttk.Frame(master=window)
|
|
179
|
+
|
|
180
|
+
color_mask = ttk.Label(input_frame4, text="Mask Colors")
|
|
181
|
+
color_mask.grid(row=0, column=0, padx=1, pady=1, sticky="w")
|
|
182
|
+
color_mask_value_val=tk.StringVar()
|
|
183
|
+
color_mask_value = ttk.Entry(input_frame4,textvariable=color_mask_value_val)
|
|
184
|
+
color_mask_value.grid(row=0, column=1, padx=1, pady=1)
|
|
185
|
+
|
|
186
|
+
color_tract = ttk.Label(input_frame4, text="Tract Colors")
|
|
187
|
+
color_tract.grid(row=1, column=0, padx=1, pady=1, sticky="w")
|
|
188
|
+
color_tract_value_val=tk.StringVar()
|
|
189
|
+
color_tract_value = ttk.Entry(input_frame4,textvariable=color_tract_value_val)
|
|
190
|
+
color_tract_value.grid(row=1, column=1, padx=1, pady=1)
|
|
191
|
+
|
|
192
|
+
color_vtk = ttk.Label(input_frame4, text="Mesh Colors")
|
|
193
|
+
color_vtk.grid(row=2, column=0, padx=1, pady=1, sticky="w")
|
|
194
|
+
color_vtk_value_val=tk.StringVar()
|
|
195
|
+
color_vtk_value = ttk.Entry(input_frame4,textvariable=color_vtk_value_val)
|
|
196
|
+
color_vtk_value.grid(row=2, column=1, padx=1, pady=1)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
input_frame4.pack(pady=10)
|
|
201
|
+
submit_button = ttk.Button(window,text='Submit',command=submit)
|
|
202
|
+
submit_button.pack()
|
|
203
|
+
window.mainloop()
|
|
204
|
+
|
|
205
|
+
|
dive/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
dive/add.png
ADDED
|
Binary file
|
dive/csv_tocolors.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import matplotlib
|
|
2
|
+
import matplotlib.colors as mcolors
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
import collections
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
from math import isnan
|
|
8
|
+
import os
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## Read this reference to update normalization ...
|
|
12
|
+
## https://matplotlib.org/stable/api/colors_api.html
|
|
13
|
+
|
|
14
|
+
class Colors_csv():
|
|
15
|
+
def __init__(self,stats_csv=None):
|
|
16
|
+
self.csv_flag = None
|
|
17
|
+
self.colors_from_csv = []
|
|
18
|
+
self.stats_csv = stats_csv
|
|
19
|
+
self.map = None
|
|
20
|
+
|
|
21
|
+
def intialize(self,log_p_value=False):
|
|
22
|
+
self.df = pd.read_csv(self.stats_csv)
|
|
23
|
+
# if self.df.shape[-1] == 2:
|
|
24
|
+
# self.col_name = 'P_value'
|
|
25
|
+
|
|
26
|
+
if log_p_value:
|
|
27
|
+
self.df['P_value'] = -np.log10(self.df['P_value'])
|
|
28
|
+
self.col_name = 'P_value'
|
|
29
|
+
else:
|
|
30
|
+
self.col_name = 'Value'
|
|
31
|
+
|
|
32
|
+
self.min_value = self.df[self.col_name].min()
|
|
33
|
+
self.max_value = self.df[self.col_name].max()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def assign_colors(self,map,range_value=[],log_p_value=False,threshold=None,output=None,filename='_color_bar.pdf'):
|
|
37
|
+
self.map = map
|
|
38
|
+
self.intialize(log_p_value)
|
|
39
|
+
cmap = matplotlib.cm.get_cmap(map)
|
|
40
|
+
di = {}
|
|
41
|
+
if range_value and len(range_value)>0:
|
|
42
|
+
self.min_value = range_value[0]
|
|
43
|
+
self.max_value = range_value[1]
|
|
44
|
+
self.csv_flag = True
|
|
45
|
+
self.df.sort_values(by=['Labels'],inplace=True)
|
|
46
|
+
|
|
47
|
+
norm = mcolors.Normalize(vmin=self.min_value, vmax=self.max_value)
|
|
48
|
+
self.df['Value_n'] = norm(self.df[self.col_name])
|
|
49
|
+
|
|
50
|
+
for i,k,j in zip(self.df['Value_n'],self.df['P_value'],self.df['Labels']):
|
|
51
|
+
if self.csv_flag == True:
|
|
52
|
+
if k>threshold:
|
|
53
|
+
r=g=b=0.5
|
|
54
|
+
else:
|
|
55
|
+
if i!= None and self.min_value<=i<=self.max_value:
|
|
56
|
+
r,g,b,a = cmap(i)
|
|
57
|
+
if i>self.max_value:
|
|
58
|
+
r,g,b,a = cmap(self.max_value)
|
|
59
|
+
if i<self.min_value:
|
|
60
|
+
r,g,b,a = cmap(self.min_value)
|
|
61
|
+
else:
|
|
62
|
+
r,g,b,a = cmap(i)
|
|
63
|
+
di[j] = [r,g,b]
|
|
64
|
+
clean_dict = {k: di[k] for k in di if not isnan(k)}
|
|
65
|
+
clean_dict = collections.OrderedDict(sorted(clean_dict.items()))
|
|
66
|
+
for k, v in clean_dict.items():
|
|
67
|
+
self.colors_from_csv.append(v)
|
|
68
|
+
self.colors_from_csv = np.asarray(self.colors_from_csv)
|
|
69
|
+
|
|
70
|
+
## Save the color bar images
|
|
71
|
+
fig, ax = plt.subplots(figsize=(6, 1))
|
|
72
|
+
print(self.df[self.col_name])
|
|
73
|
+
if output!=None:
|
|
74
|
+
cb = matplotlib.colorbar.ColorbarBase(ax, cmap=cmap, values=sorted(self.df[self.col_name]), orientation='horizontal',spacing='uniform') #
|
|
75
|
+
cb.ax.tick_params(labelsize=10)
|
|
76
|
+
plt.savefig((output + filename) , bbox_inches='tight', dpi=300)
|
|
77
|
+
|
|
78
|
+
return self.colors_from_csv
|
|
79
|
+
|
dive/helper.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import vtk
|
|
3
|
+
import webcolors
|
|
4
|
+
import matplotlib
|
|
5
|
+
import numpy as np
|
|
6
|
+
import nibabel as nib
|
|
7
|
+
from fury import actor,utils
|
|
8
|
+
from scipy.ndimage import gaussian_filter
|
|
9
|
+
from fury.colormap import colormap_lookup_table
|
|
10
|
+
from vtkmodules.vtkRenderingCore import vtkProperty
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class load_3dbrain:
|
|
14
|
+
|
|
15
|
+
def __init__(self,nifti) -> None:
|
|
16
|
+
self.data = nifti.get_fdata()
|
|
17
|
+
self.threshold = 45
|
|
18
|
+
self.sigma = 0.5
|
|
19
|
+
self.affine = nifti.affine
|
|
20
|
+
self.glass_brain_actor = actor
|
|
21
|
+
|
|
22
|
+
# def set_property(self):
|
|
23
|
+
# self.glass_brain_actor.GetProperty().EdgeVisibilityOn()
|
|
24
|
+
# self.glass_brain_actor.GetProperty().VertexVisibilityOff()
|
|
25
|
+
# self.glass_brain_actor.GetProperty().SetEdgeColor(0.5, 0.5, 0.5)
|
|
26
|
+
# glass_material = self.glass_brain_actor.GetProperty()
|
|
27
|
+
# glass_material.SetAmbient(1)
|
|
28
|
+
# glass_material.SetDiffuse(1)
|
|
29
|
+
# glass_material.SetSpecular(1.0)
|
|
30
|
+
# glass_material.SetSpecularPower(100.0)
|
|
31
|
+
# glass_material.SetOcclusionStrength(0.1)
|
|
32
|
+
# glass_material.SetRenderLinesAsTubes(True)
|
|
33
|
+
# glass_material.SetMetallic(1)
|
|
34
|
+
# self.glass_brain_actor.GetProperty().SetRoughness(0)
|
|
35
|
+
# self.glass_brain_actor.GetProperty().SetOpacity(0.05)
|
|
36
|
+
|
|
37
|
+
def loading(self):
|
|
38
|
+
self.data[self.data<self.threshold] = 0
|
|
39
|
+
smooth_data = gaussian_filter(self.data,sigma=self.sigma)
|
|
40
|
+
self.glass_brain_actor = actor.contour_from_roi(self.data,self.affine,color=[0,0,0],opacity=0.08)
|
|
41
|
+
# self.set_property()
|
|
42
|
+
return self.glass_brain_actor
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class load_2dbrain:
|
|
46
|
+
def __init__(self,nifti) -> None:
|
|
47
|
+
self.data = nifti.get_fdata()
|
|
48
|
+
# self.data[self.data == 0] = 1000
|
|
49
|
+
self.max_v = min(self.data.shape) ### not used yet
|
|
50
|
+
self.affine = nifti.affine
|
|
51
|
+
self.mean, self.std = self.data[self.data > 0].mean(), self.data[self.data > 0].std()
|
|
52
|
+
self.value_range = (self.mean - 0.1* self.std, self.mean + 3 * self.std)
|
|
53
|
+
|
|
54
|
+
def load_actor(self):
|
|
55
|
+
slice_actor = actor.slicer(self.data,self.affine,self.value_range,opacity=0.9)
|
|
56
|
+
return slice_actor
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class Mesh:
|
|
60
|
+
def __init__(self,vtk,color_list=[]) -> None:
|
|
61
|
+
self.vtk = vtk
|
|
62
|
+
self.color_list = color_list
|
|
63
|
+
|
|
64
|
+
def property(self):
|
|
65
|
+
property = vtkProperty()
|
|
66
|
+
property.SetColor(self.color_list)
|
|
67
|
+
property.SetOpacity(1.0)
|
|
68
|
+
property.SetRoughness(0.0)
|
|
69
|
+
return property
|
|
70
|
+
|
|
71
|
+
def load_mesh(self):
|
|
72
|
+
property = self.property()
|
|
73
|
+
actor_2 = vtk.vtkActor()
|
|
74
|
+
actor_2 = utils.get_actor_from_polydata(self.vtk)
|
|
75
|
+
actor_2.SetProperty(property)
|
|
76
|
+
return actor_2
|
|
77
|
+
|
|
78
|
+
def load_mesh_with_colors(self,mask,color_map):
|
|
79
|
+
voxels = nib.affines.apply_affine(np.linalg.inv(mask.affine), self.vtk.points).astype(int)
|
|
80
|
+
shape = mask.get_fdata().shape
|
|
81
|
+
array_3d = np.zeros(shape, dtype=float)
|
|
82
|
+
nifti_dict = {(i, j, k): val for (i, j, k), val in np.ndenumerate(mask.get_fdata())}
|
|
83
|
+
master_color = list(map(lambda vox: nifti_dict[vox[0], vox[1], vox[2]], voxels))
|
|
84
|
+
for index in voxels:
|
|
85
|
+
array_3d[int(index[0]),int(index[1]),int(index[2])] = mask.get_fdata()[index[0],index[1],index[2]]
|
|
86
|
+
roi_dict = np.delete(np.unique(array_3d), 0)
|
|
87
|
+
unique_roi_surfaces = vtk.vtkAssembly()
|
|
88
|
+
color_map = np.asarray(color_map)
|
|
89
|
+
for i, roi in enumerate(roi_dict):
|
|
90
|
+
roi_data = np.isin(array_3d,roi).astype(int)
|
|
91
|
+
roi_surfaces = actor.contour_from_roi(roi_data,mask.affine,color=color_map[i])
|
|
92
|
+
unique_roi_surfaces.AddPart(roi_surfaces)
|
|
93
|
+
return unique_roi_surfaces
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class Colors:
|
|
97
|
+
|
|
98
|
+
def __init__(self):
|
|
99
|
+
self.rgb_decimal_tuple = None
|
|
100
|
+
|
|
101
|
+
def get_rgb_from_color_name(self,color_name):
|
|
102
|
+
try:
|
|
103
|
+
rgb_tuple = webcolors.name_to_rgb(color_name)
|
|
104
|
+
self.rgb_decimal_tuple = tuple(component / 255.0 for component in rgb_tuple)
|
|
105
|
+
return self.rgb_decimal_tuple
|
|
106
|
+
except ValueError:
|
|
107
|
+
print("Invalid color name:",color_name)
|
|
108
|
+
return None
|
|
109
|
+
|
|
110
|
+
def hex_to_rgb(self,hex_value):
|
|
111
|
+
rgb_tuple = webcolors.hex_to_rgb(hex_value) #Check Matplotlib
|
|
112
|
+
self.rgb_decimal_tuple = tuple(component / 255.0 for component in rgb_tuple)
|
|
113
|
+
return self.rgb_decimal_tuple
|
|
114
|
+
|
|
115
|
+
def string_to_list(self,input_string):
|
|
116
|
+
list_of_lists = []
|
|
117
|
+
cleaned_string = input_string.replace('[', '').replace(']', '').replace('(','').replace(')','')
|
|
118
|
+
elements = cleaned_string.split(',')
|
|
119
|
+
for element in elements:
|
|
120
|
+
if element.startswith('#'):
|
|
121
|
+
list_of_lists.append(self.hex_to_rgb(element))
|
|
122
|
+
else:
|
|
123
|
+
list_of_lists.append(self.get_rgb_from_color_name(element))
|
|
124
|
+
return list_of_lists
|
|
125
|
+
|
|
126
|
+
def get_tab20_color(index,type_):
|
|
127
|
+
if type_=='vol':
|
|
128
|
+
tab20_colors = matplotlib.cm.get_cmap('tab20')
|
|
129
|
+
else:
|
|
130
|
+
tab20_colors = matplotlib.cm.get_cmap('Pastel1_r')
|
|
131
|
+
|
|
132
|
+
return matplotlib.colors.to_rgb(tab20_colors(index))
|
|
133
|
+
|
|
134
|
+
def load_colors(self,colors_path=None):
|
|
135
|
+
dic_colors = {}
|
|
136
|
+
if colors_path==None: return
|
|
137
|
+
with open(colors_path) as colors_file:
|
|
138
|
+
lines = [line.rstrip() for line in colors_file if not line.rstrip().startswith('#')]
|
|
139
|
+
for i in lines:
|
|
140
|
+
match = re.search(r'[a-zA-Z]', i)
|
|
141
|
+
first_alphabet_index = match.start() if match else None
|
|
142
|
+
# Find the index of the last alphabetic character
|
|
143
|
+
last_alphabet_index = None
|
|
144
|
+
for match in re.finditer(r'[a-zA-Z]', i):
|
|
145
|
+
last_alphabet_index = match.start()
|
|
146
|
+
|
|
147
|
+
key = str(i[first_alphabet_index:last_alphabet_index+1])
|
|
148
|
+
colors_str = i[last_alphabet_index+2:]
|
|
149
|
+
colors_list = colors_str.split()
|
|
150
|
+
colors_list = list(map(int, colors_list))
|
|
151
|
+
rgb_tuple = colors_list[0:-1]
|
|
152
|
+
rgb_decimal_tuple = tuple(component / 255.0 for component in rgb_tuple)
|
|
153
|
+
dic_colors[key] = rgb_decimal_tuple
|
|
154
|
+
|
|
155
|
+
return dic_colors
|
dive/loading.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
|
|
2
|
+
import io
|
|
3
|
+
import gzip
|
|
4
|
+
import zipfile
|
|
5
|
+
import numpy as np
|
|
6
|
+
from dive.mask import Mask
|
|
7
|
+
import nibabel as nib
|
|
8
|
+
from dive.tract import Tract
|
|
9
|
+
from dive.helper import Colors
|
|
10
|
+
class load:
|
|
11
|
+
def __init__(self):
|
|
12
|
+
self.index_mask = 0
|
|
13
|
+
self.flag_multple = 0
|
|
14
|
+
self.distinctpy_colormask = None
|
|
15
|
+
self.mask = None
|
|
16
|
+
|
|
17
|
+
def read_from_compressed(file = None):
|
|
18
|
+
"""
|
|
19
|
+
Args:
|
|
20
|
+
file: path to the compressed file
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
img: file object to be read by nibabel
|
|
24
|
+
This function reads compressed (zip or gz) TRK or TCK files and returns an object
|
|
25
|
+
that can be read using nibabel
|
|
26
|
+
"""
|
|
27
|
+
zip_type = file.split('.')[-1]
|
|
28
|
+
if zip_type == 'gz':
|
|
29
|
+
with gzip.open(file) as gf:
|
|
30
|
+
data = gf.read()
|
|
31
|
+
img = io.BytesIO(data)
|
|
32
|
+
elif zip_type == 'zip':
|
|
33
|
+
with zipfile.ZipFile(file, mode="r") as zf:
|
|
34
|
+
f_name = zf.namelist()[0]
|
|
35
|
+
img = zf.open(f_name)
|
|
36
|
+
else:
|
|
37
|
+
print("Wrong zip type. Either '.gz' or '.zip' ")
|
|
38
|
+
return img
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def load_mask(self,mask_args,color_map_mask=[],color=None,color_map=None):
|
|
42
|
+
|
|
43
|
+
self.flag_multple = 0
|
|
44
|
+
self.index_mask= self.index_mask+1
|
|
45
|
+
print(mask_args,color)
|
|
46
|
+
if mask_args==None: actor_mask = None
|
|
47
|
+
else:
|
|
48
|
+
mask = nib.load(mask_args)
|
|
49
|
+
self.mask = mask
|
|
50
|
+
if len(np.unique(mask.get_fdata()))>2:
|
|
51
|
+
self.flag_multple = 1
|
|
52
|
+
if len(color_map_mask)>0:
|
|
53
|
+
mask_caller = Mask(mask,colormap=color_map_mask)
|
|
54
|
+
actor_mask,self.distinctpy_colormask = mask_caller.multi_label()
|
|
55
|
+
else:
|
|
56
|
+
mask_caller = Mask(mask)
|
|
57
|
+
actor_mask,self.distinctpy_colormask = mask_caller.multi_label()
|
|
58
|
+
else:
|
|
59
|
+
if color:
|
|
60
|
+
mask_caller = Mask(mask,color)
|
|
61
|
+
actor_mask = mask_caller.one_label()
|
|
62
|
+
else:
|
|
63
|
+
if color_map!=None:
|
|
64
|
+
name = mask_args.split('/')[-1].split('.')[0]
|
|
65
|
+
dic_colors = Colors.load_colors()
|
|
66
|
+
if name in dic_colors:
|
|
67
|
+
mask_caller = Mask(mask,dic_colors[name])
|
|
68
|
+
actor_mask = mask_caller.one_label()
|
|
69
|
+
else:
|
|
70
|
+
mask_caller = Mask(mask,Colors.get_tab20_color(index = self.index_mask, type_='vol'))
|
|
71
|
+
actor_mask = mask_caller.one_label()
|
|
72
|
+
return actor_mask
|
|
73
|
+
|
|
74
|
+
def load_tract(self,tract_args=None,tract_width = 1.0,tract_color = None,color_map_csv_tract=[],color_map_csv_mask=[]):
|
|
75
|
+
|
|
76
|
+
if tract_args!=None:
|
|
77
|
+
if str(tract_args).split('.')[-1] == '.gz' or str(tract_args).split('.')[-1] == 'zip':
|
|
78
|
+
tract_image = nib.streamlines.load(self.read_from_compressed(tract_args))
|
|
79
|
+
else: tract_image = nib.streamlines.load(tract_args)
|
|
80
|
+
|
|
81
|
+
if not tract_image.header : print("The Track has no Header!")
|
|
82
|
+
|
|
83
|
+
if self.flag_multple == 1:
|
|
84
|
+
tract_caller = Tract(bundle = tract_image.streamlines,tw=tract_width)
|
|
85
|
+
if len(color_map_csv_tract)>0:
|
|
86
|
+
tract_caller.selt_colormap(instance=color_map_csv_tract)
|
|
87
|
+
|
|
88
|
+
elif len(color_map_csv_mask)>0:
|
|
89
|
+
tract_caller.selt_colormap(instance=color_map_csv_mask)
|
|
90
|
+
|
|
91
|
+
else: tract_caller.selt_colormap(instance=self.distinctpy_colormask)
|
|
92
|
+
actor_tract = tract_caller.with_colormap(mask=self.mask)
|
|
93
|
+
|
|
94
|
+
elif tract_color!=None:
|
|
95
|
+
tract_caller = Tract(bundle = tract_image.streamlines,tw=tract_width,color_list=tract_color)
|
|
96
|
+
actor_tract = tract_caller.single_color()
|
|
97
|
+
else:
|
|
98
|
+
tract_caller = Tract(bundle = tract_image.streamlines,tw=tract_width)
|
|
99
|
+
actor_tract = tract_caller.dirrection_color()
|
|
100
|
+
return actor_tract
|
|
101
|
+
|