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.
Files changed (162) hide show
  1. batoolset/GUI/__init__.py +0 -0
  2. batoolset/GUI/list_gui.py +513 -0
  3. batoolset/GUI/multi_image_display.py +989 -0
  4. batoolset/GUI/open.py +325 -0
  5. batoolset/GUI/overlay_hints.py +45 -0
  6. batoolset/GUI/paint2.py +1345 -0
  7. batoolset/GUI/scrollablepaint.py +1152 -0
  8. batoolset/IJ_ROIs/__init__.py +0 -0
  9. batoolset/IJ_ROIs/tools.py +40 -0
  10. batoolset/PATH/__init__.py +0 -0
  11. batoolset/PATH/tools.py +79 -0
  12. batoolset/SQLite_tools/__init__.py +0 -0
  13. batoolset/SQLite_tools/tools.py +840 -0
  14. batoolset/__init__.py +0 -0
  15. batoolset/binary/__init__.py +0 -0
  16. batoolset/binary/tools.py +123 -0
  17. batoolset/binarytools/__init__.py +0 -0
  18. batoolset/binarytools/cell_center_detector.py +290 -0
  19. batoolset/clipboard_tools/__init__.py +0 -0
  20. batoolset/clipboard_tools/tools.py +7 -0
  21. batoolset/colors/__init__.py +0 -0
  22. batoolset/colors/colorgen.py +193 -0
  23. batoolset/colors/tools.py +22 -0
  24. batoolset/command_line/__init__.py +0 -0
  25. batoolset/command_line/tools.py +18 -0
  26. batoolset/dialogs/__init__.py +0 -0
  27. batoolset/dialogs/opensave.py +228 -0
  28. batoolset/dicts/__init__.py +0 -0
  29. batoolset/dicts/tools.py +299 -0
  30. batoolset/dims/__init__.py +0 -0
  31. batoolset/dims/tools.py +83 -0
  32. batoolset/draw/__init__.py +0 -0
  33. batoolset/draw/shapes/Position.py +183 -0
  34. batoolset/draw/shapes/__init__.py +0 -0
  35. batoolset/draw/shapes/automated_alignment_drawing_refactored.py +346 -0
  36. batoolset/draw/shapes/circle2d.py +99 -0
  37. batoolset/draw/shapes/compute_optimal_size_all_merged.py +317 -0
  38. batoolset/draw/shapes/ellipse2d.py +336 -0
  39. batoolset/draw/shapes/freehand2d.py +235 -0
  40. batoolset/draw/shapes/group.py +1830 -0
  41. batoolset/draw/shapes/image2d.py +2469 -0
  42. batoolset/draw/shapes/line2d.py +575 -0
  43. batoolset/draw/shapes/point2d.py +257 -0
  44. batoolset/draw/shapes/polygon2d.py +357 -0
  45. batoolset/draw/shapes/polyline2d.py +235 -0
  46. batoolset/draw/shapes/rect2d.py +388 -0
  47. batoolset/draw/shapes/rectangle2d.py +601 -0
  48. batoolset/draw/shapes/scalebar.py +304 -0
  49. batoolset/draw/shapes/serializablefont.py +126 -0
  50. batoolset/draw/shapes/serializableguiparams.py +10 -0
  51. batoolset/draw/shapes/square2d.py +103 -0
  52. batoolset/draw/shapes/textorientation.py +45 -0
  53. batoolset/draw/shapes/tools.py +467 -0
  54. batoolset/draw/shapes/transform2D.py +350 -0
  55. batoolset/draw/shapes/txt2d.py +550 -0
  56. batoolset/draw/widgets/__init__.py +0 -0
  57. batoolset/draw/widgets/col.py +343 -0
  58. batoolset/draw/widgets/image_group.py +248 -0
  59. batoolset/draw/widgets/image_organizer.py +96 -0
  60. batoolset/draw/widgets/paint.py +184 -0
  61. batoolset/draw/widgets/vectorial.py +257 -0
  62. batoolset/figure/__init__.py +0 -0
  63. batoolset/figure/alignment.py +814 -0
  64. batoolset/figure/column.py +1117 -0
  65. batoolset/figure/fig_tools.py +285 -0
  66. batoolset/figure/minimal_debugger_scale_etc.py +139 -0
  67. batoolset/figure/panel.py +697 -0
  68. batoolset/figure/row.py +852 -0
  69. batoolset/figure/user_selection.py +287 -0
  70. batoolset/files/__init__.py +0 -0
  71. batoolset/files/tools.py +1321 -0
  72. batoolset/images/__init__.py +0 -0
  73. batoolset/images/tools.py +81 -0
  74. batoolset/img.py +5216 -0
  75. batoolset/linux/__init__.py +0 -0
  76. batoolset/linux/tools.py +72 -0
  77. batoolset/lists/__init__.py +0 -0
  78. batoolset/lists/tools.py +436 -0
  79. batoolset/luts/__init__.py +0 -0
  80. batoolset/luts/lut_minimal_test.py +1207 -0
  81. batoolset/matplolib/__init__.py +0 -0
  82. batoolset/matplolib/tools.py +44 -0
  83. batoolset/np_tools/__init__.py +0 -0
  84. batoolset/np_tools/tools.py +252 -0
  85. batoolset/np_tools/trash.py +15 -0
  86. batoolset/pandas_tools/__init__.py +0 -0
  87. batoolset/pandas_tools/tools.py +880 -0
  88. batoolset/partials/__init__.py +0 -0
  89. batoolset/partials/tools.py +83 -0
  90. batoolset/plot_tools/__init__.py +0 -0
  91. batoolset/plot_tools/tools.py +70 -0
  92. batoolset/pyqt/__init__.py +0 -0
  93. batoolset/pyqt/tools.py +691 -0
  94. batoolset/re_tools/__init__.py +0 -0
  95. batoolset/re_tools/tools.py +35 -0
  96. batoolset/serialization/__init__.py +0 -0
  97. batoolset/serialization/tools.py +1192 -0
  98. batoolset/sets/__init__.py +0 -0
  99. batoolset/sets/tools.py +109 -0
  100. batoolset/settings/__init__.py +0 -0
  101. batoolset/settings/global_settings.py +134 -0
  102. batoolset/strings/__init__.py +0 -0
  103. batoolset/strings/tools.py +225 -0
  104. batoolset/ta/__init__.py +0 -0
  105. batoolset/ta/database/__init__.py +0 -0
  106. batoolset/ta/database/advanced_sql_plotter.py +1170 -0
  107. batoolset/ta/database/my_qt_table.py +79 -0
  108. batoolset/ta/database/preview_and_edit_sqlite_db.py +405 -0
  109. batoolset/ta/database/sql.py +2141 -0
  110. batoolset/ta/database/sql_column_name_dialog.py +122 -0
  111. batoolset/ta/measurements/TAmeasures.py +2226 -0
  112. batoolset/ta/measurements/__init__.py +0 -0
  113. batoolset/ta/measurements/measurements3D/__init__.py +0 -0
  114. batoolset/ta/measurements/measurements3D/get_point_on_surface_if_centroid_is_bad.py +175 -0
  115. batoolset/ta/measurements/measurements3D/height_map_to_projection.py +82 -0
  116. batoolset/ta/measurements/measurements3D/measures3D.py +208 -0
  117. batoolset/ta/measurements/measurements3D/triangulate.py +331 -0
  118. batoolset/ta/measurements/nematic.py +562 -0
  119. batoolset/ta/measurements/nematic_measurements.py +107 -0
  120. batoolset/ta/segmentation/__init__.py +0 -0
  121. batoolset/ta/segmentation/neo_wshed.py +314 -0
  122. batoolset/ta/selections/__init__.py +0 -0
  123. batoolset/ta/selections/selection.py +329 -0
  124. batoolset/ta/tracking/__init__.py +0 -0
  125. batoolset/ta/tracking/last_tracking_based_on_matching_or_on_translation_from_mermaid_warp.py +653 -0
  126. batoolset/ta/tracking/local_to_track_correspondance.py +138 -0
  127. batoolset/ta/tracking/rapid_detection_of_vertices.py +517 -0
  128. batoolset/ta/tracking/registration.py +108 -0
  129. batoolset/ta/tracking/swap_detector_and_fixer.py +296 -0
  130. batoolset/ta/tracking/track_correction.py +238 -0
  131. batoolset/ta/tracking/tracking_error_detector_and_fixer.py +3099 -0
  132. batoolset/ta/tracking/tracking_yet_another_approach_pyramidal_registration_n_neo_swapping_correction.py +725 -0
  133. batoolset/ta/utils/TA_tools.py +43 -0
  134. batoolset/ta/utils/__init__.py +0 -0
  135. batoolset/ta/utils/rps_tools.py +1783 -0
  136. batoolset/tests/__init__.py +0 -0
  137. batoolset/tests/rps_tools.py +51 -0
  138. batoolset/tests/tools.py +10 -0
  139. batoolset/tools/__init__.py +0 -0
  140. batoolset/tools/early_stopper_class.py +9 -0
  141. batoolset/tools/guided_data_recoverer.py +110 -0
  142. batoolset/tools/logger.py +100 -0
  143. batoolset/tools/mytimer.py +31 -0
  144. batoolset/tools/prompt_color.py +160 -0
  145. batoolset/tools/qthandler.py +118 -0
  146. batoolset/uitools/__init__.py +0 -0
  147. batoolset/uitools/blinker.py +56 -0
  148. batoolset/unsafe/__init__.py +0 -0
  149. batoolset/unsafe/tools.py +115 -0
  150. batoolset/utils/__init__.py +0 -0
  151. batoolset/utils/commontools.py +158 -0
  152. batoolset/utils/loadlist.py +728 -0
  153. batoolset/version.py +10 -0
  154. batoolset/xml/__init__.py +0 -0
  155. batoolset/xml/tools.py +65 -0
  156. batoolset/zip_tools/__init__.py +0 -0
  157. batoolset/zip_tools/tools.py +76 -0
  158. batoolset-0.1.0.dist-info/LICENSE +24 -0
  159. batoolset-0.1.0.dist-info/METADATA +45 -0
  160. batoolset-0.1.0.dist-info/RECORD +162 -0
  161. batoolset-0.1.0.dist-info/WHEEL +5 -0
  162. batoolset-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,2226 @@
