driftlessmap 1.1.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.
- driftlessmap/__init__.py +16 -0
- driftlessmap/__main__.py +5 -0
- driftlessmap/about.py +24 -0
- driftlessmap/allen_downloader.py +908 -0
- driftlessmap/app.py +8085 -0
- driftlessmap/atlas_downloader.py +370 -0
- driftlessmap/atlas_loader.py +526 -0
- driftlessmap/atlas_processor.py +784 -0
- driftlessmap/atlas_transform.py +111 -0
- driftlessmap/atlas_view.py +1435 -0
- driftlessmap/cell_detection.py +27 -0
- driftlessmap/coordinate_validation.py +19 -0
- driftlessmap/czi_reader.py +236 -0
- driftlessmap/data/WHS_atlas_labels.pkl +0 -0
- driftlessmap/data/allen_mice_atlas_labels.pkl +0 -0
- driftlessmap/data/atlas_labels.pkl +0 -0
- driftlessmap/data/query.csv +1328 -0
- driftlessmap/download_utils.py +85 -0
- driftlessmap/herbs.png +0 -0
- driftlessmap/icons/backward.svg +15 -0
- driftlessmap/icons/dot.svg +11 -0
- driftlessmap/icons/down-arrow.svg +10 -0
- driftlessmap/icons/fast_backward.svg +14 -0
- driftlessmap/icons/fast_forward.svg +14 -0
- driftlessmap/icons/forward.svg +14 -0
- driftlessmap/icons/layers/add.png +0 -0
- driftlessmap/icons/layers/ai.png +0 -0
- driftlessmap/icons/layers/eye_off.png +0 -0
- driftlessmap/icons/layers/eye_on.png +0 -0
- driftlessmap/icons/layers/eye_white.png +0 -0
- driftlessmap/icons/layers/hi.png +0 -0
- driftlessmap/icons/layers/trash.png +0 -0
- driftlessmap/icons/object.svg +22 -0
- driftlessmap/icons/sidebar/add.png +0 -0
- driftlessmap/icons/sidebar/atlascontrol.png +0 -0
- driftlessmap/icons/sidebar/atlascontrol.svg +32 -0
- driftlessmap/icons/sidebar/bnd.svg +14 -0
- driftlessmap/icons/sidebar/c_section.png +0 -0
- driftlessmap/icons/sidebar/c_section2.png +0 -0
- driftlessmap/icons/sidebar/cell.svg +24 -0
- driftlessmap/icons/sidebar/check.svg +9 -0
- driftlessmap/icons/sidebar/compare.svg +18 -0
- driftlessmap/icons/sidebar/contour.svg +14 -0
- driftlessmap/icons/sidebar/h_section.png +0 -0
- driftlessmap/icons/sidebar/info.svg +14 -0
- driftlessmap/icons/sidebar/layers.png +0 -0
- driftlessmap/icons/sidebar/layers.svg +23 -0
- driftlessmap/icons/sidebar/line.svg +10 -0
- driftlessmap/icons/sidebar/link.svg +18 -0
- driftlessmap/icons/sidebar/link_off.svg +18 -0
- driftlessmap/icons/sidebar/merge.svg +11 -0
- driftlessmap/icons/sidebar/object.svg +13 -0
- driftlessmap/icons/sidebar/probe.png +0 -0
- driftlessmap/icons/sidebar/probe.svg +23 -0
- driftlessmap/icons/sidebar/rotation_horizontal.svg +14 -0
- driftlessmap/icons/sidebar/rotation_vertical.svg +14 -0
- driftlessmap/icons/sidebar/s_section.png +0 -0
- driftlessmap/icons/sidebar/tool.png +0 -0
- driftlessmap/icons/sidebar/tool.svg +19 -0
- driftlessmap/icons/sidebar/trash.png +0 -0
- driftlessmap/icons/sidebar/tree_checked.svg +10 -0
- driftlessmap/icons/sidebar/treeview.png +0 -0
- driftlessmap/icons/sidebar/treeview.svg +10 -0
- driftlessmap/icons/sidebar/treeview2.png +0 -0
- driftlessmap/icons/sidebar/virus.svg +24 -0
- driftlessmap/icons/tdown.svg +16 -0
- driftlessmap/icons/toolbar/accept.svg +18 -0
- driftlessmap/icons/toolbar/accept2.svg +24 -0
- driftlessmap/icons/toolbar/aim.svg +44 -0
- driftlessmap/icons/toolbar/aim_not.svg +28 -0
- driftlessmap/icons/toolbar/anchor.svg +14 -0
- driftlessmap/icons/toolbar/anticlockwise_rotation.svg +12 -0
- driftlessmap/icons/toolbar/atlas_icon.png +0 -0
- driftlessmap/icons/toolbar/boundary_register.svg +18 -0
- driftlessmap/icons/toolbar/cancel.svg +32 -0
- driftlessmap/icons/toolbar/cell_select.svg +22 -0
- driftlessmap/icons/toolbar/cell_select_not.svg +12 -0
- driftlessmap/icons/toolbar/check.svg +9 -0
- driftlessmap/icons/toolbar/clockwise_rotation.svg +11 -0
- driftlessmap/icons/toolbar/closed_path.svg +16 -0
- driftlessmap/icons/toolbar/closed_path2 copy.svg +19 -0
- driftlessmap/icons/toolbar/closed_path2.svg +20 -0
- driftlessmap/icons/toolbar/eraser.png +0 -0
- driftlessmap/icons/toolbar/eraser.svg +19 -0
- driftlessmap/icons/toolbar/eye.svg +17 -0
- driftlessmap/icons/toolbar/eye_closed.svg +19 -0
- driftlessmap/icons/toolbar/fill.svg +12 -0
- driftlessmap/icons/toolbar/gps.svg +15 -0
- driftlessmap/icons/toolbar/h_flip.png +0 -0
- driftlessmap/icons/toolbar/handle.png +0 -0
- driftlessmap/icons/toolbar/image_icon.png +0 -0
- driftlessmap/icons/toolbar/image_icon.svg +25 -0
- driftlessmap/icons/toolbar/info.svg +14 -0
- driftlessmap/icons/toolbar/inpart.png +0 -0
- driftlessmap/icons/toolbar/inpart.svg +17 -0
- driftlessmap/icons/toolbar/lasso.png +0 -0
- driftlessmap/icons/toolbar/lasso.svg +14 -0
- driftlessmap/icons/toolbar/left90.png +0 -0
- driftlessmap/icons/toolbar/line.svg +10 -0
- driftlessmap/icons/toolbar/line_sites.svg +11 -0
- driftlessmap/icons/toolbar/linear_silicon.png +0 -0
- driftlessmap/icons/toolbar/linear_silicon.svg +88 -0
- driftlessmap/icons/toolbar/list.svg +14 -0
- driftlessmap/icons/toolbar/location.svg +14 -0
- driftlessmap/icons/toolbar/magic-wand.svg +16 -0
- driftlessmap/icons/toolbar/magic_white.png +0 -0
- driftlessmap/icons/toolbar/mask.svg +10 -0
- driftlessmap/icons/toolbar/match.svg +20 -0
- driftlessmap/icons/toolbar/matchbnd.svg +18 -0
- driftlessmap/icons/toolbar/matching.svg +36 -0
- driftlessmap/icons/toolbar/merge.svg +11 -0
- driftlessmap/icons/toolbar/move_down.png +0 -0
- driftlessmap/icons/toolbar/move_left.png +0 -0
- driftlessmap/icons/toolbar/move_right.png +0 -0
- driftlessmap/icons/toolbar/move_up.png +0 -0
- driftlessmap/icons/toolbar/moving.png +0 -0
- driftlessmap/icons/toolbar/multi-probe.svg +119 -0
- driftlessmap/icons/toolbar/multi_pencil.svg +23 -0
- driftlessmap/icons/toolbar/multi_probe.png +0 -0
- driftlessmap/icons/toolbar/object.svg +13 -0
- driftlessmap/icons/toolbar/open_path.svg +22 -0
- driftlessmap/icons/toolbar/outpart.png +0 -0
- driftlessmap/icons/toolbar/outpart.svg +26 -0
- driftlessmap/icons/toolbar/pencil.png +0 -0
- driftlessmap/icons/toolbar/pencil.svg +19 -0
- driftlessmap/icons/toolbar/plasso.png +0 -0
- driftlessmap/icons/toolbar/probe.svg +19 -0
- driftlessmap/icons/toolbar/radar.svg +32 -0
- driftlessmap/icons/toolbar/rotation.svg +45 -0
- driftlessmap/icons/toolbar/rotation_clockwise.svg +18 -0
- driftlessmap/icons/toolbar/rotation_counter_clockwise.svg +18 -0
- driftlessmap/icons/toolbar/ruler.svg +27 -0
- driftlessmap/icons/toolbar/separate_sites.svg +13 -0
- driftlessmap/icons/toolbar/single_pencil.svg +16 -0
- driftlessmap/icons/toolbar/toa.svg +11 -0
- driftlessmap/icons/toolbar/toa_delete.svg +36 -0
- driftlessmap/icons/toolbar/toaa.svg +11 -0
- driftlessmap/icons/toolbar/toh.svg +11 -0
- driftlessmap/icons/toolbar/toh_delete.svg +36 -0
- driftlessmap/icons/toolbar/tohh.svg +11 -0
- driftlessmap/icons/toolbar/trans.png +0 -0
- driftlessmap/icons/toolbar/trans.svg +16 -0
- driftlessmap/icons/toolbar/triangulation.svg +10 -0
- driftlessmap/icons/toolbar/two_window.png +0 -0
- driftlessmap/icons/toolbar/unmerge.svg +16 -0
- driftlessmap/icons/toolbar/v_flip.png +0 -0
- driftlessmap/icons/toolbar/virus.svg +24 -0
- driftlessmap/icons/toolbar/virus_register.svg +31 -0
- driftlessmap/icons/toolbar/vis2d.svg +29 -0
- driftlessmap/icons/toolbar/window2.png +0 -0
- driftlessmap/icons/toolbar/window3.png +0 -0
- driftlessmap/icons/toolbar/window4.png +0 -0
- driftlessmap/icons/tree_close.svg +14 -0
- driftlessmap/icons/tree_open.svg +14 -0
- driftlessmap/icons/up-arrow.svg +10 -0
- driftlessmap/image_curves.py +579 -0
- driftlessmap/image_reader.py +186 -0
- driftlessmap/image_stacks.py +359 -0
- driftlessmap/image_view.py +646 -0
- driftlessmap/images_reader.py +5 -0
- driftlessmap/label_tree.py +278 -0
- driftlessmap/layer_validation.py +25 -0
- driftlessmap/layers_control.py +554 -0
- driftlessmap/main_window.ui +883 -0
- driftlessmap/movable_points.py +254 -0
- driftlessmap/obj_items.py +122 -0
- driftlessmap/object_control.py +1762 -0
- driftlessmap/persistence.py +376 -0
- driftlessmap/popup_message.py +16 -0
- driftlessmap/probe_csv.py +319 -0
- driftlessmap/probe_reconstruction.py +409 -0
- driftlessmap/probe_utiles.py +1442 -0
- driftlessmap/qss/atlas_view_group_box.qss +15 -0
- driftlessmap/qss/box_label.qss +7 -0
- driftlessmap/qss/channel_selector.qss +19 -0
- driftlessmap/qss/color_combo.qss +121 -0
- driftlessmap/qss/decor_label.qss +9 -0
- driftlessmap/qss/dialogs.qss +11 -0
- driftlessmap/qss/hidden_line_edit.qss +5 -0
- driftlessmap/qss/label_tree.qss +123 -0
- driftlessmap/qss/main_window.qss +243 -0
- driftlessmap/qss/menu_bar.qss +42 -0
- driftlessmap/qss/multi_handle_slider.qss +14 -0
- driftlessmap/qss/obj_ctrl_bottom_button.qss +29 -0
- driftlessmap/qss/object_text_button.qss +19 -0
- driftlessmap/qss/page_control.qss +36 -0
- driftlessmap/qss/rotation_button.qss +9 -0
- driftlessmap/qss/side_bar.qss +23 -0
- driftlessmap/qss/spinbox.qss +106 -0
- driftlessmap/qss/tabs.qss +211 -0
- driftlessmap/qss/tool_bar.qss +77 -0
- driftlessmap/resources.py +34 -0
- driftlessmap/roi_analysis.py +375 -0
- driftlessmap/run_driftlessmap.py +4 -0
- driftlessmap/slice_stacks.py +268 -0
- driftlessmap/slice_validation.py +20 -0
- driftlessmap/toolbox.py +569 -0
- driftlessmap/triangulation.py +517 -0
- driftlessmap/triangulation_points.py +108 -0
- driftlessmap/user_settings.py +92 -0
- driftlessmap/uuuuuu.py +1168 -0
- driftlessmap/version.py +3 -0
- driftlessmap/widgets_utils.py +140 -0
- driftlessmap/wtiles.py +715 -0
- driftlessmap-1.1.0.dist-info/METADATA +186 -0
- driftlessmap-1.1.0.dist-info/RECORD +210 -0
- driftlessmap-1.1.0.dist-info/WHEEL +5 -0
- driftlessmap-1.1.0.dist-info/entry_points.txt +2 -0
- driftlessmap-1.1.0.dist-info/licenses/LICENSE.txt +23 -0
- driftlessmap-1.1.0.dist-info/top_level.txt +1 -0
driftlessmap/uuuuuu.py
ADDED
|
@@ -0,0 +1,1168 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import numpy as np
|
|
3
|
+
import math
|
|
4
|
+
import pandas as pd
|
|
5
|
+
import cv2
|
|
6
|
+
import pickle
|
|
7
|
+
import colorsys
|
|
8
|
+
import pyqtgraph as pg
|
|
9
|
+
import pyqtgraph.opengl as gl
|
|
10
|
+
import scipy.ndimage as ndi
|
|
11
|
+
from scipy.interpolate import interp1d, splprep, splev
|
|
12
|
+
from .coordinate_validation import coordinates_in_bounds
|
|
13
|
+
from .persistence import load_driftlessmap_file
|
|
14
|
+
from .resources import resource_path, resolve_qss_resource_urls
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def read_qss_file(qss_file_name):
|
|
18
|
+
with open(resource_path(qss_file_name), "r", encoding="UTF-8") as file:
|
|
19
|
+
return resolve_qss_resource_urls(file.read())
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def check_loading_pickle_file(file_path, expected_kind=None):
|
|
23
|
+
return load_driftlessmap_file(file_path, expected_kind=expected_kind)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def read_excel_file(file_path):
|
|
27
|
+
msg = None
|
|
28
|
+
file_name, file_extension = os.path.splitext(file_path)
|
|
29
|
+
if file_extension == ".csv":
|
|
30
|
+
df = pd.read_csv(file_path)
|
|
31
|
+
elif file_extension == ".xlsx":
|
|
32
|
+
df = pd.read_excel(file_path)
|
|
33
|
+
else:
|
|
34
|
+
df = None
|
|
35
|
+
msg = "Only CSV file and Excel file works."
|
|
36
|
+
return df, msg
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def read_label(file):
|
|
40
|
+
lines = []
|
|
41
|
+
for line in file:
|
|
42
|
+
lines.append(line)
|
|
43
|
+
|
|
44
|
+
n_lines = len(lines)
|
|
45
|
+
label_index = np.zeros(n_lines - 14, "i")
|
|
46
|
+
label_index[:] = np.nan
|
|
47
|
+
label_colors = np.zeros((n_lines - 14, 3), "i")
|
|
48
|
+
label_colors[:] = np.nan
|
|
49
|
+
label_names = []
|
|
50
|
+
for i in range(n_lines - 14):
|
|
51
|
+
split_lines = lines[i + 14].split()
|
|
52
|
+
label_index[i] = int(split_lines[0])
|
|
53
|
+
label_colors[i] = np.array(
|
|
54
|
+
[split_lines[1], split_lines[2], split_lines[3]]
|
|
55
|
+
).astype(int)
|
|
56
|
+
split_lines2 = lines[i + 14].split('"')
|
|
57
|
+
label_names.append(split_lines2[1])
|
|
58
|
+
|
|
59
|
+
return label_index, label_names, label_colors
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def rotation_x(theta):
|
|
63
|
+
ct = np.cos(theta)
|
|
64
|
+
st = np.sin(theta)
|
|
65
|
+
rx = np.array([[1, 0, 0], [0, ct, -st], [0, st, ct]])
|
|
66
|
+
return rx
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def rotation_y(theta):
|
|
70
|
+
ct = np.cos(theta)
|
|
71
|
+
st = np.sin(theta)
|
|
72
|
+
ry = np.array([[ct, 0, st], [0, 1, 0], [-st, 0, ct]])
|
|
73
|
+
return ry
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def rotation_z(theta):
|
|
77
|
+
ct = np.cos(theta)
|
|
78
|
+
st = np.sin(theta)
|
|
79
|
+
rz = np.array([[ct, -st, 0], [st, ct, 0], [0, 0, 1]])
|
|
80
|
+
return rz
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def d2td3(pos2d, ax, ay, o):
|
|
84
|
+
pos3d = pos2d[0] * ax + pos2d[1] * ay + o
|
|
85
|
+
return pos3d
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def get_region_label(data, label_data, bregma):
|
|
89
|
+
region_label = []
|
|
90
|
+
for i in range(len(data)):
|
|
91
|
+
temp = data[i] + bregma
|
|
92
|
+
temp = temp.astype(int)
|
|
93
|
+
region_label.append(label_data[temp[0], temp[1], temp[2]])
|
|
94
|
+
return region_label
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def get_region_label_info(region_label, label_info):
|
|
98
|
+
unique_label = np.sort(np.unique(region_label))
|
|
99
|
+
label_names = []
|
|
100
|
+
label_acronym = []
|
|
101
|
+
label_color = []
|
|
102
|
+
region_count = []
|
|
103
|
+
for i in range(len(unique_label)):
|
|
104
|
+
# print(unique_label[i])
|
|
105
|
+
if unique_label[i] == 0:
|
|
106
|
+
label_names.append(" ")
|
|
107
|
+
label_acronym.append(" ")
|
|
108
|
+
label_color.append((128, 128, 128))
|
|
109
|
+
else:
|
|
110
|
+
da_ind = np.where(label_info["index"] == unique_label[i])[0][0]
|
|
111
|
+
label_names.append(label_info["label"][da_ind])
|
|
112
|
+
label_acronym.append(label_info["abbrev"][da_ind])
|
|
113
|
+
label_color.append(label_info["color"][da_ind])
|
|
114
|
+
|
|
115
|
+
region_count.append(len(np.where(np.ravel(region_label) == unique_label[i])[0]))
|
|
116
|
+
|
|
117
|
+
return region_count, label_names, label_acronym, label_color, unique_label
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def calculate_virus_info(data_list, pieces_names, label_data, label_info, bregma):
|
|
121
|
+
temp_data = data_list[0]
|
|
122
|
+
for i in range(1, len(data_list)):
|
|
123
|
+
temp_data = np.vstack([temp_data, data_list[i]])
|
|
124
|
+
|
|
125
|
+
data = temp_data.astype(int)
|
|
126
|
+
|
|
127
|
+
# data = np.array([vox_data[0]])
|
|
128
|
+
# for i in range(1, len(vox_data)):
|
|
129
|
+
# if np.any(vox_data[i] != data[-1]):
|
|
130
|
+
# data = np.vstack([data, vox_data[i]])
|
|
131
|
+
|
|
132
|
+
region_label = get_region_label(data, label_data, bregma)
|
|
133
|
+
unique_region = np.sort(np.unique(region_label))
|
|
134
|
+
region_volume = []
|
|
135
|
+
for c_region in unique_region:
|
|
136
|
+
region_volume.append(len(np.where(label_data == c_region)[0]))
|
|
137
|
+
|
|
138
|
+
# print(region_volume)
|
|
139
|
+
(
|
|
140
|
+
region_count,
|
|
141
|
+
label_names,
|
|
142
|
+
label_acronym,
|
|
143
|
+
label_color,
|
|
144
|
+
unique_label,
|
|
145
|
+
) = get_region_label_info(region_label, label_info)
|
|
146
|
+
# print(region_count)
|
|
147
|
+
|
|
148
|
+
res_dict = {
|
|
149
|
+
"object_name": "virus",
|
|
150
|
+
"data": data_list,
|
|
151
|
+
"pieces_names": pieces_names,
|
|
152
|
+
"label_id": unique_label,
|
|
153
|
+
"label_name": label_names,
|
|
154
|
+
"label_acronym": label_acronym,
|
|
155
|
+
"label_color": label_color,
|
|
156
|
+
"region_volume": region_volume,
|
|
157
|
+
"virus_volume": region_count,
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return res_dict
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def calculate_cells_info(data_list, pieces_names, label_data, label_info, bregma):
|
|
164
|
+
data = data_list[0]
|
|
165
|
+
for i in range(1, len(data_list)):
|
|
166
|
+
data = np.vstack([data, data_list[i]])
|
|
167
|
+
|
|
168
|
+
region_label = get_region_label(data, label_data, bregma)
|
|
169
|
+
(
|
|
170
|
+
region_count,
|
|
171
|
+
label_names,
|
|
172
|
+
label_acronym,
|
|
173
|
+
label_color,
|
|
174
|
+
unique_label,
|
|
175
|
+
) = get_region_label_info(region_label, label_info)
|
|
176
|
+
|
|
177
|
+
res_dict = {
|
|
178
|
+
"object_name": "cell",
|
|
179
|
+
"pieces_names": pieces_names,
|
|
180
|
+
"data": data_list,
|
|
181
|
+
"label_name": label_names,
|
|
182
|
+
"label_acronym": label_acronym,
|
|
183
|
+
"label_color": label_color,
|
|
184
|
+
"region_count": region_count,
|
|
185
|
+
}
|
|
186
|
+
return res_dict
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def calculate_drawing_info(data_list, pieces_names, label_data, label_info, bregma):
|
|
190
|
+
data = data_list[0]
|
|
191
|
+
for i in range(1, len(data_list)):
|
|
192
|
+
data = np.vstack([data, data_list[i]])
|
|
193
|
+
# print(data)
|
|
194
|
+
if "area" in pieces_names[0]:
|
|
195
|
+
plot_mode = "area"
|
|
196
|
+
else:
|
|
197
|
+
plot_mode = "line"
|
|
198
|
+
|
|
199
|
+
region_label = get_region_label(data, label_data, bregma)
|
|
200
|
+
(
|
|
201
|
+
region_count,
|
|
202
|
+
label_names,
|
|
203
|
+
label_acronym,
|
|
204
|
+
label_color,
|
|
205
|
+
unique_label,
|
|
206
|
+
) = get_region_label_info(region_label, label_info)
|
|
207
|
+
|
|
208
|
+
res_dict = {
|
|
209
|
+
"object_name": "drawing",
|
|
210
|
+
"pieces_names": pieces_names,
|
|
211
|
+
"data": data_list,
|
|
212
|
+
"label_id": unique_label,
|
|
213
|
+
"label_name": label_names,
|
|
214
|
+
"label_acronym": label_acronym,
|
|
215
|
+
"label_color": label_color,
|
|
216
|
+
"region_count": region_count,
|
|
217
|
+
"plot_mode": plot_mode,
|
|
218
|
+
}
|
|
219
|
+
return res_dict
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def order_contour_pnt(pnt):
|
|
223
|
+
order_ind = []
|
|
224
|
+
x_min = np.min(pnt[:, 0])
|
|
225
|
+
left_ind = np.where(pnt[:, 0] == x_min)[0]
|
|
226
|
+
if len(left_ind) > 1:
|
|
227
|
+
low_ind = np.where(pnt[left_ind, :] == np.min(pnt[left_ind, :]))[0]
|
|
228
|
+
left_ind = left_ind[low_ind]
|
|
229
|
+
left_pnt = pnt[left_ind, :]
|
|
230
|
+
lower_inds = np.where(pnt[:, 1] <= left_pnt[1])[0]
|
|
231
|
+
lower_pnts = pnt[:, lower_inds]
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def calculate_contour_line(data):
|
|
235
|
+
data = np.asarray(data)
|
|
236
|
+
res = splprep([data[:, 0], data[:, 1], data[:, 2]], s=2)
|
|
237
|
+
tck = res[0]
|
|
238
|
+
# x_knots, y_knots, z_knots = splev(tck[0], tck)
|
|
239
|
+
u_fine = np.linspace(0, 1, len(data))
|
|
240
|
+
x_fine, y_fine, z_fine = splev(u_fine, tck)
|
|
241
|
+
pnts = np.stack([x_fine, y_fine, z_fine], axis=1)
|
|
242
|
+
# print(pnts)
|
|
243
|
+
return pnts
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def hex2rgb(hex):
|
|
247
|
+
if "#" in hex:
|
|
248
|
+
hex = hex.lstrip("#")
|
|
249
|
+
rgb_color = [int(hex[i : i + 2], 16) for i in (0, 2, 4)]
|
|
250
|
+
else:
|
|
251
|
+
if len(hex) == 6:
|
|
252
|
+
rgb_color = [int(hex[i : i + 2], 16) for i in (0, 2, 4)]
|
|
253
|
+
return rgb_color[0], rgb_color[1], rgb_color[2]
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
# @jit()
|
|
257
|
+
def hsv2rgb(h, s, v):
|
|
258
|
+
# h [0, 1], s, v [0, 1]
|
|
259
|
+
h = h * 360
|
|
260
|
+
c = v * s
|
|
261
|
+
m = v - c
|
|
262
|
+
x = c * (1 - np.abs(np.mod(h / 60, 2) - 1))
|
|
263
|
+
if 0 <= h < 60:
|
|
264
|
+
r, g, b = (c + m, x + m, m)
|
|
265
|
+
elif 60 <= h < 120:
|
|
266
|
+
r, g, b = (x + m, c + m, m)
|
|
267
|
+
elif 120 <= h < 180:
|
|
268
|
+
r, g, b = (m, c + m, x + m)
|
|
269
|
+
elif 180 <= h < 240:
|
|
270
|
+
r, g, b = (m, x + m, c + m)
|
|
271
|
+
elif 240 <= h < 300:
|
|
272
|
+
r, g, b = (x + m, m, c + m)
|
|
273
|
+
elif 300 <= h < 360:
|
|
274
|
+
r, g, b = (c + m, m, x + m)
|
|
275
|
+
else:
|
|
276
|
+
r, g, b = (m, m, m)
|
|
277
|
+
r = r * 65535
|
|
278
|
+
b = b * 65535
|
|
279
|
+
g = g * 65535
|
|
280
|
+
return r, g, b
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def color_img(h, s, v):
|
|
284
|
+
r, g, b = hsv2rgb(h, s, v)
|
|
285
|
+
da_image = cv2.merge((r, g, b))
|
|
286
|
+
return da_image
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def merge_channels_into_single_img(czi_img, channel_colors):
|
|
290
|
+
merged_img = np.zeros((czi_img.shape[0], czi_img.shape[1], 3))
|
|
291
|
+
frac = 1 / len(channel_colors)
|
|
292
|
+
# print(frac)
|
|
293
|
+
for i in range(len(channel_colors)):
|
|
294
|
+
temp_v = czi_img[:, :, i] / 65535
|
|
295
|
+
temp_h = channel_colors[i][0]
|
|
296
|
+
temp_s = channel_colors[i][1]
|
|
297
|
+
# print(temp_h, temp_s)
|
|
298
|
+
da_img = color_img(temp_h, temp_s, temp_v)
|
|
299
|
+
merged_img = merged_img + frac * da_img
|
|
300
|
+
return merged_img
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def make_color_lut(channel_color: tuple, bit_level: int):
|
|
304
|
+
r, g, b = colorsys.hsv_to_rgb(channel_color[0], channel_color[1], channel_color[2])
|
|
305
|
+
colors = [(0, 0, 0), (r * 255, g * 255, b * 255)]
|
|
306
|
+
color_map = pg.ColorMap(pos=[0, 1], color=colors)
|
|
307
|
+
da_lut = color_map.getLookupTable(nPts=bit_level, mode=pg.ColorMap.FLOAT)
|
|
308
|
+
da_lut = da_lut * 255
|
|
309
|
+
return da_lut
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def get_qhsv_from_czi_hsv(hsv_color: tuple):
|
|
313
|
+
"""
|
|
314
|
+
Get QColor HSV color format (360, 255, 255) from czi HSV color format (1, 1, 1).
|
|
315
|
+
:param hsv_color: (float [0., 1.], float [0., 1.], float [0., 1.])
|
|
316
|
+
:return: QColor
|
|
317
|
+
"""
|
|
318
|
+
h_val = int(hsv_color[0] * 360)
|
|
319
|
+
s_val = int(hsv_color[1] * 255)
|
|
320
|
+
v_val = int(hsv_color[2] * 255)
|
|
321
|
+
da_color = (h_val, s_val, v_val)
|
|
322
|
+
return da_color
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def gamma_line(input, lims, gamma, depth_level):
|
|
326
|
+
inv_gamma = 1.0 / gamma
|
|
327
|
+
y = np.zeros(len(input))
|
|
328
|
+
inds = np.logical_and(input >= lims[0], input <= lims[1])
|
|
329
|
+
y[inds] = (
|
|
330
|
+
np.power((input[inds] - lims[0]) / (lims[1] - lims[0]), gamma) * depth_level
|
|
331
|
+
)
|
|
332
|
+
y[input <= lims[0]] = 0
|
|
333
|
+
y[input >= lims[1]] = depth_level
|
|
334
|
+
return y
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def crop_landscape(image, dim):
|
|
338
|
+
r = (dim[0] / image.shape[0]) / (dim[0] / dim[1])
|
|
339
|
+
nw = int(image.shape[1] * r)
|
|
340
|
+
|
|
341
|
+
resized = cv2.resize(image, (nw, int(dim[1])), interpolation=cv2.INTER_AREA)
|
|
342
|
+
|
|
343
|
+
half_width = int(dim[0]) / 2
|
|
344
|
+
half_shape_width = int(resized.shape[1]) / 2
|
|
345
|
+
|
|
346
|
+
start_x = half_shape_width - half_width
|
|
347
|
+
end_x = half_width + half_shape_width
|
|
348
|
+
cropped = resized[0 : dim[1], start_x:end_x]
|
|
349
|
+
|
|
350
|
+
return cropped
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
def crop_portrait(image, dim):
|
|
354
|
+
r = dim[1] / image.shape[1] / (dim[1] / dim[0])
|
|
355
|
+
nh = int(image.shape[0] * r)
|
|
356
|
+
|
|
357
|
+
resized = cv2.resize(image, (int(dim[0]), nh), interpolation=cv2.INTER_AREA)
|
|
358
|
+
half_height = int(dim[1]) / 2
|
|
359
|
+
half_shape_height = int(resized.shape[0]) / 2
|
|
360
|
+
|
|
361
|
+
start_y = half_shape_height - half_height
|
|
362
|
+
end_y = half_height + half_shape_height
|
|
363
|
+
cropped = resized[start_y:end_y, 0 : dim[0]]
|
|
364
|
+
|
|
365
|
+
return cropped
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def create_other_size(image, file_name, dim, location):
|
|
369
|
+
# 1 => width index, 0 => height index
|
|
370
|
+
if image.shape[0] > image.shape[1]:
|
|
371
|
+
cropped = crop_portrait(image, dim)
|
|
372
|
+
else:
|
|
373
|
+
cropped = crop_landscape(image, dim)
|
|
374
|
+
|
|
375
|
+
cv2.imwrite(os.path.join(location, file_name), cropped)
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def make_hist_data(image_data, max_val):
|
|
379
|
+
hist_data_list = []
|
|
380
|
+
for i in range(image_data.shape[2]):
|
|
381
|
+
if np.max(image_data[:, :, i]) == 0:
|
|
382
|
+
da_bins = max_val
|
|
383
|
+
else:
|
|
384
|
+
da_bins = np.max(image_data[:, :, i])
|
|
385
|
+
hist_y, x = np.histogram(image_data[:, :, i], bins=da_bins)
|
|
386
|
+
y = np.log1p(hist_y)
|
|
387
|
+
y = y / np.max(y) * max_val
|
|
388
|
+
y = np.append(y, 0)
|
|
389
|
+
sfunc = interp1d(x, y, "cubic")
|
|
390
|
+
inter_x = np.linspace(np.min(x), np.max(x), 200)
|
|
391
|
+
inter_y = sfunc(inter_x)
|
|
392
|
+
inter_y[inter_y < 0] = 0
|
|
393
|
+
hist_data_list.append([inter_x, inter_y])
|
|
394
|
+
return hist_data_list
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def rect_contains(rect, point):
|
|
398
|
+
if point[0] < rect[0]:
|
|
399
|
+
return False
|
|
400
|
+
elif point[1] < rect[1]:
|
|
401
|
+
return False
|
|
402
|
+
elif point[0] > rect[2] + rect[0]:
|
|
403
|
+
return False
|
|
404
|
+
elif point[1] > rect[3] + rect[1]:
|
|
405
|
+
return False
|
|
406
|
+
return True
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def get_warp_matrix(src_tri_pnts, dst_tri_pnts):
|
|
410
|
+
# Given a pair of triangles, find the affine transform.
|
|
411
|
+
warp_mat = cv2.getAffineTransform(
|
|
412
|
+
np.float32(src_tri_pnts), np.float32(dst_tri_pnts)
|
|
413
|
+
)
|
|
414
|
+
return warp_mat
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def apply_affine_transform(src_img, warp_mat, size_dst):
|
|
418
|
+
# Apply the Affine Transform just found to the src image
|
|
419
|
+
dst = cv2.warpAffine(
|
|
420
|
+
src_img.astype(np.float32),
|
|
421
|
+
warp_mat,
|
|
422
|
+
(size_dst[0], size_dst[1]),
|
|
423
|
+
None,
|
|
424
|
+
flags=cv2.INTER_LINEAR,
|
|
425
|
+
borderMode=cv2.BORDER_REFLECT_101,
|
|
426
|
+
)
|
|
427
|
+
return dst
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def warp_triangle(img1, img2, t1, t2, is_rgb=False):
|
|
431
|
+
# Find bounding rectangle for each triangle
|
|
432
|
+
r1 = cv2.boundingRect(t1.astype(np.float32))
|
|
433
|
+
r2 = cv2.boundingRect(t2.astype(np.float32))
|
|
434
|
+
|
|
435
|
+
# Offset points by left top corner of the respective rectangles
|
|
436
|
+
t1_rect = t1 - r1[:2]
|
|
437
|
+
t2_rect = t2 - r2[:2]
|
|
438
|
+
t2_rect_int = t2_rect.astype(int)
|
|
439
|
+
|
|
440
|
+
# Get mask by filling triangle
|
|
441
|
+
if is_rgb:
|
|
442
|
+
mask = np.zeros((r2[3], r2[2], img1.shape[2]), dtype=np.float32)
|
|
443
|
+
cv2.fillConvexPoly(
|
|
444
|
+
mask, np.int32(t2_rect_int), tuple(np.repeat(1.0, img1.shape[2])), 16, 0
|
|
445
|
+
)
|
|
446
|
+
else:
|
|
447
|
+
mask = np.zeros((r2[3], r2[2]), dtype=np.float32)
|
|
448
|
+
cv2.fillConvexPoly(mask, np.int32(t2_rect_int), 1, 16, 0)
|
|
449
|
+
|
|
450
|
+
# Apply warpImage to small rectangular patches
|
|
451
|
+
img1_rect = img1[r1[1] : r1[1] + r1[3], r1[0] : r1[0] + r1[2]]
|
|
452
|
+
# img2Rect = np.zeros((r2[3], r2[2]), dtype = img1Rect.dtype)
|
|
453
|
+
|
|
454
|
+
size = (r2[2], r2[3])
|
|
455
|
+
|
|
456
|
+
warp_mat = get_warp_matrix(t1_rect, t2_rect)
|
|
457
|
+
img2_rect = apply_affine_transform(img1_rect, warp_mat, size)
|
|
458
|
+
img2_rect = img2_rect * mask
|
|
459
|
+
|
|
460
|
+
# Copy triangular region of the rectangular patch to the output image
|
|
461
|
+
yr = (r2[0], r2[0] + r2[2])
|
|
462
|
+
xr = (r2[1], r2[1] + r2[3])
|
|
463
|
+
if is_rgb:
|
|
464
|
+
img2[xr[0] : xr[1], yr[0] : yr[1]] = img2[xr[0] : xr[1], yr[0] : yr[1]] * (
|
|
465
|
+
tuple(np.repeat(1.0, img1.shape[2])) - mask
|
|
466
|
+
)
|
|
467
|
+
else:
|
|
468
|
+
img2[xr[0] : xr[1], yr[0] : yr[1]] = img2[xr[0] : xr[1], yr[0] : yr[1]] * (
|
|
469
|
+
1 - mask
|
|
470
|
+
)
|
|
471
|
+
img2[xr[0] : xr[1], yr[0] : yr[1]] = img2[xr[0] : xr[1], yr[0] : yr[1]] + img2_rect
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def warp_points(pnts, t1, t2):
|
|
475
|
+
# Find bounding rectangle for each triangle
|
|
476
|
+
# r1 = cv2.boundingRect(t1.astype(np.float32))
|
|
477
|
+
# r2 = cv2.boundingRect(t2.astype(np.float32))
|
|
478
|
+
# print(r1)
|
|
479
|
+
# print(r2)
|
|
480
|
+
|
|
481
|
+
# pnts =
|
|
482
|
+
|
|
483
|
+
da_pnts = np.hstack([pnts, np.ones((len(pnts), 1))])
|
|
484
|
+
# Offset points by left top corner of the respective rectangles
|
|
485
|
+
# t1_rect = t1 - r1[:2]
|
|
486
|
+
# t2_rect = t2 - r2[:2]
|
|
487
|
+
|
|
488
|
+
warp_mat = get_warp_matrix(t1, t2)
|
|
489
|
+
output = np.dot(warp_mat, da_pnts.T).T
|
|
490
|
+
|
|
491
|
+
return output
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
# calculate delanauy triangle
|
|
495
|
+
def calculateDelaunayTriangles(rect, points):
|
|
496
|
+
# create subdiv
|
|
497
|
+
subdiv = cv2.Subdiv2D(rect)
|
|
498
|
+
|
|
499
|
+
# Insert points into subdiv
|
|
500
|
+
for p in points:
|
|
501
|
+
subdiv.insert(p)
|
|
502
|
+
|
|
503
|
+
triangleList = subdiv.getTriangleList()
|
|
504
|
+
|
|
505
|
+
delaunayTri = []
|
|
506
|
+
|
|
507
|
+
pt = []
|
|
508
|
+
|
|
509
|
+
for t in triangleList:
|
|
510
|
+
pt.append((t[0], t[1]))
|
|
511
|
+
pt.append((t[2], t[3]))
|
|
512
|
+
pt.append((t[4], t[5]))
|
|
513
|
+
|
|
514
|
+
pt1 = (t[0], t[1])
|
|
515
|
+
pt2 = (t[2], t[3])
|
|
516
|
+
pt3 = (t[4], t[5])
|
|
517
|
+
|
|
518
|
+
if (
|
|
519
|
+
rect_contains(rect, pt1)
|
|
520
|
+
and rect_contains(rect, pt2)
|
|
521
|
+
and rect_contains(rect, pt3)
|
|
522
|
+
):
|
|
523
|
+
ind = []
|
|
524
|
+
for j in range(0, 3):
|
|
525
|
+
for k in range(0, len(points)):
|
|
526
|
+
if (
|
|
527
|
+
abs(pt[j][0] - points[k][0]) < 1.0
|
|
528
|
+
and abs(pt[j][1] - points[k][1]) < 1.0
|
|
529
|
+
):
|
|
530
|
+
ind.append(k)
|
|
531
|
+
if len(ind) == 3:
|
|
532
|
+
delaunayTri.append((ind[0], ind[1], ind[2]))
|
|
533
|
+
|
|
534
|
+
pt = []
|
|
535
|
+
|
|
536
|
+
return delaunayTri
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
def get_vertex_ind_in_triangle(subdiv):
|
|
540
|
+
triangles = subdiv.getTriangleList()
|
|
541
|
+
n_triangles = len(triangles)
|
|
542
|
+
tri_vet_inds = []
|
|
543
|
+
for i in range(n_triangles):
|
|
544
|
+
da_triangle = triangles[i]
|
|
545
|
+
p1 = [da_triangle[0], da_triangle[1]]
|
|
546
|
+
p2 = [da_triangle[2], da_triangle[3]]
|
|
547
|
+
p3 = [da_triangle[4], da_triangle[5]]
|
|
548
|
+
tri_vet_inds.append(
|
|
549
|
+
[subdiv.locate(p1)[2], subdiv.locate(p2)[2], subdiv.locate(p3)[2]]
|
|
550
|
+
)
|
|
551
|
+
tri_vet_inds = np.asarray(tri_vet_inds) - 4
|
|
552
|
+
return tri_vet_inds
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
def get_pnts_triangle_ind(tri_vet_inds, tri_data, size, pnts):
|
|
556
|
+
# import cv2
|
|
557
|
+
# import numpy as np
|
|
558
|
+
# img_rec = (0, 0, 100, 200)
|
|
559
|
+
# da_triangle = np.array([[0, 0], [0, 50], [100, 100]])
|
|
560
|
+
# size = (200, 100)
|
|
561
|
+
# pnts = np.array([[0, 1], [0, 2], [60, 200]])
|
|
562
|
+
|
|
563
|
+
update_pnts = pnts.copy()
|
|
564
|
+
n_pnts = len(pnts)
|
|
565
|
+
loc = np.zeros(n_pnts)
|
|
566
|
+
loc[:] = np.nan
|
|
567
|
+
da_order = []
|
|
568
|
+
|
|
569
|
+
ct_list = []
|
|
570
|
+
for i in range(len(tri_vet_inds)):
|
|
571
|
+
da_inds = tri_vet_inds[i]
|
|
572
|
+
da_triangle = np.array(
|
|
573
|
+
[tri_data[da_inds[0]], tri_data[da_inds[1]], tri_data[da_inds[2]]]
|
|
574
|
+
)
|
|
575
|
+
mask = np.zeros(size, dtype=np.uint8)
|
|
576
|
+
cv2.fillPoly(mask, pts=[da_triangle], color=255)
|
|
577
|
+
ct, hc = cv2.findContours(
|
|
578
|
+
image=mask, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE
|
|
579
|
+
)
|
|
580
|
+
ct_list.append(ct[0])
|
|
581
|
+
|
|
582
|
+
# range_y = (np.min(da_triangle[:, 1]), np.max(da_triangle[:, 1]))
|
|
583
|
+
# range_x = (np.min(da_triangle[:, 0]), np.max(da_triangle[:, 0]))
|
|
584
|
+
#
|
|
585
|
+
# valid_pnts_ind = [ind for ind in range(n_pnts) if range_x[0] <= pnts[ind][0] <= range_x[1] and range_y[0] <= pnts[ind][1] <= range_y[1]]
|
|
586
|
+
# valid_pnts_ind = [ind for ind in valid_pnts_ind if ind not in da_order]
|
|
587
|
+
# valid_pnts = pnts[valid_pnts_ind]
|
|
588
|
+
# for j in range(len(valid_pnts)):
|
|
589
|
+
# res = cv2.pointPolygonTest(ct_list[i], (int(pnts[j][0]), int(pnts[j][1])), True)
|
|
590
|
+
# if res >= 0:
|
|
591
|
+
# loc.append(i)
|
|
592
|
+
# da_order.append(valid_pnts_ind[j])
|
|
593
|
+
|
|
594
|
+
# temp = np.zeros(len(update_pnts))
|
|
595
|
+
#
|
|
596
|
+
#
|
|
597
|
+
# for i in range(len(tri_vet_inds)):
|
|
598
|
+
# da_
|
|
599
|
+
#
|
|
600
|
+
for i in range(len(pnts)):
|
|
601
|
+
for j in range(len(ct_list)):
|
|
602
|
+
da_ct = ct_list[j]
|
|
603
|
+
res = cv2.pointPolygonTest(da_ct, (int(pnts[i][0]), int(pnts[i][1])), False)
|
|
604
|
+
if res >= 0:
|
|
605
|
+
loc[i] = j
|
|
606
|
+
break
|
|
607
|
+
|
|
608
|
+
return loc
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
def get_sides_points(img_size):
|
|
612
|
+
size0 = img_size[1] - 1
|
|
613
|
+
size1 = img_size[0] - 1
|
|
614
|
+
side_lines = np.asarray(
|
|
615
|
+
[
|
|
616
|
+
[[0, 0], [size0, 0]],
|
|
617
|
+
[[size0, 0], [size0, size1]],
|
|
618
|
+
[[0, size1], [size0, size1]],
|
|
619
|
+
[[0, 0], [0, size1]],
|
|
620
|
+
]
|
|
621
|
+
)
|
|
622
|
+
corner_points = [[0, 0], [size0, 0], [size0, size1], [0, size1]]
|
|
623
|
+
return side_lines, corner_points
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
def num_side_pnt_changed(num_pnt, corner_points, side_lines):
|
|
627
|
+
n_pnts_to_make = num_pnt - 2
|
|
628
|
+
onside_data = corner_points.copy()
|
|
629
|
+
if n_pnts_to_make > 0:
|
|
630
|
+
for i in range(4):
|
|
631
|
+
da_line = side_lines[i]
|
|
632
|
+
for j in range(n_pnts_to_make):
|
|
633
|
+
inline_point = da_line[0] + (da_line[1] - da_line[0]) / (
|
|
634
|
+
n_pnts_to_make + 1
|
|
635
|
+
) * (j + 1)
|
|
636
|
+
onside_data.append([int(inline_point[0]), int(inline_point[1])])
|
|
637
|
+
return onside_data
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
def match_sides_points(rect_atlas, size_atlas, rect_image, size_image):
|
|
641
|
+
x_factor = rect_atlas[2] / rect_image[2]
|
|
642
|
+
y_factor = rect_atlas[3] / rect_image[3]
|
|
643
|
+
|
|
644
|
+
actual_right_dist_image = size_image[1] - (rect_image[0] + rect_image[2])
|
|
645
|
+
actual_bottom_dist_image = size_image[0] - (rect_image[1] + rect_image[3])
|
|
646
|
+
|
|
647
|
+
actual_right_dist_atlas = size_atlas[1] - (rect_atlas[0] + rect_atlas[2])
|
|
648
|
+
actual_bottom_dist_atlas = size_atlas[0] - (rect_atlas[1] + rect_atlas[3])
|
|
649
|
+
|
|
650
|
+
left_dist_atlas = rect_image[0] * x_factor
|
|
651
|
+
right_dist_atlas = actual_right_dist_image * x_factor
|
|
652
|
+
|
|
653
|
+
top_dist_atlas = rect_image[1] * y_factor
|
|
654
|
+
bottom_dist_atlas = actual_bottom_dist_image * y_factor
|
|
655
|
+
|
|
656
|
+
if left_dist_atlas <= rect_atlas[0]:
|
|
657
|
+
atlas_corner_x = int(rect_atlas[0] - left_dist_atlas)
|
|
658
|
+
image_corner_x = 0
|
|
659
|
+
else:
|
|
660
|
+
atlas_corner_x = 0
|
|
661
|
+
left_dist_image = rect_atlas[0] / x_factor
|
|
662
|
+
image_corner_x = int(rect_image[0] - left_dist_image)
|
|
663
|
+
|
|
664
|
+
if right_dist_atlas <= actual_right_dist_atlas:
|
|
665
|
+
atlas_right_side = size_atlas[1] - (actual_right_dist_atlas - right_dist_atlas)
|
|
666
|
+
atlas_width = int(atlas_right_side - atlas_corner_x)
|
|
667
|
+
image_width = size_image[1] - image_corner_x
|
|
668
|
+
else:
|
|
669
|
+
atlas_width = size_atlas[1] - atlas_corner_x
|
|
670
|
+
right_dist_image = actual_right_dist_atlas / x_factor
|
|
671
|
+
image_width = int(
|
|
672
|
+
size_image[1]
|
|
673
|
+
- image_corner_x
|
|
674
|
+
- (actual_right_dist_image - right_dist_image)
|
|
675
|
+
)
|
|
676
|
+
|
|
677
|
+
if top_dist_atlas <= rect_atlas[1]:
|
|
678
|
+
atlas_corner_y = int(rect_atlas[1] - top_dist_atlas)
|
|
679
|
+
image_corner_y = 0
|
|
680
|
+
else:
|
|
681
|
+
atlas_corner_y = 0
|
|
682
|
+
top_dist_image = rect_atlas[1] / y_factor
|
|
683
|
+
image_corner_y = int(rect_image[1] - top_dist_image)
|
|
684
|
+
|
|
685
|
+
if bottom_dist_atlas <= actual_bottom_dist_atlas:
|
|
686
|
+
atlas_height = int(
|
|
687
|
+
size_atlas[0]
|
|
688
|
+
- atlas_corner_y
|
|
689
|
+
- (actual_bottom_dist_atlas - bottom_dist_atlas)
|
|
690
|
+
)
|
|
691
|
+
image_height = size_image[0] - image_corner_y
|
|
692
|
+
else:
|
|
693
|
+
atlas_height = size_atlas[0] - atlas_corner_y
|
|
694
|
+
bottom_dist_image = actual_bottom_dist_atlas / y_factor
|
|
695
|
+
image_height = int(
|
|
696
|
+
size_image[0]
|
|
697
|
+
- image_corner_y
|
|
698
|
+
- (actual_bottom_dist_image - bottom_dist_image)
|
|
699
|
+
)
|
|
700
|
+
|
|
701
|
+
atlas_rect = (atlas_corner_x, atlas_corner_y, atlas_width, atlas_height)
|
|
702
|
+
image_rect = (image_corner_x, image_corner_y, image_width, image_height)
|
|
703
|
+
|
|
704
|
+
return atlas_rect, image_rect
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
def get_corner_line_from_rect(rect):
|
|
708
|
+
corners = [
|
|
709
|
+
[rect[0], rect[1]],
|
|
710
|
+
[rect[0] + rect[2] - 1, rect[1]],
|
|
711
|
+
[rect[0] + rect[2] - 1, rect[1] + rect[3] - 1],
|
|
712
|
+
[rect[0], rect[1] + rect[3] - 1],
|
|
713
|
+
]
|
|
714
|
+
|
|
715
|
+
lines = np.asarray(
|
|
716
|
+
[
|
|
717
|
+
[corners[0], corners[1]],
|
|
718
|
+
[corners[1], corners[2]],
|
|
719
|
+
[corners[3], corners[2]],
|
|
720
|
+
[corners[0], corners[3]],
|
|
721
|
+
]
|
|
722
|
+
)
|
|
723
|
+
|
|
724
|
+
return corners, lines
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
def make_label_rgb_img(label_img, lut):
|
|
728
|
+
fimg = np.dstack([label_img, label_img, label_img])
|
|
729
|
+
unique_label = np.unique(label_img).astype(int)
|
|
730
|
+
for ind in np.unique(unique_label):
|
|
731
|
+
if ind == 0:
|
|
732
|
+
continue
|
|
733
|
+
loc = np.where(label_img == ind)
|
|
734
|
+
# print(lut[ind])
|
|
735
|
+
fimg[loc[0], loc[1], 0] = lut[ind][0]
|
|
736
|
+
fimg[loc[0], loc[1], 1] = lut[ind][1]
|
|
737
|
+
fimg[loc[0], loc[1], 2] = lut[ind][2]
|
|
738
|
+
return fimg.astype("uint8")
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
def make_contour_img(lable_img):
|
|
742
|
+
unique_label = np.unique(lable_img).astype("int")
|
|
743
|
+
img_size = lable_img.shape
|
|
744
|
+
contour_img = np.zeros(img_size, "uint8")
|
|
745
|
+
for label_ind in unique_label:
|
|
746
|
+
if label_ind == 0:
|
|
747
|
+
continue
|
|
748
|
+
temp = np.zeros(img_size, "uint8")
|
|
749
|
+
temp[lable_img == label_ind] = 1
|
|
750
|
+
ct, hc = cv2.findContours(
|
|
751
|
+
image=temp, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE
|
|
752
|
+
)
|
|
753
|
+
for j in range(len(ct)):
|
|
754
|
+
da_contour = ct[j].copy()
|
|
755
|
+
da_shp = da_contour.shape
|
|
756
|
+
da_contour = np.reshape(da_contour, (da_shp[0], da_shp[2]))
|
|
757
|
+
contour_img[da_contour[:, 1], da_contour[:, 0]] = 1
|
|
758
|
+
return contour_img
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
def get_tri_lines(rect, pnts):
|
|
762
|
+
# print(rect)
|
|
763
|
+
subdiv = cv2.Subdiv2D(rect)
|
|
764
|
+
for p in pnts:
|
|
765
|
+
# print(p)
|
|
766
|
+
subdiv.insert((int(p[0]), int(p[1])))
|
|
767
|
+
edge_list = subdiv.getEdgeList()
|
|
768
|
+
lines_list = []
|
|
769
|
+
# special_pnt = []
|
|
770
|
+
for el in edge_list:
|
|
771
|
+
pt1 = [el[0], el[1]]
|
|
772
|
+
pt2 = [el[2], el[3]]
|
|
773
|
+
if rect_contains(rect, pt1) and rect_contains(rect, pt2):
|
|
774
|
+
lines_list.append(el)
|
|
775
|
+
# else:
|
|
776
|
+
# if not rect_contains(rect, pt1) and pt1 not in special_pnt:
|
|
777
|
+
# special_pnt.append(pt1)
|
|
778
|
+
# if not rect_contains(rect, pt2) and pt2 not in special_pnt:
|
|
779
|
+
# special_pnt.append(pt2)
|
|
780
|
+
return lines_list # , special_pnt
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
# czi_img = image_file.data['scene 0'].copy()
|
|
784
|
+
# channel_hsv = image_file.hsv_colors
|
|
785
|
+
# temp_img = merge_channels_into_single_img(czi_img, channel_hsv)
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
def gamma_correction(src, gamma):
|
|
789
|
+
inv_gamma = 1 / gamma
|
|
790
|
+
|
|
791
|
+
table = [((i / 255) ** inv_gamma) * 255 for i in range(256)]
|
|
792
|
+
table = np.array(table, np.uint8)
|
|
793
|
+
|
|
794
|
+
return cv2.LUT(src, table)
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
def get_lower_val(val, tol, lim):
|
|
798
|
+
lower_val = val - tol if tol < val else lim
|
|
799
|
+
return lower_val
|
|
800
|
+
|
|
801
|
+
|
|
802
|
+
def get_upper_val(val, tol, lim):
|
|
803
|
+
upper_val = val + tol
|
|
804
|
+
upper_val = upper_val if upper_val <= lim else lim
|
|
805
|
+
return upper_val
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
def get_bound_color(color, tol, level, mode):
|
|
809
|
+
tol = float(tol)
|
|
810
|
+
if mode == "gray":
|
|
811
|
+
lower_val = get_lower_val(color, tol, 0)
|
|
812
|
+
upper_val = get_upper_val(color, tol, level)
|
|
813
|
+
elif mode == "hsv":
|
|
814
|
+
lower_val = [get_lower_val(color[0], 1.0, 0)]
|
|
815
|
+
upper_val = [get_upper_val(color[0], 1.0, 180)]
|
|
816
|
+
for i in range(1, 3):
|
|
817
|
+
lower_val.append(get_lower_val(color[i], tol, 0))
|
|
818
|
+
upper_val.append(get_upper_val(color[i], tol, 255))
|
|
819
|
+
else:
|
|
820
|
+
lower_val = []
|
|
821
|
+
upper_val = []
|
|
822
|
+
for i in range(3):
|
|
823
|
+
lower_val.append(get_lower_val(color[i], tol, 0))
|
|
824
|
+
upper_val.append(get_upper_val(color[i], tol, level))
|
|
825
|
+
return lower_val, upper_val
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
# ----------------------------------------------------------------------------------
|
|
829
|
+
# ----------------------------------------------------------------------------------
|
|
830
|
+
|
|
831
|
+
|
|
832
|
+
def get_statusbar_style(col):
|
|
833
|
+
style = (
|
|
834
|
+
"background-color: #323232;"
|
|
835
|
+
" color: {}; border-top: 1px solid #272727; "
|
|
836
|
+
"padding-left: 30px;".format(col)
|
|
837
|
+
)
|
|
838
|
+
return style
|
|
839
|
+
|
|
840
|
+
|
|
841
|
+
def rotate(image, angle, img_center=None, scale=1.0):
|
|
842
|
+
(h, w) = image.shape[:2]
|
|
843
|
+
|
|
844
|
+
if img_center is None:
|
|
845
|
+
img_center = (w // 2, h // 2)
|
|
846
|
+
|
|
847
|
+
rot_mat = cv2.getRotationMatrix2D(img_center, angle, scale)
|
|
848
|
+
rotated_img = cv2.warpAffine(image, rot_mat, (w, h))
|
|
849
|
+
|
|
850
|
+
return rotated_img
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
def rotate_bound(image, angle):
|
|
854
|
+
(h, w) = image.shape[:2]
|
|
855
|
+
(center_x, center_y) = (w / 2, h / 2)
|
|
856
|
+
|
|
857
|
+
rot_mat = cv2.getRotationMatrix2D((center_x, center_y), -angle, 1.0)
|
|
858
|
+
cos = np.abs(rot_mat[0, 0])
|
|
859
|
+
sin = np.abs(rot_mat[0, 1])
|
|
860
|
+
|
|
861
|
+
bound_w = int((h * sin) + (w * cos))
|
|
862
|
+
bound_h = int((h * cos) + (w * sin))
|
|
863
|
+
|
|
864
|
+
rot_mat[0, 2] += (bound_w / 2) - center_x
|
|
865
|
+
rot_mat[1, 2] += (bound_h / 2) - center_y
|
|
866
|
+
|
|
867
|
+
return cv2.warpAffine(image, rot_mat, (bound_w, bound_h))
|
|
868
|
+
|
|
869
|
+
|
|
870
|
+
def center_resize(img, dim):
|
|
871
|
+
img_shape = img.shape
|
|
872
|
+
width, height = img_shape[1], img_shape[0]
|
|
873
|
+
scale_factor = np.min(np.array([dim[0] / width, dim[1] / height]))
|
|
874
|
+
resize_dim = (int(width * scale_factor), int(height * scale_factor))
|
|
875
|
+
resize_img = cv2.resize(img, resize_dim, interpolation=cv2.INTER_LINEAR)
|
|
876
|
+
|
|
877
|
+
y = int(0.5 * (dim[0] - resize_dim[0]))
|
|
878
|
+
x = int(0.5 * (dim[1] - resize_dim[1]))
|
|
879
|
+
|
|
880
|
+
if len(img_shape) == 3:
|
|
881
|
+
center_img = np.zeros((dim[1], dim[0], img.shape[2])).astype(img.dtype)
|
|
882
|
+
else:
|
|
883
|
+
center_img = np.zeros((dim[1], dim[0])).astype(img.dtype)
|
|
884
|
+
|
|
885
|
+
center_img[x : (x + resize_dim[1]), y : (y + resize_dim[0])] = resize_img
|
|
886
|
+
|
|
887
|
+
return center_img
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
def get_tb_size(img_size):
|
|
891
|
+
scale_factor = np.max(np.ravel(img_size) / 80)
|
|
892
|
+
tb_size = (int(img_size[1] / scale_factor), int(img_size[0] / scale_factor))
|
|
893
|
+
return tb_size
|
|
894
|
+
|
|
895
|
+
|
|
896
|
+
def get_slice_atlas_coord(points, cut, size, width, height, distance, origin):
|
|
897
|
+
"""
|
|
898
|
+
|
|
899
|
+
:param points: pnts on image
|
|
900
|
+
:param cut: the cut of slice image
|
|
901
|
+
:param size: the size (height, width) of slice image in pixel
|
|
902
|
+
:param width: width of image in mm
|
|
903
|
+
:param height: height of image in mm
|
|
904
|
+
:param distance: distance of slice with respect to Bregma in mm
|
|
905
|
+
:param origin: the coord of bregma on the current slice image
|
|
906
|
+
:return:
|
|
907
|
+
"""
|
|
908
|
+
width_factor = width / size[1] * 1000
|
|
909
|
+
height_factor = height / size[0] * 1000
|
|
910
|
+
if cut == "Coronal":
|
|
911
|
+
y_val = np.repeat(distance * 1000, len(points))
|
|
912
|
+
x_val = (points[:, 0] - origin[0]) * width_factor
|
|
913
|
+
z_val = (points[:, 1] - origin[1]) * height_factor
|
|
914
|
+
elif cut == "Sagittal":
|
|
915
|
+
x_val = np.repeat(distance * 1000, len(points))
|
|
916
|
+
y_val = (points[:, 0] - origin[0]) * width_factor
|
|
917
|
+
z_val = (points[:, 1] - origin[1]) * height_factor
|
|
918
|
+
else:
|
|
919
|
+
z_val = np.repeat(distance * 1000, len(points))
|
|
920
|
+
y_val = (points[:, 0] - origin[0]) * width_factor
|
|
921
|
+
x_val = (points[:, 1] - origin[1]) * height_factor
|
|
922
|
+
return x_val, y_val, z_val
|
|
923
|
+
|
|
924
|
+
|
|
925
|
+
def delete_points_inside_eraser(points, ct, r):
|
|
926
|
+
x_min, y_min, x_max, y_max = ct[0] - r, ct[1] - r, ct[0] + r, ct[1] + r
|
|
927
|
+
x_bool = np.logical_and(points[:, 0] <= x_max, points[:, 0] >= x_min)
|
|
928
|
+
y_bool = np.logical_and(points[:, 1] <= y_max, points[:, 1] >= y_min)
|
|
929
|
+
chk_inds = np.where(np.logical_and(x_bool, y_bool))[0]
|
|
930
|
+
if len(chk_inds) == 0:
|
|
931
|
+
return None, None
|
|
932
|
+
chk_pnt = points[chk_inds]
|
|
933
|
+
dist = np.sum(np.power(chk_pnt - ct, 2), 1)
|
|
934
|
+
del_ind = np.where(dist < np.power(r, 2))[0]
|
|
935
|
+
if len(del_ind) == 0:
|
|
936
|
+
return None, None
|
|
937
|
+
real_del_ind = chk_inds[del_ind]
|
|
938
|
+
remain_inds = np.zeros(len(points)) < 1
|
|
939
|
+
remain_inds[real_del_ind] = False
|
|
940
|
+
remain_points = points[remain_inds]
|
|
941
|
+
return remain_points, real_del_ind
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
def interpolate_contour_points(points):
|
|
945
|
+
if not np.all(points[-1] == points[0]):
|
|
946
|
+
points[:, 0] = np.r_[points[:, 0], points[:, 0]]
|
|
947
|
+
points[:, 1] = np.r_[points[:, 1], points[:, 1]]
|
|
948
|
+
|
|
949
|
+
tck = splprep([points[:, 0], points[:, 1]], s=0, per=True)
|
|
950
|
+
|
|
951
|
+
xi, yi = splev(np.linspace(0, 1, 1000), tck[0])
|
|
952
|
+
return xi, yi
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
def create_vis_img(size, point_data, color, vis_type="p", closed=False):
|
|
956
|
+
if isinstance(point_data, list):
|
|
957
|
+
point_data = np.asarray(point_data).astype(int)
|
|
958
|
+
else:
|
|
959
|
+
point_data = point_data.astype(int)
|
|
960
|
+
img = np.zeros((size[0], size[1], 3), "uint8")
|
|
961
|
+
da_color = (int(color[0]), int(color[1]), int(color[2]))
|
|
962
|
+
if vis_type == "p":
|
|
963
|
+
for i in range(len(point_data)):
|
|
964
|
+
cv2.circle(
|
|
965
|
+
img,
|
|
966
|
+
(int(point_data[i][0]), int(point_data[i][1])),
|
|
967
|
+
radius=5,
|
|
968
|
+
color=da_color,
|
|
969
|
+
thickness=-1,
|
|
970
|
+
)
|
|
971
|
+
else:
|
|
972
|
+
if closed:
|
|
973
|
+
cv2.fillPoly(img, pts=[point_data], color=da_color)
|
|
974
|
+
else:
|
|
975
|
+
for i in range(len(point_data) - 1):
|
|
976
|
+
cv2.line(
|
|
977
|
+
img,
|
|
978
|
+
(int(point_data[i][0]), int(point_data[i][1])),
|
|
979
|
+
(int(point_data[i + 1][0]), int(point_data[i + 1][1])),
|
|
980
|
+
color=da_color,
|
|
981
|
+
thickness=8,
|
|
982
|
+
)
|
|
983
|
+
return img
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
def color_vis_img(img, color):
|
|
987
|
+
temp = np.zeros((img.shape[0], img.shape[1], 3), "uint8")
|
|
988
|
+
temp[img != 0, 0] = color[0]
|
|
989
|
+
temp[img != 0, 1] = color[1]
|
|
990
|
+
temp[img != 0, 2] = color[2]
|
|
991
|
+
return temp
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
def check_loaded_project(project_dict):
|
|
995
|
+
required_keys = {
|
|
996
|
+
"atlas_path",
|
|
997
|
+
"img_path",
|
|
998
|
+
"current_atlas",
|
|
999
|
+
"num_windows",
|
|
1000
|
+
"probe_settings",
|
|
1001
|
+
"probe_type",
|
|
1002
|
+
"np_onside",
|
|
1003
|
+
"processing_slice",
|
|
1004
|
+
"processing_img",
|
|
1005
|
+
"overlay_img",
|
|
1006
|
+
"atlas_control",
|
|
1007
|
+
"img_ctrl_data",
|
|
1008
|
+
"setting_data",
|
|
1009
|
+
"tool_data",
|
|
1010
|
+
"layer_data",
|
|
1011
|
+
"working_img_data",
|
|
1012
|
+
"working_atlas_data",
|
|
1013
|
+
"object_data",
|
|
1014
|
+
}
|
|
1015
|
+
# ``probe_type`` was present only in early project files.
|
|
1016
|
+
required_keys.discard("probe_type")
|
|
1017
|
+
return isinstance(project_dict, dict) and required_keys.issubset(project_dict)
|
|
1018
|
+
|
|
1019
|
+
|
|
1020
|
+
def check_bounding_contains(points, size):
|
|
1021
|
+
points = np.asarray(points)
|
|
1022
|
+
if points.ndim != 2 or points.shape[1] != 2 or len(points) == 0:
|
|
1023
|
+
return False
|
|
1024
|
+
return coordinates_in_bounds(points, (size[1], size[0]))
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
def obj_data_to_mesh3d(filename):
|
|
1028
|
+
vertices = []
|
|
1029
|
+
faces = []
|
|
1030
|
+
|
|
1031
|
+
with open(filename, "r") as objf:
|
|
1032
|
+
for line in objf:
|
|
1033
|
+
slist = line.split()
|
|
1034
|
+
if slist:
|
|
1035
|
+
if slist[0] == "v":
|
|
1036
|
+
vertex = np.array(slist[1:], dtype=float)
|
|
1037
|
+
vertices.append(vertex)
|
|
1038
|
+
elif slist[0] == "f":
|
|
1039
|
+
face = []
|
|
1040
|
+
for k in range(1, len(slist)):
|
|
1041
|
+
face.append(
|
|
1042
|
+
[int(s) for s in slist[k].replace("//", "/").split("/")]
|
|
1043
|
+
)
|
|
1044
|
+
if len(face) > 3: # triangulate the n-polyonal face, n>3
|
|
1045
|
+
faces.extend(
|
|
1046
|
+
[
|
|
1047
|
+
[face[0][0] - 1, face[k][0] - 1, face[k + 1][0] - 1]
|
|
1048
|
+
for k in range(1, len(face) - 1)
|
|
1049
|
+
]
|
|
1050
|
+
)
|
|
1051
|
+
else:
|
|
1052
|
+
faces.append([face[j][0] - 1 for j in range(len(face))])
|
|
1053
|
+
else:
|
|
1054
|
+
pass
|
|
1055
|
+
|
|
1056
|
+
return np.array(vertices), np.array(faces)
|
|
1057
|
+
|
|
1058
|
+
|
|
1059
|
+
def make_atlas_label_contour(atlas_folder, segmentation_data):
|
|
1060
|
+
sagital_contour_img = np.zeros(segmentation_data.shape, "i")
|
|
1061
|
+
coronal_contour_img = np.zeros(segmentation_data.shape, "i")
|
|
1062
|
+
horizontal_contour_img = np.zeros(segmentation_data.shape, "i")
|
|
1063
|
+
|
|
1064
|
+
# pre-process boundary
|
|
1065
|
+
for i in range(len(segmentation_data)):
|
|
1066
|
+
da_slice = segmentation_data[i, :, :].copy()
|
|
1067
|
+
contour_img = make_contour_img(da_slice)
|
|
1068
|
+
sagital_contour_img[i, :, :] = contour_img
|
|
1069
|
+
|
|
1070
|
+
for i in range(segmentation_data.shape[1]):
|
|
1071
|
+
da_slice = segmentation_data[:, i, :].copy()
|
|
1072
|
+
contour_img = make_contour_img(da_slice)
|
|
1073
|
+
coronal_contour_img[:, i, :] = contour_img
|
|
1074
|
+
|
|
1075
|
+
for i in range(segmentation_data.shape[2]):
|
|
1076
|
+
da_slice = segmentation_data[:, :, i].copy()
|
|
1077
|
+
contour_img = make_contour_img(da_slice)
|
|
1078
|
+
horizontal_contour_img[:, :, i] = contour_img
|
|
1079
|
+
|
|
1080
|
+
boundary = {
|
|
1081
|
+
"s_contour": sagital_contour_img,
|
|
1082
|
+
"c_contour": coronal_contour_img,
|
|
1083
|
+
"h_contour": horizontal_contour_img,
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
bnd = {"data": boundary}
|
|
1087
|
+
|
|
1088
|
+
outfile_ct = open(os.path.join(atlas_folder, "contour_pre_made.pkl"), "wb")
|
|
1089
|
+
pickle.dump(bnd, outfile_ct)
|
|
1090
|
+
outfile_ct.close()
|
|
1091
|
+
|
|
1092
|
+
return boundary
|
|
1093
|
+
|
|
1094
|
+
|
|
1095
|
+
def get_angle_two_vector(vec1, vec2):
|
|
1096
|
+
"""
|
|
1097
|
+
in 2d
|
|
1098
|
+
:param vec1:
|
|
1099
|
+
:param vec2:
|
|
1100
|
+
:return:
|
|
1101
|
+
"""
|
|
1102
|
+
|
|
1103
|
+
vec = np.array([-vec2[1], vec2[0]])
|
|
1104
|
+
b_coord = np.dot(vec1, vec2)
|
|
1105
|
+
p_coord = np.dot(vec1, vec)
|
|
1106
|
+
da_ang = np.arctan2(p_coord, b_coord)
|
|
1107
|
+
|
|
1108
|
+
return da_ang
|
|
1109
|
+
|
|
1110
|
+
|
|
1111
|
+
def rotate_base_points(data, base_loc):
|
|
1112
|
+
temp = np.stack([base_loc, np.repeat(0, len(base_loc))], axis=1)
|
|
1113
|
+
vec1 = data[1] - data[0]
|
|
1114
|
+
vec2 = np.array([0, 1])
|
|
1115
|
+
ang = get_angle_two_vector(vec1, vec2)
|
|
1116
|
+
rotm = np.array([[np.cos(ang), -np.sin(ang)], [np.sin(ang), np.cos(ang)]])
|
|
1117
|
+
base_pnt = np.dot(rotm, temp.T).T
|
|
1118
|
+
start_pnt = base_pnt + data[0]
|
|
1119
|
+
end_pnt = base_pnt + data[1]
|
|
1120
|
+
return start_pnt, end_pnt
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
def get_cell_count(cell_layer_index):
|
|
1124
|
+
cell_count = [0 for _ in range(5)]
|
|
1125
|
+
cell_layer_index = np.ravel(cell_layer_index)
|
|
1126
|
+
for i in range(5):
|
|
1127
|
+
cell_count[i] = np.sum(cell_layer_index == i)
|
|
1128
|
+
return cell_count
|
|
1129
|
+
|
|
1130
|
+
|
|
1131
|
+
def load_point_data(data_file_path):
|
|
1132
|
+
file_basename = os.path.basename(data_file_path)
|
|
1133
|
+
file_name, file_ext = os.path.splitext(file_basename)
|
|
1134
|
+
msg = None
|
|
1135
|
+
data = None
|
|
1136
|
+
try:
|
|
1137
|
+
if file_ext == ".npy":
|
|
1138
|
+
data = np.load(data_file_path, allow_pickle=False)
|
|
1139
|
+
elif file_ext == ".pkl":
|
|
1140
|
+
data, msg = load_driftlessmap_file(data_file_path)
|
|
1141
|
+
if msg is not None:
|
|
1142
|
+
return data, msg
|
|
1143
|
+
except (
|
|
1144
|
+
IOError,
|
|
1145
|
+
OSError,
|
|
1146
|
+
ValueError,
|
|
1147
|
+
KeyError,
|
|
1148
|
+
IndexError,
|
|
1149
|
+
pickle.PickleError,
|
|
1150
|
+
pickle.UnpicklingError,
|
|
1151
|
+
):
|
|
1152
|
+
msg = "Can not open atlas axis information file, please check the Tutorial on GitHub."
|
|
1153
|
+
return data, msg
|
|
1154
|
+
|
|
1155
|
+
if not isinstance(data, np.ndarray):
|
|
1156
|
+
msg = "Data is not numpy ndarray, please check the Tutorial on GitHub."
|
|
1157
|
+
return data, msg
|
|
1158
|
+
|
|
1159
|
+
data_shape = data.shape
|
|
1160
|
+
if len(data_shape) != 2:
|
|
1161
|
+
msg = "Data has wrong size, please check the Tutorial on GitHub."
|
|
1162
|
+
return data, msg
|
|
1163
|
+
|
|
1164
|
+
if data_shape[1] != 3:
|
|
1165
|
+
msg = "Data has wrong size, please check the Tutorial on GitHub."
|
|
1166
|
+
return data, msg
|
|
1167
|
+
|
|
1168
|
+
return data, msg
|