batoolset 0.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.
- batoolset/GUI/__init__.py +0 -0
- batoolset/GUI/list_gui.py +513 -0
- batoolset/GUI/multi_image_display.py +989 -0
- batoolset/GUI/open.py +325 -0
- batoolset/GUI/overlay_hints.py +45 -0
- batoolset/GUI/paint2.py +1345 -0
- batoolset/GUI/scrollablepaint.py +1152 -0
- batoolset/IJ_ROIs/__init__.py +0 -0
- batoolset/IJ_ROIs/tools.py +40 -0
- batoolset/PATH/__init__.py +0 -0
- batoolset/PATH/tools.py +79 -0
- batoolset/SQLite_tools/__init__.py +0 -0
- batoolset/SQLite_tools/tools.py +840 -0
- batoolset/__init__.py +0 -0
- batoolset/binary/__init__.py +0 -0
- batoolset/binary/tools.py +123 -0
- batoolset/binarytools/__init__.py +0 -0
- batoolset/binarytools/cell_center_detector.py +290 -0
- batoolset/clipboard_tools/__init__.py +0 -0
- batoolset/clipboard_tools/tools.py +7 -0
- batoolset/colors/__init__.py +0 -0
- batoolset/colors/colorgen.py +193 -0
- batoolset/colors/tools.py +22 -0
- batoolset/command_line/__init__.py +0 -0
- batoolset/command_line/tools.py +18 -0
- batoolset/dialogs/__init__.py +0 -0
- batoolset/dialogs/opensave.py +228 -0
- batoolset/dicts/__init__.py +0 -0
- batoolset/dicts/tools.py +299 -0
- batoolset/dims/__init__.py +0 -0
- batoolset/dims/tools.py +83 -0
- batoolset/draw/__init__.py +0 -0
- batoolset/draw/shapes/Position.py +183 -0
- batoolset/draw/shapes/__init__.py +0 -0
- batoolset/draw/shapes/automated_alignment_drawing_refactored.py +346 -0
- batoolset/draw/shapes/circle2d.py +99 -0
- batoolset/draw/shapes/compute_optimal_size_all_merged.py +317 -0
- batoolset/draw/shapes/ellipse2d.py +336 -0
- batoolset/draw/shapes/freehand2d.py +235 -0
- batoolset/draw/shapes/group.py +1830 -0
- batoolset/draw/shapes/image2d.py +2469 -0
- batoolset/draw/shapes/line2d.py +575 -0
- batoolset/draw/shapes/point2d.py +257 -0
- batoolset/draw/shapes/polygon2d.py +357 -0
- batoolset/draw/shapes/polyline2d.py +235 -0
- batoolset/draw/shapes/rect2d.py +388 -0
- batoolset/draw/shapes/rectangle2d.py +601 -0
- batoolset/draw/shapes/scalebar.py +304 -0
- batoolset/draw/shapes/serializablefont.py +126 -0
- batoolset/draw/shapes/serializableguiparams.py +10 -0
- batoolset/draw/shapes/square2d.py +103 -0
- batoolset/draw/shapes/textorientation.py +45 -0
- batoolset/draw/shapes/tools.py +467 -0
- batoolset/draw/shapes/transform2D.py +350 -0
- batoolset/draw/shapes/txt2d.py +550 -0
- batoolset/draw/widgets/__init__.py +0 -0
- batoolset/draw/widgets/col.py +343 -0
- batoolset/draw/widgets/image_group.py +248 -0
- batoolset/draw/widgets/image_organizer.py +96 -0
- batoolset/draw/widgets/paint.py +184 -0
- batoolset/draw/widgets/vectorial.py +257 -0
- batoolset/figure/__init__.py +0 -0
- batoolset/figure/alignment.py +814 -0
- batoolset/figure/column.py +1117 -0
- batoolset/figure/fig_tools.py +285 -0
- batoolset/figure/minimal_debugger_scale_etc.py +139 -0
- batoolset/figure/panel.py +697 -0
- batoolset/figure/row.py +852 -0
- batoolset/figure/user_selection.py +287 -0
- batoolset/files/__init__.py +0 -0
- batoolset/files/tools.py +1321 -0
- batoolset/images/__init__.py +0 -0
- batoolset/images/tools.py +81 -0
- batoolset/img.py +5216 -0
- batoolset/linux/__init__.py +0 -0
- batoolset/linux/tools.py +72 -0
- batoolset/lists/__init__.py +0 -0
- batoolset/lists/tools.py +436 -0
- batoolset/luts/__init__.py +0 -0
- batoolset/luts/lut_minimal_test.py +1207 -0
- batoolset/matplolib/__init__.py +0 -0
- batoolset/matplolib/tools.py +44 -0
- batoolset/np_tools/__init__.py +0 -0
- batoolset/np_tools/tools.py +252 -0
- batoolset/np_tools/trash.py +15 -0
- batoolset/pandas_tools/__init__.py +0 -0
- batoolset/pandas_tools/tools.py +880 -0
- batoolset/partials/__init__.py +0 -0
- batoolset/partials/tools.py +83 -0
- batoolset/plot_tools/__init__.py +0 -0
- batoolset/plot_tools/tools.py +70 -0
- batoolset/pyqt/__init__.py +0 -0
- batoolset/pyqt/tools.py +691 -0
- batoolset/re_tools/__init__.py +0 -0
- batoolset/re_tools/tools.py +35 -0
- batoolset/serialization/__init__.py +0 -0
- batoolset/serialization/tools.py +1192 -0
- batoolset/sets/__init__.py +0 -0
- batoolset/sets/tools.py +109 -0
- batoolset/settings/__init__.py +0 -0
- batoolset/settings/global_settings.py +134 -0
- batoolset/strings/__init__.py +0 -0
- batoolset/strings/tools.py +225 -0
- batoolset/ta/__init__.py +0 -0
- batoolset/ta/database/__init__.py +0 -0
- batoolset/ta/database/advanced_sql_plotter.py +1170 -0
- batoolset/ta/database/my_qt_table.py +79 -0
- batoolset/ta/database/preview_and_edit_sqlite_db.py +405 -0
- batoolset/ta/database/sql.py +2141 -0
- batoolset/ta/database/sql_column_name_dialog.py +122 -0
- batoolset/ta/measurements/TAmeasures.py +2226 -0
- batoolset/ta/measurements/__init__.py +0 -0
- batoolset/ta/measurements/measurements3D/__init__.py +0 -0
- batoolset/ta/measurements/measurements3D/get_point_on_surface_if_centroid_is_bad.py +175 -0
- batoolset/ta/measurements/measurements3D/height_map_to_projection.py +82 -0
- batoolset/ta/measurements/measurements3D/measures3D.py +208 -0
- batoolset/ta/measurements/measurements3D/triangulate.py +331 -0
- batoolset/ta/measurements/nematic.py +562 -0
- batoolset/ta/measurements/nematic_measurements.py +107 -0
- batoolset/ta/segmentation/__init__.py +0 -0
- batoolset/ta/segmentation/neo_wshed.py +314 -0
- batoolset/ta/selections/__init__.py +0 -0
- batoolset/ta/selections/selection.py +329 -0
- batoolset/ta/tracking/__init__.py +0 -0
- batoolset/ta/tracking/last_tracking_based_on_matching_or_on_translation_from_mermaid_warp.py +653 -0
- batoolset/ta/tracking/local_to_track_correspondance.py +138 -0
- batoolset/ta/tracking/rapid_detection_of_vertices.py +517 -0
- batoolset/ta/tracking/registration.py +108 -0
- batoolset/ta/tracking/swap_detector_and_fixer.py +296 -0
- batoolset/ta/tracking/track_correction.py +238 -0
- batoolset/ta/tracking/tracking_error_detector_and_fixer.py +3099 -0
- batoolset/ta/tracking/tracking_yet_another_approach_pyramidal_registration_n_neo_swapping_correction.py +725 -0
- batoolset/ta/utils/TA_tools.py +43 -0
- batoolset/ta/utils/__init__.py +0 -0
- batoolset/ta/utils/rps_tools.py +1783 -0
- batoolset/tests/__init__.py +0 -0
- batoolset/tests/rps_tools.py +51 -0
- batoolset/tests/tools.py +10 -0
- batoolset/tools/__init__.py +0 -0
- batoolset/tools/early_stopper_class.py +9 -0
- batoolset/tools/guided_data_recoverer.py +110 -0
- batoolset/tools/logger.py +100 -0
- batoolset/tools/mytimer.py +31 -0
- batoolset/tools/prompt_color.py +160 -0
- batoolset/tools/qthandler.py +118 -0
- batoolset/uitools/__init__.py +0 -0
- batoolset/uitools/blinker.py +56 -0
- batoolset/unsafe/__init__.py +0 -0
- batoolset/unsafe/tools.py +115 -0
- batoolset/utils/__init__.py +0 -0
- batoolset/utils/commontools.py +158 -0
- batoolset/utils/loadlist.py +728 -0
- batoolset/version.py +10 -0
- batoolset/xml/__init__.py +0 -0
- batoolset/xml/tools.py +65 -0
- batoolset/zip_tools/__init__.py +0 -0
- batoolset/zip_tools/tools.py +76 -0
- batoolset-0.1.0.dist-info/LICENSE +24 -0
- batoolset-0.1.0.dist-info/METADATA +45 -0
- batoolset-0.1.0.dist-info/RECORD +162 -0
- batoolset-0.1.0.dist-info/WHEEL +5 -0
- batoolset-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,725 @@
|
|
|
1
|
+
# maybe detect those big shifts and see whether I could find a better solution to handle them ???
|
|
2
|
+
# marche mais qd meme big big à l'interface entre les duex tissus
|
|
3
|
+
|
|
4
|
+
# pb --> par moment il y a des shifts enormes de tonnes de cellules --> peut etre faut Il un truc plus mieux
|
|
5
|
+
|
|
6
|
+
# ce code est vraiment excellent maintenant --> a good starting point then get dividing cells --> mais un peu lent mais pourrait accélerer en limitant la recherche aux cellules les plus proches (anyway long swappings do not exist)
|
|
7
|
+
# then find under and oversegmented cells and I'll be done...
|
|
8
|
+
# could maybe try to speed up by computing overlap and calculating local translation of matching pairs
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# TODO do a division code --> detect new cell in an image compared to the previous and see if cell is present in next maybe then the sum of neighbors should be the closest to the parent of the cell --> find parent
|
|
12
|
+
# à tester --> devrait pas être difficile
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# just two cells flipped --> is there any fix
|
|
16
|
+
# do code to dissect stuff
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# nb le regular multiswap est meilleur --> mais pkoi ??--> moins de swapping
|
|
20
|
+
# really excell
|
|
21
|
+
|
|
22
|
+
# that seems to work miraculously well -->just try a comparison to the other method but at least it's much smarter
|
|
23
|
+
# 10 secs per image
|
|
24
|
+
|
|
25
|
+
# I can easily add
|
|
26
|
+
# this is really very good but can it be improved and made faster by reducing the cells to be checked and applying the dual assignment
|
|
27
|
+
# qd même 7h de processing c long, but on the other hand this is not human time so we don't CARE
|
|
28
|
+
# it seems to work and even looks faster now
|
|
29
|
+
|
|
30
|
+
from batoolset.img import RGB_to_int24, int24_to_RGB
|
|
31
|
+
from timeit import default_timer as timer
|
|
32
|
+
import traceback
|
|
33
|
+
import numpy as np
|
|
34
|
+
from skimage.measure import label
|
|
35
|
+
from batoolset.img import Img
|
|
36
|
+
from batoolset.colors.colorgen import get_forbidden_colors_int24
|
|
37
|
+
from batoolset.ta.measurements.measurements3D.get_point_on_surface_if_centroid_is_bad import point_on_surface
|
|
38
|
+
from batoolset.ta.tracking.registration import get_pyramidal_registration
|
|
39
|
+
from batoolset.files.tools import assign_random_ID_to_missing_cells, first_image_tracking, get_list_of_files, \
|
|
40
|
+
get_input_files_and_output_folders, get_TA_file, smart_name_parser
|
|
41
|
+
from skimage.measure import regionprops
|
|
42
|
+
from skimage import measure
|
|
43
|
+
|
|
44
|
+
# parameters
|
|
45
|
+
__DEBUG__ = False
|
|
46
|
+
|
|
47
|
+
# gain correlates with depth!!!
|
|
48
|
+
# KEEP for the parameter below if cells are big one can decrease it for some images it does make a big difference!!! --> TODO SET THIS AS A
|
|
49
|
+
from batoolset.ta.tracking.tracking_error_detector_and_fixer import find_vertices, associate_cell_to_its_neighbors2, \
|
|
50
|
+
associate_cells_to_neighbors_ID_in_dict, compute_neighbor_score, optimize_score, get_cells_in_image_n_fisrt_pixel, \
|
|
51
|
+
map_track_id_to_label, apply_color_to_labels
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# PYRAMIDAL_DEPTH = 3 # 2 #3 # computing pyramidal translation can be time consuming and the gain vs time cost is not always worth it
|
|
55
|
+
# MAX_ITER = 15 # max nb of optimizatuion loops):
|
|
56
|
+
from batoolset.tools.early_stopper_class import early_stop
|
|
57
|
+
# from personal.pyTA.tsts.new_registration_code import criss_cross_reg
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def track_cells_dynamic_tissue(path, channel=None, PYRAMIDAL_DEPTH=3, MAX_ITER=15, progress_callback=None):
|
|
61
|
+
start_all = timer()
|
|
62
|
+
|
|
63
|
+
# PYRAMIDAL_DEPTH = 3 # 2 #3 # computing pyramidal translation can be time consuming and the gain vs time cost is not always worth it
|
|
64
|
+
|
|
65
|
+
# the swapping correction is so good that it does not require deep (hence slow pyramid) to work!!!
|
|
66
|
+
|
|
67
|
+
# still some errors
|
|
68
|
+
# why
|
|
69
|
+
|
|
70
|
+
# PYRAMIDAL_SKIP=1 #0 # skip some division step
|
|
71
|
+
# MIN_CUT_OFF_SWAPPING = None # only swap/assign cells if they have a high score/high match
|
|
72
|
+
# swap_fix_recursions = 3
|
|
73
|
+
seed = 1 # always start tracking with same seed to have roughly the same color
|
|
74
|
+
assigned_ids = get_forbidden_colors_int24()
|
|
75
|
+
|
|
76
|
+
# TODO add forbidden colors to it
|
|
77
|
+
images_to_analyze = get_list_of_files(path)
|
|
78
|
+
|
|
79
|
+
# print(range(len(images_to_analyze) - 1))
|
|
80
|
+
|
|
81
|
+
# if list is empty need enter at least once
|
|
82
|
+
# print(range(len(images_to_analyze) - 1))
|
|
83
|
+
|
|
84
|
+
# for cases that contain just one image --> this is a code duplication --> maybe try to get rid of it someday
|
|
85
|
+
if len(images_to_analyze)==1:
|
|
86
|
+
# file_path_0, file_path_1, filename0_without_ext, filename1_without_ext = get_input_files_and_output_folders(
|
|
87
|
+
# images_to_analyze, 0)
|
|
88
|
+
filename0_without_ext = smart_name_parser(images_to_analyze[0], 'full_no_ext')
|
|
89
|
+
mask_t0 = Img(get_TA_file(filename0_without_ext, 'handCorrection.tif'))
|
|
90
|
+
if mask_t0.has_c():
|
|
91
|
+
mask_t0 = mask_t0[..., 0]
|
|
92
|
+
labels_t0 = measure.label(mask_t0, connectivity=1, background=255) # FOUR_CONNECTED
|
|
93
|
+
# if l == 0:
|
|
94
|
+
tracked_cells_t0 = first_image_tracking(mask_t0, labels_t0, assigned_ids=assigned_ids, seed=seed)
|
|
95
|
+
Img(int24_to_RGB(tracked_cells_t0), dimensions='hwc').save(
|
|
96
|
+
get_TA_file(filename0_without_ext, 'tracked_cells_resized.tif'),
|
|
97
|
+
mode='raw') # should work --> DO the job
|
|
98
|
+
return
|
|
99
|
+
|
|
100
|
+
for l in range(len(images_to_analyze) - 1):
|
|
101
|
+
try:
|
|
102
|
+
if early_stop.stop == True:
|
|
103
|
+
return
|
|
104
|
+
if progress_callback is not None:
|
|
105
|
+
progress_callback.emit(int((l * 100) / len(images_to_analyze)))
|
|
106
|
+
else:
|
|
107
|
+
print(str((l * 100) / len(images_to_analyze)) + '%')
|
|
108
|
+
except:
|
|
109
|
+
pass
|
|
110
|
+
|
|
111
|
+
start_loop = timer()
|
|
112
|
+
|
|
113
|
+
file_path_0, file_path_1, filename0_without_ext, filename1_without_ext = get_input_files_and_output_folders(
|
|
114
|
+
images_to_analyze, l)
|
|
115
|
+
|
|
116
|
+
orig_t0 = Img(file_path_0) # [455:455+122,544:544+127] #[384:512,512:640]
|
|
117
|
+
orig_t1 = Img(file_path_1) # [455:455+122,544:544+127] #[384:512,512:640]
|
|
118
|
+
|
|
119
|
+
if channel is not None:
|
|
120
|
+
# we reensure image has channel otherwise skip
|
|
121
|
+
if len(orig_t0.shape) > 2:
|
|
122
|
+
orig_t0 = orig_t0[..., channel]
|
|
123
|
+
if len(orig_t1.shape) > 2:
|
|
124
|
+
orig_t1 = orig_t1[..., channel]
|
|
125
|
+
|
|
126
|
+
# gros bug qq part je pense
|
|
127
|
+
# ça marche --> trop cool
|
|
128
|
+
print('intermediate time before pyramidal registration', timer() - start_loop)
|
|
129
|
+
|
|
130
|
+
# in fact this is really the pyramidal reg that is so slow now --> try speed it up
|
|
131
|
+
|
|
132
|
+
# reducing depth makes a huge gain of time and the gain is limited --> maybe offer depth as a parameters
|
|
133
|
+
translation_matrix = get_pyramidal_registration(orig_t0, orig_t1, depth=PYRAMIDAL_DEPTH,threshold_translation=20) # , threshold_translation=20 , pyramidal_skip=PYRAMIDAL_SKIP
|
|
134
|
+
# translation_matrix = criss_cross_reg(orig_t0, orig_t1) # , threshold_translation=20 , pyramidal_skip=PYRAMIDAL_SKIP # marche mieux mais pas encore ça --> comment comparer et trouver scores # can I exclude no specific objects from tracking --> so that it is working better
|
|
135
|
+
print('intermediate time after pyramidal registration', timer() - start_loop)
|
|
136
|
+
|
|
137
|
+
Img(translation_matrix).save(get_TA_file(filename0_without_ext, 'translation_matrix.tif'))
|
|
138
|
+
|
|
139
|
+
mask_t0 = Img(get_TA_file(filename0_without_ext, 'handCorrection.tif'))
|
|
140
|
+
|
|
141
|
+
if mask_t0.has_c():
|
|
142
|
+
mask_t0 = mask_t0[..., 0]
|
|
143
|
+
labels_t0 = measure.label(mask_t0, connectivity=1, background=255) # FOUR_CONNECTED
|
|
144
|
+
|
|
145
|
+
if __DEBUG__:
|
|
146
|
+
print(mask_t0.shape, get_TA_file(filename0_without_ext, 'handCorrection.tif'))
|
|
147
|
+
|
|
148
|
+
mask_t1 = Img(get_TA_file(filename1_without_ext, 'handCorrection.tif'))
|
|
149
|
+
if mask_t1.has_c():
|
|
150
|
+
mask_t1 = mask_t1[..., 0]
|
|
151
|
+
if l == 0:
|
|
152
|
+
tracked_cells_t0 = first_image_tracking(mask_t0, labels_t0, assigned_ids=assigned_ids, seed=seed)
|
|
153
|
+
Img(int24_to_RGB(tracked_cells_t0), dimensions='hwc').save(
|
|
154
|
+
get_TA_file(filename0_without_ext, 'tracked_cells_resized.tif'),
|
|
155
|
+
mode='raw') # should work --> DO the job
|
|
156
|
+
else:
|
|
157
|
+
tracked_cells_t0 = RGB_to_int24(Img(get_TA_file(filename0_without_ext, 'tracked_cells_resized.tif')))
|
|
158
|
+
|
|
159
|
+
if __DEBUG__:
|
|
160
|
+
print(mask_t0.shape)
|
|
161
|
+
print(mask_t1.shape)
|
|
162
|
+
|
|
163
|
+
height = mask_t0.shape[0]
|
|
164
|
+
width = mask_t0.shape[1]
|
|
165
|
+
|
|
166
|
+
centroids_t0 = []
|
|
167
|
+
|
|
168
|
+
for iii, region in enumerate(regionprops(labels_t0)):
|
|
169
|
+
# take regions with large enough areas
|
|
170
|
+
# centroid = region.centroid
|
|
171
|
+
centroid = point_on_surface(region, labels_t0)
|
|
172
|
+
|
|
173
|
+
# print(labels_t0[int(centroid[0]), int(centroid[0])],iii+1)
|
|
174
|
+
|
|
175
|
+
centroids_t0.append(centroid)
|
|
176
|
+
|
|
177
|
+
# KEEP NB BE CAREFUL SOMEHOW THE CODE BELOW CREATES A LOT MORE SWAPPING ALTHOUGH IT SHOULD NOT --> NO CLUE WHY BUT BAD
|
|
178
|
+
# TODO maybe if cell is big I should really take the center of area even if by luck the value falls in it can I identify big cells based on area ???
|
|
179
|
+
# maybe it's really at the matching level that it becomes the most interesting this stuff
|
|
180
|
+
# if labels_t0[int(centroid[0]), int(centroid[0])] == iii + 1:
|
|
181
|
+
# centroids_t0.append(centroid)
|
|
182
|
+
# else:
|
|
183
|
+
# print('replacing centroid by center of area because of mismatch')
|
|
184
|
+
# # replace centroid by center of area to always be in the shape no matter how its shape looks like
|
|
185
|
+
# centroids_t0.append((region.coords[int(region.area / 2)][0], region.coords[int(region.area / 2)][
|
|
186
|
+
# 1])) # cree des erreurs --> take centroid except if mismatch
|
|
187
|
+
|
|
188
|
+
# print(region.centroid)
|
|
189
|
+
|
|
190
|
+
# points1 = get_ordered_list(points1,0,0)
|
|
191
|
+
centroids_t0 = np.array(centroids_t0) # parfait
|
|
192
|
+
|
|
193
|
+
labels_t1 = measure.label(mask_t1, connectivity=1, background=255) # FOUR_CONNECTED
|
|
194
|
+
if __DEBUG__:
|
|
195
|
+
print(labels_t1.shape)
|
|
196
|
+
|
|
197
|
+
t0_cells_n_vertices = {}
|
|
198
|
+
t1_cells_n_vertices = {}
|
|
199
|
+
|
|
200
|
+
# NB if I wanna use that then I need 255 to be a forbidden color everywhere otherwise a pure blue cell will give an error --> see how I can do that otherwise really need invert but in a smart way --> think about it
|
|
201
|
+
# could also get a mapping --> gain of time maybe... --> such as a mapping to the coords
|
|
202
|
+
centroids_t1 = []
|
|
203
|
+
for iii, region in enumerate(regionprops(labels_t1)):
|
|
204
|
+
# take regions with large enough areas
|
|
205
|
+
# centroid = region.centroid
|
|
206
|
+
centroid = point_on_surface(region, labels_t1)
|
|
207
|
+
centroids_t1.append(centroid)
|
|
208
|
+
# if labels_t1[int(centroid[0]), int(centroid[0])] == iii + 1:
|
|
209
|
+
# centroids_t1.append(centroid)
|
|
210
|
+
# else:
|
|
211
|
+
# print('replacing centroid by center of area because of mismatch')
|
|
212
|
+
# # replace centroid by center of area to always be in the shape no matter how its shape looks like
|
|
213
|
+
# centroids_t1.append((region.coords[int(region.area / 2)][0], region.coords[int(region.area / 2)][1]))
|
|
214
|
+
|
|
215
|
+
centroids_t1 = np.array(centroids_t1)
|
|
216
|
+
|
|
217
|
+
tile_width = 64 # 256 #128
|
|
218
|
+
tile_height = 64 # 256 #128
|
|
219
|
+
|
|
220
|
+
# nb sometimes further cropping cause the registration issue and sometimes it helps
|
|
221
|
+
# if I could crop further I may be able to perform better --> see how I can do that though
|
|
222
|
+
|
|
223
|
+
# otherwise could simply do a swap and reassign it...
|
|
224
|
+
rps_t1_mask = regionprops(labels_t1)
|
|
225
|
+
|
|
226
|
+
# TODO --> do a table matching pair of id
|
|
227
|
+
|
|
228
|
+
matched_cells = {}
|
|
229
|
+
|
|
230
|
+
matched_cells_in_t1 = []
|
|
231
|
+
# matched_cells_in_t1_correspondance = {}
|
|
232
|
+
|
|
233
|
+
# TODO REMOVE just raw alignment to try to see if post process error
|
|
234
|
+
# tracks_trash = np.zeros((*mask_t1.shape, 3), dtype=np.uint8)
|
|
235
|
+
|
|
236
|
+
#
|
|
237
|
+
|
|
238
|
+
tracks = np.zeros_like(mask_t1, dtype=np.uint32)
|
|
239
|
+
for centroid_t0 in centroids_t0:
|
|
240
|
+
|
|
241
|
+
t0 = translation_matrix[int(centroid_t0[0]), int(centroid_t0[1]), 0]
|
|
242
|
+
t1 = translation_matrix[int(centroid_t0[0]), int(centroid_t0[1]), 1]
|
|
243
|
+
|
|
244
|
+
try:
|
|
245
|
+
# this is ok so far but could take the center of the area instead!!!
|
|
246
|
+
cell_id_in_t0 = tracked_cells_t0[
|
|
247
|
+
int(centroid_t0[0]), int(centroid_t0[1])]
|
|
248
|
+
|
|
249
|
+
translation_corrected_y = int(centroid_t0[0] + t0)
|
|
250
|
+
translation_corrected_x = int(centroid_t0[1] + t1)
|
|
251
|
+
if not (
|
|
252
|
+
translation_corrected_y < height and translation_corrected_y >= 0 and translation_corrected_x < width and translation_corrected_x >= 0):
|
|
253
|
+
# out of bounds --> continue
|
|
254
|
+
continue
|
|
255
|
+
possible_matching_cell = labels_t1[translation_corrected_y, translation_corrected_x]
|
|
256
|
+
|
|
257
|
+
if possible_matching_cell > 0: # could check if was already matched
|
|
258
|
+
|
|
259
|
+
# in fact I could allow it and check doublons later
|
|
260
|
+
if possible_matching_cell in matched_cells_in_t1:
|
|
261
|
+
# best would be to keep the best of the two --> the one that preserves the best vector maybe
|
|
262
|
+
# en effet il y a des mismatch et des dupes mais pas une bonne idee de les enlever car ils sont pas bons
|
|
263
|
+
# ideally should keep the biggest cell here instead
|
|
264
|
+
# if __DEBUG__:
|
|
265
|
+
# print('duplicated cell already matched', matched_cells_in_t1_correspondance[possible_matching_cell],
|
|
266
|
+
# '-->', labels_t0[int(centroid_t0[0]), int(
|
|
267
|
+
# centroid_t0[1])], 'color',cell_id_in_t0) # 107 duplicates --> but not real dupes cause same cell I bet
|
|
268
|
+
continue
|
|
269
|
+
|
|
270
|
+
if __DEBUG__:
|
|
271
|
+
print('assigned id-->', cell_id_in_t0)
|
|
272
|
+
|
|
273
|
+
# bug of assigning a white cell as a label --> need fix but
|
|
274
|
+
if cell_id_in_t0 == 0xFFFFFF:
|
|
275
|
+
if __DEBUG__:
|
|
276
|
+
print(
|
|
277
|
+
'error assigning white --> continuing') # TODO maybe fix this some day to make sure we try to reassign the cell afterwards
|
|
278
|
+
continue
|
|
279
|
+
# import sys
|
|
280
|
+
# sys.exit(0)
|
|
281
|
+
|
|
282
|
+
tracks[labels_t1 == possible_matching_cell] = cell_id_in_t0
|
|
283
|
+
matched_cells_in_t1.append(possible_matching_cell)
|
|
284
|
+
|
|
285
|
+
if __DEBUG__:
|
|
286
|
+
if labels_t0[int(centroid_t0[0]), int(centroid_t0[1])] in matched_cells:
|
|
287
|
+
print('duplicated cell', labels_t0[int(centroid_t0[0]), int(centroid_t0[1])],
|
|
288
|
+
matched_cells[labels_t0[int(centroid_t0[0]), int(centroid_t0[1])]], '-->',
|
|
289
|
+
possible_matching_cell)
|
|
290
|
+
|
|
291
|
+
# TODO check DO I REALLY NEED THAT ANYMORE ???
|
|
292
|
+
matched_cells[labels_t0[int(centroid_t0[0]), int(centroid_t0[1])]] = possible_matching_cell
|
|
293
|
+
# matched_cells_in_t1_correspondance[possible_matching_cell] = labels_t0[ int(centroid_t0[0]), int(centroid_t0[1])]
|
|
294
|
+
except:
|
|
295
|
+
# assume cell is out of bonds --> ignore ot could correct axis
|
|
296
|
+
traceback.print_exc()
|
|
297
|
+
|
|
298
|
+
if __DEBUG__:
|
|
299
|
+
print('all_matched_cells', matched_cells) # all is ok
|
|
300
|
+
|
|
301
|
+
# very good in fact
|
|
302
|
+
|
|
303
|
+
# missing_cells_t1 = []
|
|
304
|
+
matched_cells_ids = []
|
|
305
|
+
|
|
306
|
+
for iii, region in enumerate(rps_t1_mask):
|
|
307
|
+
color = tracks[region.coords[0][0], region.coords[0][1]]
|
|
308
|
+
if color == 0:
|
|
309
|
+
# missing_cells_t1.append(iii)
|
|
310
|
+
pass
|
|
311
|
+
else:
|
|
312
|
+
matched_cells_ids.append(color)
|
|
313
|
+
|
|
314
|
+
if __DEBUG__:
|
|
315
|
+
# print('missing_cells_t1', len(missing_cells_t1), '/', len(rps_t1_mask), missing_cells_t1)
|
|
316
|
+
print('matched_cells_ids', len(matched_cells_ids), '/', len(rps_t1_mask), matched_cells_ids)
|
|
317
|
+
|
|
318
|
+
labels_tracking_t0 = measure.label(tracked_cells_t0, connectivity=1, background=0xFFFFFF)
|
|
319
|
+
|
|
320
|
+
# plt.imshow(tracked_cells_t0[...,0], cmap='gray') #
|
|
321
|
+
# plt.show()
|
|
322
|
+
|
|
323
|
+
rps_t0 = regionprops(labels_tracking_t0)
|
|
324
|
+
|
|
325
|
+
unmatched_cells_in_t0 = []
|
|
326
|
+
# all ok so why bug there
|
|
327
|
+
for iii, region in enumerate(rps_t0):
|
|
328
|
+
# there is a bug there and I don't get it
|
|
329
|
+
color = tracked_cells_t0[region.coords[0][0], region.coords[0][1]]
|
|
330
|
+
# print(color) # why always the same color -->
|
|
331
|
+
if color not in matched_cells_ids: # why bug --> is it due to hash error
|
|
332
|
+
unmatched_cells_in_t0.append(iii)
|
|
333
|
+
|
|
334
|
+
if __DEBUG__:
|
|
335
|
+
print('missing_cells_t0', len(unmatched_cells_in_t0), '/', len(rps_t0), unmatched_cells_in_t0)
|
|
336
|
+
|
|
337
|
+
# I have already added them --> REDUNDANT AND I AM NOT EVEB SURE I USE THE MATCHING PAIRS --> REMOVE THEM no it's ok
|
|
338
|
+
def associate_cell_id_to_idx(rps, image):
|
|
339
|
+
cell_id_n_ips = {}
|
|
340
|
+
for iii, region in enumerate(rps):
|
|
341
|
+
cell_id = image[region.coords[0][0], region.coords[0][1]]
|
|
342
|
+
cell_id_n_ips[cell_id] = iii
|
|
343
|
+
return cell_id_n_ips
|
|
344
|
+
|
|
345
|
+
# cell_id_n_ips_t0 = associate_cell_id_to_idx(rps_t0, tracked_cells_t0)
|
|
346
|
+
# cell_id_n_ips_t1 = associate_cell_id_to_idx(rps_t1_mask, tracks)
|
|
347
|
+
|
|
348
|
+
# check pixels by neighborhood
|
|
349
|
+
# if several cells are missing together --> try to match them together --> best match maybe --> faut vraiment essayer
|
|
350
|
+
# essayer de faire mieux
|
|
351
|
+
|
|
352
|
+
# MEGA TODO TRY REIDENTIFY MISSING CELLS BASED ON NEIGHBORHOOD MAYBE
|
|
353
|
+
|
|
354
|
+
# TODO add missing cells in the very end --> all cells in new image that haven't been assigned
|
|
355
|
+
#
|
|
356
|
+
# for iii, region in enumerate(rps_t1_mask):
|
|
357
|
+
# color_of_first_pixel_of_potential_match = tracks[region.coords[0][0], region.coords[0][1]]
|
|
358
|
+
#
|
|
359
|
+
# if color_of_first_pixel_of_potential_match == 0:
|
|
360
|
+
# new_col = get_unique_random_color_int24(forbidden_colors=assigned_ids, assign_new_col_to_forbidden=True)
|
|
361
|
+
# tracks[labels_t1 == labels_t1[region.coords[0][0], region.coords[0][1]]] = new_col
|
|
362
|
+
|
|
363
|
+
# NB does not seem to work as some cells clearly miss some data --> TODO
|
|
364
|
+
tracks = assign_random_ID_to_missing_cells(tracks, labels_t1, regprps=rps_t1_mask, assigned_ids=assigned_ids)
|
|
365
|
+
|
|
366
|
+
# TODO sort cells by the nb of neighbors missing take the ones with most neighbors to reidentify them soon
|
|
367
|
+
|
|
368
|
+
# just for TA compatibility...
|
|
369
|
+
tracks[labels_t1 == 0] = 0xFFFFFF
|
|
370
|
+
|
|
371
|
+
# plt.imshow(int24_to_RGB(tracks))
|
|
372
|
+
# plt.show()
|
|
373
|
+
|
|
374
|
+
if __DEBUG__:
|
|
375
|
+
print('out', get_TA_file(filename1_without_ext, 'tracked_cells_resized.tif'))
|
|
376
|
+
# Img(tracks, dimensions='hwc').save(get_TA_file(filename1_without_ext, 'tracked_cells_resized.tif'), mode='raw')
|
|
377
|
+
tracked_cells_t1 = tracks
|
|
378
|
+
|
|
379
|
+
print('intermediate time before swap correction0', timer() - start_loop)
|
|
380
|
+
|
|
381
|
+
# THIS IS STARTING FROM HERE THAT I SHOULD USE THE NEW SCORING AND SWAPPING ALGO --> TODO
|
|
382
|
+
# Img(int24_to_RGB(tracks)).save(get_TA_file(filename1_without_ext, 'tracked_cells_resized.tif'),mode='raw')
|
|
383
|
+
|
|
384
|
+
##################################################################################NEO CODE
|
|
385
|
+
|
|
386
|
+
# en fait c'est très bon j'ai juste à peaufiner pr sauver du temps de processing et aussi ajouter le score --> avec un nb max de recursion
|
|
387
|
+
# prevent analysing too many times the images
|
|
388
|
+
|
|
389
|
+
# get score and if not imrpoving anymore --> early stop and if improves get a max nb of recursion and really speed up the whole process
|
|
390
|
+
# see how to better handle missing cells without reprocessing everything !!!
|
|
391
|
+
|
|
392
|
+
# just for mapping
|
|
393
|
+
track_t_cur = tracks
|
|
394
|
+
track_t_minus_1 = tracked_cells_t0
|
|
395
|
+
|
|
396
|
+
# recursion is really needed but I don't need do all that for the recursion
|
|
397
|
+
# assign new cell
|
|
398
|
+
|
|
399
|
+
# could compare this to the other
|
|
400
|
+
# vertices_t_minus_1 = find_vertices(track_t_minus_1, return_vertices=True, return_bonds=False)
|
|
401
|
+
vertices_t_minus_1 = np.stack(np.where(track_t_minus_1 == 0xFFFFFF), axis=1)
|
|
402
|
+
# vertices_t_cur = find_vertices(track_t_cur, return_vertices=True, return_bonds=False)
|
|
403
|
+
vertices_t_cur = np.stack(np.where(track_t_cur == 0xFFFFFF), axis=1)
|
|
404
|
+
# plt.imshow(vertices)
|
|
405
|
+
# plt.show()
|
|
406
|
+
|
|
407
|
+
# maybe also if too many rejected changes --> ignore
|
|
408
|
+
# DO I NEED SO MUCH PYRAMIDAL REG WITH SUCH A POWERFUL ALGO ??? --> probably not ??? --> check that and really compare to the other method and clean code heavily !!!
|
|
409
|
+
|
|
410
|
+
cells_and_their_neighbors_minus_1 = np.unique(
|
|
411
|
+
np.asarray(associate_cell_to_its_neighbors2(vertices_t_minus_1, track_t_minus_1)), axis=0)
|
|
412
|
+
cells_and_their_neighbors_minus_1 = associate_cells_to_neighbors_ID_in_dict(cells_and_their_neighbors_minus_1)
|
|
413
|
+
cells_in_t_minus_1 = np.unique(track_t_minus_1)
|
|
414
|
+
# print('neighbs found', cells_and_their_neighbors_minus_1[10287288])
|
|
415
|
+
|
|
416
|
+
initial_score = -1
|
|
417
|
+
|
|
418
|
+
# it's better but there are still some swapping --> need be fixed
|
|
419
|
+
for lll in range(MAX_ITER):
|
|
420
|
+
|
|
421
|
+
# print(get_vx_neighbors(vertices, RGB24img=img)) # is that slow??? --
|
|
422
|
+
|
|
423
|
+
# get_vx_neighbors(vertices_t_minus_1, RGB24img=track_t_minus_1) # ça marche et pas trop long par contre ça me donne juste la correspondance one to one avec le vx array ce qui est peut etre ce que je veux d'ailleurs mais faut pas changer l'ordre
|
|
424
|
+
|
|
425
|
+
# ce truc est slow --> can I speed up using vertices --> most likely yes
|
|
426
|
+
# print(np.unique(np.asarray(associate_cell_to_its_neighbors(img)), axis=0)) # really get cell neighbors # ça a l'air de marcher # maybe I can speed up by using just the vertices or not ???? --> think about it
|
|
427
|
+
# print(associate_cell_to_its_neighbors(img)) # really get cell neighbors # ça a l'air de marcher # maybe I can speed up by using just the vertices or not ???? --> think about it
|
|
428
|
+
# aussi voir comment associer les vertices à une seule cellule --> car très utile
|
|
429
|
+
# print() # a bit faster indeed but not outstanding
|
|
430
|
+
|
|
431
|
+
# get cells and their neigbs for -1 and 0 and do a scoring --> will highlight potential swapping and or division and or other things in a way --> REALLY TRY THAT
|
|
432
|
+
|
|
433
|
+
cells_and_their_neighbors_cur = np.unique(
|
|
434
|
+
np.asarray(associate_cell_to_its_neighbors2(vertices_t_cur, track_t_cur)), axis=0)
|
|
435
|
+
cells_and_their_neighbors_cur = associate_cells_to_neighbors_ID_in_dict(cells_and_their_neighbors_cur)
|
|
436
|
+
|
|
437
|
+
# FOR DEBUG
|
|
438
|
+
# print('cells_and_their_neighbors_minus_1', cells_and_their_neighbors_minus_1)
|
|
439
|
+
# print('cells_and_their_neighbors_cur', cells_and_their_neighbors_cur)
|
|
440
|
+
|
|
441
|
+
# print('neighbs found2', cells_and_their_neighbors_minus_1[10287288])
|
|
442
|
+
# print('neighbs found', cells_and_their_neighbors_cur[10287288])
|
|
443
|
+
# print('cells_and_their_neighbors_plus_1', cells_and_their_neighbors_plus_1)
|
|
444
|
+
|
|
445
|
+
# for all the common cells --> compute a score
|
|
446
|
+
# nb of matching neighbs / total nb of neighbs in both
|
|
447
|
+
|
|
448
|
+
# create and color
|
|
449
|
+
|
|
450
|
+
# cells_present_in_t_cur_but_absent_in_t_plus_1 = []
|
|
451
|
+
# cells_present_in_t_cur_but_absent_in_t_plus_1_score={}
|
|
452
|
+
# matching_neighorhood_score_t_cur_with_t_plus_1 = np.zeros_like(track_t_cur, dtype=float)
|
|
453
|
+
#
|
|
454
|
+
# compute_neighbor_score(cells_and_their_neighbors_cur, cells_and_their_neighbors_plus_1,cells_present_in_t_cur_but_absent_in_t_plus_1, cells_present_in_t_cur_but_absent_in_t_plus_1_score, matching_neighorhood_score_t_cur_with_t_plus_1)
|
|
455
|
+
|
|
456
|
+
# for cell, neigbs in cells_and_their_neighbors_cur.items():
|
|
457
|
+
# if cell in cells_and_their_neighbors_plus_1:
|
|
458
|
+
# # compute score and color cell
|
|
459
|
+
# neigbsb = cells_and_their_neighbors_plus_1[cell]
|
|
460
|
+
# score = (len(list(set(neigbs) & set(neigbsb))) * 2) / (len(neigbsb) + len(neigbs))
|
|
461
|
+
# cells_present_in_t_cur_but_absent_in_t_plus_1_score[cell]=score
|
|
462
|
+
# matching_neighorhood_score_t_cur_with_t_plus_1[track_t_cur == cell] = score
|
|
463
|
+
# else:
|
|
464
|
+
# cells_present_in_t_cur_but_absent_in_t_plus_1.append(cell)
|
|
465
|
+
# cells_present_in_t_cur_but_absent_in_t_plus_1_score[cell] = 0
|
|
466
|
+
|
|
467
|
+
cells_present_in_t_cur_but_absent_in_t_minus_1 = []
|
|
468
|
+
cells_present_in_t_cur_but_absent_in_t_minus_1_score = {}
|
|
469
|
+
# matching_neighorhood_score_t_cur_with_t_minus_1 = np.zeros_like(track_t_cur, dtype=float)
|
|
470
|
+
|
|
471
|
+
score = compute_neighbor_score(cells_and_their_neighbors_cur, cells_and_their_neighbors_minus_1,
|
|
472
|
+
cells_present_in_t_cur_but_absent_in_t_minus_1,
|
|
473
|
+
cells_present_in_t_cur_but_absent_in_t_minus_1_score) # , cells_present_in_t_cur_but_absent_in_t_minus_1, cells_present_in_t_cur_but_absent_in_t_minus_1_score, matching_neighorhood_score_t_cur_with_t_minus_1)
|
|
474
|
+
|
|
475
|
+
# print('defined score', cells_present_in_t_cur_but_absent_in_t_minus_1_score[10287288])
|
|
476
|
+
|
|
477
|
+
if initial_score < 0:
|
|
478
|
+
initial_score = score
|
|
479
|
+
# for cell, neigbs in cells_and_their_neighbors_cur.items():
|
|
480
|
+
# if cell in cells_and_their_neighbors_minus_1:
|
|
481
|
+
# # compute score and color cell
|
|
482
|
+
# neigbsb=cells_and_their_neighbors_minus_1[cell]
|
|
483
|
+
# score = (len(list(set(neigbs) & set(neigbsb)))*2)/(len(neigbsb)+len(neigbs))
|
|
484
|
+
# cells_present_in_t_cur_but_absent_in_t_minus_1_score[cell]=score
|
|
485
|
+
# matching_neighorhood_score_t_cur_with_t_minus_1[track_t_cur == cell]=score
|
|
486
|
+
# else:
|
|
487
|
+
# cells_present_in_t_cur_but_absent_in_t_minus_1.append(cell)
|
|
488
|
+
# cells_present_in_t_cur_but_absent_in_t_minus_1_score[cell] = 0
|
|
489
|
+
|
|
490
|
+
# offer solutions based on scores --> TODO
|
|
491
|
+
|
|
492
|
+
# do I have a bug here ???
|
|
493
|
+
|
|
494
|
+
# print(type(cells_and_their_neighbors_cur), type(cells_and_their_neighbors_minus_1)) # le second est une liste mais ne devrait pas !!!! --> un bug qq part
|
|
495
|
+
# test after optimization
|
|
496
|
+
|
|
497
|
+
# can probably store that
|
|
498
|
+
|
|
499
|
+
# ça rend le code un peu plus long mais vraiment pas deconnant --> doit etre assez facile à faire
|
|
500
|
+
# lab_t_minus_1 = label(track_t_minus_1, connectivity=1, background=0xFFFFFF)
|
|
501
|
+
# rps_t_minus_1 = regionprops(lab_t_minus_1)
|
|
502
|
+
lab_t_cur = label(track_t_cur, connectivity=1, background=0xFFFFFF)
|
|
503
|
+
# rps_t_cur = regionprops(lab_t_cur)
|
|
504
|
+
|
|
505
|
+
# can I read all the neighbors in a smart way now by first index of one
|
|
506
|
+
|
|
507
|
+
# can compare neigbors for a cell in two instances --> give it a try
|
|
508
|
+
# all should be easy I guess !!!
|
|
509
|
+
|
|
510
|
+
# to get cells in one I can get unique of the first col and compare it to the other --> in fact not that hard I think
|
|
511
|
+
# pb if a cell has no vertex it will be ignored
|
|
512
|
+
# --> purely isolated cell
|
|
513
|
+
|
|
514
|
+
# in fact I can simply do unique otherwise directly on the image
|
|
515
|
+
|
|
516
|
+
cells_in_t_cur, first_pixels_t_cur = get_cells_in_image_n_fisrt_pixel(track_t_cur) # np.unique(track_t_cur)
|
|
517
|
+
map_tracks_n_label_t_cur = map_track_id_to_label(first_pixels_t_cur, track_t_cur, lab_t_cur)
|
|
518
|
+
|
|
519
|
+
# print('first_pixels_t_cur', first_pixels_t_cur) # this is the ravel index --> how can I convert it back ???
|
|
520
|
+
# print('cells_in_t_cur', cells_in_t_cur)
|
|
521
|
+
# print('map_tracks_n_label_t_cur', map_tracks_n_label_t_cur)
|
|
522
|
+
|
|
523
|
+
# I'm ready to use this for the tracking of cells
|
|
524
|
+
# just see how fast and efficient this is
|
|
525
|
+
|
|
526
|
+
# l'ancien code est bien meilleur en fait --> voir pkoi parce que le code là est plus beau et plus logique --> essayer de comprendre pkoi moins bon en fait est -ce trop stringent au niveau des scores ????
|
|
527
|
+
# essayer de comprendre le pb!!!!
|
|
528
|
+
|
|
529
|
+
FIX_SWAPS = True
|
|
530
|
+
# threshold = 1.0 # 0.5 # 1.0
|
|
531
|
+
threshold = 0.8 # 0.76 # 0.5 # 1.0 # really required to be above 1 to cope with concurrent drifts of several cells
|
|
532
|
+
if FIX_SWAPS:
|
|
533
|
+
# DETECT SWAPS AND FIX THEM AND COMPUTE SCORE --> TODO also fix cell correspondance then --> really necessary!!!
|
|
534
|
+
# we update both the cells and their local correspondance --> I think I have it --> just need few more crosses to identify more errors
|
|
535
|
+
# can I use that as a tracking algo on top of the other with a minimization of the stuff and just do the coloring in the end --> TODO
|
|
536
|
+
|
|
537
|
+
cells_and_their_neighbors_cur, map_tracks_n_label_t_cur, last_score_reached = optimize_score(
|
|
538
|
+
cells_and_their_neighbors_cur, cells_and_their_neighbors_minus_1,
|
|
539
|
+
cells_present_in_t_cur_but_absent_in_t_minus_1_score, map_tracks_n_label_t_cur, threshold=threshold)
|
|
540
|
+
# print('map_tracks_n_label_t_cur2',map_tracks_n_label_t_cur2)
|
|
541
|
+
# print('map_tracks_n_label_t_cur',map_tracks_n_label_t_cur)
|
|
542
|
+
|
|
543
|
+
# style if improvment < 5 early stop
|
|
544
|
+
# score improved from 617.7013813251964 to 692.6711356897581
|
|
545
|
+
# score improved from 692.6711356897581 to 708.2236112791516
|
|
546
|
+
# score improved from 708.2236112791516 to 711.5193129630884
|
|
547
|
+
# score improved from 711.5193129630884 to 712.606217724993
|
|
548
|
+
# score improved from 712.606217724993 to 713.5926725744915
|
|
549
|
+
|
|
550
|
+
# max reached after 10 iter on the same just for fun it stopped at 6 and I couldn't detect any improvment --> ok in fact!!!
|
|
551
|
+
# use a detector of divisions and of T1s
|
|
552
|
+
# can also be used to detect intercalation maybe ???
|
|
553
|
+
|
|
554
|
+
# could also have a minimum improvment and break if not really improving anymore
|
|
555
|
+
if last_score_reached == initial_score:
|
|
556
|
+
print('early stop', lll)
|
|
557
|
+
break
|
|
558
|
+
|
|
559
|
+
if last_score_reached > initial_score:
|
|
560
|
+
print('score improved from', initial_score, 'to', last_score_reached)
|
|
561
|
+
initial_score = last_score_reached
|
|
562
|
+
else:
|
|
563
|
+
print('score did not improve', initial_score)
|
|
564
|
+
|
|
565
|
+
# depending on the corrections I apply I could also identify cells that have changed between -1 and 1 and that are missassigned cells in 3 and
|
|
566
|
+
# could in fact try tracking with three images to be more efficient in fact directly because post correction will be time consuming in fact especially for swapped cells
|
|
567
|
+
# but still i need that
|
|
568
|
+
# do a version of the tracking using pyramidal reg that relies on that!!! --> TODO
|
|
569
|
+
|
|
570
|
+
# possible assignment 10240303 6824721 0.6666666666666666 (156, 65, 47) (104, 35, 17) 0.6666666666666666 --> a dividing cell --> really a good peak
|
|
571
|
+
# 0
|
|
572
|
+
# possible assignment 10369245 10443693 0.5714285714285714 (158, 56, 221) (159, 91, 173) 0.5714285714285714 --> une misegmented cell en bas au milieu) et une cellule adjacente qui elle est bien placee mais je suppose que faire ce changment fera baisser le core et que donc ce changement sera ignoré...
|
|
573
|
+
# 0
|
|
574
|
+
# possible assignment 11560212 8271832 0.5714285714285714 (176, 101, 20) (126, 55, 216) 0.5714285714285714 --> une autre misegmented cell à gauche un peu apres le centre de l'image!!! et une cellule bien trackee à coté --> pareil faire le score et voir
|
|
575
|
+
# 0
|
|
576
|
+
# possible assignment 12248378 7043456 1.0 (186, 229, 58) (107, 121, 128) 1.0 --> mis tracked cell
|
|
577
|
+
|
|
578
|
+
# cells_in_t_cur = cells_and_their_neighbors_cur.keys()
|
|
579
|
+
|
|
580
|
+
# TO MANUALLY FIND A CELL
|
|
581
|
+
# for jjj, missing in enumerate(cells_in_t_cur):
|
|
582
|
+
# if missing == 0xFFFFFF:
|
|
583
|
+
# continue
|
|
584
|
+
#
|
|
585
|
+
# # if missing != r_g_b_to_rgb( 4,77,109):# for sure it's a swapped cell
|
|
586
|
+
# # continue
|
|
587
|
+
#
|
|
588
|
+
# # the cell 9829855 is not shown properly --> it has no score --> why ?? maybe because no vx ???
|
|
589
|
+
# if missing == 10369245:# 11560212
|
|
590
|
+
# label_id = map_tracks_n_label_t_cur[jjj][1]
|
|
591
|
+
# rps = rps_t_cur[label_id - 1]
|
|
592
|
+
# bbox = rps.bbox
|
|
593
|
+
# # bbox = [bbox[0] - 50, bbox[1] - 50, bbox[2] + 50, bbox[3] + 50]
|
|
594
|
+
# # Bounding box ``(min_row, min_col, max_row, max_col)
|
|
595
|
+
# # do a crop of the region of interest
|
|
596
|
+
#
|
|
597
|
+
# print('bbox pos of cell to assign' ,bbox)
|
|
598
|
+
|
|
599
|
+
# plot change
|
|
600
|
+
|
|
601
|
+
# print('tests of alm', 12248378 in cells_and_their_neighbors_cur.keys(), 12248378 in cells_and_their_neighbors_minus_1.keys(), 7043456 in cells_and_their_neighbors_cur.keys(), 7043456 in cells_and_their_neighbors_minus_1.keys())
|
|
602
|
+
# False False True True --> ok in fact
|
|
603
|
+
|
|
604
|
+
# check why some of the cells are swapped --> especially because it cannot imrpove the code --> see why not detected and really need change this !!!
|
|
605
|
+
#
|
|
606
|
+
compute_neighbor_score(cells_and_their_neighbors_cur, cells_and_their_neighbors_minus_1,
|
|
607
|
+
cells_present_in_t_cur_but_absent_in_t_minus_1,
|
|
608
|
+
cells_present_in_t_cur_but_absent_in_t_minus_1_score)
|
|
609
|
+
|
|
610
|
+
# FOR DEBUG KEEP
|
|
611
|
+
# matching_neighorhood_score_t_cur_with_t_minus_1 = np.zeros_like(track_t_cur, dtype=float)
|
|
612
|
+
# compute_neighbor_score(cells_and_their_neighbors_cur, cells_and_their_neighbors_minus_1,
|
|
613
|
+
# cells_present_in_t_cur_but_absent_in_t_minus_1,
|
|
614
|
+
# cells_present_in_t_cur_but_absent_in_t_minus_1_score,
|
|
615
|
+
# matching_neighorhood_score_t_cur_with_t_minus_1, track_t_cur)
|
|
616
|
+
#
|
|
617
|
+
#
|
|
618
|
+
# plt.imshow(matching_neighorhood_score_t_cur_with_t_minus_1)
|
|
619
|
+
# plt.show()
|
|
620
|
+
|
|
621
|
+
# if I really need swap then I also need
|
|
622
|
+
|
|
623
|
+
# ça marche mais du coup je dois lui faire faire la coloration maintenant
|
|
624
|
+
|
|
625
|
+
corrected_track = apply_color_to_labels(lab_t_cur, map_tracks_n_label_t_cur)
|
|
626
|
+
# plt.imshow(int24_to_RGB(corrected_track))
|
|
627
|
+
# plt.show()
|
|
628
|
+
|
|
629
|
+
corrected_track = assign_random_ID_to_missing_cells(corrected_track, labels_t1, regprps=rps_t1_mask,
|
|
630
|
+
assigned_ids=assigned_ids)
|
|
631
|
+
# update mask!!!
|
|
632
|
+
track_t_cur = corrected_track
|
|
633
|
+
|
|
634
|
+
##################################################################################END NEO CODE
|
|
635
|
+
|
|
636
|
+
# # now we really do the swapping the swapping correction --> I could reuse this code in the other
|
|
637
|
+
# # MEGA TODO just to speed up things here just restrict the swapping to the problematic cells and new cells could also exclude cells that match full dark of main image --> indeed could gain some time when big translations
|
|
638
|
+
# vertices_t0 = detect_vertices_and_bonds(labels_t0)
|
|
639
|
+
# vertices_t0 = np.where(vertices_t0 == 255)
|
|
640
|
+
# vertices_t1 = detect_vertices_and_bonds(labels_t1)
|
|
641
|
+
# vertices_t1 = np.where(vertices_t1 == 255)
|
|
642
|
+
#
|
|
643
|
+
# # ça c'est facile mais faut juste looper sur les cellules problematiques --> ajouter une liste de cellules à checker et les supprimer si ok ??? peut etre --> à faire
|
|
644
|
+
# print('intermediate time before swap correction1', timer() - start_loop)
|
|
645
|
+
# for fix in range(swap_fix_recursions):
|
|
646
|
+
# if __DEBUG__:
|
|
647
|
+
# print('swapping fix recursion #', fix)
|
|
648
|
+
# # print(tracked_cells_t1.shape)
|
|
649
|
+
# tracked_cells_t1 = _fix_swapping_internal(tracked_cells_t0, tracked_cells_t1, vertices_t0=vertices_t0,
|
|
650
|
+
# vertices_t1=vertices_t1, MIN_CUT_OFF_SWAPPING=MIN_CUT_OFF_SWAPPING)
|
|
651
|
+
# # print('-->', tracked_cells_t1.shape)
|
|
652
|
+
# # Img(tracked_cells_t1).save(get_TA_file(filename0_without_ext, 'track_after_swap_correction'+ str(fix)+ '.tif'), mode='raw')
|
|
653
|
+
|
|
654
|
+
# example of swapped cells
|
|
655
|
+
# print('total time', timer() - start_all) # --> 47 secs --> un peu lent qd meme
|
|
656
|
+
|
|
657
|
+
# Img(tracked_cells_t1).save(get_TA_file(filename0_without_ext, 'track_after_swap_correction.tif'), mode='raw')
|
|
658
|
+
print('end loop', timer() - start_loop)
|
|
659
|
+
|
|
660
|
+
print(get_TA_file(filename1_without_ext, 'tracked_cells_resized.tif'))
|
|
661
|
+
|
|
662
|
+
# NB it still contains small swapping errors I don't get --> why
|
|
663
|
+
# swap first then assign and assign if not swapped --> check cell
|
|
664
|
+
|
|
665
|
+
# celui qui m'interesse c'est le 2
|
|
666
|
+
# Img(int24_to_RGB(corrected_track)).save(get_TA_file(filename1_without_ext, 'tracked_cells_resized_v2.tif'),mode='raw')
|
|
667
|
+
Img(int24_to_RGB(corrected_track)).save(get_TA_file(filename1_without_ext, 'tracked_cells_resized.tif'),
|
|
668
|
+
mode='raw')
|
|
669
|
+
|
|
670
|
+
# with a recursion it's very good actually and really is optimized
|
|
671
|
+
|
|
672
|
+
# print(r_g_b_to_rgb(137,134,15))
|
|
673
|
+
|
|
674
|
+
print('total time', timer() - start_all)
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
if __name__ == '__main__':
|
|
678
|
+
# TODO --> do that recursively in order to really track all --> need a loop over image
|
|
679
|
+
|
|
680
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/200319/GT/predict/predict_model_nb_0'
|
|
681
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/210128_dpov1_female_48h10APF/predict/predict_model_nb_0'
|
|
682
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/210121_armGFP_suz_line2_47h30_APF/predict/before_crash/predict_model_nb_0'
|
|
683
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/210128_dpov1_female_48h10APF/registered_stack/splitted_stack'
|
|
684
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/201104_armGFP_different_lines_tila/predict/predict_model_nb_0/registered/splitted' # done slow
|
|
685
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/21-03/GT/predict/predict_model_nb_3'
|
|
686
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/25-1/GT/predict/predict_model_nb_3'
|
|
687
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/27-03/GT/predict/predict_model_nb_3'
|
|
688
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/05-04/GT/predict/predict_model_nb_3'
|
|
689
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/24-1/GT/predict/predict_model_nb_0'
|
|
690
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/210108_armGFP_48hAPF_female/predict/predict_model_nb_4'
|
|
691
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/210108_armGFP_48hAPF_female/predict/predict_model_nb_1'
|
|
692
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/200722_armGFP_suz_ON_47hAPF/predict/predict_model_nb_4/list.lst' # done slow
|
|
693
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/legs/100807_leg4_male/predict/predict_model_nb_0/list.lst' # done but very slow --> need improve and by quite a lot...
|
|
694
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/200709_armGFP_suz_46hAPF_ON/predict/predict_model_nb_0best/list.lst' # last test 190secs much better very slow using new code --> 500-600secs per loop --> now 215 secs per loop with the cleaned up algo --> much better
|
|
695
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/210324_ON_suz_22h45_armGFP_line2/predict/predict_model_nb_0/list.lst'
|
|
696
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/210312_armGFP_line2_suz_39h30APF/predict/predict_model_nb_0/list.lst'
|
|
697
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/05-04/GT/predict/predict_model_nb_3/list.lst'
|
|
698
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/210402_EcadKI_mel_female_26hAPF_pupae_from_old_tube/predict/predict_model_nb_0_not_best_but_very_good_still/list.lst' #TODO
|
|
699
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/210219/predict/predict_model_nb_0' #TODO
|
|
700
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/20-2/predict/predict_model_nb_0' #TODO
|
|
701
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/26-02/predict/predict_model_nb_0' #TODO
|
|
702
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/30-1/predict/predict_model_nb_0' #TODO
|
|
703
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/070219/predict/predict_model_nb_0' #TODO
|
|
704
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/05-2/predict/predict_model_nb_0' #TODO
|
|
705
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/27-02/predict/predict_model_nb_0' #TODO
|
|
706
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/210409_EcadKI_ovipo_female_around_40hAPF/predict/predict_model_nb_4' #TODO
|
|
707
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/fullset_Manue/Ovipositors/06-2/predict/predict_model_nb_0/list.lst' #TODO
|
|
708
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/legs/100611_female_leg/predict/predict_model_nb_2/list.lst' # done slow
|
|
709
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/legs/100706_leg4_female/predict/predict_model_nb_2' # latest measure 1103s --> even better --> ALMOST OK AND CAN INCREASE SPEED BY NB OF PROCS TOO --> 2473secs --> before and now is 1612 secs --> much better because results are identical and I just changhed two lines of code... --> again a bit slow --> try speed this up but really good in fact
|
|
710
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/legs/100608_leg3/predict/predict_model_nb_2best_maybe/list.lst' # --> 7491.503101537935secs --> a bit slow --> really try to improve that in the future but kinda ok for now
|
|
711
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/legs/legs_le_bivic/181023_ON_tila_SC_EcadKI_around16H_APF/predict/predict_model_nb_0/list.lst' # done slow
|
|
712
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/200709_armGFP_suz_46hAPF_ON/predict/predict_model_nb_0/list.lst' # done slow
|
|
713
|
+
# path = '/E/Sample_images/segmentation_assistant/ovipo_uncropped' # done test
|
|
714
|
+
# path = '/E/Sample_images/sample_images_denoise_manue/201104_armGFP_different_lines_tila/predict/predict_model_nb_0/list.lst' # done test
|
|
715
|
+
# path = '/E/Sample_images/test_tracking_with_shift' # quick test of the algo
|
|
716
|
+
# path = '/E/Sample_images/tracking_test' # quick test of the tracking algo
|
|
717
|
+
# path = '/E/Sample_images/tracking_test/test_uncropped' # quick test of the tracking algo # local version is much worse --> not worth it --> do I have a bug ????
|
|
718
|
+
path = '/E/Sample_images/tracking_test/test_quick_TA_tracking/list.lst' #total time 296.99147817201447 --> 308.14404578204267 with criss cross reg --> mieux mais bcp de drift sur les bords --> pkoi ??? et des rigions de big shift car too coarse --> maybe need further split it like the other maybe
|
|
719
|
+
# ideally I should detect and prevent the big difts
|
|
720
|
+
# or need 6 and divide by
|
|
721
|
+
# path = '/E/Sample_images/tracking_test/test_cropped' # quick test of the tracking algo
|
|
722
|
+
# path = '/E/Sample_images/tracking_test/leg_uncropped' # quick test of the tracking algo # quite good --> very few swaps in fact # total time 152.38672435702756 sec nouveau vs total time 164.57967406092212 secs for the old one --> not really useful to restrict then best score global =733.1310118292632, best score local =730.04 --> early stop 730.9823090293312
|
|
723
|
+
# path = '/E/Sample_images/tracking_test/leg_cropped' # quick test of the tracking algo
|
|
724
|
+
|
|
725
|
+
track_cells_dynamic_tissue(path)
|