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,653 @@
|
|
|
1
|
+
import os.path
|
|
2
|
+
from skimage import measure
|
|
3
|
+
from skimage.measure import regionprops
|
|
4
|
+
import numpy as np
|
|
5
|
+
from batoolset.img import Img, RGB_to_int24, int24_to_RGB
|
|
6
|
+
from timeit import default_timer as timer
|
|
7
|
+
|
|
8
|
+
# if the stuff has been done by the module then
|
|
9
|
+
from batoolset.colors.colorgen import get_forbidden_colors_int24
|
|
10
|
+
from batoolset.ta.tracking.registration import pre_register_images, apply_translation
|
|
11
|
+
from batoolset.files.tools import assign_random_ID_to_missing_cells, get_TA_file, first_image_tracking
|
|
12
|
+
from batoolset.ta.tracking.tracking_error_detector_and_fixer import find_vertices, associate_cell_to_its_neighbors2, \
|
|
13
|
+
associate_cells_to_neighbors_ID_in_dict, compute_neighbor_score, optimize_score, get_cells_in_image_n_fisrt_pixel, \
|
|
14
|
+
map_track_id_to_label, apply_color_to_labels
|
|
15
|
+
|
|
16
|
+
# TODO also finalize this tracking code and offer it as a registration
|
|
17
|
+
# also offer it as a check for segmentation --> try run the wshed locally with that
|
|
18
|
+
|
|
19
|
+
# TODO --> if two or more cells match then maybe try to find the best fit
|
|
20
|
+
# --> a good idea --> maybe could use area or cell elongation as the main criterion
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# def sort_rps_by_area(rps):
|
|
24
|
+
# --> TODO add the possibility to warp
|
|
25
|
+
# also do a code to reconnect tracks that I may also use to MT the tracking --> I may need to know how to handle shared colored cell list or do two by two and do a code that can handle the junction of al the two by two pairs --> TODO
|
|
26
|
+
# indeed try to do that
|
|
27
|
+
# hack the other tracking code so that it does not need the cells
|
|
28
|
+
# TODO add checks...
|
|
29
|
+
# I still need to have and store all the cells to avoid duplicating IDs --> also need check that this is done properly ...
|
|
30
|
+
|
|
31
|
+
# le code doit surement etre ok --> à finaliser... et à tester
|
|
32
|
+
# en fait le code peut aussi etre utilisé pour de la segmentation --> à essayer...
|
|
33
|
+
# --> warper une segmentation existante et l'appliquer au suivant et si une autre seg est dispo alors voir si on peut prendre le meilleur des deux mondes...
|
|
34
|
+
|
|
35
|
+
# TODO --> also finalize the code so that it can be used on a regular image to track
|
|
36
|
+
# if first image --> need generate the iamge then I need to be sure whether the stuff is working or not
|
|
37
|
+
# I need to have the already assigned colors passed in too
|
|
38
|
+
from batoolset.tools.early_stopper_class import early_stop
|
|
39
|
+
from batoolset.utils.loadlist import loadlist
|
|
40
|
+
|
|
41
|
+
def match_by_max_overlap(name_t1, name_t0, channel_of_interest=None, assigned_IDs=[], recursive_assignment=True, warp_using_mermaid_if_map_is_available=True, pre_register=True):
|
|
42
|
+
"""
|
|
43
|
+
Match cells between two timepoints based on maximizing overlap.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
name_t1 (str): Filename of the first timepoint.
|
|
47
|
+
name_t0 (str): Filename of the second timepoint.
|
|
48
|
+
channel_of_interest (str): Name of the channel of interest.
|
|
49
|
+
assigned_IDs (list): List of already assigned cell IDs.
|
|
50
|
+
recursive_assignment (bool): Flag indicating whether to perform recursive assignment.
|
|
51
|
+
warp_using_mermaid_if_map_is_available (bool): Flag indicating whether to warp using Mermaid if a map is available.
|
|
52
|
+
pre_register (bool): Flag indicating whether to perform pre-registration.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
None
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
# Get the filename of the first timepoint without the extension
|
|
59
|
+
filename1_without_ext = os.path.splitext(name_t1)[0]
|
|
60
|
+
|
|
61
|
+
# Load the hand-corrected mask for the first timepoint
|
|
62
|
+
mask_t1 = Img(os.path.join(filename1_without_ext, 'handCorrection.tif'))
|
|
63
|
+
|
|
64
|
+
# Load the warped and resized cell tracks for the second timepoint
|
|
65
|
+
int_24_warped_track_t0 = RGB_to_int24(Img(os.path.join(os.path.splitext(name_t0)[0], 'tracked_cells_resized.tif')))
|
|
66
|
+
|
|
67
|
+
if warp_using_mermaid_if_map_is_available:
|
|
68
|
+
try:
|
|
69
|
+
from personal.mermaid.deep_warping_uing_mermaid_minimal import warp_image_directly_using_phi
|
|
70
|
+
|
|
71
|
+
filename0_without_ext = os.path.splitext(name_t0)[0]
|
|
72
|
+
|
|
73
|
+
if os.path.exists(os.path.join(filename0_without_ext, 'mermaid_map.tif')):
|
|
74
|
+
# Warp the cell tracks using Mermaid if the map is available
|
|
75
|
+
warp_map = Img(os.path.join(filename0_without_ext, 'mermaid_map.tif'))
|
|
76
|
+
int_24_warped_track_t0 = warp_image_directly_using_phi(int_24_warped_track_t0, warp_map, pre_registration=name_t0 if pre_register else None).astype(np.uint32)
|
|
77
|
+
else:
|
|
78
|
+
if pre_register:
|
|
79
|
+
# Perform pre-registration if specified
|
|
80
|
+
trans_dim_0, trans_dim_1 = _pre_reg(name_t0, name_t1, channel_of_interest)
|
|
81
|
+
int_24_warped_track_t0 = apply_translation(int_24_warped_track_t0, -trans_dim_0, -trans_dim_1)
|
|
82
|
+
except:
|
|
83
|
+
print("Mermaid registration failed... continuing without")
|
|
84
|
+
if pre_register:
|
|
85
|
+
# Perform pre-registration if specified
|
|
86
|
+
trans_dim_0, trans_dim_1 = _pre_reg(name_t0, name_t1, channel_of_interest)
|
|
87
|
+
int_24_warped_track_t0 = apply_translation(int_24_warped_track_t0, -trans_dim_0, -trans_dim_1)
|
|
88
|
+
else:
|
|
89
|
+
if pre_register:
|
|
90
|
+
# Perform pre-registration if specified
|
|
91
|
+
trans_dim_0, trans_dim_1 = _pre_reg(name_t0, name_t1, channel_of_interest)
|
|
92
|
+
int_24_warped_track_t0 = apply_translation(int_24_warped_track_t0, -trans_dim_0, -trans_dim_1)
|
|
93
|
+
|
|
94
|
+
# Convert the mask to label image
|
|
95
|
+
if len(mask_t1.shape) == 3:
|
|
96
|
+
mask_t1 = mask_t1[..., 0]
|
|
97
|
+
|
|
98
|
+
label_t1 = measure.label(mask_t1, connectivity=1, background=255)
|
|
99
|
+
|
|
100
|
+
rps_label_t1 = regionprops(label_t1)
|
|
101
|
+
|
|
102
|
+
track_t1 = np.zeros_like(mask_t1, dtype=np.uint64)
|
|
103
|
+
|
|
104
|
+
matched_IDs = []
|
|
105
|
+
|
|
106
|
+
# Iterate over the labeled regions in the first timepoint, sorted by area in descending order
|
|
107
|
+
for rps in sorted(rps_label_t1, key=lambda r: r.area, reverse=True):
|
|
108
|
+
if track_t1[rps.coords[0][0], rps.coords[0][1]] != 0:
|
|
109
|
+
# Skip the region if it has already been assigned
|
|
110
|
+
continue
|
|
111
|
+
|
|
112
|
+
pixels = int_24_warped_track_t0[rps.coords[:, 0], rps.coords[:, 1]]
|
|
113
|
+
unique, counts = np.unique(pixels, return_counts=True)
|
|
114
|
+
|
|
115
|
+
color_to_assign = unique[np.argmax(counts)]
|
|
116
|
+
|
|
117
|
+
if color_to_assign in matched_IDs:
|
|
118
|
+
# Skip the region if the assigned color has already been matched
|
|
119
|
+
continue
|
|
120
|
+
|
|
121
|
+
matched_IDs.append(color_to_assign)
|
|
122
|
+
|
|
123
|
+
track_t1[rps.coords[:, 0], rps.coords[:, 1]] = color_to_assign
|
|
124
|
+
|
|
125
|
+
track_t1[label_t1 == 0] = 0xFFFFFF
|
|
126
|
+
|
|
127
|
+
if recursive_assignment:
|
|
128
|
+
# Perform recursive assignment to further identify cells
|
|
129
|
+
run_swapping_correction_recursively_to_further_identify_cells(track_t1, int_24_warped_track_t0, label_t1, rps_label_t1, assigned_IDs, filename1_without_ext, MAX_ITER=15)
|
|
130
|
+
else:
|
|
131
|
+
# I need at least to make sure that all the black cells have been assigned an ID
|
|
132
|
+
track_t1 = assign_random_ID_to_missing_cells(track_t1, label_t1, regprps=rps_label_t1,
|
|
133
|
+
assigned_ids=assigned_IDs)
|
|
134
|
+
|
|
135
|
+
# Save the tracked cells for the first timepoint
|
|
136
|
+
Img(int24_to_RGB(track_t1)).save(get_TA_file(filename1_without_ext, 'tracked_cells_resized.tif'), mode='raw')
|
|
137
|
+
|
|
138
|
+
def _pre_reg(name_t0, name_t1, channel_of_interest):
|
|
139
|
+
"""
|
|
140
|
+
Perform pre-registration between two images.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
name_t0 (str): Filename of the first image.
|
|
144
|
+
name_t1 (str): Filename of the second image.
|
|
145
|
+
channel_of_interest (str): Name of the channel of interest.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
tuple: Tuple containing the translation dimensions (trans_dim_0, trans_dim_1).
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
I0 = Img(name_t0)
|
|
152
|
+
if channel_of_interest is not None and len(I0.shape) > 2:
|
|
153
|
+
I0 = I0[..., channel_of_interest]
|
|
154
|
+
I1 = Img(name_t1)
|
|
155
|
+
if channel_of_interest is not None and len(I1.shape) > 2:
|
|
156
|
+
I1 = I1[..., channel_of_interest]
|
|
157
|
+
trans_dim_0, trans_dim_1 = pre_register_images(orig_t0=I0, orig_t1=I1)
|
|
158
|
+
return trans_dim_0, trans_dim_1
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def get_matched_ids(rps_t1_mask, tracks):
|
|
162
|
+
"""
|
|
163
|
+
Get the matched cell IDs from the labeled regions.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
rps_t1_mask (list): List of labeled regions from the first timepoint mask.
|
|
167
|
+
tracks (ndarray): Array containing the cell tracks.
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
list: List of matched cell IDs.
|
|
171
|
+
"""
|
|
172
|
+
|
|
173
|
+
matched_cells_ids = []
|
|
174
|
+
|
|
175
|
+
for iii, region in enumerate(rps_t1_mask):
|
|
176
|
+
color = tracks[region.coords[0][0], region.coords[0][1]]
|
|
177
|
+
if color == 0:
|
|
178
|
+
# missing_cells_t1.append(iii)
|
|
179
|
+
pass
|
|
180
|
+
else:
|
|
181
|
+
matched_cells_ids.append(color)
|
|
182
|
+
|
|
183
|
+
return matched_cells_ids
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def run_swapping_correction_recursively_to_further_identify_cells(tracks, tracked_cells_t0, labels_t1, rps_t1_mask,
|
|
187
|
+
assigned_ids, filename1_without_ext, MAX_ITER=15):
|
|
188
|
+
start_all = timer()
|
|
189
|
+
# print('intermediate time before swap correction0', timer() - start_loop)
|
|
190
|
+
|
|
191
|
+
# THIS IS STARTING FROM HERE THAT I SHOULD USE THE NEW SCORING AND SWAPPING ALGO --> TODO
|
|
192
|
+
# Img(int24_to_RGB(tracks)).save(get_TA_file(filename1_without_ext, 'tracked_cells_resized.tif'),mode='raw')
|
|
193
|
+
|
|
194
|
+
##################################################################################NEO CODE
|
|
195
|
+
|
|
196
|
+
# 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
|
|
197
|
+
# prevent analysing too many times the images
|
|
198
|
+
|
|
199
|
+
# 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
|
|
200
|
+
# see how to better handle missing cells without reprocessing everything !!!
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
# just for mapping
|
|
205
|
+
track_t_cur = tracks
|
|
206
|
+
track_t_minus_1 = tracked_cells_t0
|
|
207
|
+
|
|
208
|
+
# recursion is really needed but I don't need do all that for the recursion
|
|
209
|
+
# assign new cell
|
|
210
|
+
|
|
211
|
+
# could compare this to the other
|
|
212
|
+
# vertices_t_minus_1 = find_vertices(track_t_minus_1, return_vertices=True, return_bonds=False)
|
|
213
|
+
vertices_t_minus_1 = np.stack(np.where(track_t_minus_1 == 0xFFFFFF), axis=1)
|
|
214
|
+
# vertices_t_cur = find_vertices(track_t_cur, return_vertices=True, return_bonds=False)
|
|
215
|
+
vertices_t_cur = np.stack(np.where(track_t_cur == 0xFFFFFF), axis=1)
|
|
216
|
+
|
|
217
|
+
# print('vertices_t_minus_1',vertices_t_minus_1)
|
|
218
|
+
# print('vertices_t_cur',vertices_t_cur)
|
|
219
|
+
|
|
220
|
+
# print('sum all', np.sum(vertices_t_minus_1-vertices_t_cur))
|
|
221
|
+
# somehow the two images are the same --> did I do a mistake somewhere ???
|
|
222
|
+
|
|
223
|
+
# print(vertices_t_minus_1.shape)
|
|
224
|
+
|
|
225
|
+
# plt.imshow(vertices_t_minus_1)
|
|
226
|
+
# plt.show()
|
|
227
|
+
|
|
228
|
+
# maybe also if too many rejected changes --> ignore
|
|
229
|
+
# 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 !!!
|
|
230
|
+
|
|
231
|
+
cells_and_their_neighbors_minus_1 = np.unique(
|
|
232
|
+
np.asarray(associate_cell_to_its_neighbors2(vertices_t_minus_1, track_t_minus_1)), axis=0)
|
|
233
|
+
cells_and_their_neighbors_minus_1 = associate_cells_to_neighbors_ID_in_dict(cells_and_their_neighbors_minus_1)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
# cells_in_t_minus_1 = np.unique(track_t_minus_1)
|
|
237
|
+
# print('neighbs found', cells_and_their_neighbors_minus_1[10287288])
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
# il y a des bugs dans ce code --> maybe recode all
|
|
241
|
+
# some of the cells are not
|
|
242
|
+
|
|
243
|
+
initial_score = -1
|
|
244
|
+
|
|
245
|
+
# it's better but there are still some swapping --> need be fixed
|
|
246
|
+
for lll in range(MAX_ITER):
|
|
247
|
+
start_loop = timer()
|
|
248
|
+
|
|
249
|
+
# print(get_vx_neighbors(vertices, RGB24img=img)) # is that slow??? --
|
|
250
|
+
|
|
251
|
+
# 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
|
|
252
|
+
|
|
253
|
+
# ce truc est slow --> can I speed up using vertices --> most likely yes
|
|
254
|
+
# 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
|
|
255
|
+
# 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
|
|
256
|
+
# aussi voir comment associer les vertices à une seule cellule --> car très utile
|
|
257
|
+
# print() # a bit faster indeed but not outstanding
|
|
258
|
+
|
|
259
|
+
# 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
|
|
260
|
+
|
|
261
|
+
cells_and_their_neighbors_cur = np.unique(
|
|
262
|
+
np.asarray(associate_cell_to_its_neighbors2(vertices_t_cur, track_t_cur)), axis=0)
|
|
263
|
+
cells_and_their_neighbors_cur = associate_cells_to_neighbors_ID_in_dict(cells_and_their_neighbors_cur)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
# because this is the label of the cell and not its id ???
|
|
267
|
+
# print('difference', set(cells_and_their_neighbors_cur.keys())-set(cells_and_their_neighbors_minus_1.keys())) # this difference is 0 --> but why
|
|
268
|
+
# print('difference2', set(cells_and_their_neighbors_minus_1.keys())-set(cells_and_their_neighbors_cur.keys())) # this difference is 0 --> but why # both differences are 0 --> does not make any sense then
|
|
269
|
+
# print('1',len(cells_and_their_neighbors_cur.keys())) # both exactly have the same size --> have I done a mistake ???
|
|
270
|
+
# print('2',len(cells_and_their_neighbors_minus_1.keys()))
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
# FOR DEBUG
|
|
277
|
+
# print('cells_and_their_neighbors_minus_1', cells_and_their_neighbors_minus_1)
|
|
278
|
+
# print('cells_and_their_neighbors_cur', cells_and_their_neighbors_cur)
|
|
279
|
+
|
|
280
|
+
# print('neighbs found2', cells_and_their_neighbors_minus_1[10287288])
|
|
281
|
+
# print('neighbs found', cells_and_their_neighbors_cur[10287288])
|
|
282
|
+
# print('cells_and_their_neighbors_plus_1', cells_and_their_neighbors_plus_1)
|
|
283
|
+
|
|
284
|
+
# for all the common cells --> compute a score
|
|
285
|
+
# nb of matching neighbs / total nb of neighbs in both
|
|
286
|
+
|
|
287
|
+
# create and color
|
|
288
|
+
|
|
289
|
+
# cells_present_in_t_cur_but_absent_in_t_plus_1 = []
|
|
290
|
+
# cells_present_in_t_cur_but_absent_in_t_plus_1_score={}
|
|
291
|
+
# matching_neighorhood_score_t_cur_with_t_plus_1 = np.zeros_like(track_t_cur, dtype=float)
|
|
292
|
+
#
|
|
293
|
+
# 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)
|
|
294
|
+
|
|
295
|
+
# for cell, neigbs in cells_and_their_neighbors_cur.items():
|
|
296
|
+
# if cell in cells_and_their_neighbors_plus_1:
|
|
297
|
+
# # compute score and color cell
|
|
298
|
+
# neigbsb = cells_and_their_neighbors_plus_1[cell]
|
|
299
|
+
# score = (len(list(set(neigbs) & set(neigbsb))) * 2) / (len(neigbsb) + len(neigbs))
|
|
300
|
+
# cells_present_in_t_cur_but_absent_in_t_plus_1_score[cell]=score
|
|
301
|
+
# matching_neighorhood_score_t_cur_with_t_plus_1[track_t_cur == cell] = score
|
|
302
|
+
# else:
|
|
303
|
+
# cells_present_in_t_cur_but_absent_in_t_plus_1.append(cell)
|
|
304
|
+
# cells_present_in_t_cur_but_absent_in_t_plus_1_score[cell] = 0
|
|
305
|
+
|
|
306
|
+
cells_present_in_t_cur_but_absent_in_t_minus_1 = []
|
|
307
|
+
cells_present_in_t_cur_but_absent_in_t_minus_1_score = {}
|
|
308
|
+
|
|
309
|
+
# matching_neighorhood_score_t_cur_with_t_minus_1 = np.zeros_like(track_t_cur, dtype=float)
|
|
310
|
+
|
|
311
|
+
score = compute_neighbor_score(cells_and_their_neighbors_cur, cells_and_their_neighbors_minus_1,
|
|
312
|
+
cells_present_in_t_cur_but_absent_in_t_minus_1,
|
|
313
|
+
cells_present_in_t_cur_but_absent_in_t_minus_1_score)#,score_plotting_image=matching_neighorhood_score_t_cur_with_t_minus_1) # , 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)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
print('cells_present_in_t_cur_but_absent_in_t_minus_1', cells_present_in_t_cur_but_absent_in_t_minus_1) # --> big bug because this is empty and it does not make sense
|
|
317
|
+
# plt.imshow(matching_neighorhood_score_t_cur_with_t_minus_1)
|
|
318
|
+
# plt.show()
|
|
319
|
+
|
|
320
|
+
# print('defined score', cells_present_in_t_cur_but_absent_in_t_minus_1_score[10287288])
|
|
321
|
+
|
|
322
|
+
if initial_score < 0:
|
|
323
|
+
initial_score = score
|
|
324
|
+
# for cell, neigbs in cells_and_their_neighbors_cur.items():
|
|
325
|
+
# if cell in cells_and_their_neighbors_minus_1:
|
|
326
|
+
# # compute score and color cell
|
|
327
|
+
# neigbsb=cells_and_their_neighbors_minus_1[cell]
|
|
328
|
+
# score = (len(list(set(neigbs) & set(neigbsb)))*2)/(len(neigbsb)+len(neigbs))
|
|
329
|
+
# cells_present_in_t_cur_but_absent_in_t_minus_1_score[cell]=score
|
|
330
|
+
# matching_neighorhood_score_t_cur_with_t_minus_1[track_t_cur == cell]=score
|
|
331
|
+
# else:
|
|
332
|
+
# cells_present_in_t_cur_but_absent_in_t_minus_1.append(cell)
|
|
333
|
+
# cells_present_in_t_cur_but_absent_in_t_minus_1_score[cell] = 0
|
|
334
|
+
|
|
335
|
+
# offer solutions based on scores --> TODO
|
|
336
|
+
|
|
337
|
+
# do I have a bug here ???
|
|
338
|
+
|
|
339
|
+
# 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
|
|
340
|
+
# test after optimization
|
|
341
|
+
|
|
342
|
+
# can probably store that
|
|
343
|
+
|
|
344
|
+
# ça rend le code un peu plus long mais vraiment pas deconnant --> doit etre assez facile à faire
|
|
345
|
+
# lab_t_minus_1 = label(track_t_minus_1, connectivity=1, background=0xFFFFFF)
|
|
346
|
+
# rps_t_minus_1 = regionprops(lab_t_minus_1)
|
|
347
|
+
lab_t_cur = measure.label(track_t_cur, connectivity=1, background=0xFFFFFF)
|
|
348
|
+
# rps_t_cur = regionprops(lab_t_cur)
|
|
349
|
+
|
|
350
|
+
# can I read all the neighbors in a smart way now by first index of one
|
|
351
|
+
|
|
352
|
+
# can compare neigbors for a cell in two instances --> give it a try
|
|
353
|
+
# all should be easy I guess !!!
|
|
354
|
+
|
|
355
|
+
# 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
|
|
356
|
+
# pb if a cell has no vertex it will be ignored
|
|
357
|
+
# --> purely isolated cell
|
|
358
|
+
|
|
359
|
+
# in fact I can simply do unique otherwise directly on the image
|
|
360
|
+
|
|
361
|
+
cells_in_t_cur, first_pixels_t_cur = get_cells_in_image_n_fisrt_pixel(track_t_cur) # np.unique(track_t_cur)
|
|
362
|
+
map_tracks_n_label_t_cur = map_track_id_to_label(first_pixels_t_cur, track_t_cur, lab_t_cur)
|
|
363
|
+
|
|
364
|
+
# print('first_pixels_t_cur', first_pixels_t_cur) # this is the ravel index --> how can I convert it back ???
|
|
365
|
+
# print('cells_in_t_cur', cells_in_t_cur)
|
|
366
|
+
# print('map_tracks_n_label_t_cur', map_tracks_n_label_t_cur)
|
|
367
|
+
|
|
368
|
+
# I'm ready to use this for the tracking of cells
|
|
369
|
+
# just see how fast and efficient this is
|
|
370
|
+
|
|
371
|
+
# 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 ????
|
|
372
|
+
# essayer de comprendre le pb!!!!
|
|
373
|
+
|
|
374
|
+
FIX_SWAPS = True
|
|
375
|
+
# threshold = 1.0 # 0.5 # 1.0
|
|
376
|
+
threshold = 0.8 # 0.76 # 0.5 # 1.0 # really required to be above 1 to cope with concurrent drifts of several cells
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
# even though there are errors it really doe not find them
|
|
380
|
+
if FIX_SWAPS:
|
|
381
|
+
# DETECT SWAPS AND FIX THEM AND COMPUTE SCORE --> TODO also fix cell correspondance then --> really necessary!!!
|
|
382
|
+
# we update both the cells and their local correspondance --> I think I have it --> just need few more crosses to identify more errors
|
|
383
|
+
# 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
|
|
384
|
+
|
|
385
|
+
cells_and_their_neighbors_cur, map_tracks_n_label_t_cur, last_score_reached = optimize_score(
|
|
386
|
+
cells_and_their_neighbors_cur, cells_and_their_neighbors_minus_1,
|
|
387
|
+
cells_present_in_t_cur_but_absent_in_t_minus_1_score, map_tracks_n_label_t_cur, threshold=threshold)
|
|
388
|
+
# print('map_tracks_n_label_t_cur2',map_tracks_n_label_t_cur2)
|
|
389
|
+
# print('map_tracks_n_label_t_cur',map_tracks_n_label_t_cur)
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
# style if improvment < 5 early stop
|
|
394
|
+
# score improved from 617.7013813251964 to 692.6711356897581
|
|
395
|
+
# score improved from 692.6711356897581 to 708.2236112791516
|
|
396
|
+
# score improved from 708.2236112791516 to 711.5193129630884
|
|
397
|
+
# score improved from 711.5193129630884 to 712.606217724993
|
|
398
|
+
# score improved from 712.606217724993 to 713.5926725744915
|
|
399
|
+
|
|
400
|
+
# 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!!!
|
|
401
|
+
# use a detector of divisions and of T1s
|
|
402
|
+
# can also be used to detect intercalation maybe ???
|
|
403
|
+
|
|
404
|
+
# could also have a minimum improvment and break if not really improving anymore
|
|
405
|
+
# 1388
|
|
406
|
+
# do i have a bug because no possible alignment
|
|
407
|
+
if last_score_reached == initial_score:
|
|
408
|
+
print(last_score_reached, initial_score)
|
|
409
|
+
print('early stop', lll)
|
|
410
|
+
break
|
|
411
|
+
|
|
412
|
+
if last_score_reached > initial_score:
|
|
413
|
+
print('score improved from', initial_score, 'to', last_score_reached)
|
|
414
|
+
initial_score = last_score_reached
|
|
415
|
+
else:
|
|
416
|
+
print('score did not improve', initial_score)
|
|
417
|
+
|
|
418
|
+
# 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
|
|
419
|
+
# 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
|
|
420
|
+
# but still i need that
|
|
421
|
+
# do a version of the tracking using pyramidal reg that relies on that!!! --> TODO
|
|
422
|
+
|
|
423
|
+
# possible assignment 10240303 6824721 0.6666666666666666 (156, 65, 47) (104, 35, 17) 0.6666666666666666 --> a dividing cell --> really a good peak
|
|
424
|
+
# 0
|
|
425
|
+
# 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é...
|
|
426
|
+
# 0
|
|
427
|
+
# 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
|
|
428
|
+
# 0
|
|
429
|
+
# possible assignment 12248378 7043456 1.0 (186, 229, 58) (107, 121, 128) 1.0 --> mis tracked cell
|
|
430
|
+
|
|
431
|
+
# cells_in_t_cur = cells_and_their_neighbors_cur.keys()
|
|
432
|
+
|
|
433
|
+
# TO MANUALLY FIND A CELL
|
|
434
|
+
# for jjj, missing in enumerate(cells_in_t_cur):
|
|
435
|
+
# if missing == 0xFFFFFF:
|
|
436
|
+
# continue
|
|
437
|
+
#
|
|
438
|
+
# # if missing != r_g_b_to_rgb( 4,77,109):# for sure it's a swapped cell
|
|
439
|
+
# # continue
|
|
440
|
+
#
|
|
441
|
+
# # the cell 9829855 is not shown properly --> it has no score --> why ?? maybe because no vx ???
|
|
442
|
+
# if missing == 10369245:# 11560212
|
|
443
|
+
# label_id = map_tracks_n_label_t_cur[jjj][1]
|
|
444
|
+
# rps = rps_t_cur[label_id - 1]
|
|
445
|
+
# bbox = rps.bbox
|
|
446
|
+
# # bbox = [bbox[0] - 50, bbox[1] - 50, bbox[2] + 50, bbox[3] + 50]
|
|
447
|
+
# # Bounding box ``(min_row, min_col, max_row, max_col)
|
|
448
|
+
# # do a crop of the region of interest
|
|
449
|
+
#
|
|
450
|
+
# print('bbox pos of cell to assign' ,bbox)
|
|
451
|
+
|
|
452
|
+
# plot change
|
|
453
|
+
|
|
454
|
+
# 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())
|
|
455
|
+
# False False True True --> ok in fact
|
|
456
|
+
|
|
457
|
+
# check why some of the cells are swapped --> especially because it cannot imrpove the code --> see why not detected and really need change this !!!
|
|
458
|
+
#
|
|
459
|
+
compute_neighbor_score(cells_and_their_neighbors_cur, cells_and_their_neighbors_minus_1,
|
|
460
|
+
cells_present_in_t_cur_but_absent_in_t_minus_1,
|
|
461
|
+
cells_present_in_t_cur_but_absent_in_t_minus_1_score)
|
|
462
|
+
|
|
463
|
+
# FOR DEBUG KEEP
|
|
464
|
+
# matching_neighorhood_score_t_cur_with_t_minus_1 = np.zeros_like(track_t_cur, dtype=float)
|
|
465
|
+
# compute_neighbor_score(cells_and_their_neighbors_cur, cells_and_their_neighbors_minus_1,
|
|
466
|
+
# cells_present_in_t_cur_but_absent_in_t_minus_1,
|
|
467
|
+
# cells_present_in_t_cur_but_absent_in_t_minus_1_score,
|
|
468
|
+
# matching_neighorhood_score_t_cur_with_t_minus_1, track_t_cur)
|
|
469
|
+
#
|
|
470
|
+
#
|
|
471
|
+
# plt.imshow(matching_neighorhood_score_t_cur_with_t_minus_1)
|
|
472
|
+
# plt.show()
|
|
473
|
+
|
|
474
|
+
# if I really need swap then I also need
|
|
475
|
+
|
|
476
|
+
# ça marche mais du coup je dois lui faire faire la coloration maintenant
|
|
477
|
+
|
|
478
|
+
corrected_track = apply_color_to_labels(lab_t_cur, map_tracks_n_label_t_cur)
|
|
479
|
+
# plt.imshow(int24_to_RGB(corrected_track))
|
|
480
|
+
# plt.show()
|
|
481
|
+
|
|
482
|
+
corrected_track = assign_random_ID_to_missing_cells(corrected_track, labels_t1, regprps=rps_t1_mask,
|
|
483
|
+
assigned_ids=assigned_ids)
|
|
484
|
+
# update mask!!!
|
|
485
|
+
track_t_cur = corrected_track
|
|
486
|
+
|
|
487
|
+
##################################################################################END NEO CODE
|
|
488
|
+
|
|
489
|
+
# # now we really do the swapping the swapping correction --> I could reuse this code in the other
|
|
490
|
+
# # 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
|
|
491
|
+
# vertices_t0 = detect_vertices_and_bonds(labels_t0)
|
|
492
|
+
# vertices_t0 = np.where(vertices_t0 == 255)
|
|
493
|
+
# vertices_t1 = detect_vertices_and_bonds(labels_t1)
|
|
494
|
+
# vertices_t1 = np.where(vertices_t1 == 255)
|
|
495
|
+
#
|
|
496
|
+
# # ç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
|
|
497
|
+
# print('intermediate time before swap correction1', timer() - start_loop)
|
|
498
|
+
# for fix in range(swap_fix_recursions):
|
|
499
|
+
# if __DEBUG__:
|
|
500
|
+
# print('swapping fix recursion #', fix)
|
|
501
|
+
# # print(tracked_cells_t1.shape)
|
|
502
|
+
# tracked_cells_t1 = _fix_swapping_internal(tracked_cells_t0, tracked_cells_t1, vertices_t0=vertices_t0,
|
|
503
|
+
# vertices_t1=vertices_t1, MIN_CUT_OFF_SWAPPING=MIN_CUT_OFF_SWAPPING)
|
|
504
|
+
# # print('-->', tracked_cells_t1.shape)
|
|
505
|
+
# # Img(tracked_cells_t1).save(get_TA_file(filename0_without_ext, 'track_after_swap_correction'+ str(fix)+ '.tif'), mode='raw')
|
|
506
|
+
|
|
507
|
+
# example of swapped cells
|
|
508
|
+
# print('total time', timer() - start_all) # --> 47 secs --> un peu lent qd meme
|
|
509
|
+
|
|
510
|
+
# Img(tracked_cells_t1).save(get_TA_file(filename0_without_ext, 'track_after_swap_correction.tif'), mode='raw')
|
|
511
|
+
print('end loop', timer() - start_loop)
|
|
512
|
+
|
|
513
|
+
# make sure to fix missing not found cells
|
|
514
|
+
track_t_cur = assign_random_ID_to_missing_cells(track_t_cur, labels_t1, regprps=rps_t1_mask,
|
|
515
|
+
assigned_ids=assigned_ids)
|
|
516
|
+
|
|
517
|
+
print(get_TA_file(filename1_without_ext, 'tracked_cells_resized.tif'))
|
|
518
|
+
|
|
519
|
+
# NB it still contains small swapping errors I don't get --> why
|
|
520
|
+
# swap first then assign and assign if not swapped --> check cell
|
|
521
|
+
|
|
522
|
+
# celui qui m'interesse c'est le 2
|
|
523
|
+
# Img(int24_to_RGB(corrected_track)).save(get_TA_file(filename1_without_ext, 'tracked_cells_resized_v2.tif'),mode='raw')
|
|
524
|
+
Img(int24_to_RGB(track_t_cur)).save(get_TA_file(filename1_without_ext, 'tracked_cells_resized.tif'),mode='raw')
|
|
525
|
+
|
|
526
|
+
# with a recursion it's very good actually and really is optimized
|
|
527
|
+
|
|
528
|
+
# print(r_g_b_to_rgb(137,134,15))
|
|
529
|
+
|
|
530
|
+
print('total time all recusrsions', timer() - start_all)
|
|
531
|
+
# return track_t_cur
|
|
532
|
+
|
|
533
|
+
def track_first_frame(original_t0, assigned_ids, seed):
|
|
534
|
+
filename0_without_ext = os.path.splitext(original_t0)[0]
|
|
535
|
+
mask_t0 = Img(get_TA_file(filename0_without_ext, 'handCorrection.tif'))
|
|
536
|
+
|
|
537
|
+
if mask_t0.has_c():
|
|
538
|
+
mask_t0 = mask_t0[..., 0]
|
|
539
|
+
labels_t0 = measure.label(mask_t0, connectivity=1, background=255) # FOUR_CONNECTED
|
|
540
|
+
tracked_cells_t0 = first_image_tracking(mask_t0, labels_t0, assigned_ids=assigned_ids, seed=seed)
|
|
541
|
+
Img(int24_to_RGB(tracked_cells_t0), dimensions='hwc').save(
|
|
542
|
+
get_TA_file(filename0_without_ext, 'tracked_cells_resized.tif'), mode='raw') # should work --> DO the job
|
|
543
|
+
|
|
544
|
+
def match_by_max_overlap_lst(lst, channel_of_interest=None, recursive_assignment=True,
|
|
545
|
+
warp_using_mermaid_if_map_is_available=True, pre_register=True,
|
|
546
|
+
progress_callback=None):
|
|
547
|
+
"""
|
|
548
|
+
Performs tracking and matching on a list of images.
|
|
549
|
+
|
|
550
|
+
Args:
|
|
551
|
+
lst (list): The list of images.
|
|
552
|
+
channel_of_interest (None, optional): The channel of interest. Defaults to None.
|
|
553
|
+
recursive_assignment (bool, optional): Whether to use recursive assignment. Defaults to True.
|
|
554
|
+
warp_using_mermaid_if_map_is_available (bool, optional): Whether to warp using Mermaid if a map is available.
|
|
555
|
+
Defaults to True.
|
|
556
|
+
pre_register (bool, optional): Whether to perform pre-registration. Defaults to True.
|
|
557
|
+
progress_callback (None, optional): A callback function for progress updates. Defaults to None.
|
|
558
|
+
|
|
559
|
+
Returns:
|
|
560
|
+
None
|
|
561
|
+
|
|
562
|
+
Notes:
|
|
563
|
+
- If the list contains only one image, it performs tracking on that image and returns.
|
|
564
|
+
- Otherwise, it tracks and matches each pair of consecutive images in the list.
|
|
565
|
+
|
|
566
|
+
# Examples:
|
|
567
|
+
# >>> images = [image1, image2, image3]
|
|
568
|
+
# >>> match_by_max_overlap_lst(images, channel_of_interest=1, recursive_assignment=False)
|
|
569
|
+
"""
|
|
570
|
+
|
|
571
|
+
start_all = timer()
|
|
572
|
+
seed = 1 # always start tracking with the same seed to have roughly the same color
|
|
573
|
+
assigned_ids = get_forbidden_colors_int24()
|
|
574
|
+
|
|
575
|
+
try:
|
|
576
|
+
zipped_list = zip(lst, lst[1:])
|
|
577
|
+
except:
|
|
578
|
+
# Assume list contains only one image --> return just the first image tracking
|
|
579
|
+
track_first_frame(lst[0], assigned_ids, seed)
|
|
580
|
+
return
|
|
581
|
+
|
|
582
|
+
for iii, (original_t0, original_t1) in enumerate(zipped_list):
|
|
583
|
+
try:
|
|
584
|
+
if early_stop.stop:
|
|
585
|
+
return
|
|
586
|
+
if progress_callback is not None:
|
|
587
|
+
progress_callback.emit(int((iii * 100) / len(zipped_list)))
|
|
588
|
+
else:
|
|
589
|
+
print(str((iii * 100) / len(zipped_list)) + '%')
|
|
590
|
+
except:
|
|
591
|
+
pass
|
|
592
|
+
|
|
593
|
+
if iii == 0:
|
|
594
|
+
# Need to create the track for the first image then recursively go on
|
|
595
|
+
track_first_frame(original_t0, assigned_ids, seed)
|
|
596
|
+
|
|
597
|
+
match_by_max_overlap(original_t1, original_t0, channel_of_interest=channel_of_interest,
|
|
598
|
+
recursive_assignment=recursive_assignment,
|
|
599
|
+
warp_using_mermaid_if_map_is_available=warp_using_mermaid_if_map_is_available,
|
|
600
|
+
pre_register=pre_register)
|
|
601
|
+
|
|
602
|
+
print('total time', timer() - start_all)
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
if __name__ == '__main__':
|
|
606
|
+
import sys
|
|
607
|
+
|
|
608
|
+
if True:
|
|
609
|
+
# lst = loadlist('/E/Sample_images/sample_images_PA/mini_empty/list.lst')
|
|
610
|
+
lst = loadlist('/E/Sample_images/sample_images_PA/mini (copie)/*.png')
|
|
611
|
+
|
|
612
|
+
print(lst)
|
|
613
|
+
# match_by_max_overlap_lst(lst, recursive_assignment=False, warp_using_mermaid_if_map_is_available=True) # --> 2.76 secs without recursion
|
|
614
|
+
# match_by_max_overlap_lst(lst, recursive_assignment=True, warp_using_mermaid_if_map_is_available=True) # --> 21 secs with recursion vs 2.76 secs without recursion... --> *10
|
|
615
|
+
|
|
616
|
+
# shall I assign or not lost cells
|
|
617
|
+
# I should probably ask for prereg or not --> check
|
|
618
|
+
# or do pre reg by default because fast and useful --> I would need the channel
|
|
619
|
+
# match_by_max_overlap_lst(lst, channel_of_interest=1, recursive_assignment=True, warp_using_mermaid_if_map_is_available=False, pre_register=True) # good and does not load mermaid files yet
|
|
620
|
+
match_by_max_overlap_lst(lst, channel_of_interest=1, recursive_assignment=False, warp_using_mermaid_if_map_is_available=False, pre_register=True) # good and does not load mermaid files yet
|
|
621
|
+
sys.exit(0)
|
|
622
|
+
|
|
623
|
+
# if True:
|
|
624
|
+
# ça marche meme si la key est dupliquée...
|
|
625
|
+
# student_tuples = [
|
|
626
|
+
# ('john', 'A', 15),
|
|
627
|
+
# ('jane', 'B', 12),
|
|
628
|
+
# ('dave', 'B', 10),
|
|
629
|
+
# ('dan', 'C', 10),
|
|
630
|
+
# ]
|
|
631
|
+
# print(sorted(student_tuples, key=lambda student: student[2])) # sort by age
|
|
632
|
+
#
|
|
633
|
+
# sys.exit(0)
|
|
634
|
+
|
|
635
|
+
from timeit import default_timer as timer
|
|
636
|
+
|
|
637
|
+
start = timer()
|
|
638
|
+
match_by_max_overlap(
|
|
639
|
+
'/E/Sample_images/sample_images_PA/trash_test_mem/trash_registration_network/1/210930_EcadKI_mel_40-54hAPF_ON.lif - Series011_t001.tif',
|
|
640
|
+
'/E/Sample_images/sample_images_PA/trash_test_mem/trash_registration_network/1/210930_EcadKI_mel_40-54hAPF_ON.lif - Series011_t000_fake.tif')
|
|
641
|
+
# match_by_max_overlap(Img('/E/Sample_images/sample_images_PA/trash_test_mem/trash_registration_network/1/210930_EcadKI_mel_40-54hAPF_ON.lif - Series011_t001/handCorrection.tif'), RGB_to_int24(Img('/E/Sample_images/sample_images_PA/trash_test_mem/trash_registration_network/1/warped_mask.tif')))
|
|
642
|
+
# match_by_amx_overlap(Img('/E/Sample_images/sample_images_PA/trash_test_mem/trash_registration_network/1/210930_EcadKI_mel_40-54hAPF_ON.lif - Series011_t001/handCorrection.tif'),RGB_to_int24(Img('/E/Sample_images/sample_images_PA/trash_test_mem/trash_registration_network/1/210930_EcadKI_mel_40-54hAPF_ON.lif - Series011_t000/tracked_cells_resized.tif'))) # ça marche vraiment mieux en utilisant la pre registration en fait!!!
|
|
643
|
+
|
|
644
|
+
# need pre reg it
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
print('stop', timer() - start)
|
|
650
|
+
|
|
651
|
+
# faire une pipeline qui peut etre va generer un shifted track or un shifted --> ideally I should just put this code within mermaid --> it would be a new tracking --> that would read the cell label file and
|
|
652
|
+
|
|
653
|
+
# finalize this
|