1
+ import math
2
+ import os.path
3
+ from multiprocessing import Pool
4
+ from scipy import ndimage
5
+ import random
6
+ from scipy.spatial.distance import squareform
7
+ from skimage.measure._regionprops import RegionProperties
8
+ from batoolset.img import Img, pad_border_xy
9
+ from skimage.measure import label, regionprops
10
+ import numpy as np
11
+ import traceback
12
+ from batoolset.ta.measurements.nematic import compute_stretch_nematic
13
+ from batoolset.tools.early_stopper_class import early_stop
14
+ from batoolset.utils.loadlist import loadlist
15
+ from batoolset.ta.database.sql import TAsql, get_property
16
+ from batoolset.ta.segmentation.neo_wshed import wshed
17
+ # from epyseg.ta.clones.clone_fuser import distance_between_points
18
+ from batoolset.ta.measurements.nematic_measurements import compute_polarity_nematic
19
+ from batoolset.ta.measurements.measurements3D.get_point_on_surface_if_centroid_is_bad import point_on_surface
20
+ from batoolset.ta.measurements.measurements3D.measures3D import compute_3D_surfacearea, perimeter_3D
21
+ from batoolset.ta.measurements.measurements3D.triangulate import triangulate
22
+ from batoolset.ta.tracking.rapid_detection_of_vertices import detect_vertices_and_bonds, cantor_color_bonds, neighbors8
23
+ from timeit import default_timer as timer
24
+ from batoolset.files.tools import smart_name_parser
25
+ from batoolset.ta.tracking.tracking_error_detector_and_fixer import get_border_cells, get_border_cells_plus_one, \
26
+ get_cells_and_their_neighbors_from_image
27
+ from batoolset.ta.utils.rps_tools import pavlidis, compute_distance_between_consecutive_points
28
+ import math
29
+ from math import sqrt
30
+ from batoolset.tools.logger import TA_logger # logging
31
+
32
+ logger = TA_logger()
33
+
34
+ __DEBUG__ = False
35
+
36
+ import numpy as np
37
+ from math import sqrt, atan, degrees
38
+ from skimage.measure import label, regionprops
39
+
40
+ def distance_between_points_deprecated(p1, p2):
41
+ """
42
+ Deprecated function to compute the distance between two points in 2D.
43
+
44
+ Args:
45
+ p1 (tuple): First point coordinates (x, y).
46
+ p2 (tuple): Second point coordinates (x, y).
47
+
48
+ Returns:
49
+ float: Distance between the points.
50
+
51
+ """
52
+ return sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
53
+
54
+
55
+ def distance_between_points_nD(p1, p2, rescaling_factor=None):
56
+ """
57
+ Computes the distance between two points in n-dimensional space.
58
+
59
+ Args:
60
+ p1 (numpy.ndarray): First point coordinates.
61
+ p2 (numpy.ndarray): Second point coordinates.
62
+ rescaling_factor (float, optional): Rescaling factor for real distance computation. Defaults to None.
63
+
64
+ Returns:
65
+ float: Distance between the points.
66
+
67
+ Examples:
68
+ >>> p1 = np.array([1, 2, 3])
69
+ >>> p2 = np.array([4, 5, 6])
70
+ >>> distance_between_points_nD(p1, p2)
71
+ 5.196152422706632
72
+
73
+ """
74
+ return distance_between_points(p1, p2, rescaling_factor=rescaling_factor)
75
+
76
+
77
+ def distance_between_points(p1, p2, rescaling_factor=None):
78
+ """
79
+ Computes n-dimensional distance between points (2D, 3D, nD) and can return real distance instead of pixel distance
80
+ when the optional rescaling_factor is set.
81
+
82
+ Args:
83
+ p1 (numpy.ndarray): First point coordinates.
84
+ p2 (numpy.ndarray): Second point coordinates.
85
+ rescaling_factor (numpy.ndarray, optional): Voxel scaling factors corresponding to the dimensions. Defaults to None.
86
+
87
+ Returns:
88
+ float: Distance between the points.
89
+
90
+ Examples:
91
+ >>> p1 = np.array([1, 2, 3])
92
+ >>> p2 = np.array([4, 5, 6])
93
+ >>> distance_between_points(p1, p2)
94
+ 5.196152422706632
95
+ >>> p1 = np.array([1, 2, 3])
96
+ >>> p2 = np.array([4, 5, 6])
97
+ >>> rescaling_factor = [0.0691888, 0.0691888, 0.2500000] # e.g. conversion of pixels to µm
98
+ >>> distance_between_points(p1, p2, rescaling_factor) # dist in µm
99
+ 0.8053990444605208
100
+ >>> p1 = np.array([[1, 2, 3],[4, 5, 6]])
101
+ >>> p2 = np.array([[1, 2, 3],[4, 5, 6]])
102
+ >>> rescaling_factor = [0.0691888, 0.0691888, 0.2500000] # e.g. conversion of pixels to µm
103
+ >>> distance_between_points(p1, p2, rescaling_factor) # dist in µm
104
+ array([0., 0.])
105
+ >>> p1 = np.array([[4, 5, 6],[1, 2, 3]])
106
+ >>> p2 = np.array([[1, 2, 3],[4, 5, 6]])
107
+ >>> rescaling_factor = [0.0691888, 0.0691888, 0.2500000] # e.g. conversion of pixels to µm
108
+ >>> distance_between_points(p1, p2, rescaling_factor) # dist in µm
109
+ array([0.80539904, 0.80539904])
110
+ """
111
+
112
+ if not isinstance(p1, np.ndarray):
113
+ p1 = np.asarray(p1)
114
+ if not isinstance(p2, np.ndarray):
115
+ p2 = np.asarray(p2)
116
+
117
+ if rescaling_factor is not None:
118
+ p1 = p1 * rescaling_factor
119
+ p2 = p2 * rescaling_factor
120
+
121
+ # that should always work but is that True --> do tests
122
+ axis = 0
123
+ if len(p1.shape)==2:
124
+ axis=1
125
+ return np.sqrt(np.sum(np.square(p1 - p2), axis=axis))
126
+
127
+
128
+
129
+ def get_sum_and_avg_intensity(original_image, reg, idx=None, y_shift_to_transform_local_coords_to_global_coords=0,
130
+ x_shift_to_transform_local_coords_to_global_coords=0):
131
+ """
132
+ Computes the sum and average intensity of a region in an image.
133
+
134
+ Args:
135
+ original_image (numpy.ndarray): Original image.
136
+ reg (numpy.ndarray or regionprops): Region of interest.
137
+ idx (int, optional): Index of the region if reg is a list of regionprops. Defaults to None.
138
+ y_shift_to_transform_local_coords_to_global_coords (int, optional): Y shift to transform local coordinates to global coordinates. Defaults to 0.
139
+ x_shift_to_transform_local_coords_to_global_coords (int, optional): X shift to transform local coordinates to global coordinates. Defaults to 0.
140
+
141
+ Returns:
142
+ tuple: Sum and average intensity of the region.
143
+
144
+ # Examples:
145
+ # >>> image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
146
+ # >>> region = np.array([[0, 0], [1, 1]])
147
+ # >>> get_sum_and_avg_intensity(image, region)
148
+ # (6, 3.0)
149
+
150
+ """
151
+ if len(original_image.shape) >= 3:
152
+ axis = 0
153
+ else:
154
+ axis = None
155
+
156
+ if idx is not None:
157
+ final_reg = reg[idx]
158
+ else:
159
+ final_reg = reg
160
+
161
+ if isinstance(final_reg, RegionProperties):
162
+ ys = final_reg.coords[:, 0]
163
+ xs = final_reg.coords[:, 1]
164
+ else:
165
+ ys = final_reg[:, 0]
166
+ xs = final_reg[:, 1]
167
+
168
+ sum_bd_intensity = np.sum(original_image[
169
+ ys + y_shift_to_transform_local_coords_to_global_coords,
170
+ xs + x_shift_to_transform_local_coords_to_global_coords],
171
+ axis=axis)
172
+ avg_bd_intensity = sum_bd_intensity / float(len(xs))
173
+
174
+ return sum_bd_intensity, avg_bd_intensity
175
+
176
+
177
+ def get_orientation(first_vertex, second_vertex):
178
+ """
179
+ Computes the orientation (in degrees) between two vertices.
180
+
181
+ Args:
182
+ first_vertex (tuple): First vertex coordinates (x, y).
183
+ second_vertex (tuple): Second vertex coordinates (x, y).
184
+
185
+ Returns:
186
+ float: Orientation between the vertices.
187
+
188
+ Examples:
189
+ >>> v1 = (1, 2)
190
+ >>> v2 = (4, 5)
191
+ >>> get_orientation(v1, v2)
192
+ 45.0
193
+
194
+ """
195
+ bd_orientation = degrees(atan_RAD(first_vertex[0] - second_vertex[0], first_vertex[1] - second_vertex[1]))
196
+ while bd_orientation >= 180.:
197
+ bd_orientation -= 180.
198
+ return bd_orientation
199
+
200
+ def atan_RAD(y, x):
201
+ """
202
+ Computes the arctangent of y/x in radians, taking into account the quadrant.
203
+
204
+ Args:
205
+ y (float): y-coordinate.
206
+ x (float): x-coordinate.
207
+
208
+ Returns:
209
+ float: Arctangent value in radians.
210
+
211
+ Notes:
212
+ This function uses a custom implementation to handle the quadrant correctly.
213
+
214
+ """
215
+ if abs(x) == 0.:
216
+ return math.pi / 2.
217
+ res = math.atan(abs(y) / abs(x))
218
+ res = math.pi - res if x <= 0. and y > 0. else res
219
+ res = math.pi + res if x <= 0. and y <= 0. else res
220
+ res = 2. * math.pi - res if x > 0. and y <= 0. else res
221
+ return res
222
+
223
+
224
+ def fill_missing_with_Nones(database):
225
+ """
226
+ Fills missing entries in a database dictionary with None values.
227
+
228
+ Args:
229
+ database (dict): Database dictionary.
230
+
231
+ Returns:
232
+ dict: Updated database with missing entries filled with None.
233
+
234
+ """
235
+ max_length = 0
236
+ for k, v in database.items():
237
+ max_length = max(max_length, len(v))
238
+ for k, v in database.items():
239
+ if len(v) != max_length:
240
+ missing = [None] * (max_length - len(v))
241
+ v.extend(missing)
242
+ return database
243
+
244
+ def TAMeasurements(file_or_list, __forced_orig=None, __forced_cells=None, __forced_heightmap=None,
245
+ measure_polarity=False, measure_3D=False, min_cell_size=10, progress_callback=None,
246
+ bond_cut_off=2, multi_threading=True): # if less or equal to 2 --> is not a bond but is a vertex
247
+
248
+ # print('file_or_list', type(file_or_list))
249
+ # we MT the whole stuff because it's fairly easy to do so
250
+ if isinstance(file_or_list, list):
251
+ start = timer()
252
+ if multi_threading:
253
+ from tqdm import tqdm
254
+ from functools import partial
255
+ import sys
256
+ import multiprocessing
257
+ import gc
258
+ # given that python copies all the content of the memory for multiprocessing, it's probably a good idea to clean it up
259
+ gc.collect()
260
+ # import platform
261
+ #
262
+ # if platform.system() == "Darwin":
263
+ # multiprocessing.set_start_method('spawn')
264
+
265
+ nb_procs = multiprocessing.cpu_count()-1
266
+ if nb_procs<=0:
267
+ nb_procs = 1
268
+ print('using',nb_procs, 'processors')
269
+
270
+ # nb none of these alternatives work on macOS X... I guess this may have to do that I am launching threads from within a pyqt thread which may not be a good idea
271
+ # from concurrent.futures import ThreadPoolExecutor
272
+ # from concurrent.futures import ProcessPoolExecutor
273
+ with Pool(processes=nb_procs) as pool:
274
+ # with ThreadPoolExecutor(max_workers=nb_procs) as pool:
275
+ # with ProcessPoolExecutor(max_workers=nb_procs) as pool:
276
+ # pool = Pool(processes=nb_procs)
277
+ process = partial(TAMeasurements, measure_polarity=measure_polarity, measure_3D=measure_3D,
278
+ min_cell_size=min_cell_size, bond_cut_off=bond_cut_off)
279
+ for i, _ in enumerate(tqdm(pool.imap_unordered(process, file_or_list), total=len(file_or_list))):
280
+ # for i, _ in enumerate(tqdm(pool.map(process, file_or_list), total=len(file_or_list))): # does not work with threadpool executor I am doing smthg wrong ???
281
+ # pass
282
+ # sys.stderr.write('\rdone {0:%}'.format(i / len(merge_names))) # --> I could use that to plot with the other progressbar --> ok
283
+ # cool --> I can use that to display progress in the other progress bar --> the QT one
284
+ # pass
285
+ if early_stop.stop:
286
+ # for multiprocpool
287
+ pool.close()
288
+ pool.join()
289
+ return
290
+ if progress_callback is not None:
291
+ progress_callback.emit(int((i / len(file_or_list)) * 100))
292
+
293
+ # not sure I should put the lines below...
294
+ # https://stackoverflow.com/questions/38271547/when-should-we-call-multiprocessing-pool-join --> maybe still a good idea to keep that
295
+ # for multiprocpool
296
+ pool.close()
297
+ pool.join()
298
+ print('total time', timer() - start)
299
+ return
300
+ else:
301
+ for iii, file in enumerate(file_or_list):
302
+ try:
303
+ if early_stop.stop:
304
+ return
305
+ if progress_callback is not None:
306
+ progress_callback.emit(int((iii / len(file_or_list)) * 100))
307
+ else:
308
+ print(str((iii / len(file_or_list)) * 100) + '%')
309
+ except:
310
+ pass
311
+ try:
312
+ TAMeasurements(file, measure_polarity=measure_polarity, measure_3D=measure_3D,
313
+ min_cell_size=min_cell_size, bond_cut_off=bond_cut_off)
314
+ except:
315
+ if __DEBUG__:
316
+ print('an error occurred while processing file ' + str(file))
317
+ traceback.print_exc()
318
+ logger.error('an error occurred while processing file ' + str(file))
319
+ print('total time', timer() - start)
320
+ return
321
+
322
+ start = timer()
323
+
324
+
325
+ if __DEBUG__:
326
+ print('processing file',file_or_list)
327
+ #
328
+ bonds_associated_to_a_given_cell = {}
329
+ bond_lengths_associated_to_a_given_cell = {}
330
+ local_bond_ID_and_px_count = {}
331
+
332
+ TA_path = None
333
+ db_path = None
334
+
335
+ # original_image = Img('/E/Sample_images/sample_images_PA/mini/focused_Series012.png')[..., 1]
336
+
337
+ if early_stop.stop == True:
338
+ # print('early stop')
339
+ return
340
+
341
+ # instantiate the different databases
342
+
343
+ # some will be dynamically added such as the channels --> but will be a pb if several images have different channel nb --> think about an easy fix ???
344
+ # things from TA that also need be added
345
+
346
+ # TO BE ADDED vx_coords_cells sum_px_intensity_cells_ch1 S1_stretch_cells vx_coords_cells orientation_cells ALSO NEED CENTER OF MASS FOR EACH CHANNEL!!! sum_px_intensity_perimeter_ch1 P1_polarity_ch1 P1_polarity_ch1_normalized V1_polarity_ch1 x_centroid_intensity_weighted_ch1 local_id_of_bonds
347
+ vertices_2D = {'local_ID': [],
348
+ 'x': [],
349
+ 'y': [],
350
+ 'is_border': [],
351
+ 'is_border_plus_one': [],
352
+ }
353
+ # axis_major_length
354
+ # axis_minor_length
355
+ # eccentricity
356
+ # orientation ranging from -pi/2 to pi/2 counter-clockwise.
357
+ cells_2D = {'local_ID': [],
358
+ 'cytoplasmic_area': [],
359
+ 'area': [],
360
+ # 'major_axis_length': [],
361
+ # 'minor_axis_length': [],
362
+ 'orientation': [],
363
+ 'elongation': [],
364
+ 'S1': [],
365
+ 'S2': [],
366
+ 'pixel_within_cell_x': [],
367
+ 'pixel_within_cell_y': [],
368
+ 'centroid_x': [],
369
+ 'centroid_y': [],
370
+ 'first_pixel_x': [],
371
+ 'first_pixel_y': [],
372
+ 'perimeter': [],
373
+ 'perimeter_pixel_count': [],
374
+ 'vertices': [],
375
+ 'nb_of_vertices_or_neighbours': [],
376
+ 'nb_of_vertices_or_neighbours_cut_off': [],
377
+ 'bond_cut_off': [], # --> same as bd_size_cut_off in TA
378
+ 'bonds': [],
379
+ 'is_border': [],
380
+ # formerly is_border_cell --> smarter this way so that I can have the same code for all the databases
381
+ 'is_border_plus_one': [], # TODO
382
+ } # local_id_cells --> do I need that instead --> think about it
383
+ cells_3D = {'local_ID': [],
384
+ # 'centroid_z': [], # in fact does that make sense to have that and there are several ways to get it --> wait and see if users or I need and implement it the smart way then
385
+ # 'pixel_within_cell_z': [], # in fact does that make sense to have that and there are several ways to get it --> wait and see if users or I need and implement it the smart way then
386
+ 'area3D': [],
387
+ # NB adding 3D is smarter for using proper natural join because otherwise it does not work well
388
+ 'area_flat_height': [],
389
+ 'perimeter3D': [],
390
+ }
391
+ # TO BE ADDED TO BONDS DYNAMICALLY: sum_px_int_vertices_excluded_ch1 sum_px_int_vertices_included_ch1
392
+ bonds_2D = {'local_ID': [],
393
+ 'length': [],
394
+ 'pixel_count': [],
395
+ 'orientation': [],
396
+ # 'vx_1_x': [],
397
+ # 'vx_1_y': [],
398
+ # 'vx_2_x': [],
399
+ # 'vx_2_y': [],
400
+ 'vx_1': [],
401
+ 'vx_2': [],
402
+ 'first_pixel_x': [],
403
+ 'first_pixel_y': [],
404
+ 'cell_id1_around_bond': [],
405
+ 'cell_id2_around_bond': [],
406
+ 'is_border': [], # is_border_bond # new addition but can be useful
407
+ 'is_border_plus_one': [],
408
+ }
409
+ bonds_3D = {'local_ID': [],
410
+ 'length3D': [],
411
+ 'vx_1_z': [], # do I want that --> yes, may be useful in fact...
412
+ 'vx_2_z': [],
413
+ # 'first_pixel_z': [],
414
+ }
415
+ # see what else I can add and how I can handle all of these things myself
416
+ # cells_2D
417
+
418
+ if __DEBUG__:
419
+ print('debug #1')
420
+
421
+ # TODO handle several channels for polarity and alike
422
+ if __forced_orig is not None:
423
+ original_image = __forced_orig # if no shift max and min should always be 255 otherwise there is an error somewhere
424
+ else:
425
+ original_image = Img(file_or_list)
426
+ TA_path = smart_name_parser(file_or_list, ordered_output='full_no_ext')
427
+ db_path = os.path.join(TA_path, 'pyTA.db')
428
+
429
+ # if this path is None then debug --> display the image otherwise save it then save stuff
430
+
431
+ cells = None
432
+ if __forced_cells is not None:
433
+ cells = __forced_cells # TODO --> hack this
434
+ if len(cells.shape) >= 3:
435
+ cells = cells[..., 0]
436
+ else:
437
+ handCorrection1, handCorrection2 = smart_name_parser(file_or_list,
438
+ ordered_output=['handCorrection.png',
439
+ 'handCorrection.tif'])
440
+ if os.path.isfile(handCorrection2):
441
+ cells = Img(handCorrection2)
442
+ elif os.path.isfile(handCorrection1):
443
+ cells = Img(handCorrection1)
444
+ if cells is None:
445
+ if __DEBUG__:
446
+ print('File not found ' + str(handCorrection2) + ' please segment the images first')
447
+ logger.error('File not found ' + str(handCorrection2) + ' please segment the images first')
448
+ return
449
+ if len(cells.shape) >= 3:
450
+ cells = cells[..., 0]
451
+
452
+ if __DEBUG__:
453
+ print('debug #2')
454
+
455
+ # I need add a border to this image otherwise there will be a bug --> must be done in any case
456
+ if min_cell_size is not None and min_cell_size > 0:
457
+ # plt.imshow(cells)
458
+ # plt.show()
459
+ cells = wshed(cells, seeds='mask', min_seed_area=min_cell_size) # restore border
460
+ # plt.imshow(cells)
461
+ # plt.show()
462
+
463
+ # add a fake border to the image --> that is absolutely necessary !!! --> KEEP
464
+ cells = pad_border_xy(cells, mode=255) # add a wite border to the seg mask
465
+ # plt.imshow(cells)
466
+ # plt.show()
467
+
468
+ # need save the mask
469
+ if TA_path is not None:
470
+ Img(cells, dimensions='hw').save(os.path.join(TA_path,
471
+ 'handCorrection.tif')) # TODO --> replace this with a clean save function because that is a bit complicated what i do here!!!
472
+ else:
473
+ # plt.imshow(cells)
474
+ # plt.show()
475
+ pass
476
+
477
+
478
+ if __DEBUG__:
479
+ print('debug #3')
480
+
481
+ # TODO also store vertices and bonds ids --> a quite good idea in fact --> can be used for plots --> fairly good idea
482
+
483
+ height_map = None
484
+ if measure_3D:
485
+ if __forced_heightmap is not None:
486
+ height_map = __forced_heightmap
487
+ else:
488
+ height_map_file = smart_name_parser(file_or_list, ordered_output=['height_map.tif'])[0]
489
+
490
+ # ideally should apply the rescaling factor to the heightmap if any or assume rescaling factor is 1 --> see and make sure everything is done in there
491
+ if os.path.isfile(height_map_file):
492
+ try:
493
+ height_map = Img(height_map_file)
494
+ if db_path is not None:
495
+ try:
496
+ voxel_z_over_x_ratio = get_property(db_path, 'voxel_z_over_x_ratio') # imp
497
+ except:
498
+ if __DEBUG__:
499
+ print('voxel_z_over_x_ratio property not found in the db "' + str(
500
+ db_path) + '", assuming scaling factor is 1, which is very unlikely.')
501
+ logger.warning('voxel_z_over_x_ratio property not found in the db "' + str(
502
+ db_path) + '", assuming scaling factor is 1, which is very unlikely.')
503
+ else:
504
+ voxel_z_over_x_ratio = 1. # no change to the heightmap
505
+ # logger.warning('db not found, assuming scaling factor is 1, which is very unlikely.')
506
+ if voxel_z_over_x_ratio != 1.:
507
+ height_map = height_map * voxel_z_over_x_ratio
508
+ if __DEBUG__:
509
+ print(
510
+ 'applying aspect ratio ' + str(voxel_z_over_x_ratio) + ' to the height map of file ' + str(
511
+ file_or_list))
512
+ logger.info(
513
+ 'applying aspect ratio ' + str(voxel_z_over_x_ratio) + ' to the height map of file ' + str(
514
+ file_or_list))
515
+ except:
516
+ # logger.error(
517
+ # 'height map' + str(height_map_file) + ' could not be loaded, 3D measurements are not possible')
518
+ traceback.print_exc()
519
+ pass
520
+ if height_map is None:
521
+ if __DEBUG__:
522
+ print('height map' + str(height_map_file) + ' file is missing, 3D measurements are not possible')
523
+ logger.error('height map' + str(height_map_file) + ' file is missing, 3D measurements are not possible') # log that there is a missing height map and that not much can be done
524
+
525
+
526
+ if __DEBUG__:
527
+ print('debug #4')
528
+ # height_map = None #Img('/E/Sample_images/sample_images_PA/mini/focused_Series012.png')[..., 1]
529
+ # height_map = Img('/E/Sample_images/sample_images_PA/mini/focused_Series012.png')[..., 0] # another good test because all is 0 there --> marche car aire est proche de l'aire 2D par contre pr handcorrection ça marche pas car tres different de l'aire 2D --> see why and how to fix it
530
+ # height_map = Img('/E/Sample_images/sample_images_PA/mini/focused_Series012/handCorrection.png')[..., 0] # good for a test as all heights are the same... --> in fact that makes sense since some heigts are 0 and some are 255 since the centroid of the polygon is always 0
531
+
532
+ # all seems to work now
533
+ lab_cells = label(cells, connectivity=1, background=255)
534
+
535
+ if __DEBUG__:
536
+ print('debug #4a')
537
+ if TA_path is not None:
538
+ Img(lab_cells, dimensions='hw').save(os.path.join(TA_path,
539
+ 'cells.tif')) # Pretty much the same as cell_identity.tif in TA --> cool and more useful in a way!!!
540
+ else:
541
+ # plt.imshow(cells)
542
+ # plt.show()
543
+ pass
544
+ if __DEBUG__:
545
+ print('debug #4b')
546
+ #
547
+ # vertices = detect_vertices_and_bonds(lab_cells, boundary_color=0)
548
+ vertices = detect_vertices_and_bonds(lab_cells, boundary_color=0)
549
+
550
+ if __DEBUG__:
551
+ print('debug #4c')
552
+
553
+ width = vertices.shape[1]
554
+ height = vertices.shape[0]
555
+
556
+
557
+ if __DEBUG__:
558
+ print('debug #4d')
559
+ # ok whereas the other one gives a bug
560
+
561
+ # c'est ce code qui donne une seg fault
562
+ try:
563
+ border_cells = get_border_cells(lab_cells, bg_color=0)
564
+ except:
565
+ traceback.print_exc()
566
+ logger.error('Could not detect border cells')
567
+ border_cells=[]
568
+ # border_cells=[]
569
+ # border_cells_plus_one = get_border_cells_plus_one(get_cells_and_their_neighbors_from_image(lab_cells, vertices=np.asarray(np.where(vertices==255))), border_cells, remove_border_cells=True)
570
+
571
+ if __DEBUG__:
572
+ print('debug #4e')
573
+
574
+ # this is super slow --> 4 secs --> that really sucks --> but in fact the overhead is just for the first image then it's faster --> that probably would work
575
+ # works as nicely with pixels of the boundary
576
+ # border_cells_plus_one = get_border_cells_plus_one(get_cells_and_their_neighbors_from_image(lab_cells, vertices=np.stack(np.where(vertices != 0), axis=1),bg_color=0), border_cells, remove_border_cells=True)
577
+ border_cells_plus_one = get_border_cells_plus_one(
578
+ get_cells_and_their_neighbors_from_image(lab_cells, vertices=np.stack(np.where(lab_cells == 0), axis=1),
579
+ bg_color=0), border_cells,
580
+ remove_border_cells=True) # this is as fast and detects nicely the cells having no vertices --> maybe I should by the way rather use that for cell neighborhood --> TODO
581
+
582
+
583
+ if __DEBUG__:
584
+ print('debug #4f')
585
+ # exclude border cells plus one for now and add it later --> need a bit of recoding and no big deal!!!
586
+
587
+ # print(np.nonzero(vertices))
588
+
589
+ border_vertices = []
590
+ border_vertices_plus_one = []
591
+
592
+ if __DEBUG__:
593
+ print('debug #5')
594
+
595
+ # this creates a local ID for vertices (same as a label for vertices) # may be numbaised to gain speed if needed
596
+ non_zero_y, non_zero_x = np.nonzero(vertices)
597
+ locally_labeled_vertices = np.zeros_like(vertices, dtype=lab_cells.dtype)
598
+ for iii in range(len(non_zero_x)):
599
+ locally_labeled_vertices[non_zero_y[iii], non_zero_x[iii]] = iii + 1
600
+ # also we add it to the database
601
+ vertices_2D['local_ID'].append(iii + 1)
602
+ # print('non_zero_x[iii]',non_zero_x[iii])
603
+ x = non_zero_x[iii]
604
+ y = non_zero_y[iii]
605
+ vertices_2D['y'].append(y)
606
+ vertices_2D['x'].append(x)
607
+ if x == 0 or y == 0 or x == width - 1 or y == height - 1:
608
+ vertices_2D['is_border'].append(1)
609
+ border_vertices.append(iii + 1)
610
+ else:
611
+ vertices_2D['is_border'].append(0)
612
+ if x == 1 or y == 1 or x == width - 2 or y == height - 2:
613
+ vertices_2D['is_border_plus_one'].append(1)
614
+ border_vertices_plus_one.append(iii + 1)
615
+ else:
616
+ vertices_2D['is_border_plus_one'].append(0)
617
+
618
+ if __DEBUG__:
619
+ print('debug #6')
620
+
621
+ if TA_path is not None:
622
+ Img(locally_labeled_vertices, dimensions='hw').save(
623
+ os.path.join(TA_path, 'vertices.tif')) # similar but not identical to TA vertices.tif file
624
+ else:
625
+ # plt.imshow(locally_labeled_vertices)
626
+ # plt.show()
627
+ pass
628
+
629
+ # plt.imshow(localy_labeled_vertices)
630
+ # plt.show()
631
+
632
+ # need color all vertices
633
+ # vertices_coords = np.nonzero(vertices)
634
+
635
+ # plt.imshow(vertices)
636
+ # plt.show()
637
+ # should I label the vertices ??? --> maybe because that could be useful but ok maybe for now
638
+
639
+ # bonds = np.copy(lab_cells)
640
+ bonds = cantor_color_bonds(lab_cells, vertices, boundary_color=0) #
641
+ bonds[vertices == 255] = 0 # really needs be done --> do a meta function that does all
642
+ # in fact real bonds need remove vertices
643
+
644
+ lab_bonds = label(bonds, connectivity=2,
645
+ background=0) # nb I SHOULD NOT RELABEL THEM BECAUSE I MAY CREATE ERRORS BY DOING SO
646
+ # lab_bonds = np.copy(bonds)
647
+
648
+ if TA_path is not None:
649
+ # print(lab_bonds.dtype)
650
+ Img(lab_bonds, dimensions='hw').save(
651
+ os.path.join(TA_path, 'bonds.tif')) # pretty much the same as boundaryPlotter.tif in TA!!!
652
+ # print('--->'*5,lab_bonds.dtype)
653
+ else:
654
+ # plt.imshow(lab_bonds)
655
+ # plt.show()
656
+ pass
657
+
658
+ rps_bonds = regionprops(lab_bonds)
659
+
660
+
661
+ if __DEBUG__:
662
+ print('debug #7')
663
+ # try to add vertices to bonds but in fact does not work well --> need an alternative method --> should be easy to do I guess !! --> TODO or I do have a mistake
664
+ # or get feret points and find vertex for it or take points with 7 false around them and get the corresponding vertex on the image --> maybe a good idea
665
+ # take first and last and if not good scan all points to find real edges
666
+
667
+ # then find pairs of vertices --> not hard --> gives new bonds
668
+ # get coord in real image
669
+
670
+ # can I get the vertices of every bond
671
+ # need specify an ID per bond and increment for super tiny ones --> would be the local ID and can make it that there is table that can be joined that connects local and global ids --> easy todo I think
672
+
673
+ # if any error occurs --> skip the whole stuff
674
+
675
+ # if anything goes wrong with the bond skip the whole line from saving --> can I do that --> not really except if all is saved at the same time in the very end --> I could try that
676
+
677
+ max_bond_id = 0
678
+ for bond in rps_bonds:
679
+
680
+ if early_stop.stop == True:
681
+ # print('early stop')
682
+ return
683
+ # print('False perimeter', bond.perimeter)
684
+ # --> ok
685
+
686
+ bbox = bond.bbox
687
+
688
+ # y_shift_to_transfrom_local_coords_to_global_coords = 0
689
+ # x_shift_to_transfrom_local_coords_to_global_coords = 0
690
+
691
+ if bbox[0] == 0 or bbox[0] == lab_bonds.shape[0] - 1:
692
+
693
+ x_shift_to_transfrom_local_coords_to_global_coords = bbox[1] - 1
694
+ y_shift_to_transfrom_local_coords_to_global_coords = bbox[0]
695
+ # print(bbox[0],bbox)
696
+
697
+ img = np.zeros((bond.image.shape[0], bond.image.shape[1] + 2), dtype=bond.image.dtype)
698
+ img[:, 1:-1] = bond.image
699
+ # print(bond.image.shape, img.shape)
700
+ # if bbox[0]==0:
701
+ img[0, 0] = True
702
+ img[0, img.shape[1] - 1] = True
703
+ # else:
704
+ # img[img.shape[0]-1, 0] = True
705
+ # img[img.shape[0]-1, img.shape[1]-1] = True
706
+ # plt.imshow(img.astype(np.uint8)*255, cmap='gray', vmin=0)
707
+ # plt.show()
708
+ # if img.shape[0]!=1:
709
+ # plt.imshow(img.astype(np.uint8) * 255, cmap='gray', vmin=0)
710
+ # plt.show()
711
+ elif bbox[1] == 0 or bbox[1] == lab_bonds.shape[1] - 1:
712
+ x_shift_to_transfrom_local_coords_to_global_coords = bbox[1]
713
+ y_shift_to_transfrom_local_coords_to_global_coords = bbox[0] - 1
714
+ # print(bbox[0],bbox)
715
+ img = np.zeros((bond.image.shape[0] + 2, bond.image.shape[1]), dtype=bond.image.dtype)
716
+ img[1:-1, :] = bond.image
717
+ # print(bond.image.shape, img.shape)
718
+ # if bbox[1] == 0:
719
+ img[0, 0] = True
720
+ img[img.shape[0] - 1, 0] = True
721
+ # else:
722
+ # img[img.shape[0] - 1, 0] = True
723
+ # img[img.shape[0] - 1, img.shape[0] - 1] = True
724
+ # plt.imshow(img.astype(np.uint8)*255, cmap='gray', vmin=0)
725
+ # plt.show()
726
+ # if img.shape[1] != 1:
727
+ # plt.imshow(img.astype(np.uint8) * 255, cmap='gray', vmin=0)
728
+ # plt.show()
729
+ else:
730
+ x_shift_to_transfrom_local_coords_to_global_coords = bbox[1] - 1
731
+ y_shift_to_transfrom_local_coords_to_global_coords = bbox[0] - 1
732
+ img = np.pad(bond.image, pad_width=1, mode='constant', constant_values=False)
733
+ # how can I get these coords
734
+
735
+ # can use those coords of vertices to add vertices associated to bonds into a db --> I need correct their y and x but ok
736
+ # coords = np.nonzero(vertices[bbox[0] - 1:bbox[2] + 1, bbox[1] - 1: bbox[
737
+ # 3] + 1] == 255) # TODO DO THIS FOR ALL CHANNELS --> recover vertices here --> clone this for all --> TODO
738
+
739
+ # print('coords vertices', coords) # --> gives me the coords of the vertices
740
+ # print('zipped coords', np.c_[coords[0], coords[1]]) # this is how to zip numpy arrays -> in fact simpler than doing too complicated things --> VRAIMENT COOL
741
+ # NB I could also use np.dstack((coords[0], coords[1]))
742
+
743
+ # TODO add things to the DB if necessary
744
+ # in tracks and in seg --> make sure to add a boundary around the image --> do this as an option -> but in fact really useful to do
745
+
746
+ # --> can associate local bond id to that
747
+ img[vertices[bbox[0] - 1:bbox[2] + 1, bbox[1] - 1: bbox[
748
+ 3] + 1] == 255] = True # add vertices to the mask because they are not captured by the dilation
749
+
750
+ # print('global coords', x_shift_to_transfrom_local_coords_to_global_coords, y_shift_to_transfrom_local_coords_to_global_coords)
751
+ # associate a bond to a local id
752
+ # very good idea in fact
753
+ # also measure intensity
754
+
755
+ # create bonds and find a way to transform local coords into global ones -> must not be hard --> can compute intensity for several channels if needed
756
+ # store as NA depending on the channel
757
+ # not bad and much better than before in fact
758
+
759
+ # if negative values --> need a double fix so that same size --> see how to do that but probably not so hard
760
+ # img[vertices[bbox[0] :bbox[2] + 2, bbox[1] : bbox[3] + 2] == 255] = True # add vertices to the mask because they are not captured by the dilation
761
+
762
+ # img[0][0]=True
763
+ # first and last pixel
764
+ # first_point = [bond.coords[0][0],bond.coords[0][1]]
765
+ # last_point = [bond.coords[len(bond.coords[0])][0],bond.coords[len(bond.coords[0])][1]]
766
+ #
767
+ # print(first_point, last_point)
768
+
769
+ # plt.imshow(img)
770
+ # plt.show()
771
+
772
+ # if __DEBUG__:
773
+ # print('debug #8')
774
+
775
+ lab_perim = label(img, connectivity=2)
776
+ reg = regionprops(lab_perim)
777
+ idx = 0
778
+ if len(reg) != 1:
779
+ # print('error too many things for bonds')
780
+ # plt.imshow(lab_perim)
781
+ # plt.show()
782
+
783
+ max_area = 0
784
+ for ppp, perim in enumerate(reg):
785
+ if perim.area > max_area:
786
+ max_area = perim.area
787
+ idx = ppp
788
+
789
+ # print(idx, )
790
+ # again need take biggest
791
+
792
+ # print('fixed 000', idx)
793
+
794
+ # make it measure intensity for the different channels of the image
795
+ # do quantifs for all channels --> TODO
796
+
797
+ # code seems ok but maybe I need to split it
798
+ # see how to do
799
+ # could check if it is a real bond for packing in fact --> TODO
800
+
801
+ # print('real_perimeter bond', reg[idx].perimeter,reg[idx].area) # the latter is pixel count reg[idx].perimeter_crofton,
802
+
803
+ # juts plot it to be sure no error of vertices --> otherwise needs a fix
804
+
805
+ # could do that for all the channels
806
+
807
+ # could also do that before adding vertices in fact --> TODO
808
+
809
+ vertices_tmp = locally_labeled_vertices[
810
+ reg[idx].coords[:, 0] + y_shift_to_transfrom_local_coords_to_global_coords,
811
+ reg[idx].coords[:, 1] + x_shift_to_transfrom_local_coords_to_global_coords]
812
+ vertices_indices = np.nonzero(vertices_tmp)
813
+
814
+ # get vertices in the region...
815
+
816
+ # print('vertices_indices',vertices_indices)
817
+ vertices_ids = vertices_tmp[vertices_indices]
818
+ del vertices_tmp
819
+ vertices_indices = vertices_indices[0]
820
+ vertices_ids = vertices_ids.tolist()
821
+ vertices_indices = vertices_indices.tolist()
822
+
823
+ # print('vertices_ids', vertices_ids, vertices_indices)
824
+
825
+ # can this be a bug --> I guess yes --> need a fix then --> maybe take the two closest bonds and remove one ???
826
+
827
+ # VERY DIRTY FIX FOR CASE WHERE TOO MANY VERTICES ARE THERE --> SEE IF THERE IS NO SIMPLER SOLUTION WHEN ADDING THE VERTICES TO ONLY GET THE RIGHT ONES
828
+
829
+ # if __DEBUG__:
830
+ # print('debug #9')
831
+ # FORCES ME TO REPEAT A LOT OF CODE --> NOT A GOOD IDEA!!!
832
+ if len(vertices_ids) > 2:
833
+ try:
834
+ # logger.error( 'error: wrong number of vertices --> please report this to baigouy@gmail.com' + str(vertices_ids))
835
+
836
+ # for debug KEEP
837
+ # vx_0 = (
838
+ # reg[idx].coords[vertices_indices[0], 0] ,
839
+ # reg[idx].coords[vertices_indices[0], 1] )
840
+ # vx_1 = (reg[idx].coords[vertices_indices[1], 0] ,
841
+ # reg[idx].coords[vertices_indices[1], 1] )
842
+ # vx_2 = (reg[idx].coords[vertices_indices[2], 0] ,
843
+ # reg[idx].coords[vertices_indices[2], 1] )
844
+ #
845
+ # print(vx_0,vx_1, vx_2)
846
+ # lab_perim[vx_0[0], vx_0[1]]+=1
847
+ # lab_perim[vx_1[0], vx_1[1]]+=1
848
+ # lab_perim[vx_2[0], vx_2[1]]+=1
849
+
850
+ # In fact need take the last vx encounter on the left and the last starting from the right
851
+ tmp = list(zip(reg[idx].coords[:, 0], reg[idx].coords[:, 1]))
852
+ vx_coords = [(reg[idx].coords[indx, 0], reg[idx].coords[indx, 1]) for indx in vertices_indices]
853
+
854
+ tmp2 = list(set(tmp) - set(vx_coords))
855
+ from scipy.spatial import distance
856
+
857
+ C = distance.pdist(vx_coords)
858
+
859
+ valid_idx = np.where(C > math.sqrt(2))[0]
860
+ out = valid_idx[C[valid_idx].argmin()]
861
+
862
+ coords = np.argwhere(squareform(C) == C[out])[0]
863
+
864
+ vx_0 = vx_coords[coords[0]]
865
+ vx_1 = vx_coords[coords[1]]
866
+
867
+ # print('vx_0, vx_1', vx_0, vx_1)
868
+
869
+ group1 = []
870
+ group2 = []
871
+
872
+ for coord in vx_coords:
873
+ if distance_between_points(vx_0, coord) <= math.sqrt(2):
874
+ group1.append(coord)
875
+ if distance_between_points(vx_1, coord) <= math.sqrt(2):
876
+ group2.append(coord)
877
+
878
+ # print('groups', group1, group2)
879
+
880
+ if len(group1) == 1:
881
+ vx_0 = group1[0]
882
+ else:
883
+ # find closest vx to non vx pixels and that will always be my two real vertices!
884
+ min_dist = 1000
885
+ closest = group1[0]
886
+ for coord in group1:
887
+ dist = distance.cdist(tmp2, [coord]).min()
888
+ if dist < min_dist:
889
+ min_dist = dist
890
+ closest = coord
891
+ if dist == 1:
892
+ break
893
+ vx_0 = closest
894
+
895
+ if len(group2) == 1:
896
+ vx_1 = group2[0]
897
+ else:
898
+ # find closest vx to non vx pixels and that will always be my two real vertices!
899
+ min_dist = 1000
900
+ closest = group2[0]
901
+ for coord in group2:
902
+ dist = distance.cdist(tmp2, [coord]).min()
903
+ if dist < min_dist:
904
+ min_dist = dist
905
+ closest = coord
906
+ if dist == 1:
907
+ break
908
+ vx_1 = closest
909
+
910
+ # this is now always ok --> I have finally my code !!!
911
+ # need get the indices and finalize the stuff
912
+
913
+ # idx1 = tmp.index(vx_0)
914
+ # idx2 = tmp.index(vx_1)
915
+
916
+ # print('idx1, idx2', idx1, idx2)
917
+
918
+ # print('pre', vertices_indices, vertices_ids)
919
+
920
+ # vertices_ids = [vertices_ids[vertices_indices.index(idx1)], vertices_ids[vertices_indices.index(idx2)]]
921
+
922
+ # vertices_indices = [idx1, idx2]
923
+ # print('corrected', vertices_ids, vertices_indices)
924
+
925
+ # for debug --> keep
926
+ # lab_perim[vx_0[0], vx_0[1]] += 1
927
+ # lab_perim[vx_1[0], vx_1[1]] += 1
928
+
929
+ # plt.imshow(lab_perim)
930
+ # plt.show()
931
+
932
+ # update mask and reg with the removed vertices so that all measures and alike are correct --> TOO BAD I HAVE TO DUPLICTAE SO MUCH CODE (SEE ALL THE LINES BELOW) BUT OK FOR NOW
933
+ for vx in vx_coords:
934
+ img[vx[0], vx[1]] = False
935
+
936
+ img[vx_0[0], vx_0[1]] = True
937
+ img[vx_1[0], vx_1[1]] = True
938
+ lab_perim = label(img, connectivity=2)
939
+ reg = regionprops(lab_perim)
940
+ idx = 0
941
+ if len(reg) != 1:
942
+ # print('error too many things for bonds')
943
+ # plt.imshow(lab_perim)
944
+ # plt.show()
945
+
946
+ max_area = 0
947
+ for ppp, perim in enumerate(reg):
948
+ if perim.area > max_area:
949
+ max_area = perim.area
950
+ idx = ppp
951
+
952
+ vertices_tmp = locally_labeled_vertices[
953
+ reg[idx].coords[:, 0] + y_shift_to_transfrom_local_coords_to_global_coords,
954
+ reg[idx].coords[:, 1] + x_shift_to_transfrom_local_coords_to_global_coords]
955
+ vertices_indices = np.nonzero(vertices_tmp)
956
+
957
+ # get vertices in the region...
958
+
959
+ # print('vertices_indices',vertices_indices)
960
+ vertices_ids = vertices_tmp[vertices_indices]
961
+ del vertices_tmp
962
+ vertices_indices = vertices_indices[0]
963
+ vertices_ids = vertices_ids.tolist()
964
+ vertices_indices = vertices_indices.tolist()
965
+
966
+ # plt.imshow(lab_perim)
967
+ # plt.show()
968
+ except:
969
+ traceback.print_exc()
970
+ if __DEBUG__:
971
+ print('error correcting the number of vertices of the bond --> please report this to benoit.aigouy@gmail.com')
972
+ logger.error(
973
+ 'error correcting the number of vertices of the bond --> please report this to benoit.aigouy@gmail.com')
974
+
975
+ # TODO see how to handle that because this is super frequent in fact !!!! but not easy to deal with...
976
+
977
+ # if __DEBUG__:
978
+ # print('debug #10')
979
+ # TODO DO THIS FOR ALL CHANNELS
980
+ # maybe do that vertices included or not ??? MAYBE
981
+
982
+ # print(type(reg), type(reg[idx]))
983
+
984
+ sum_bd_intensity, avg_bd_intensity = get_sum_and_avg_intensity(original_image, reg, idx,
985
+ y_shift_to_transfrom_local_coords_to_global_coords,
986
+ x_shift_to_transfrom_local_coords_to_global_coords)
987
+
988
+ # nb the vertices are the two points of the region coords to be white in the parent image with local transform --> how cna I find them
989
+
990
+ # print('reg[idx]',reg[idx])
991
+ # if not vertices_ids:
992
+ # plt.imshow(lab_perim)
993
+ # plt.show()
994
+
995
+ # in some case the vertices_indices can be empty --> is that normal or a bug ??? --> probably a bug that needs be fixed --> this is because vertices ids is also empty --> how can I fix that wand why does this happens
996
+ # print('neo vertices', vertices_indices) # this gives me the indices of the vertices of the bonds --> see how I can associate them with a cell at some point maybe if necessary
997
+
998
+ # KEEP nb a cell can have 0 vertices --> indeed a floating cell embedded in another would have 0 vertex --> shall I give it a nb of vertices of 1 or 0??? --> maybe smart to set its vertex id to None/Null
999
+
1000
+ # In case the bond has no vertices do as follows
1001
+ first_vx = None
1002
+ second_vertex = None
1003
+ bd_orientation = None
1004
+
1005
+ if vertices_indices:
1006
+ first_vertex = (
1007
+ reg[idx].coords[vertices_indices[0], 0] + y_shift_to_transfrom_local_coords_to_global_coords,
1008
+ reg[idx].coords[vertices_indices[0], 1] + x_shift_to_transfrom_local_coords_to_global_coords)
1009
+ second_vertex = (
1010
+ reg[idx].coords[vertices_indices[-1], 0] + y_shift_to_transfrom_local_coords_to_global_coords,
1011
+ reg[idx].coords[vertices_indices[-1], 1] + x_shift_to_transfrom_local_coords_to_global_coords)
1012
+ bd_orientation = get_orientation(first_vertex, second_vertex)
1013
+
1014
+ # TODO action required if more than two vertices --> take the two furthest appart or the first and last --> MAYBE WILL NEED A CLEAN/SMART FIX SOME DAY
1015
+ # print('first_vertex, second_vertex',first_vertex, second_vertex)
1016
+ first_vx = vertices_ids[0]
1017
+ second_vertex = vertices_ids[-1]
1018
+
1019
+ # print('TODO sum_bd_intensity,avg_bd_intensity',sum_bd_intensity,avg_bd_intensity)
1020
+
1021
+ # keep for debug --> if the original mask is passed max and min should always be 255 --> the mask color --> seems to work perfectly --> and also avg should always be 255, if less --> bug somewhere --> needs a fix --> TODO
1022
+ # could do the same with the cells in fact
1023
+ # also need fix local centoid wit that in fact i can probably still take the centroid
1024
+ # print('max, min', original_image[reg[idx].coords[:, 0]+y_shift_to_transfrom_local_coords_to_global_coords, reg[idx].coords[:, 1]+x_shift_to_transfrom_local_coords_to_global_coords].max(), original_image[reg[idx].coords[:, 0]+y_shift_to_transfrom_local_coords_to_global_coords, reg[idx].coords[:, 1]+x_shift_to_transfrom_local_coords_to_global_coords].min()) # alw
1025
+
1026
+ # required prior to quantification of 3D length of bonds
1027
+
1028
+ # TODO NEED PATCH THE COORDS THERE IN FACT
1029
+ # print('sorted_bond', sorted_bond)
1030
+
1031
+ x_shift_to_transfrom_local_coords_to_global_coords = bbox[1] - 1 # why -1 --> should in fact be the right stuff
1032
+ y_shift_to_transfrom_local_coords_to_global_coords = bbox[0] - 1
1033
+
1034
+ # if __DEBUG__:
1035
+ # print('debug #11')
1036
+
1037
+ if measure_3D and height_map is not None:
1038
+ sorted_bond = pavlidis(reg[idx], closed_contour=False)
1039
+ sorted_bond = [
1040
+ [y + y_shift_to_transfrom_local_coords_to_global_coords,
1041
+ x + x_shift_to_transfrom_local_coords_to_global_coords]
1042
+ for y, x in sorted_bond]
1043
+
1044
+ bd_length3D = perimeter_3D(sorted_bond, heightmap=height_map, points_are_sorted=True,
1045
+ is_closed_contour=False)
1046
+
1047
+ # print('length3D', bd_length3D)
1048
+
1049
+ # we save all the data in the very end so that if anything goes wrong no data is added at all
1050
+ max_bond_id = max(max_bond_id, bond.label)
1051
+ bonds_2D['local_ID'].append(bond.label)
1052
+ bonds_3D['local_ID'].append(bond.label)
1053
+ bonds_2D['length'].append(reg[idx].perimeter)
1054
+ bonds_2D['pixel_count'].append(reg[idx].area)
1055
+ local_bond_ID_and_px_count[bond.label] = reg[idx].area
1056
+
1057
+ bonds_2D['first_pixel_x'].append(bond.coords[0][0])
1058
+ bonds_2D['first_pixel_y'].append(bond.coords[0][1])
1059
+
1060
+ # bug because some bonds lie at the margin and their neighb should not be found like that --> in fact that would still work I guess
1061
+ # if nothing --> border bond ???? --> think about it
1062
+ # cells_around_bond = set(lab_cells[bond.coords[0][0] - 1:bond.coords[0][0] + 2, bond.coords[0][1] - 1:bond.coords[0][1] + 2].ravel().tolist())# THIS CREATES A BUG WITH NEGATIVE SLICES BUT NO CLUE WHY --> IS THAT A SECURITY ANYWAY NOT WHAT I WANT !!!
1063
+ cells_around_bond = set(
1064
+ neighbors8(bond.coords[0], lab_cells)) # nb this is another way of detecting border cells!!!
1065
+ if 0 in cells_around_bond:
1066
+ cells_around_bond.remove(0)
1067
+ cells_around_bond = list(cells_around_bond)
1068
+ # print('cells_around_bond',cells_around_bond)
1069
+
1070
+ # --> indeed border bonds ???
1071
+
1072
+ # border bonds have just one neighbor --> easy to spot them
1073
+ # --> in fact should still be one
1074
+ # if len(cells_around_bond)==0:
1075
+ #
1076
+ #
1077
+ #
1078
+ # print('bug')
1079
+ # print(bond.coords[0][0], bond.coords[0][1])
1080
+ # # somehow there is a bug here
1081
+ # # print(lab_cells[int(bond.coords[0][0] - 1):int(bond.coords[0][0] + 2), int(bond.coords[0][1] - 1):int(bond.coords[0][1] + 2)], bond.coords[0][0] - 1,bond.coords[0][0] + 2, bond.coords[0][1] - 1,bond.coords[0][1] + 2)
1082
+ # # print(neighbors8(bond.coords[0], lab_cells))
1083
+ # plt.imshow(lab_cells)
1084
+ # plt.show()
1085
+
1086
+ # bonds_2D['vx_1_y'].append(first_vertex[0])
1087
+ # bonds_2D['vx_1_x'].append(first_vertex[1])
1088
+ # bonds_2D['vx_2_y'].append(second_vertex[0])
1089
+ # bonds_2D['vx_2_x'].append(second_vertex[1])
1090
+
1091
+ bonds_2D['vx_1'].append(first_vx)
1092
+ bonds_2D['vx_2'].append(second_vertex)
1093
+
1094
+ # how is it possible that some bonds have 0 id around them --> need think abount it
1095
+ if cells_around_bond:
1096
+ bonds_2D['cell_id1_around_bond'].append(cells_around_bond[0])
1097
+ bonds_2D['cell_id2_around_bond'].append(cells_around_bond[-1])
1098
+ else:
1099
+ bonds_2D['cell_id1_around_bond'].append(None)
1100
+ bonds_2D['cell_id2_around_bond'].append(None)
1101
+ is_border_bond = 0 if len(
1102
+ cells_around_bond) > 1 else 1 # a bit hacky but since anyways it is saved as an int in the sqlite database then no pb to have it directly written as 0 and 1 instead of True and False
1103
+ # i need the coords of these vertices --> where are they
1104
+ # if first_vx[0] == height-1 or first_vx[0] == 0 or first_vx[1] == 0 or first_vx[1]==width-1 or second_vertex[0] == height-1 or second_vertex[0] == 0 or second_vertex[1] == 0 or second_vertex[1]==width-1:
1105
+ # is_border_bond = 1
1106
+ if first_vx in border_vertices or second_vertex in border_vertices:
1107
+ is_border_bond = 1
1108
+
1109
+ is_border_bond_plus_one = 0
1110
+ # if first_vx[0] == height-2 or first_vx[0] == 1 or first_vx[1] == 1 or first_vx[1]==width-2 or second_vertex[0] == height-2 or second_vertex[0] == 1 or second_vertex[1] == 1 or second_vertex[1]==width-2:
1111
+ # is_border_bond_plus_one = 1
1112
+ if first_vx in border_vertices_plus_one or second_vertex in border_vertices_plus_one:
1113
+ is_border_bond_plus_one = 1
1114
+
1115
+ # print(type(is_border_bond))
1116
+ bonds_2D['is_border'].append(is_border_bond)
1117
+ bonds_2D['is_border_plus_one'].append(is_border_bond_plus_one)
1118
+
1119
+ # get common ids around the two vertices --> recommended for pairs of vertices
1120
+ # qsqdqd
1121
+ # or get two ids around fisrt pixel --> would also work here
1122
+
1123
+ bonds_2D['orientation'].append(bd_orientation)
1124
+
1125
+ if len(original_image.shape) >= 3:
1126
+ for ccc in range(original_image.shape[-1]):
1127
+ # print('TODO sum_bd_intensity,avg_bd_intensity', sum_bd_intensity[ccc], avg_bd_intensity[ccc])
1128
+ if 'sum_px_int_vertices_included_ch' + str(ccc) not in bonds_2D:
1129
+ bonds_2D['sum_px_int_vertices_included_ch' + str(ccc)] = []
1130
+ bonds_2D['avg_px_int_vertices_included_ch' + str(ccc)] = []
1131
+ bonds_2D['sum_px_int_vertices_included_ch' + str(ccc)].append(sum_bd_intensity[ccc])
1132
+ bonds_2D['avg_px_int_vertices_included_ch' + str(ccc)].append(avg_bd_intensity[ccc])
1133
+ else:
1134
+ if 'sum_px_int_vertices_included_ch' + str(0) not in bonds_2D:
1135
+ bonds_2D['sum_px_int_vertices_included_ch' + str(0)] = []
1136
+ bonds_2D['avg_px_int_vertices_included_ch' + str(0)] = []
1137
+ bonds_2D['sum_px_int_vertices_included_ch' + str(0)].append(sum_bd_intensity)
1138
+ bonds_2D['avg_px_int_vertices_included_ch' + str(0)].append(avg_bd_intensity)
1139
+
1140
+ if measure_3D and height_map is not None:
1141
+ bonds_3D['length3D'].append(bd_length3D)
1142
+ #
1143
+ # if __DEBUG__:
1144
+ # print('debug #12')
1145
+
1146
+ # count nb of neighbs
1147
+ # will need to remove as many bonds below cutoff --> whole bond then serves as a vertex obviously...
1148
+
1149
+ # TODO get the vertices then almost all done in fact
1150
+
1151
+ # can I get the vertices per image -> ce seront juste tow added points and then I can associate this ID there
1152
+ # tst = np.zeros_like(img, dtype=np.uint8)
1153
+ # tst = original_image[reg[idx].coords[:, 0], reg[idx].coords[:, 1]]
1154
+
1155
+ # print(tst.shape) # ---> 41,
1156
+
1157
+ # plt.imshow( tst)
1158
+ # plt.show()
1159
+
1160
+ # print('sum_bd_intensity, avg_bd_intensity', sum_bd_intensity, avg_bd_intensity)
1161
+
1162
+ # I am almost there this time!!!
1163
+
1164
+ # when I will add bonds at the margin i will create errors --> need temporarily remove them then bring them back --> TODO
1165
+
1166
+ # if bbox touches an extremity --> just remove stuff
1167
+
1168
+ # en fait j'y suis presque
1169
+
1170
+ # easy to sort the pixels as any pixel touching the border is my real starting point in fact --> easy to fix in fact and to sort
1171
+ # --> juts need transform fake coords into real ones --> should be easy --> just try but maybe not that hard
1172
+
1173
+ # could also easily compute polarity
1174
+
1175
+ # very good --> just need the cantor stuff here!!!
1176
+
1177
+ # or scan along border and count neighbs if exactly 2 colors --> this is a bond --> how do I give it an id --> define a forbidden color that represent the border of the image and can then apply the cantor formula --> could be a way todo that
1178
+ # or increment
1179
+
1180
+ # to find bonds at edges I need to scan in lines until I find vertices ??? then change idea
1181
+ # in fact those bonds are splitted --> think if that is true or not
1182
+
1183
+ # need apply id to bonds to get things to work perfectly --> TODO maybe
1184
+ # all is ok soon
1185
+
1186
+ # bonds = np.zeros_like(vertices)
1187
+ # bonds[vertices==128]=128 # make a bond specific file
1188
+ # vertices[vertices==128]=0 # make a vertex specific file
1189
+ # plt.imshow(vertices)
1190
+ # plt.show()
1191
+
1192
+ # TODO just need the cantor coloring of bonds !!! --> TODO --> shall I do a generic filter or ignore in fact and just do cantor on the colored image directly
1193
+ # plt.imshow(bonds)
1194
+ # plt.show()
1195
+
1196
+ # plt.imshow(lab_cells)
1197
+ # plt.show()
1198
+
1199
+ # can I do that before cells as I need that for computing nb of neighbors !!! --> I think yes
1200
+ # I need associate to cell id in order to lower their counts
1201
+
1202
+ # new position #############################
1203
+
1204
+ lab_vertices = label(vertices, connectivity=2, background=0)
1205
+ rps_verts = regionprops(lab_vertices)
1206
+
1207
+ if __DEBUG__:
1208
+ print('debug #14')
1209
+
1210
+ # could simply get their ID and length between them --> quite easy in fact --> compute 2D distance in fact
1211
+ # pairs_of_vertices = []
1212
+ # detect tiny bonds that just consist of exactly two pixels --> TODO
1213
+ for vertex in rps_verts:
1214
+ if early_stop.stop == True:
1215
+ # print('early stop')
1216
+ return
1217
+ if vertex.area >= 2:
1218
+ # we have found a vertex pair --> need fix it
1219
+ # print('pair found', vertex.area, vertex.coords)
1220
+
1221
+ # if more than 2 --> can have trouble (is that even possible ??? I don't think so but would really need to check
1222
+ if vertex.area > 2: # in fact that is easy I could split it into n closest pairs of points --> that should work, but first let's see if it is possible or not ???
1223
+ # logger.error('error please contact baigouy@gmail.com to let him know that up to '+str(vertex.area)+ 'vertices can be adjacent to each other and provide him with a test image so that he can fix the bug'+str( vertex.coords))
1224
+ # sys.exit(0)
1225
+
1226
+ # array([[154, 519],
1227
+ # [155, 518],
1228
+ # [156, 519]]))
1229
+
1230
+ # need sort the three points by distance
1231
+
1232
+ # more than ntwo vertices are found side by side --> these are series of four ways vertices adjacent to each others --> sort them and split them into pairs and parse them
1233
+ sorted = pavlidis(vertex)
1234
+
1235
+ # print(sorted)
1236
+ # print(compute_distance_between_consecutive_points(sorted))
1237
+ # now that the list is sorted I need parse it 2 by 2 --> if I do so this is generic and i will have no pb
1238
+
1239
+ # sqdsqdsqd
1240
+ # TODO need a fix for that too cause very important
1241
+ # sort vertices by distance --> just make sure they are all sorted
1242
+ # need sort them so that I minimize the
1243
+
1244
+ lst = sorted
1245
+ else:
1246
+ # if bond_cut_off is not None:
1247
+ # if vertex.area<=bond_cut_off:
1248
+ # nb_of_vertices_or_neighbours_cut_off-=1
1249
+
1250
+ # print(type(vertex.coords)) # --> np.ndarray
1251
+ # print(type(vertex.coords.tolist()))
1252
+ lst = vertex.coords.tolist()
1253
+ # print('sls lsts ', lst)
1254
+ # print(len(lst)) # --> 2 --> juste deux points que je pourrais ajouter à une table --> en fait ce serait assez facile
1255
+ # faudra tt sauver dans du vectoriel et tt plotter
1256
+ # permettre du plot as bonds ou alike
1257
+ # faire un image compositer basique et plus puissant, un plotteur de fleches et de nematic et de vecteur et de trait --> TODO then all will be done --> then I will have even something better than TA and simpler to use and that can be command line driven
1258
+
1259
+ # peut etre faire un object qui calcule et ecrit ttes les propriétés des objets --> facile à handler je pense --> quite a good idea I think
1260
+ # call area cytoplasmic_area
1261
+ # area being (cytoplasmic area + 2 perimeter_area/2)
1262
+ # maybe have a header that explains it all what the measures are
1263
+ # maybe allow plots in ROIs and or in clones
1264
+ # TODO --> some day
1265
+ # pairs_of_vertices.append(lst)
1266
+
1267
+ # need get the ids of the vertices and invent a local id --> max of previous --> TODO
1268
+
1269
+ # print('ids sdqsdqs',ids)
1270
+
1271
+ # print('pairs of vertices', lst)
1272
+ # print('perimeter2D',vertex.perimeter) # why always 0 ??? --> shall I compute it myself # compute distance 2D --> clearly the perimeter algo of scipy does not work in such case
1273
+ # print('length',distance_between_points(lst[0], lst[-1]))
1274
+ # print('pixel_count', len(lst))
1275
+ # print('vx_1', ids[0])
1276
+ # print('vx_2', ids[-1])
1277
+
1278
+ # do it generically by pairs of points
1279
+ # convert a list to another list of pairs and execute the code below!!!
1280
+ # pair each element with the next in the list and loop over this!!
1281
+
1282
+ pairs = list(zip(lst, lst[1:]))
1283
+ # if len(lst) == 3:
1284
+ #
1285
+ # print('lst',lst)
1286
+ # print('pairs', pairs)
1287
+ # print(compute_distance_between_consecutive_points(lst))
1288
+
1289
+ # print('before', locally_labeled_vertices[vertex.coords[:, 0], vertex.coords[:, 1]])
1290
+
1291
+ for lst in pairs:
1292
+ # again changing this code will be a pain... because very long
1293
+ crds = np.asarray(lst)
1294
+ # need get the id locally
1295
+ ids = locally_labeled_vertices[crds[:, 0], crds[:, 1]] # this works and is generic
1296
+ # print('after', ids)
1297
+ max_bond_id += 1
1298
+
1299
+ # print('lst',lst)
1300
+
1301
+ bonds_2D['local_ID'].append(max_bond_id)
1302
+ # bonds_3D['local_ID'].append(max_bond_id) # --> maybe add id --> also so that one can pair it with the other db --> see what I can do!!!
1303
+ bonds_2D['length'].append(
1304
+ distance_between_points(lst[0], lst[-1])) # pb is here I need more to be generic...
1305
+ bonds_2D['pixel_count'].append(len(lst))
1306
+
1307
+ bonds_2D['vx_1'].append(ids[0])
1308
+ bonds_2D['vx_2'].append(ids[-1])
1309
+
1310
+ # bonds_2D['cell_id1_around_bond'].append(cells_around_bond[0])
1311
+ # bonds_2D['cell_id2_around_bond'].append(cells_around_bond[-1]) # --> TODO but a bit more complex in fact !!!
1312
+ bd_orientation = get_orientation(lst[0], lst[-1])
1313
+ bonds_2D['orientation'].append(
1314
+ bd_orientation) # --> although largely meaningless...
1315
+
1316
+ # TODO --> here too
1317
+ # bonds_2D['cell_id1_around_bond'].append(cells_around_bond[0])
1318
+ # bonds_2D['cell_id2_around_bond'].append(cells_around_bond[-1]) # --> TODO but a bit more complex in fact !!!
1319
+
1320
+ # TODO need do that also with list because this is gonna be wrong
1321
+
1322
+ # this will be wrong --> need fix it
1323
+ sum_bd_intensity, avg_bd_intensity = get_sum_and_avg_intensity(original_image,
1324
+ crds) # this line will be wrong --> need fix it
1325
+ if len(original_image.shape) >= 3:
1326
+ for ccc in range(original_image.shape[-1]):
1327
+ # print('TODO sum_bd_intensity,avg_bd_intensity', sum_bd_intensity[ccc], avg_bd_intensity[ccc])
1328
+ if 'sum_px_int_vertices_included_ch' + str(ccc) not in bonds_2D:
1329
+ bonds_2D['sum_px_int_vertices_included_ch' + str(ccc)] = []
1330
+ bonds_2D['avg_px_int_vertices_included_ch' + str(ccc)] = []
1331
+ bonds_2D['sum_px_int_vertices_included_ch' + str(ccc)].append(sum_bd_intensity[ccc])
1332
+ bonds_2D['avg_px_int_vertices_included_ch' + str(ccc)].append(avg_bd_intensity[ccc])
1333
+ else:
1334
+ if 'sum_px_int_vertices_included_ch' + str(0) not in bonds_2D:
1335
+ bonds_2D['sum_px_int_vertices_included_ch' + str(0)] = []
1336
+ bonds_2D['avg_px_int_vertices_included_ch' + str(0)] = []
1337
+ bonds_2D['sum_px_int_vertices_included_ch' + str(0)].append(sum_bd_intensity)
1338
+ bonds_2D['avg_px_int_vertices_included_ch' + str(0)].append(avg_bd_intensity)
1339
+
1340
+ # not so hard to do I guess because I have id and bond id
1341
+
1342
+ # CHECK NEIGHBORHOOD TO FIND id -> need get common ids
1343
+ # can this stuff be a border bond ??? --> I guess not but maybe --> need think further about it!!!
1344
+
1345
+ cells_around_vx1 = set(
1346
+ neighbors8(lst[0],
1347
+ lab_cells)) # nb this is another way of detecting border cells!!!vertex.coords[0]
1348
+ cells_around_vx2 = set(
1349
+ neighbors8(lst[-1],
1350
+ lab_cells)) # nb this is another way of detecting border cells!!! #vertex.coords[1]
1351
+ # get common cells of the set --> these are the two ids of the cells sharing this mini bond
1352
+ cells_around_bond = cells_around_vx1.intersection(cells_around_vx2)
1353
+ if 0 in cells_around_bond:
1354
+ cells_around_bond.remove(0)
1355
+ cells_around_bond = list(cells_around_bond)
1356
+
1357
+ if len(cells_around_bond) > 2:
1358
+ print('pairs of vertices have too many cells in common, please report error to benoit.aigouy@gmail.com')
1359
+ # print('cells_around_bond',cells_around_bond, cells_around_vx1, cells_around_vx2)
1360
+ # cells_around_bond
1361
+
1362
+ if cells_around_bond:
1363
+ bonds_2D['cell_id1_around_bond'].append(cells_around_bond[0])
1364
+ bonds_2D['cell_id2_around_bond'].append(cells_around_bond[-1])
1365
+ else:
1366
+ bonds_2D['cell_id1_around_bond'].append(None)
1367
+ bonds_2D['cell_id2_around_bond'].append(None)
1368
+
1369
+ # bonds_2D['cell_id1_around_bond'].append(cells_around_bond[0])
1370
+ # bonds_2D['cell_id2_around_bond'].append(cells_around_bond[-1])
1371
+ is_border_bond = 0 if len(
1372
+ cells_around_bond) > 1 else 1 # a bit hacky but since anyways it is saved as an int in the sqlite database then no pb to have it directly written as 0 and 1 instead of True and False
1373
+
1374
+ if first_vx in border_vertices or second_vertex in border_vertices:
1375
+ is_border_bond = 1
1376
+
1377
+ is_border_bond_plus_one = 0
1378
+ # if first_vx[0] == height-2 or first_vx[0] == 1 or first_vx[1] == 1 or first_vx[1]==width-2 or second_vertex[0] == height-2 or second_vertex[0] == 1 or second_vertex[1] == 1 or second_vertex[1]==width-2:
1379
+ # is_border_bond_plus_one = 1
1380
+ if first_vx in border_vertices_plus_one or second_vertex in border_vertices_plus_one:
1381
+ is_border_bond_plus_one = 1
1382
+
1383
+ # print(type(is_border_bond))
1384
+ bonds_2D['is_border'].append(is_border_bond)
1385
+ bonds_2D['is_border_plus_one'].append(is_border_bond_plus_one)
1386
+
1387
+ # print(type(is_border_bond))
1388
+ # bonds_2D['is_border'].append(is_border_bond)
1389
+
1390
+ # check if real and really normal
1391
+ if cells_around_bond:
1392
+ if cells_around_bond[0] not in bonds_associated_to_a_given_cell:
1393
+ bonds_associated_to_a_given_cell[cells_around_bond[0]] = []
1394
+ bond_lengths_associated_to_a_given_cell[cells_around_bond[0]] = []
1395
+ bonds_associated_to_a_given_cell[cells_around_bond[0]].append(max_bond_id)
1396
+ bond_lengths_associated_to_a_given_cell[cells_around_bond[0]].append(len(lst))
1397
+ if cells_around_bond[-1] != cells_around_bond[0]:
1398
+ if cells_around_bond[-1] not in bonds_associated_to_a_given_cell:
1399
+ bonds_associated_to_a_given_cell[cells_around_bond[-1]] = []
1400
+ bond_lengths_associated_to_a_given_cell[cells_around_bond[-1]] = []
1401
+ bonds_associated_to_a_given_cell[cells_around_bond[-1]].append(max_bond_id)
1402
+ bond_lengths_associated_to_a_given_cell[cells_around_bond[-1]].append(len(lst))
1403
+
1404
+ # new position #############################
1405
+
1406
+ if __DEBUG__:
1407
+ print('debug #15')
1408
+
1409
+ rps = regionprops(lab_cells, intensity_image=original_image)
1410
+
1411
+ # ça marche mais ne detecte qd meme pas ts les vertices
1412
+ # faire un detecteur de vertex à la boundary --> useful and put bonds there too --> simpler in fact
1413
+
1414
+ # draw a small shape just to see
1415
+ # le code de perimeter de scipy est bon --> cool
1416
+
1417
+ cells[cells != 0] = 1
1418
+
1419
+ # in fact if image is passed in I can directly get avg intensity --> easy peasy
1420
+ # --> TODO
1421
+ # set in fact do on a channel by channel basis
1422
+
1423
+ for cell in rps:
1424
+ if early_stop.stop == True:
1425
+ # print('early stop')
1426
+ return
1427
+
1428
+ # print('wrong perimeter',cell.perimeter) # --> 94.14213562373095 vs 95.799 in IJ --> no clue how they do that and need check the real one --> maybe this is ok in fact because I count 97 in fact for outer
1429
+ # manually computed for the circle:
1430
+ # print(math.sqrt(2) * 8 + 2 * 4) # same perimeter but --> needs contour --> i need find the countour first then it is gonna be ok
1431
+
1432
+ # as expected --> in IJ perimeter is completely wrong... and really makes no sense to me...
1433
+
1434
+ # https://stackoverflow.com/questions/12747319/scipy-label-dilation --> maybe exactly what I want in fact
1435
+
1436
+ # plt.imshow(cell.filled_image) # --> ok this is what I want in fact but it is cropped --> need pad and have bounding box to compute coords of dilation
1437
+ # plt.show()
1438
+
1439
+ # what I could do is pas the image and dilate it and then just get the mask in the original image for that exact region and measure its perimeter
1440
+ # and or sort it and compute the 3D perimeter!!!
1441
+ # TODO
1442
+
1443
+ # seems ok I think
1444
+ # plt.imshow(cell.image)
1445
+ # plt.title('toto')
1446
+ # plt.show()
1447
+
1448
+ # maybe need change structuring element though
1449
+ # plt.imshow(ndimage.binary_dilation(cell.image))
1450
+ # plt.show()
1451
+ bbox = cell.bbox
1452
+ # print(cell.bbox)
1453
+ #
1454
+
1455
+ # img = np.pad(cell.image, tuple(cell.image.shape[0]+2, cell.image.shape[1]+2), mode='constant', constant_values=False)
1456
+ # img = np.pad(cell.image, tuple(cell.image.shape[0]+2, cell.image.shape[1]+2), mode='constant', constant_values=False)
1457
+ img = np.pad(cell.image, pad_width=1, mode='constant', constant_values=False)
1458
+ # print(cell.perimeter_crofton) --> not good at all --> forget
1459
+
1460
+ # struct2 = ndimage.generate_binary_structure(2, 2) # --> better because would get TA vertices because it gets the borders
1461
+ # print(struct2)
1462
+ # dilated_mask = ndimage.binary_dilation(img, structure=struct2)
1463
+ dilated_mask = ndimage.binary_dilation(img)
1464
+
1465
+ dilated_mask ^= np.pad(cell.image, pad_width=1, mode='constant', constant_values=False)
1466
+
1467
+ # seems exactly what I want in fact --> do I even need more ????
1468
+
1469
+ # dilated_mask[vertices[bbox[0]:bbox[2] + 2, bbox[1]: bbox[3] + 2] == 255] = True # add vertices to the mask because they are not captured by the dilation
1470
+
1471
+ # x_shift_to_transfrom_local_coords_to_global_coords = bbox[1] - 1
1472
+ # y_shift_to_transfrom_local_coords_to_global_coords = bbox[0] - 1
1473
+
1474
+ # ça marche c'est sans les vertices
1475
+ # if cell.label == 6:
1476
+ # # the dialted mask seems be correct
1477
+ # plt.imshow(dilated_mask)
1478
+ # plt.show()
1479
+
1480
+ dilated_mask[vertices[bbox[0] - 1:bbox[2] + 1, bbox[1] - 1: bbox[
1481
+ 3] + 1] == 255] = True # add vertices to the mask because they are not captured by the dilation
1482
+ # the pb here is that some vertices are outside the cell which does not make sense and is dangerous for the label
1483
+
1484
+ # ça marche --> avec les vertices
1485
+ # if cell.label == 6:
1486
+ # the dialted mask seems be correct
1487
+ # plt.imshow(dilated_mask)
1488
+ # plt.show()
1489
+
1490
+ lab_perim = label(dilated_mask, connectivity=2)
1491
+ reg = regionprops(lab_perim)
1492
+
1493
+ idx = 0
1494
+ if len(reg) != 1:
1495
+ # Too many cells detected --> needs a fix --> need take the biggest one or need a trick
1496
+ # print('error wrong length', cell.label)
1497
+ # plt.imshow(lab_perim)
1498
+ # plt.show()
1499
+ # need a fix if vertex is outside the cell
1500
+
1501
+ max_area = 0
1502
+ for ppp, perim in enumerate(reg):
1503
+ if perim.area > max_area:
1504
+ max_area = perim.area
1505
+ idx = ppp
1506
+
1507
+ # print('fixed index', idx, cell.label)
1508
+
1509
+ # if cell.label == 6:
1510
+ # # the bug is because of two cells due to the presence of a vertex --> if len is not 0 --> need take the biggest I guess
1511
+ # plt.imshow(lab_perim)
1512
+ # plt.show()
1513
+
1514
+ # print('real_perimeter', reg[idx].perimeter, reg[idx].area) # nb half of this area needs be added to the cell area in fact # , reg[0].perimeter_crofton) # --> probably ok but if I need compute intensities I need place it back --> can replace it in several of my codes
1515
+
1516
+ # need sort pixels to recover the real polarity nematic of the cell
1517
+
1518
+ # c'est plutot long (ça double le temps mais pas si mal car me permet de calculer le perimeter 3D et de
1519
+ # faire une table appelee measurements 3D
1520
+ # faire une table appelee measurements 3D
1521
+ # permettre des natural joins de pleins de tables en fait --> un peu plus flexible et modulaire qu'avant
1522
+ # faire un calcul de l'intensite du cytoplasme aussi --> pas trop dur en fait à faire
1523
+
1524
+ # TODO make this optional --> required for polarity and also for 3D
1525
+
1526
+ # print('reg[0].coords',reg[0].coords)
1527
+ #
1528
+ # print('sorted_contour', sorted_contour)
1529
+
1530
+ # # measure 3D perimeter
1531
+ # y_shift_to_transfrom_local_coords_to_global_coords = bbox[0] - 1
1532
+ # x_shift_to_transfrom_local_coords_to_global_coords = bbox[1] - 1
1533
+
1534
+ # need translate all the contour points
1535
+ y_shift_to_transfrom_local_coords_to_global_coords = bbox[0] - 1
1536
+ x_shift_to_transfrom_local_coords_to_global_coords = bbox[1] - 1
1537
+
1538
+ if measure_3D or measure_polarity:
1539
+ sorted_contour = pavlidis(reg[idx], closed_contour=True)
1540
+ # need correct coords of sorted contour --> this must also be done before computing polarity!!!
1541
+ sorted_contour = [
1542
+ [y + y_shift_to_transfrom_local_coords_to_global_coords,
1543
+ x + x_shift_to_transfrom_local_coords_to_global_coords]
1544
+ for y, x in sorted_contour]
1545
+
1546
+ if measure_polarity:
1547
+ # compute polarity nematic:
1548
+ centoid_corrected = [reg[idx].centroid[0] + y_shift_to_transfrom_local_coords_to_global_coords,
1549
+ reg[idx].centroid[1] + x_shift_to_transfrom_local_coords_to_global_coords]
1550
+
1551
+ # is that because the contour is not corrected ???
1552
+ polarity_nematic = compute_polarity_nematic(centoid_corrected, sorted_contour, original_image)
1553
+
1554
+ # print(polarity_nematic, centoid_corrected) # centroid is correct but there is a bug in the polarity
1555
+ # need save the data for every channel in the db --> TODO
1556
+
1557
+ # print('polarity nematic', polarity_nematic) # TODO DO THIS FOR ALL CHANNELS
1558
+
1559
+ if measure_3D and height_map is not None:
1560
+ # measure 3D perimeter
1561
+
1562
+ # print('sorted_bond perim3D', sorted_contour)
1563
+ perimeter3D = perimeter_3D(sorted_contour, heightmap=height_map, points_are_sorted=True,
1564
+ is_closed_contour=False)
1565
+ # print('perimeter3D', perimeter3D)
1566
+
1567
+ # TODO allow intensity measurements here too
1568
+
1569
+ # print('plenty of measurements')
1570
+ # print(cell.mean_intensity, cell.max_intensity, cell.min_intensity)
1571
+ # print(cell.weighted_centroid, cell.centroid)
1572
+ # print('first point', cell.coords[0][0], cell.coords[0][1])
1573
+
1574
+ # get cell vertices here
1575
+ vertices_indices_cells = np.nonzero(vertices[
1576
+ reg[idx].coords[:,
1577
+ 0] + y_shift_to_transfrom_local_coords_to_global_coords,
1578
+ reg[idx].coords[:,
1579
+ 1] + x_shift_to_transfrom_local_coords_to_global_coords])[
1580
+ 0].tolist()
1581
+
1582
+ # if len(vertices_indices) > 2:
1583
+ # logger.error(
1584
+ # 'error: wrong number of vertices --> please report this to baigouy@gmail.com' + str(vertices_indices))
1585
+ #
1586
+ # # print('neo vertices', vertices_indices) # this gives me the indices of the vertices of the bonds --> see how I can associate them with a cell at some point maybe if necessary
1587
+ # first_vertex = (reg[idx].coords[vertices_indices[0], 0] + y_shift_to_transfrom_local_coords_to_global_coords,
1588
+ # reg[idx].coords[vertices_indices[0], 1] + x_shift_to_transfrom_local_coords_to_global_coords)
1589
+ # second_vertex = (reg[idx].coords[vertices_indices[-1], 0] + y_shift_to_transfrom_local_coords_to_global_coords,
1590
+ # reg[idx].coords[vertices_indices[-1], 1] + x_shift_to_transfrom_local_coords_to_global_coords)
1591
+
1592
+ # could in fact just get vertices local id and then can be recovered using joins
1593
+ # maybe sort the ids ????
1594
+ # print('neo vertices_indices_cells', vertices_indices_cells)
1595
+
1596
+ # plt.imshow(vertices)
1597
+ # plt.show()
1598
+ # print('oubs',vertices_indices_cells, len( reg[idx].coords), idx)# why None
1599
+
1600
+ vx_local_ids = []
1601
+ for cell_vertex in vertices_indices_cells:
1602
+ # print(idx, len(reg), cell_vertex, len(reg[idx].coords))
1603
+ # print(reg[idx])
1604
+ # print(vertices_indices_cells[cell_vertex])
1605
+ y = reg[idx].coords[cell_vertex, 0] + y_shift_to_transfrom_local_coords_to_global_coords,
1606
+ x = reg[idx].coords[cell_vertex, 1] + x_shift_to_transfrom_local_coords_to_global_coords,
1607
+ vx_local_ids.append(locally_labeled_vertices[y, x][0])
1608
+ # qsdqsdqsd
1609
+
1610
+ bond_indices_cells = list(set(lab_bonds[
1611
+ reg[idx].coords[:,
1612
+ 0] + y_shift_to_transfrom_local_coords_to_global_coords,
1613
+ reg[idx].coords[:,
1614
+ 1] + x_shift_to_transfrom_local_coords_to_global_coords].tolist()))
1615
+ if 0 in bond_indices_cells:
1616
+ bond_indices_cells.remove(0)
1617
+ # bond_local_ID = []
1618
+
1619
+ # print('bond_indices_cells',bond_indices_cells) # this contains all 'long' bonds of the current cell
1620
+
1621
+ if cell.label not in bonds_associated_to_a_given_cell:
1622
+ bonds_associated_to_a_given_cell[cell.label] = []
1623
+ bond_lengths_associated_to_a_given_cell[cell.label] = []
1624
+ bonds_associated_to_a_given_cell[cell.label].extend(bond_indices_cells)
1625
+ # need add all the bond lengthes corresponding to these values --> TODO
1626
+ for bd_id in bond_indices_cells:
1627
+ bond_lengths_associated_to_a_given_cell[cell.label].append(local_bond_ID_and_px_count[bd_id])
1628
+ # if I now store the length of the bonds i can easily get the apcking
1629
+
1630
+ # split by comma for example
1631
+ # print('vx_local_ids',vx_local_ids)
1632
+
1633
+ # T0D0 NEED A 3D version of this
1634
+ point_awlays_inside_the_cell = point_on_surface(cell, lab_cells)
1635
+ # print('point inside cell', point_awlays_inside_the_cell)
1636
+
1637
+ if measure_3D and height_map is not None:
1638
+ # all is ok now
1639
+ triangulation_centroid = point_awlays_inside_the_cell # central point for triangulation
1640
+ # if int(ceil(cell.centroid[0]))==point_awlays_inside_the_cell[0] and int(ceil(cell.centroid[1]))==point_awlays_inside_the_cell[1]:
1641
+ # now just need to triangulate the cell
1642
+
1643
+ # get the vertices of the contour and the triangulation centroid to triangulate a cell
1644
+ # alternatively could take all points of the contour --> maybe try both
1645
+
1646
+ # compute_3D_surfacearea
1647
+
1648
+ # print(reg[0].coords)
1649
+ # print('test', reg[0].coords[:,0])
1650
+
1651
+ # there is a bug in the detection of vertices at least for the border cells --> needs a fix
1652
+
1653
+ y_corrected = [y_shift_to_transfrom_local_coords_to_global_coords + y for y in reg[idx].coords[:,
1654
+ 0].tolist()] # see how I handle the relative coords here --> do I have a bug???
1655
+ x_corrected = [x_shift_to_transfrom_local_coords_to_global_coords + x for x in
1656
+ reg[idx].coords[:, 1].tolist()]
1657
+
1658
+ verts = np.where(vertices[
1659
+ y_corrected, x_corrected] == 255) # TODO need add this to the cell or maybe the ids of those ??? --> good idea
1660
+
1661
+ # print(verts)
1662
+
1663
+ # vertices not found properly --> why
1664
+ # if cell.label == 6:
1665
+ # print('verts',verts, y_shift_to_transfrom_local_coords_to_global_coords,x_shift_to_transfrom_local_coords_to_global_coords)
1666
+
1667
+ y_corrected = np.asarray(y_corrected)[verts[0]]
1668
+ x_corrected = np.asarray(x_corrected)[verts[0]]
1669
+
1670
+ # if cell.label == 6:
1671
+ # print('x_corrected,y_corrected',x_corrected,y_corrected)
1672
+
1673
+ x_corrected = x_corrected.tolist()
1674
+ y_corrected = y_corrected.tolist()
1675
+
1676
+ # y_corrected = [y_shift_to_transfrom_local_coords_to_global_coords + y for y in verts[:, 0].tolist()]
1677
+ # x_corrected = [x_shift_to_transfrom_local_coords_to_global_coords + x for x in verts[:, 1].tolist()]
1678
+
1679
+ # just get coords where
1680
+
1681
+ # I think that is 100% what I want now!!!
1682
+
1683
+ # this is very fast just need heightmap and try compute 3D area just for fun, for a test try on a real sample
1684
+
1685
+ # en fait c'est à peine plus long en 3D ...
1686
+
1687
+ try:
1688
+
1689
+ # je pense qu'il y a des bugs
1690
+
1691
+ y_corrected.append(triangulation_centroid[0])
1692
+ x_corrected.append(triangulation_centroid[1])
1693
+
1694
+ # why so few points -> bug here
1695
+ points_for_triangulation = list(zip(y_corrected, x_corrected))
1696
+
1697
+ if len(points_for_triangulation) < 4:
1698
+ if __DEBUG__:
1699
+ print('not enough vertices for cell #' + str(
1700
+ cell.label) + ' --> trying to add a subset of contour pixels instead, in order to triangulate')
1701
+ logger.warning('not enough vertices for cell #' + str(
1702
+ cell.label) + ' --> trying to add a subset of contour pixels instead, in order to triangulate')
1703
+
1704
+ # try add n random points from the table
1705
+ # points_for_triangulation.append()
1706
+
1707
+ y_corrected = [y_shift_to_transfrom_local_coords_to_global_coords + y for y in reg[idx].coords[:,
1708
+ 0].tolist()] # see how I handle the relative coords here --> do I have a bug???
1709
+ x_corrected = [x_shift_to_transfrom_local_coords_to_global_coords + x for x in
1710
+ reg[idx].coords[:, 1].tolist()]
1711
+
1712
+ # get x% random values from both
1713
+ # print('y_corrected, x_corrected', len(y_corrected), len(x_corrected))
1714
+ tmp = list(zip(y_corrected, x_corrected))
1715
+
1716
+ nb_of_point_to_get = 12 # could also take x percent of the contour --> TODO or take n points maybe as if the cell was an n sided cell --> maybe take 10 --> enough in fact
1717
+ # if nb_of_point_to_get<4:
1718
+ # nb_of_point_to_get = 4
1719
+ if nb_of_point_to_get > len(y_corrected):
1720
+ nb_of_point_to_get = len(y_corrected)
1721
+
1722
+ seleted_points = random.sample(tmp, nb_of_point_to_get)
1723
+ points_for_triangulation.extend(seleted_points)
1724
+
1725
+ # print('points_for_triangulation',points_for_triangulation)
1726
+
1727
+ # points_for_triangulation.append(triangulation_centroid)
1728
+
1729
+ # can I do that ???
1730
+
1731
+ # points_for_triangulation =[reg[0].coords]
1732
+ # there is a bug in there dunno where
1733
+
1734
+ # nb rather just take vertices because a bit bigger than the cell and mention it is an approximation
1735
+ # --> pas mal mais rajoute encore deux seqs de plus mais pas mal qd meme
1736
+ # triangles = triangulate(np.asarray(points_for_triangulation), triangulated_object_ID=cell.label, labels_to_check=lab_cells)#,triangulated_object_ID=cell.label) # need filter the triangulation for concave shapes of clones which is very frequent
1737
+
1738
+ # nb si seulement deux points --> pas de triangulation --> la question c'est pkoi seulement deux points
1739
+ # if cell.label == 6:
1740
+ # print('np.asarray(points_for_triangulation)',np.asarray(points_for_triangulation))
1741
+ # print('points_for_triangulation',points_for_triangulation)
1742
+
1743
+ triangles = triangulate(np.asarray(
1744
+ points_for_triangulation)) # ,triangulated_object_ID=cell.label) # need filter the triangulation for concave shapes of clones which is very frequent
1745
+
1746
+ # make it measure the 3D area of the clone --> TODO
1747
+ # if __DEBUG__:
1748
+ # print('area cell 3D', cell.label, compute_3D_surfacearea(triangles,
1749
+ # heightmap=height_map)) # --> ça marche enfin on dirait! --> cool
1750
+
1751
+ # small hack debug to make centroid same height as vertices if handcorrection is passed in --> so that all points are the same height and area is 0 in fact
1752
+
1753
+ # finally just do the length meaurement in 3D for the perimeter and bonds and i'll be done --> this will also be useful for Amrutha
1754
+
1755
+ # maybe I could also save the area for flat 3D as it will not be the same as the real area --> very good idea in fact --> quite smart in fact I really love it
1756
+ # height_map[triangulation_centroid[0], triangulation_centroid[1]]=255 # --> ça marche super en fait et pas de bugs
1757
+ # TODO define the 3D stuff
1758
+
1759
+ # if measure_3D and height_map is not None:
1760
+
1761
+ area3D_flat_3D = compute_3D_surfacearea(triangles, disable_2D_warning=True)
1762
+ area3D = compute_3D_surfacearea(triangles, heightmap=height_map)
1763
+
1764
+ # print('area in 3D', area3D_flat_3D, area3D,cell.area) # there has to be a bug ??? because since all at same height the area must be the same as in 2D --> check that
1765
+
1766
+
1767
+ # ferets_of_interest.append(area3D)
1768
+
1769
+ # seems almost ok
1770
+
1771
+ # plot_triangulation(triangles, out)
1772
+ # if __DEBUG__:
1773
+ # plot_triangulation(triangles, original_image)
1774
+ # plot_triangulation(triangles)
1775
+ except:
1776
+ traceback.print_exc()
1777
+ # clearly it misses most of the vertices of the cell --> big bug ---> see what is going wrong and why
1778
+ # it also fails for cells without vertices
1779
+ print('failed for cell2', cell.label, cell.area, cell.bbox, verts, points_for_triangulation,
1780
+ cell.coords)
1781
+ # print('np.asarray(points_for_triangulation)', np.asarray(points_for_triangulation))
1782
+
1783
+
1784
+ # TODO try cell triangulation for 3D --> should be easy todo in fact !!!
1785
+
1786
+ # plt.imshow(original_image)
1787
+ # plt.show()
1788
+
1789
+ # see what's left to be done
1790
+
1791
+ # now that I have the point inside the cell I can take it
1792
+
1793
+ # on top of cell centroid I can take a point in the cell
1794
+ # first point
1795
+ # or could take a point always in the cell for sure --> smart
1796
+ # coords --> can be a table named coords
1797
+
1798
+ # almost all ok --> see how long it can take to reimplement PCP --> I guess can be quite fast indeed
1799
+
1800
+ #
1801
+
1802
+ # try also triangulation and compute 3D area in fact using height map --> need be sure the centroid is in the cell
1803
+
1804
+ # print('real cell area', cell.area + reg[idx].perimeter / 2)
1805
+
1806
+ # qsdqsqsd
1807
+ # almost ok but then would need the vertices and the bonds --> see how to do
1808
+ # for bonds I have the perfect algo juts need to add pairs of vertices
1809
+ # and this does not require sorting bonds
1810
+
1811
+ # place back on orig image --> easy if one dilation --> bbox -1 and +1 for all dims
1812
+
1813
+ #
1814
+ # plt.imshow(dilated_mask) # seems ok then just need merge with the original mask and I'll have what I need
1815
+ # plt.show()
1816
+ #
1817
+
1818
+ # plt.imshow(lab_perim)
1819
+ # plt.show()
1820
+
1821
+ # is there a bug
1822
+
1823
+ # that's very good but I just miss vertices at the border from this image --> rescue them maybe, see if with no border that works or not ???
1824
+
1825
+ # the funny thing is this code labels all the vertices --> except at the border --> that is very funny in fact and also labels bonds --> really cool in fact I love it
1826
+ # en fait si les vertices at the border sont labeles par des 1 une foir fini
1827
+
1828
+ # DO I NEED THAT ???? --> try nactivate this line then all ok !!!
1829
+ cells[bbox[0] - 1:bbox[2] + 1, bbox[1] - 1: bbox[3] + 1] += dilated_mask.astype(np.uint8)
1830
+ # cells[bbox[0]-1:bbox[2]+1, bbox[1]-1: bbox[3]+1] = cell.label+1
1831
+
1832
+ # place back the mask on original maybe for quantification such as intensity --> TODO
1833
+
1834
+ # seems like the perimeter is in fact what I want in 2D at least: Perimeter of object which approximates the contour as a line through the centers of border pixels using a 4-connectivity.
1835
+
1836
+ # probably not good in fact
1837
+
1838
+ # break
1839
+
1840
+ # again we save all the data in the very end so that if anything goes wrong the stuff is not added at all
1841
+ # in fact that trick may be a super code to label all the cells and all the bonds of it --> really cool in fact -->think about it and how to integrate it some day, almost there though
1842
+ cells_2D['local_ID'].append(cell.label)
1843
+ if cell.label in border_cells:
1844
+ cells_2D['is_border'].append(
1845
+ 1) # somehow there is a bug here because it is saved as a text and I wanted to have it as a boolean --> no clue why
1846
+ else:
1847
+ cells_2D['is_border'].append(0)
1848
+ # this is very slow --> is there no better way ??
1849
+ if cell.label in border_cells_plus_one: # TODO
1850
+ cells_2D['is_border_plus_one'].append(
1851
+ 1) # somehow there is a bug here because it is saved as a text and I wanted to have it as a boolean --> no clue why
1852
+ else:
1853
+ cells_2D['is_border_plus_one'].append(0)
1854
+ cells_2D['bond_cut_off'].append(bond_cut_off)
1855
+ cells_3D['local_ID'].append(cell.label)
1856
+ cells_2D['pixel_within_cell_y'].append(point_awlays_inside_the_cell[0])
1857
+ cells_2D['pixel_within_cell_x'].append(point_awlays_inside_the_cell[1])
1858
+ cells_2D['first_pixel_y'].append(cell.coords[0][0])
1859
+ cells_2D['first_pixel_x'].append(cell.coords[0][1])
1860
+ cells_2D['cytoplasmic_area'].append(cell.area)
1861
+ # print('centroid', cell.centroid)
1862
+ centroid = cell.centroid
1863
+ # if len(centroid)==3:
1864
+ # cells_3D['centroid_z']=centroid[0] # impossible cause 2D
1865
+ # image is 2D
1866
+ cells_2D['centroid_y'].append(centroid[-2])
1867
+ cells_2D['centroid_x'].append(centroid[-1])
1868
+
1869
+ cells_2D['perimeter'].append(reg[idx].perimeter)# nb maybe this value is incorrect because it's an apporximation --> probably I should replace it even if it will be much slower
1870
+ cells_2D['perimeter_pixel_count'].append(reg[idx].area)
1871
+ cells_2D['area'].append(cell.area + reg[idx].perimeter / 2.) # NB should I do that in 3D too???
1872
+
1873
+ # scipy elongation and orientation of cells --> TODO --> maybe also add the TA one just for compatibility
1874
+ # cells_2D['major_axis_length'].append(cell.major_axis_length)
1875
+ # cells_2D['minor_axis_length'].append(cell.minor_axis_length)
1876
+
1877
+ try:
1878
+ # stretch is slow --> so maybe offer this as an option ???
1879
+ stretch_nematic = compute_stretch_nematic(cell)
1880
+ cells_2D['orientation'].append(stretch_nematic.get_angle2())
1881
+ # cells_2D['eccentricity'].append(cell.eccentricity)
1882
+ cells_2D['elongation'].append(stretch_nematic.getS0())
1883
+ cells_2D['S1'].append(stretch_nematic.S1)
1884
+ cells_2D['S2'].append(stretch_nematic.S2)
1885
+ except:
1886
+ # if True:
1887
+ # traceback.print_exc()
1888
+ cells_2D['orientation'].append(None)
1889
+ # cells_2D['eccentricity'].append(cell.eccentricity)
1890
+ cells_2D['elongation'].append(None)
1891
+ cells_2D['S1'] .append( None)
1892
+ cells_2D['S2'].append( None)
1893
+
1894
+
1895
+ # sqsqdsq
1896
+
1897
+ if measure_polarity:
1898
+ # print('polarity nematic', polarity_nematic) # TODO DO THIS FOR ALL CHANNELS
1899
+ for ppp in range(len(polarity_nematic) - 1):
1900
+ if isinstance(polarity_nematic[0], list):
1901
+ for ccc in range(len(polarity_nematic[0])):
1902
+ # print('TODO sum_bd_intensity,avg_bd_intensity', sum_bd_intensity[ccc], avg_bd_intensity[ccc])
1903
+ if 'Q' + str(ppp + 1) + '_polarity_ch' + str(ccc) not in cells_2D:
1904
+ cells_2D['Q' + str(ppp + 1) + '_polarity_ch' + str(ccc)] = []
1905
+ cells_2D['normalized_Q' + str(ppp + 1) + '_polarity_ch' + str(ccc)] = []
1906
+ cells_2D['Q' + str(ppp + 1) + '_polarity_ch' + str(ccc)].append(polarity_nematic[ppp][ccc])
1907
+ try:
1908
+ cells_2D['normalized_Q' + str(ppp + 1) + '_polarity_ch' + str(ccc)].append(
1909
+ polarity_nematic[ppp][ccc] / polarity_nematic[-1][ccc])
1910
+ except:
1911
+ # error division by 0 --> set it to 0
1912
+ cells_2D['normalized_Q' + str(ppp + 1) + '_polarity_ch' + str(ccc)].append(0.)
1913
+ else:
1914
+ if 'Q' + str(ppp + 1) + '_polarity_ch' + str(0) not in cells_2D:
1915
+ cells_2D['Q' + str(ppp + 1) + '_polarity_ch' + str(0)] = []
1916
+ cells_2D['normalized_Q' + str(ppp + 1) + '_polarity_ch' + str(0)] = []
1917
+ cells_2D['Q' + str(ppp + 1) + '_polarity_ch' + str(0)].append(polarity_nematic[ppp])
1918
+ try:
1919
+ cells_2D['normalized_Q' + str(ppp + 1) + '_polarity_ch' + str(0)].append(
1920
+ polarity_nematic[ppp] / polarity_nematic[-1])
1921
+ except:
1922
+ # error division by 0 --> set it to 0
1923
+ cells_2D['normalized_Q' + str(ppp + 1) + '_polarity_ch' + str(0)].append(0.)
1924
+
1925
+ # qssqsqqssqsqsqdsqdsqd
1926
+ # print(type(polarity_nematic[0])) # --> why is it an image ???
1927
+ # plot the intensities too!!!
1928
+ # plot cytoplasmic intensity
1929
+ # plot cortical intensity
1930
+ # plot nematics and I'll be done...
1931
+
1932
+ # store all the cell vertices ids
1933
+
1934
+ cells_2D['vertices'].append(vx_local_ids) # TODO shall I add bonds --> also need create a vertices table
1935
+ cells_2D['nb_of_vertices_or_neighbours'].append(len(vx_local_ids))
1936
+ # nb_of_vertices_or_neighbours_cut_off = len(vx_local_ids)
1937
+
1938
+ bond_length_of_the_cell = bond_lengths_associated_to_a_given_cell[cell.label]
1939
+ nb_of_vertices_or_neighbours_cut_off = len(bond_length_of_the_cell)
1940
+ if bond_cut_off is not None and bond_cut_off > 0:
1941
+ bond_length_of_the_cell = [bdl for bdl in bond_length_of_the_cell if bdl > bond_cut_off]
1942
+ nb_of_vertices_or_neighbours_cut_off = len(bond_length_of_the_cell)
1943
+ # del bond_lengths_associated_to_a_given_cell[cell.label]
1944
+ cells_2D['nb_of_vertices_or_neighbours_cut_off'].append(nb_of_vertices_or_neighbours_cut_off)
1945
+ bonds_of_cll = bonds_associated_to_a_given_cell[cell.label]
1946
+ cells_2D['bonds'].append(bonds_of_cll)
1947
+
1948
+ if measure_3D and height_map is not None:
1949
+ cells_3D['area3D'].append(area3D)
1950
+ cells_3D['area_flat_height'].append(area3D_flat_3D)
1951
+ cells_3D['perimeter3D'].append(perimeter3D)
1952
+
1953
+ # print('cytoplasmic area',cell.area) # area is the area without the perimeter, see how the perim is computed --> same as in IJ
1954
+
1955
+ if __DEBUG__:
1956
+ print('debug #17')
1957
+ # cells[vertices==255]=6
1958
+
1959
+ # plt.imshow(cells)
1960
+ # plt.show()
1961
+
1962
+ # Img(lab_cells).save('/E/Sample_images/sample_images_PA/mini/focused_Series012/0_test_IJ_perimeter.tif')
1963
+
1964
+ # all is ok I may just need to get bonds and their perimeter now etc and do also 3D measurements --> in same or in new table --> think about it
1965
+ # almost there and almost have a TA that is even working better than original and much simpler to code and maintain
1966
+
1967
+ # need get bonds and measure them --> should be easy in fact
1968
+ # get the bonds, fill them and get their 2D perimeter then find their associated vertices and create the final version of the bond and measure its length --> not so hard then can give it an id --> TODO
1969
+
1970
+ # skimage.measure.perimeter(image, neighbourhood=4)
1971
+
1972
+ # finally just need get now the pairs of vertices and add them to bonds
1973
+ # maybe also smart to measure average intensity
1974
+
1975
+ # detect vertex pairs
1976
+ # --> just detect them and pair them maybe --> TODO
1977
+ # see the most efficient way to do that
1978
+
1979
+ # vertices_coords = np.where(vertices==255)
1980
+ #
1981
+ #
1982
+ # # print(vertices_coords)
1983
+ # for vvv in range(len(vertices_coords[0])):
1984
+ # y = vertices_coords[0][vvv]
1985
+ # x = vertices_coords[1][vvv]
1986
+ #
1987
+ # print(y,x)
1988
+ # # get its neighbors in a safe way
1989
+ # for iii in range[-1,2,1]:
1990
+ # for jjj in range[-1,2,1]:
1991
+ # if vertices[]
1992
+
1993
+ # easiest way is to flood the vertices and get those with area >= 2 --> a piece of cake TODO
1994
+
1995
+ # TODO REALLY NEED ADD THAT TOO
1996
+ # I need add this to bonds 2D and remove missing ones
1997
+
1998
+ # in fact that is easy I need add the stuff to the cell only in the very end
1999
+ # cells_2D['nb_of_vertices_or_neighbours_cut_off'].append(nb_of_vertices_or_neighbours_cut_off)
2000
+
2001
+ # en fait marche pas --> see how I can do that
2002
+
2003
+ # all is ok
2004
+ # print(pairs_of_vertices)
2005
+ # print(len(pairs_of_vertices)) # -->18
2006
+ # print(len(pairs_of_vertices[0])) # -->2
2007
+
2008
+ # final thing that must be done is the polarity --> but it requires sorting vertices and so will be slow --> do not do it by default
2009
+
2010
+ # these can also be considered as fourway vertices in the same way as bonds below a cutoff --> I could do that and save those
2011
+ # shall I store local vx id too
2012
+
2013
+ # almost all is saved and finally I need also do things in 3D --> not that hard by the way and can be done if I have the height map --> enable it by default if height map is there
2014
+ # just need triangulate all the cells
2015
+ # maybe offer control of the nb of CPUs to use at startup or in settings and try to MT things --> probably not hard and can be done at the level of the list --> should not be too hard
2016
+ # need also count the nb of vertices per cell to get nb of neighbours and need get
2017
+ # need create a viewer and something that can export to IJ from the command line --> à tester en fait mais devrait pas etre trop dur je pense et je peux facilement generer des stacks on demand --> TODO
2018
+
2019
+ # do all of that and get rid of TA
2020
+
2021
+ # try to really finalize something
2022
+ # see how much memory I would need in the end for that
2023
+ # do a nematic class and allow it to be plotted
2024
+
2025
+ # see how much time it would take just for one case of one big image ????
2026
+ # do the parallelization
2027
+ # finalize tracking error correction --> TODO
2028
+ # then try to finalize a GUI, and really clean all too
2029
+ # try speed up also labels by having it to compute just the really necessary things...
2030
+
2031
+ # print('bonds_associated_to_a_given_cell',bonds_associated_to_a_given_cell)
2032
+ # print('bond_lengths_associated_to_a_given_cell',bond_lengths_associated_to_a_given_cell)
2033
+
2034
+ if __DEBUG__:
2035
+ print('debug #18')
2036
+ if TA_path is not None:
2037
+ db = TAsql(db_path)
2038
+ # print('cells_2D'*20)
2039
+ db.create_and_append_table(table_name='vertices_2D', datas=fill_missing_with_Nones(vertices_2D))
2040
+ db.create_and_append_table(table_name='cells_2D', datas=fill_missing_with_Nones(cells_2D))
2041
+ # print('cells_3D'*20)
2042
+ # print('bonds_2D' * 20)
2043
+ db.create_and_append_table(table_name='bonds_2D', datas=fill_missing_with_Nones(bonds_2D))
2044
+ if measure_3D and height_map is not None:
2045
+ db.create_and_append_table(table_name='cells_3D', datas=fill_missing_with_Nones(cells_3D))
2046
+ db.create_and_append_table(table_name='bonds_3D', datas=fill_missing_with_Nones(bonds_3D))
2047
+ elif measure_3D and height_map is None:
2048
+ db.drop_table('cells_3D')
2049
+ db.drop_table('bonds_3D')
2050
+
2051
+ db.close()
2052
+ else:
2053
+ # plt.imshow(cells)
2054
+ # plt.show()
2055
+ # maybe return an error and always close the db
2056
+
2057
+ print('cells_2D', cells_2D)
2058
+ print('cells_3D', cells_3D)
2059
+ print('bonds_2D', bonds_2D)
2060
+ print('bonds_3D', bonds_3D)
2061
+ print('vertices_2D', vertices_2D)
2062
+
2063
+ for k, v in cells_2D.items():
2064
+ print(len(v))
2065
+
2066
+ cells_2D = fill_missing_with_Nones(cells_2D)
2067
+ print('#' * 20)
2068
+ for k, v in cells_2D.items():
2069
+ print(len(v))
2070
+
2071
+ if __DEBUG__:
2072
+ print('debug #19')
2073
+ print('total time', timer() - start)
2074
+
2075
+ # do it a class and make it modular so that the minimal nb of things are executed
2076
+
2077
+ # je pense 4-5 secs par image sans trier les contours --> not super slow but also not very fast
2078
+ # speed up computation of contour by using numpy array --> remember my distance code
2079
+
2080
+ # should all be fast to do --> 3-4 days I think
2081
+
2082
+ # see what's missing
2083
+ # 2.3 secs per stuff --> not bad, in fact maybe as fast as TA now
2084
+ # need sort contour
2085
+ # need get bonds and their vertices --> TODO
2086
+ # need all other parameters
2087
+ # if scaling parameter then one needs to specify
2088
+ # need scaling factors if heightmap is there
2089
+
2090
+ # finalize everything and maybe retrain a model that already works very well for the projection
2091
+
2092
+ # TODO do the db part
2093
+ # also do the sorting part
2094
+
2095
+ # and also I need to do the intensity part --> TODO
2096
+ # also make it a class that is easy to use
2097
+
2098
+ # also do the triangulation part for 3D --> should not be too hard to do
2099
+
2100
+
2101
+ if __name__ == '__main__':
2102
+ from datetime import datetime
2103
+ print(datetime.now())
2104
+
2105
+
2106
+ if False:
2107
+ print(round(5.59)) # not good
2108
+ print(round(5.39)) # not good
2109
+ import sys
2110
+
2111
+ sys.exit(0)
2112
+
2113
+ if False:
2114
+ # original_image = Img('/E/Sample_images/sample_images_PA/mini/focused_Series012/handCorrection.png')[..., 1] # if no shift max and min should always be 255 otherwise there is an error somewhere
2115
+ original_image = Img('/E/Sample_images/sample_images_PA/mini/focused_Series012.png')[
2116
+ ..., 1] # if no shift max and min should always be 255 otherwise there is an error somewhere
2117
+ # cells = Img('/E/Sample_images/sample_images_PA/mini/focused_Series012/handCorrection.png')[..., 0]
2118
+ cells = Img('/E/Sample_images/sample_images_PA/mini/focused_Series012/handCorrection.tif')
2119
+ # height_map = None # Img('/E/Sample_images/sample_images_PA/mini/focused_Series012.png')[..., 1]
2120
+ height_map = Img('/E/Sample_images/sample_images_PA/mini/focused_Series012.png')[..., 1]
2121
+ # height_map = Img('/E/Sample_images/sample_images_PA/mini/focused_Series012.png')[..., 0] # another good test because all is 0 there --> marche car aire est proche de l'aire 2D par contre pr handcorrection ça marche pas car tres different de l'aire 2D --> see why and how to fix it
2122
+ # height_map = Img('/E/Sample_images/sample_images_PA/mini/focused_Series012/handCorrection.png')[..., 0] # good for a test as all heights are the same... --> in fact that makes sense since some heigts are 0 and some are 255 since the centroid of the polygon is always 0
2123
+
2124
+ # for manual debug KEEP:
2125
+ # TAMeasurements(None,__forced_orig=original_image, __forced_cells=cells, __forced_heightmap=height_map)
2126
+
2127
+ # TAMeasurements(None, __forced_orig=original_image, __forced_cells=cells, __forced_heightmap=height_map,measure_polarity=True, measure_3D=True)
2128
+ # import sys
2129
+ # sys.exit(0)
2130
+
2131
+ # make it loop add nb of neighbors à la TA with cut off and also add support for lists of files--> in the same self loop by the way --> no waste of time this way and add support for progress
2132
+
2133
+ # TAMeasurements('/E/Sample_images/sample_images_PA/mini/focused_Series012.png', measure_polarity=True, measure_3D=True) # --> almost there just need create one db per file now!!!
2134
+ # TAMeasurements('/E/Sample_images/sample_images_PA/mini_different_nb_of_channels/focused_Series012.png', measure_polarity=True, measure_3D=True) # --> almost there just need create one db per file now!!!
2135
+ # TAMeasurements(loadlist('/E/Sample_images/sample_images_PA/mini_different_nb_of_channels/list.lst'),measure_polarity=True, measure_3D=True) # --> almost there just need create one db per file now!!!
2136
+ # TAMeasurements(['/E/Sample_images/sample_images_pyta/surface_projection/210219.lif_t000.tif'], measure_polarity=True, measure_3D=True) # --> almost there just need create one db per file now!!!
2137
+ # TAMeasurements(['/E/Sample_images/sample_images_pyta/surface_projection/exposures_1_P04.tif'],measure_polarity=True, measure_3D=True) # --> almost there just need create one db per file now!!!
2138
+ # TAMeasurements(loadlist('/E/Sample_images/sample_images_pyta/surface_projection/list.lst'),measure_polarity=True, measure_3D=True) # --> almost there just need create one db per file now!!!
2139
+ # TAMeasurements(loadlist('/E/Sample_images/sample_images_pyta/surface_projection/list.lst'),measure_polarity=False, measure_3D=False) # causes a bug --> try see why ????
2140
+ # TAMeasurements(['/E/Sample_images/sample_images_PA/mini_different_nb_of_channels/mini_focused_Series014_for_debug_polarity_nematic.tif'], measure_polarity=True,measure_3D=True) # --> almost there just need create one db per file now!!!
2141
+
2142
+ # test with list
2143
+ TAMeasurements(['/E/Sample_images/sample_images_PA/mini/focused_Series012.png','/E/Sample_images/sample_images_PA/mini/focused_Series014.png'], measure_polarity=False, measure_3D=False) # --> almost there just need create one db per file now!!!
2144
+
2145
+
2146
+ # /E/Sample_images/sample_images_pyta/surface_projection/list.lst
2147
+
2148
+ # TODO make it also save the vertices, cells and bonds ??? --> easy TODO in fact
2149
+ import sys
2150
+ sys.exit(0)
2151
+
2152
+ if True:
2153
+ start = timer()
2154
+ merge_names = loadlist('/E/Sample_images/sample_images_PA/mini_vide/list_simple.lst')
2155
+ # TAMeasurements(merge_names, measure_polarity=False, measure_3D=False, multi_threading=False)
2156
+ TAMeasurements(merge_names, measure_polarity=False, measure_3D=False, multi_threading=True) # vrai gain mais pas sur mac... comprend rien quand meme --> est ce du à numba
2157
+ print('total execution time', timer() - start)
2158
+
2159
+ import sys
2160
+ sys.exit(0)
2161
+
2162
+ # if False:
2163
+ # # failed attempt to launch it in a thread
2164
+ #
2165
+ # start = timer()
2166
+ # # try MT the finish all
2167
+ # # import multiprocessing
2168
+ # # merge_names = ['/E/Sample_images/sample_images_PA/mini/focused_Series012.png','/E/Sample_images/sample_images_PA/mini/focused_Series014.png','/E/Sample_images/sample_images_PA/mini/focused_Series015.png','/E/Sample_images/sample_images_PA/mini/focused_Series016.png','/E/Sample_images/sample_images_PA/mini/focused_Series018.png','/E/Sample_images/sample_images_PA/mini/focused_Series019.png']
2169
+ # # TRY MY THE MeA
2170
+ # # pas mal mais il me faudrait une progress bar en fait
2171
+ # # with multiprocessing.Pool(processes=8) as pool:
2172
+ # # results = pool.map(TAMeasurements, merge_names)
2173
+ #
2174
+ # # merge_names = loadlist('/E/Sample_images/trash/complete/liste.lst')
2175
+ # # merge_names = loadlist('/E/Sample_images/sample_images_denoise_manue/211029_EcadKI_mel_40-54hAPF_ON/surface_projection/list.lst')
2176
+ # merge_names = loadlist('/E/Sample_images/sample_images_PA/mini_vide/list_simple.lst')
2177
+ #
2178
+ # from functools import partial
2179
+ # from epyseg.ta.pyqt_test_threads_instead_of_threadpool import Worker2
2180
+ #
2181
+ # func = partial(TAMeasurements)
2182
+ # thread = Worker2(func, merge_names, measure_polarity=False, measure_3D=False)
2183
+ #
2184
+ # # self.thread.result.connect(self.print_output)
2185
+ # # self.thread.finished.connect(self.thread_complete)
2186
+ # # this is specific of this method I must update the nb of inputs and outputs of the model # be CAREFUL IF COPYING THIS CODE THE FOLLOWING MUST BE REMOVED
2187
+ # # worker.signals.finished.connect(self._set_model_inputs_and_outputs)
2188
+ # # self.thread.progress.connect(self.progress_fn)
2189
+ # thread.setTerminationEnabled(True)
2190
+ #
2191
+ # # Execute
2192
+ # # if isinstance(self.thread, FakeWorker2):
2193
+ # # # no threading
2194
+ # # self.thread.run()
2195
+ # # else:
2196
+ # # threading
2197
+ # # self.threadpool.start(worker)
2198
+ # # self.threads.append(worker)
2199
+ # # worker.moveToThread(self.thread)
2200
+ #
2201
+ # # self.thread.started.connect(self.thread.run)
2202
+ # thread.start()
2203
+ #
2204
+ # # NON MT --> 1400secs
2205
+ #
2206
+ # # marche mais pas qd lancé depuis pyqt --> why -> can I simulate launch in a thread ????
2207
+ #
2208
+ # # MT --> 176secs --> really worth it!!!
2209
+ # # from tqdm import tqdm
2210
+ # # import sys
2211
+ # # pool = Pool(processes=15)
2212
+ # # for i, _ in enumerate(tqdm(pool.imap_unordered(TAMeasurements, merge_names), total=len(merge_names))):
2213
+ # # # pass
2214
+ # # # sys.stderr.write('\rdone {0:%}'.format(i / len(merge_names))) # --> I could use that to plot with the other progressbar --> ok
2215
+ # # # cool --> I can use that to display progress in the other progress bar --> the QT one
2216
+ # # pass
2217
+ # #
2218
+ # # pool.close()
2219
+ # # pool.join()
2220
+ #
2221
+ # print('total execution time', timer() - start)
2222
+ # # import sys
2223
+ # # sys.exit(0)
2224
+ #
2225
+ # # why not running ???
2226
+