Skip to content
Permalink
b9be5f63b6
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
1036 lines (913 sloc) 42.7 KB
# utils for visualization
import numpy as np
import vtk
import time
def read_xyz_file(file_name):
with open('{}'.format(file_name), 'r') as data_fid:
points, x, y, z = [], [], [], []
for row in data_fid.readlines():
row = row.replace('\n', '')
numbers = row.split(' ')
try:
point_coord = [float(item) for item in numbers[0:3]]
point_x = point_coord[0]
point_y = point_coord[1]
point_z = point_coord[2]
points.append(point_coord)
x.append(point_x)
y.append(point_y)
z.append(point_z)
except ValueError:
print('ValueError: {}, row {}'.format(file_name, row))
except IndexError:
print('IndexError: {}, row {}'.format(file_name, row))
else:
pass
return np.array(x), np.array(y), np.array(z)
def read_feature_file(file_name):
with open('{}'.format(file_name), 'r') as data_fid:
features = []
for row in data_fid.readlines():
row = row.replace('\n', '')
row_features = row.split(' ')
try:
row_features = [float(item) for item in row_features]
features.append(row_features)
except ValueError:
print('ValueError: {}, row {}'.format(file_name, row))
except IndexError:
print('IndexError: {}, row {}'.format(file_name, row))
else:
pass
return features
class Point(object):
def __init__(self, coord):
self.coord = coord
self.string = '{}_{}_{}'.format(coord[0], coord[1], coord[2])
self.order = None
def get_coord(self):
return self.coord
class Cubic(object):
"""
A class that describe a cubic in 3D space.
Can detect if this cubic contain points, then spilt into 8 child cubics and plot.
"""
def __init__(self, coord, id):
self.id = id
min_coord = coord[0]
max_coord = coord[1]
self.min_coord = min_coord
self.max_coord = max_coord
self.min_x = min_coord[0]
self.min_y = min_coord[1]
self.min_z = min_coord[2]
self.max_x = max_coord[0]
self.max_y = max_coord[1]
self.max_z = max_coord[2]
self.dot1 = [self.min_x, self.min_y, self.min_z]
self.dot2 = [self.min_x, self.min_y, self.max_z]
self.dot3 = [self.min_x, self.max_y, self.min_z]
self.dot4 = [self.min_x, self.max_y, self.max_z]
self.dot5 = [self.max_x, self.min_y, self.min_z]
self.dot6 = [self.max_x, self.min_y, self.max_z]
self.dot7 = [self.max_x, self.max_y, self.min_z]
self.dot8 = [self.max_x, self.max_y, self.max_z]
self.resolution = self.max_z - self.min_z
self.mid_point = [(self.min_x + self.max_x)/2, (self.min_y + self.max_y)/2, (self.min_z + self.max_z)/2]
def set_color_new(self, value):
if value == 'Protein':
self.color = [.4, .4, 1, 1]
self.color_scale = 11
elif value == 'Ligand':
self.color = [.4, 1, .4, 1]
self.color_scale = 12
elif value == 'Mixture':
self.color = [.4, 1, 1, 1]
self.color_scale = 13
elif value == 'Empty':
self.color = [1, 1, 1, 1]
self.color_scale = 14
else:
print('error in assign color')
def member_test(self, points):
if points[0] >= self.min_x and points[0] <= self.max_x and \
points[1] >= self.min_y and points[1] <= self.max_y and \
points[2] >= self.min_z and points[2] <= self.max_z:
return True
else:
return False
def load_to_vtk(self, vtk_dic):
if 'points' not in vtk_dic:
vtk_dic['points'] = []
vtk_dic['num_points'] = 0
vtk_dic['cells'] = []
vtk_dic['num_cells'] = 0
vtk_dic['cell_color_scale'] = []
vtk_dic['Ligand'] = 0
vtk_dic['Protein'] = 0
vtk_dic['Mixture'] = 0
vtk_dic['Empty'] = 0
vtk_dic['points'] += [self.dot1, self.dot2, self.dot3, self.dot4, self.dot5, self.dot6, self.dot7, self.dot8]
index_start = vtk_dic['num_points']
# use all 6 surfaces as cells.
new_cells = [[4, 0 + index_start, 1 + index_start, 3 + index_start, 2 + index_start],
[4, 4 + index_start, 5 + index_start, 7 + index_start, 6 + index_start],
[4, 0 + index_start, 4 + index_start, 6 + index_start, 2 + index_start],
[4, 2 + index_start, 6 + index_start, 7 + index_start, 3 + index_start],
[4, 3 + index_start, 7 + index_start, 5 + index_start, 1 + index_start],
[4, 0 + index_start, 4 + index_start, 5 + index_start, 1 + index_start]]
vtk_dic['cells'] += new_cells
vtk_dic['num_cells'] += 6
for i in range(6):
vtk_dic['cell_color_scale'].append(self.color_scale)
if self.color_scale == 11:
vtk_dic['Protein'] += 1
elif self.color_scale == 12:
vtk_dic['Ligand'] += 1
elif self.color_scale == 13:
vtk_dic['Mixture'] += 1
elif self.color_scale == 14:
vtk_dic['Empty'] += 1
vtk_dic['num_points'] += 8
if len(vtk_dic['points']) != vtk_dic['num_points']:
print('points error')
print(len(vtk_dic['points']), vtk_dic['num_points'])
if len(vtk_dic['cells']) != vtk_dic['num_cells']:
print('cell error')
return vtk_dic
# print('number of ligand cells: {}'.format(vtk_dic['ligand']))
# print('number of pocket cells: {}'.format(vtk_dic['pocket']))
# print('number of mix cells: {}'.format(vtk_dic['mix']))
# print('number of empty cells: {}'.format(vtk_dic['empty']))
# print('number of total cells: {}'.format(vtk_dic['ligand'] + vtk_dic['pocket'] + vtk_dic['mix'] + vtk_dic['empty']))
def load_to_vtk_opt(self, vtk_dic_opt):
if 'points' not in vtk_dic_opt:
vtk_dic_opt['points'] = {}
vtk_dic_opt['num_points'] = 0
vtk_dic_opt['cells'] = []
vtk_dic_opt['num_cells'] = 0
vtk_dic_opt['cell_color_scale'] = []
vtk_dic_opt['Ligand'] = 0
vtk_dic_opt['Protein'] = 0
vtk_dic_opt['Mixture'] = 0
vtk_dic_opt['Empty'] = 0
# current_cubic_points = [self.dot1, self.dot2, self.dot3, self.dot4, self.dot5, self.dot6, self.dot7, self.dot8]
current_cubic_cells = [[self.dot1, self.dot2, self.dot4, self.dot3],
[self.dot5, self.dot6, self.dot8, self.dot7],
[self.dot1, self.dot5, self.dot7, self.dot3],
[self.dot3, self.dot7, self.dot8, self.dot4],
[self.dot4, self.dot8, self.dot6, self.dot2],
[self.dot1, self.dot5, self.dot6, self.dot2]]
for cell in current_cubic_cells:
cell_order = []
for point in cell:
point = Point(point)
if point.string in vtk_dic_opt['points']:
point_order = vtk_dic_opt['points'][point.string]
cell_order.append(point_order)
else:
point_order = len(vtk_dic_opt['points'])
vtk_dic_opt['points'][point.string] = point_order
cell_order.append(point_order)
vtk_dic_opt['cells'].append(cell_order)
vtk_dic_opt['cell_color_scale'].append(self.color_scale)
vtk_dic_opt['num_cells'] += 6
if self.color_scale == 11:
vtk_dic_opt['Protein'] += 1
elif self.color_scale == 12:
vtk_dic_opt['Ligand'] += 1
elif self.color_scale == 13:
vtk_dic_opt['Mixture'] += 1
elif self.color_scale == 14:
vtk_dic_opt['Empty'] += 1
else:
print('Cubic {} have no color scale settled.'.format(self.id))
if len(vtk_dic_opt['cells']) != vtk_dic_opt['num_cells']:
print('cell error')
return vtk_dic_opt
def write_oct_line_opt(self, vtk_line_dic, color):
"""
:param pts_dic: {key, value}, where key is Point.string, value is order of the point.
:param lines_list:
:param colors_list:
:param color:
:return:
"""
if len(vtk_line_dic) == 0:
vtk_line_dic['pts_dic'] = {}
vtk_line_dic['lines_dic'] = {}
vtk_line_dic['colors_list'] = []
pts_dic = vtk_line_dic['pts_dic']
lines_dic = vtk_line_dic['lines_dic']
colors_list = vtk_line_dic['colors_list']
pts_len = len(pts_dic)
pts_inc = 0
p0 = [self.min_x, (self.min_y + self.max_y) / 2, (self.min_z + self.max_z) / 2]
p1 = [self.max_x, (self.min_y + self.max_y) / 2, (self.min_z + self.max_z) / 2]
p2 = [(self.min_x + self.max_x) / 2, self.min_y, (self.min_z + self.max_z) / 2]
p3 = [(self.min_x + self.max_x) / 2, self.max_y, (self.min_z + self.max_z) / 2]
p4 = [(self.min_x + self.max_x) / 2, (self.min_y + self.max_y) / 2, self.min_z]
p5 = [(self.min_x + self.max_x) / 2, (self.min_y + self.max_y) / 2, self.max_z]
p6 = [self.min_x, (self.min_y + self.max_y) / 2, self.min_z]
p7 = [self.min_x, (self.min_y + self.max_y) / 2, self.max_z]
p8 = [self.min_x, self.min_y, (self.min_z + self.max_z) / 2]
p9 = [self.min_x, self.max_y, (self.min_z + self.max_z) / 2]
p10 = [(self.min_x + self.max_x) / 2, self.min_y, self.min_z]
p11 = [(self.min_x + self.max_x) / 2, self.min_y, self.max_z]
p12 = [(self.min_x + self.max_x) / 2, self.max_y, self.min_z]
p13 = [(self.min_x + self.max_x) / 2, self.max_y, self.max_z]
p14 = [self.max_x, (self.min_y + self.max_y) / 2, self.min_z]
p15 = [self.max_x, (self.min_y + self.max_y) / 2, self.max_z]
p16 = [self.max_x, self.min_y, (self.min_z + self.max_z) / 2]
p17 = [self.max_x, self.max_y, (self.min_z + self.max_z) / 2]
line_list = [[p0, p1], [p2,p3], [p4, p5], [p6, p7], [p8, p9], [p14, p15], [p16, p17],
[p8, p16], [p10, p11], [p9, p17], [p12, p13], [p11, p13], [p7, p15],
[p6, p14], [p10, p12]]
for line in line_list:
start_point = Point(line[0])
end_point = Point(line[1])
if start_point.string in pts_dic and end_point.string in pts_dic:
start_point_order = pts_dic[start_point.string]
end_point_order = pts_dic[end_point.string]
elif start_point.string not in pts_dic and end_point.string in pts_dic:
start_point_order = pts_len + pts_inc
pts_dic[start_point.string] = start_point_order
pts_inc += 1
end_point_order = pts_dic[end_point.string]
elif start_point.string in pts_dic and end_point.string not in pts_dic:
end_point_order = pts_len + pts_inc
pts_dic[end_point.string] = end_point_order
pts_inc += 1
start_point_order = pts_dic[start_point.string]
else:
start_point_order = pts_len + pts_inc
pts_dic[start_point.string] = start_point_order
pts_inc += 1
end_point_order = pts_len + pts_inc
pts_dic[end_point.string] = end_point_order
pts_inc += 1
line_string = '{}_{}'.format(start_point_order, end_point_order)
if line_string not in lines_dic:
lines_dic[line_string] = len(lines_dic)
colors_list.append(color)
vtk_line_dic['pts_dic'] = pts_dic
vtk_line_dic['lines_dic'], vtk_line_dic['colors_list'] = lines_dic, colors_list
return vtk_line_dic
def write_edge_line_opt(self, vtk_line_dic, color):
if 'pts_dic' not in vtk_line_dic:
vtk_line_dic['pts_dic'] = {}
vtk_line_dic['lines_dic'] = {}
vtk_line_dic['colors_list'] = []
pts_dic = vtk_line_dic['pts_dic']
lines_dic, colors_list = vtk_line_dic['lines_dic'], vtk_line_dic['colors_list']
pts_len = len(pts_dic)
pts_inc = 0
p0 = self.dot1 #= [self.min_x, self.min_y, self.min_z]
p1 = self.dot2 #= [self.min_x, self.min_y, self.max_z]
p2 = self.dot3 #= [self.min_x, self.max_y, self.min_z]
p3 = self.dot4 #= [self.min_x, self.max_y, self.max_z]
p4 = self.dot5 #= [self.max_x, self.min_y, self.min_z]
p5 = self.dot6 #= [self.max_x, self.min_y, self.max_z]
p6 = self.dot7 #= [self.max_x, self.max_y, self.min_z]
p7 = self.dot8 #= [self.max_x, self.max_y, self.max_z]
line_list = [[p0,p1], [p1,p3], [p2,p3], [p0,p2], [p4,p5], [p5,p7], [p6,p7], [p4,p6],
[p0,p4], [p2,p6], [p3,p7], [p1,p5]]
for line in line_list:
start_point = Point(line[0])
end_point = Point(line[1])
if start_point.string in pts_dic and end_point.string in pts_dic:
start_point_order = pts_dic[start_point.string]
end_point_order = pts_dic[end_point.string]
elif start_point.string not in pts_dic and end_point.string in pts_dic:
start_point_order = pts_len + pts_inc
pts_dic[start_point.string] = start_point_order
pts_inc += 1
end_point_order = pts_dic[end_point.string]
elif start_point.string in pts_dic and end_point.string not in pts_dic:
end_point_order = pts_len + pts_inc
pts_dic[end_point.string] = end_point_order
pts_inc += 1
start_point_order = pts_dic[start_point.string]
else:
start_point_order = pts_len + pts_inc
pts_dic[start_point.string] = start_point_order
pts_inc += 1
end_point_order = pts_len + pts_inc
pts_dic[end_point.string] = end_point_order
pts_inc += 1
line_string = '{}_{}'.format(start_point_order, end_point_order)
if line_string not in lines_dic:
lines_dic[line_string] = len(lines_dic)
colors_list.append(color)
vtk_line_dic['pts_dic'] = pts_dic
vtk_line_dic['lines_dic'], vtk_line_dic['colors_list'] = lines_dic, colors_list
return vtk_line_dic
class Adaptive_Cubics(object):
def __init__(self, cubic_dic, complex_id, focus_center = [0,0,0], center = [0,0,0],
adaptive_line = True, differ = False,
count = False):
self.cubic_dic = cubic_dic
self.complex_id = complex_id
self.differ = differ
self.adaptive_line = adaptive_line
self.focus_center = focus_center
self.center = center
self.count = count
def get_adaptive_cubic(self, core_area, side_area1, side_area2, side_area3,
target_range, line_depth, total_depth, save_folder, light = False):
"""
:param core_area: the range core area that need the finest resolution
:param side_area1: the range side area that need less resolution
:param side_area2: more range side area that need much less resolution
:return:
"""
self.vtk_dic = {}
self.fine_cubic_id_set = set()
self.parent_cubic_id_set = set()
self.fine_cubic_count = {}
# self.non_fine_cubic_id_set = set()
for value in ['Protein', 'Ligand', 'Mixture', 'Empty']:
self.fine_cubic_count[value] = 0
side1_layer_dic = self.construct_adaptive_dic_V1(self.cubic_dic, core_area,
target_range, self.focus_center, light)
side2_layer_dic = self.construct_adaptive_dic_V1(side1_layer_dic, side_area1,
target_range, self.focus_center, light)
side3_layer_dic = self.construct_adaptive_dic_V1(side2_layer_dic, side_area2,
target_range, self.focus_center, light)
side4_layer_dic = self.construct_adaptive_dic_V1(side3_layer_dic, side_area3,
target_range, self.focus_center, light)
side5_layer_dic = self.construct_adaptive_dic_V1(side4_layer_dic, target_range,
target_range, self.focus_center, light)
print('Fine Cubic Dic Length: {}'.format(len(self.fine_cubic_id_set)))
# add for adaptive count:
# count_cubic_id_set = set()
# parent_cubic_id_set = set()
if self.adaptive_line:
segline_cubic_id_set = set()
vtk_line_dic = {}
for cubic_id in self.fine_cubic_id_set:
# if not light:
# segline_cubic_id_set.add(cubic.id) # why need this?
# pass
# self.get_complement_adaptive_id(cubic_id, count_cubic_id_set, target_range)
parent_cubic_id = get_parent_cubic_id(cubic_id, target_range)
if parent_cubic_id in self.fine_cubic_id_set:
print('Parent and Fine conflict: {}'.format(parent_cubic_id))
while int(parent_cubic_id.split('_')[0]) >= 0:
# self.get_complement_adaptive_id(parent_cubic_id, parent_cubic_id_set, target_range)
# parent_cubic_set.add(parent_cubic)
# self.get_complement_adaptive(parent_cubic, count_cubic_set, target_range)
if int(parent_cubic_id.split('_')[0]) < line_depth:
segline_cubic_id_set.add(parent_cubic_id)
parent_cubic_id = get_parent_cubic_id(parent_cubic_id, target_range)
if not light:
# for parent_cubic_id in parent_cubic_id_set:
# if int(parent_cubic_id.split('_')[0]) < line_depth:
# segline_cubic_id_set.add(parent_cubic_id)
print('parent_cubic_id_set length: {}'.format(len(self.parent_cubic_id_set)))
print('segline_cubic_id_set: {}'.format(len(segline_cubic_id_set)))
for cubic_id in segline_cubic_id_set:
depth = int(cubic_id.split('_')[0])
color = get_color_for_dep(depth + 1, self.differ)
cubic = cubic_id_to_cubic(cubic_id, target_range)
vtk_line_dic = cubic.write_oct_line_opt(vtk_line_dic, color)
max_cubic = Cubic(
[[-target_range, -target_range, -target_range], [target_range, target_range, target_range]],
'0_0_0_0')
color = get_color_for_dep(0, self.differ)
vtk_line_dic = max_cubic.write_edge_line_opt(vtk_line_dic, color)
pts, lines, colors = fill_vtk_lines(vtk_line_dic, self.center)
write_seg_vtk(pts, lines, colors, self.complex_id, target_range, line_depth, save_folder)
#
# for cubic_id in self.parent_cubic_id_set:
# if cubic_id not in segline_cubic_id_set:
# print('parent cubic {} not in segline_cubic_id_set'.format(cubic_id))
print('Final Node: {}'.format(len(self.fine_cubic_id_set)))
print('Mid Node: {}'.format(len(segline_cubic_id_set)))
if not light:
file_name = '{}/{}/{}_Octree_Adaptive_{}_{}'.format(save_folder, self.complex_id, self.complex_id, target_range, total_depth)
vtk_writer(vtk_dic=self.vtk_dic, file_name=file_name, shift=self.center)
def get_adaptive_count(self,core_area, side_area1, side_area2, side_area3,
target_range, line_depth, total_depth, save_folder, light = False):
depth_cubic_dic = {}
for depth in range(0, total_depth + 1):
depth_cubic_dic[depth] = set()
for cubic_id, value in self.cubic_dic:
[depth, x, y, z] = [int(item) for item in cubic_id.split('_')]
while depth >= 0:
depth_cubic_dic[depth].add(cubic_id)
depth = depth - 1
x >> 1
y >> 1
z >> 1
cubic_id = '{}_{}_{}_{}'.format(depth, x, y, z)
def get_complement_adaptive_id(self, cubic_id, count_cubic_id_set, target_range):
[depth, x, y, z] = [int(item) for item in cubic_id.split('_')]
if depth <= 0:
count_cubic_id_set.add(cubic_id)
return
x = x >> 1 << 1
y = y >> 1 << 1
z = z >> 1 << 1
for i in range(0, 2):
for j in range(0, 2):
for k in range(0, 2):
string = '{}_{}_{}_{}'.format(depth, x + i, y + j, z + k)
# base = target_range * 2 / 2 ** depth
# coord_x = x * base - target_range + i
# coord_y = y * base - target_range + j
# coord_z = z * base - target_range + k
# min_coord = [coord_x, coord_y, coord_z]
# max_coord = [coord_x + base, coord_y + base, coord_z + base]
# comp_cubic = Cubic([min_coord, max_coord], string)
# count_cubic_set.add(comp_cubic)
count_cubic_id_set.add(string)
def construct_adaptive_dic_V1(self, cubic_dic, area, target_range,
focus_center=[0, 0, 0], light=False):
'''
:param cubic_dic: dictionary, key is cubic.id, value is Protein, Mixture, Ligand.
:param area: within this area, use current depth in cubic_dic, otherwise need to compute upper layer
:param vtk_dic: dictionary that used to plot cubic.
:param seg_dic: dictionary that used to plot segment line of adaptive cibics.
:return:
'''
side_dic = {}
for key, value in cubic_dic.items():
[depth, x, y, z] = [int(item) for item in key.split('_')]
# if cubic's parent in the core range, the all child of its parent should be in fine_cubic_set.
p_x = x >> 1
p_y = y >> 1
p_z = z >> 1
p_depth = depth - 1
p_base = target_range * 2 / 2 ** p_depth
p_coord_x = p_x * p_base - target_range
p_coord_y = p_y * p_base - target_range
p_coord_z = p_z * p_base - target_range
[focus_x, focus_y, focus_z] = focus_center
# test if this cubic is in core area, if so, dump into adaptive cubic_dic
core_flag_z = min(abs(p_coord_z - focus_z), abs(p_coord_z + p_base - focus_z)) <= area
core_flag_y = min(abs(p_coord_y - focus_y), abs(p_coord_y + p_base - focus_y)) <= area
core_flag_x = min(abs(p_coord_x - focus_x), abs(p_coord_x + p_base - focus_x)) <= area
core_flag = core_flag_x and core_flag_y and core_flag_z
p_id = '{}_{}_{}_{}'.format(p_depth, p_x, p_y, p_z)
if not core_flag:
if p_id not in side_dic:
side_dic[p_id] = value
elif value != side_dic[p_id]:
side_dic[p_id] = 'Mixture'
else:
pass
else:
self.parent_cubic_id_set.add(p_id)
# self.non_fine_cubic_id_set.add(p_id)
b_x = p_x << 1
b_y = p_y << 1
b_z = p_z << 1
for i in range(0, 2):
for j in range(0, 2):
for k in range(0, 2):
n_x = b_x + i
n_y = b_y + j
n_z = b_z + k
n_id = '{}_{}_{}_{}'.format(depth, n_x, n_y, n_z)
if n_id in self.parent_cubic_id_set:
continue
if n_id in self.fine_cubic_id_set:
continue
self.fine_cubic_id_set.add(n_id)
if n_id in cubic_dic:
base = target_range * 2 / 2 ** depth
n_coord_x = n_x * base - target_range
n_coord_y = n_y * base - target_range
n_coord_z = n_z * base - target_range
min_coord = [n_coord_x, n_coord_y, n_coord_z]
max_coord = [n_coord_x + base, n_coord_y + base, n_coord_z + base]
n_cubic = Cubic([min_coord, max_coord], n_id)
n_value = cubic_dic[n_cubic.id]
n_cubic.set_color_new(value)
if not light:
self.vtk_dic = n_cubic.load_to_vtk_opt(self.vtk_dic)
self.fine_cubic_count[n_value] += 1
else:
self.fine_cubic_count['Empty'] += 1
#cubic.set_color_new('Empty')
pass
return side_dic
def cubic_id_to_cubic(id, target_range):
'''
based on id, target range, the cubic is identicle.
:param id:
:param target_range:
:return:
'''
[depth, x, y, z] = [int(item) for item in id.split('_')]
# (depth, x, y, z) = id
base = target_range * 2 / 2 ** depth
coord_x = x * base - target_range
coord_y = y * base - target_range
coord_z = z * base - target_range
min_coord = [coord_x, coord_y, coord_z]
max_coord = [coord_x + base, coord_y + base, coord_z + base]
return Cubic([min_coord, max_coord], id)
def point_string_to_coord(string):
coord = string.split('_')
return [float(item) for item in coord]
def write_seg_vtk(pts, lines, colors, complex_id, target_range, line_depth, save_folder):
linesPolyData = vtk.vtkPolyData()
linesPolyData.SetPoints(pts)
linesPolyData.SetLines(lines)
linesPolyData.GetCellData().SetScalars(colors)
# clean = vtk.vtkCleanPolyData()
# clean.SetInputConnection(linesPolyData)
# clean.Update()
# pd = clean.GetOutput()
# print('clean segline_Adaptive data.')
# then = time.time()
# # pd = linesPolyData.getPolyData()
# # clean = vtk.vtkCleanPolyData()
# # clean.SetInput(linesPolyData)
# # clean.Update()
# # pd = clean.GetOutput()
#
# # clean = vtk.vtkCleanPolyData()
# # clean.SetInputConnection(linesPolyData)
# # clean.Update()
# # pd = clean.GetOutput()
#
# now = time.time()
# diff = int(now - then)
# print('clean segline_Adaptive data done. spend {} seconds'.format(diff))
ShellVolmapper = vtk.vtkDataSetMapper()
ShellVolmapper.SetScalarModeToUseCellData()
ShellVolmapper.UseLookupTableScalarRangeOn()
# ShellVolmapper.SetLookupTable(lut)
ShellVolmapper.SetInputData(linesPolyData)
ShellVolactor = vtk.vtkActor()
ShellVolactor.SetMapper(ShellVolmapper)
# modelwriter = vtk.vtkUnstructuredGridWriter()
modelwriter = vtk.vtkDataSetWriter()
modelwriter.SetFileName('{}/{}/{}_segline_Adaptive_{}_{}.vtk'.format(save_folder, complex_id, complex_id,
target_range, line_depth))
# modelwriter.SetInputData(grid)
modelwriter.SetInputData(ShellVolmapper.GetInput())
modelwriter.Write()
print('Save {}/{}/{}_segline_Adaptive_{}_{}.vtk'.format(save_folder, complex_id, complex_id, target_range, line_depth))
def get_parent_cubic(cubic, target_range):
id = cubic.id
[depth, x, y, z] = [int(item) for item in id.split('_')]
x = x >> 1
y = y >> 1
z = z >> 1
depth -= 1
base = target_range * 2 / 2 ** depth
coord_x = x * base - target_range
coord_y = y * base - target_range
coord_z = z * base - target_range
min_coord = [coord_x, coord_y, coord_z]
max_coord = [coord_x + base, coord_y + base, coord_z + base]
string = '{}_{}_{}_{}'.format(depth, x, y, z)
parent_cubic = Cubic([min_coord, max_coord], string)
return parent_cubic
def get_parent_cubic_id(id, target_range):
[depth, x, y, z] = [int(item) for item in id.split('_')]
x = x >> 1
y = y >> 1
z = z >> 1
depth -= 1
# base = target_range * 2 / 2 ** depth
# coord_x = x * base - target_range
# coord_y = y * base - target_range
# coord_z = z * base - target_range
# min_coord = [coord_x, coord_y, coord_z]
# max_coord = [coord_x + base, coord_y + base, coord_z + base]
parent_id = '{}_{}_{}_{}'.format(depth, x, y, z)
# parent_cubic = Cubic([min_coord, max_coord], string)
return parent_id
def get_color_for_dep(depth, differ = True):
# need to be different with the volume scaler (0,1,2,3).
if differ == False:
color = 0
return color
# if depth == 0:
# color = 0 #[0, 0, 0] # white
# elif depth == 1:
# color = 1 # [255, 0, 0] # red
# elif depth == 2:
# color = 2 # [255, 128, 0]
# elif depth == 3:
# color = 3 #[255,255,0]
# elif depth == 4:
# color = 4 # [0, 255, 0]
# elif depth == 5:
# color = 5 #[0, 255, 255]
# elif depth == 6:
# color = 6 #[0, 0, 255]
# elif depth == 7:
# color = 7 # [255, 0 , 255]
# elif depth == 8 :
# color = 8
# else:
# color = 9
return depth
# A better way is use class in vtk package, this solve the color issue to distinguish ligand, pocket.
def vtk_writer(vtk_dic, file_name, shift = [0,0,0]):
points = vtk.vtkPoints()
grid = vtk.vtkUnstructuredGrid()
Color = vtk.vtkFloatArray()
Scale = vtk.vtkFloatArray()
sorted_dic = sorted(vtk_dic['points'].items(), key=lambda x: x[1])
pts = vtk.vtkPoints()
for item in sorted_dic:
# pts.InsertNextPoint(point_string_to_coord(item[0]))
coord = point_string_to_coord(item[0])
coord = [coord[0] + shift[0], coord[1] + shift[1], coord[2] + shift[2]]
pts.InsertNextPoint(coord)
grid.SetPoints(pts)
# for vtk_point in vtk_dic['points']:
# Coord = vtk_point
# test = points.InsertNextPoint(*Coord)
# #Color.InsertTuple1(test, 0)
# grid.SetPoints(points)
for i in range(len(vtk_dic['cells'])):
vtk_node = vtk_dic['cells'][i]
elem = vtk.vtkQuad()
elem.GetPointIds().SetId(0, vtk_node[0])
elem.GetPointIds().SetId(1, vtk_node[1])
elem.GetPointIds().SetId(2, vtk_node[2])
elem.GetPointIds().SetId(3, vtk_node[3])
Quad4cell = grid.InsertNextCell(elem.GetCellType(), elem.GetPointIds())
color = vtk_dic['cell_color_scale'][i]
Color.InsertTuple1(Quad4cell, color)
lut = vtk.vtkLookupTable()
lut.SetNumberOfTableValues(5)
lut.SetTableRange(0, 5)
lut.Build()
lut.SetTableValue(0, 0, 0, 0, 1) # Black
lut.SetTableValue(1, 1, 0, 0, 1) # Red
lut.SetTableValue(2, 0, 1, 0, 1) # Green
lut.SetTableValue(3, 0, 0, 1, 1) # Blue
lut.SetTableValue(4, 1, 1, 1, 1) # White
grid.GetCellData().SetScalars(Color)
ShellVolmapper = vtk.vtkDataSetMapper()
# ShellVolmapper = vtk.vtkUnstructuredGridVolumeRayCastMapper()
ShellVolmapper.SetScalarModeToUseCellData()
ShellVolmapper.UseLookupTableScalarRangeOn()
ShellVolmapper.SetLookupTable(lut)
ShellVolmapper.SetInputData(grid)
ShellVolactor = vtk.vtkActor()
ShellVolactor.SetMapper(ShellVolmapper)
modelwriter = vtk.vtkUnstructuredGridWriter()
modelwriter.SetFileName('{}.vtk'.format(file_name))
#modelwriter.SetInputData(grid)
modelwriter.SetInputData(ShellVolmapper.GetInput())
modelwriter.Write()
print('Save {}.vtk'.format(file_name))
def construct_adaptive_dic(cubic_dic, area, vtk_dic, fine_cubic_set, target_range,
focus_center = [0,0,0], light =False):
'''
:param cubic_dic: dictionary, key is cubic.id, value is Protein, Mixture, Ligand.
:param area: within this area, use current depth in cubic_dic, otherwise need to compute upper layer
:param vtk_dic: dictionary that used to plot cubic.
:param seg_dic: dictionary that used to plot segment line of adaptive cibics.
:return:
'''
side_dic = {}
for key, value in cubic_dic.items():
[depth, x, y, z] = [int(item) for item in key.split('_')]
base = target_range * 2 / 2 ** depth
coord_x = x * base - target_range
coord_y = y * base - target_range
coord_z = z * base - target_range
min_coord = [coord_x, coord_y, coord_z]
max_coord = [coord_x + base, coord_y + base, coord_z + base]
[focus_x, focus_y, focus_z] = focus_center
# test if this cubic is in core area, if so, dump into adaptive cubic_dic
core_flag_z = min(abs(coord_z - focus_z), abs(coord_z + base - focus_z)) <= area
core_flag_y = min(abs(coord_y - focus_y), abs(coord_y + base - focus_y)) <= area
core_flag_x = min(abs(coord_x - focus_x), abs(coord_x + base - focus_x)) <= area
core_flag = core_flag_x and core_flag_y and core_flag_z
# find parent cubic or upper layer cubic.
# parent cubic for adaptive segment line, upper layer cubic for cubic plot.
x = x >> 1
y = y >> 1
z = z >> 1
depth -= 1
string = '{}_{}_{}_{}'.format(depth, x, y, z)
if core_flag:
cubic = Cubic([min_coord, max_coord], key)
cubic.set_color_new(value)
if not light:
vtk_dic = cubic.load_to_vtk_opt(vtk_dic)
fine_cubic_set.add(cubic)
else:
if string not in side_dic:
side_dic[string] = value
elif value != side_dic[string]:
side_dic[string] = 'Mixture'
else:
pass
return side_dic
def centerize(pocket_xyz, ligand_xyz, by_ligand = True, protein_xyz = None):
if by_ligand:
[x, y, z] = ligand_xyz
center_x, center_y, center_z = x.mean(), y.mean(), z.mean()
x, y, z = x - center_x, y - center_y, z - center_z
ligand_xyz = [x, y, z]
[x, y, z] = pocket_xyz
x, y, z = x - center_x, y - center_y, z - center_z
pocket_xyz = [x, y, z]
ligand_center = [0, 0, 0]
center = [center_x, center_y, center_z]
if protein_xyz is not None:
[x, y, z] = protein_xyz
x, y, z = x - center_x, y - center_y, z - center_z
protein_xyz = [x, y, z]
else:
[x_ligand, y_ligand, z_ligand] = ligand_xyz
x_ligand_max, y_ligand_max, z_ligand_max = x_ligand.max(), y_ligand.max(), z_ligand.max()
x_ligand_min, y_ligand_min, z_ligand_min = x_ligand.min(), y_ligand.min(), z_ligand.min()
if protein_xyz is None:
[x_pocket, y_pocket, z_pocket] = pocket_xyz
x_protein_max, y_protein_max, z_protein_max = x_pocket.max(), y_pocket.max(), z_pocket.max()
x_protein_min, y_protein_min, z_protein_min = x_pocket.min(), y_pocket.min(), z_pocket.min()
else:
[x_protein, y_protein, z_protein] = protein_xyz
x_protein_max, y_protein_max, z_protein_max = x_protein.max(), y_protein.max(), z_protein.max()
x_protein_min, y_protein_min, z_protein_min = x_protein.min(), y_protein.min(), z_protein.min()
x_max, y_max, z_max = max(x_ligand_max, x_protein_max), max(y_ligand_max, y_protein_max), max(z_ligand_max, z_protein_max)
x_min, y_min, z_min = min(x_ligand_min, x_protein_min), min(y_ligand_min, y_protein_min), min(z_ligand_min, z_protein_min)
center = [(x_max+x_min)/2, (y_max+y_min)/2, (z_max+z_min)/2]
ligand_center = [x_ligand.mean() - center[0], y_ligand.mean() - center[1], z_ligand.mean()- center[2]]
ligand_xyz = [ligand_xyz[0] - center[0], ligand_xyz[1] - center[1], ligand_xyz[2] - center[2]]
pocket_xyz = [pocket_xyz[0] - center[0], pocket_xyz[1] - center[1], pocket_xyz[2] - center[2]]
if protein_xyz is not None:
[x, y, z] = protein_xyz
x, y, z = x - center[0], y - center[1], z - center[2]
protein_xyz = [x, y, z]
return pocket_xyz, ligand_xyz, protein_xyz, center, ligand_center
def filter_by_center_range(x, y, z, target_range, feature=None): # Here x, y, z is list
x = np.array(x)
y = np.array(y)
z = np.array(z)
min_x, min_y, min_z = -target_range, -target_range, -target_range
max_x, max_y, max_z = target_range, target_range, target_range
flags_x = np.logical_and(x > min_x, x < max_x)
flags_y = np.logical_and(y > min_y, y < max_y)
flags_z = np.logical_and(z > min_z, z < max_z)
flag1 = np.logical_and(flags_x, flags_y)
flag2 = np.logical_and(flag1, flags_z)
x = x[(flag2)]
y = y[(flag2)]
z = z[(flag2)]
if feature is not None:
feature = np.array(feature)
feature = feature[(flag2)]
return x,y,z,feature
return x, y, z
def get_vol_index(x, y, z, depth, target_range):
min_x, min_y, min_z = -target_range, -target_range, -target_range
x = x - min_x
y = y - min_y
z = z - min_z
resolution = target_range*2 / 2 ** depth
x = (x // resolution).astype(int)
y = (y // resolution).astype(int)
z = (z // resolution).astype(int)
# vol_set = set()
# for i in range(len(x)):
# vol_set.add((x[i], y[i], z[i]))
# print(vol_set)
# print(min(x), max(x))
return x, y, z
def get_comp_dic(cubic_dic, comp_layer_dic = {}):
for key, value in cubic_dic.items():
[depth, x, y, z] = [int(item) for item in key.split('_')]
x = x >> 1 << 1
y = y >> 1 << 1
z = z >> 1 << 1
for i in range(0,2):
for j in range(0,2):
for k in range(0,2):
string = '{}_{}_{}_{}'.format(depth, x+i, y+j, z+k)
if string not in cubic_dic:
comp_layer_dic[string] = 'Empty'
else:
comp_layer_dic[string] = cubic_dic[string]
pass
# for key, value in comp_layer_dic.items():
# if value == 'Ligand':
# print(key)
return comp_layer_dic
def get_upper_layer_dic(cubic_dic):
upper_layer_dic = {}
for key, value in cubic_dic.items():
[depth, x, y, z] = [int(item) for item in key.split('_')]
x = x >> 1
y = y >> 1
z = z >> 1
depth -= 1
string = '{}_{}_{}_{}'.format(depth, x,y,z)
if string not in upper_layer_dic:
upper_layer_dic[string] = value
elif value != upper_layer_dic[string]:
upper_layer_dic[string] = 'Mixture'
else:
pass
return upper_layer_dic
def create_cubic_dic(protein_xyz, ligand_xyz, depth):
cubic_dic = {}
[x, y, z] = protein_xyz
print('Protein points number: {}'.format(len(x)))
for i in range(len(x)):
string = '{}_{}_{}_{}'.format(depth, x[i], y[i], z[i])
if string not in cubic_dic:
cubic_dic[string] = 'Protein'
else:
pass
[x, y, z] = ligand_xyz
print('Ligand points number: {}'.format(len(x)))
for i in range(len(x)):
string = '{}_{}_{}_{}'.format(depth, x[i], y[i], z[i])
if string not in cubic_dic:
cubic_dic[string] = 'Ligand'
elif cubic_dic[string] == 'Protein':
cubic_dic[string] = 'Mixture'
else:
pass
return cubic_dic
def create_cubic_dic_with_feature(protein_xyz, ligand_xyz, depth, pocket_feature, ligand_feature):
cubic_dic = {}
[x, y, z] = protein_xyz
for i in range(len(x)):
string = '{}_{}_{}_{}'.format(depth, x[i], y[i], z[i])
feature = pocket_feature[i]
atom_type = feature[0]
atom_index = 'P' + str(feature[1])
atom_detail_type = 'P' + str(feature[0])
if string not in cubic_dic:
cubic_dic[string] = {}
cubic_dic[string]['PLM'] = 'Protein'
cubic_dic[string]['Atoms'] = [atom_type]
cubic_dic[string]['Atom_index'] = [atom_index]
cubic_dic[string]['Atom_Detail_Type'] = [atom_detail_type]
else:
cubic_dic[string]['Atom_Detail_Type'].append(atom_detail_type)
if atom_type not in cubic_dic[string]['Atoms']:
cubic_dic[string]['Atoms'].append(atom_type)
if atom_index not in cubic_dic[string]['Atom_index']:
cubic_dic[string]['Atom_index'].append(atom_index)
[x, y, z] = ligand_xyz
for i in range(len(x)):
string = '{}_{}_{}_{}'.format(depth, x[i], y[i], z[i])
feature = ligand_feature[i]
atom_type = feature[0]
atom_index = 'L' + str(feature[1])
atom_detail_type = 'L' + str(feature[0])
if string not in cubic_dic:
cubic_dic[string] = {}
cubic_dic[string]['PLM'] = 'Ligand'
cubic_dic[string]['Atoms'] = [atom_type]
cubic_dic[string]['Atom_index'] = [atom_index]
cubic_dic[string]['Atom_Detail_Type'] = [atom_detail_type]
elif cubic_dic[string]['PLM'] == 'Protein':
cubic_dic[string]['PLM'] = 'Mixture'
cubic_dic[string]['Atom_Detail_Type'].append(atom_detail_type)
else:
cubic_dic[string]['Atom_Detail_Type'].append(atom_detail_type)
if atom_type not in cubic_dic[string]['Atoms']:
cubic_dic[string]['Atoms'].append(atom_type)
if atom_index not in cubic_dic[string]['Atom_index']:
cubic_dic[string]['Atom_index'].append(atom_index)
return cubic_dic
def line_string_to_idx(string):
contents = string.split('_')
contents = [int(item) for item in contents]
return contents
def fill_vtk_lines(vtk_line_dic, shift = [0,0,0]):
pts_dic = vtk_line_dic['pts_dic']
lines_dic, colors_list = vtk_line_dic['lines_dic'], vtk_line_dic['colors_list']
pts = vtk.vtkPoints()
sorted_dic = sorted(pts_dic.items(), key=lambda x: x[1])
for item in sorted_dic:
coord = point_string_to_coord(item[0])
coord = [coord[0] + shift[0], coord[1] + shift[1], coord[2] + shift[2]]
pts.InsertNextPoint(coord)
lines = vtk.vtkCellArray()
colors = vtk.vtkFloatArray()
sorted_line_dic = sorted(lines_dic.items(), key=lambda x: x[1])
for item in sorted_line_dic:
line_idx = line_string_to_idx(item[0])
line0 = vtk.vtkLine()
line0.GetPointIds().SetId(0, line_idx[0])
line0.GetPointIds().SetId(1, line_idx[1])
lines.InsertNextCell(line0)
# for line in lines_list:
# points = line.split('_')
# points = [int(item) for item in points]
# line0 = vtk.vtkLine()
# line0.GetPointIds().SetId(0, points[0])
# line0.GetPointIds().SetId(1, points[1])
# lines.InsertNextCell(line0)
for color in colors_list:
colors.InsertNextTuple1(color)
return pts, lines, colors