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,1321 @@
1
+ """
2
+ A collection of file related methods
3
+
4
+
5
+ """
6
+ from batoolset.lists.tools import find_first_index, flatten_list
7
+ from batoolset.strings.tools import is_string_a_list_string, reload_string_list
8
+ from datetime import datetime
9
+ import subprocess
10
+ import tempfile
11
+ import glob
12
+ import hashlib
13
+ import platform
14
+ from batoolset.utils.loadlist import loadlist
15
+ import os
16
+ import shutil
17
+ import uuid
18
+
19
+
20
+
21
+ import numpy as np
22
+ from skimage.draw import polygon, polygon_perimeter
23
+ from skimage.measure import regionprops
24
+ from skimage import measure
25
+ from collections import Counter
26
+ from natsort import natsorted
27
+ from batoolset.utils.loadlist import loadlist
28
+ from batoolset.colors.colorgen import get_unique_random_color_int24
29
+ import os
30
+
31
+ from batoolset.tools.logger import TA_logger # logging
32
+
33
+ logger = TA_logger()
34
+
35
+
36
+ def get_TA_file(file_name_without_ext, TA_file):
37
+ """
38
+ Returns the path to the TA file by joining the file name without extension and the TA file.
39
+
40
+ Args:
41
+ file_name_without_ext (str): File name without extension.
42
+ TA_file (str): TA file.
43
+
44
+ Returns:
45
+ str: Path to the TA file.
46
+
47
+ """
48
+ return os.path.join(file_name_without_ext, TA_file)
49
+
50
+
51
+ def get_n_consecutive_input_files_and_output_folders(images_to_analyze, start_idx, nb_of_images_to_get, incr=1):
52
+ """
53
+ Returns a list of consecutive input files and output folders.
54
+
55
+ Args:
56
+ images_to_analyze (list): List of images to analyze.
57
+ start_idx (int): Starting index.
58
+ nb_of_images_to_get (int): Number of consecutive images to get.
59
+ incr (int, optional): Increment value. Defaults to 1.
60
+
61
+ Returns:
62
+ list: List of input files and output folders.
63
+
64
+ """
65
+ return get_n_input_files_and_output_folders(images_to_analyze, start_idx, 0, nb_of_images_to_get, incr=incr)
66
+
67
+
68
+ def get_n_input_files_and_output_folders(images_to_analyze, start_idx, start_range, end_range_inclusive, incr=1):
69
+ """
70
+ Returns a list of input files and output folders within a specified range.
71
+
72
+ Args:
73
+ images_to_analyze (list): List of images to analyze.
74
+ start_idx (int): Starting index.
75
+ start_range (int): Starting range.
76
+ end_range_inclusive (int): Ending range (inclusive).
77
+ incr (int, optional): Increment value. Defaults to 1.
78
+
79
+ Returns:
80
+ list: List of input files and output folders.
81
+
82
+ """
83
+ try:
84
+ return images_to_analyze[start_idx + start_range: start_idx + end_range_inclusive: incr]
85
+ except:
86
+ output_data = []
87
+ for i in range(start_range, end_range_inclusive + 1, incr):
88
+ output_data.append(get_input_file_and_output_folder(images_to_analyze, start_idx + i))
89
+ return output_data
90
+
91
+
92
+ def get_n_files_from_list(images_to_analyze, start_idx, start_range, end_range_inclusive, incr=1):
93
+ """
94
+ Returns a list of files from a given list within a specified range.
95
+
96
+ Args:
97
+ images_to_analyze (list): List of images to analyze.
98
+ start_idx (int): Starting index.
99
+ start_range (int): Starting range.
100
+ end_range_inclusive (int): Ending range (inclusive).
101
+ incr (int, optional): Increment value. Defaults to 1.
102
+
103
+ Returns:
104
+ list: List of files.
105
+
106
+ Raises:
107
+ Exception: Raises an exception if the list is empty.
108
+
109
+ """
110
+ if images_to_analyze is None or not images_to_analyze:
111
+ raise Exception('Empty list, nothing to do...')
112
+ try:
113
+ if start_idx + start_range < 0 or start_idx + end_range_inclusive >= len(images_to_analyze):
114
+ raise IndexError("List index out of range")
115
+ return images_to_analyze[start_idx + start_range: start_idx + end_range_inclusive + 1: incr]
116
+ except:
117
+ output_data = []
118
+ for i in range(start_range, end_range_inclusive + 1, incr):
119
+ if start_idx + i < 0 or start_idx + i >= len(images_to_analyze):
120
+ output_data.append(None)
121
+ continue
122
+ output_data.append(images_to_analyze[start_idx + i])
123
+ return output_data
124
+
125
+
126
+ known_parsers = ['parent',
127
+ 'ext',
128
+ 'short',
129
+ 'full_no_ext',
130
+ 'TA', # same as full no ext
131
+ 'short_no_ext',
132
+ 'full',
133
+ 'full_no_end_slash',
134
+ 'short_pop_all_exts', # extreme version of short no ext where series of exts are removed, e.g. hiC_250522.pairs.txt.gz -−> hiC_250522
135
+ ]
136
+
137
+
138
+ def replace_empty_string_by_none(input_string):
139
+ """
140
+ Replaces an empty string with None.
141
+
142
+ Args:
143
+ input_string (str): Input string.
144
+
145
+ Returns:
146
+ str: Input string with empty string replaced by None.
147
+
148
+ """
149
+ if not input_string:
150
+ return None
151
+ return input_string
152
+
153
+
154
+ def smart_name_appender(name, condition_boolean, text_to_append_if_condition_is_true=None,
155
+ text_to_append_if_condition_is_false=None):
156
+ """
157
+ Appends a string to a name depending on a condition.
158
+
159
+ Args:
160
+ name (str): Name to append the string.
161
+ condition_boolean (bool): Condition.
162
+ text_to_append_if_condition_is_true (str, optional): Text to append if the condition is True. Defaults to None.
163
+ text_to_append_if_condition_is_false (str, optional): Text to append if the condition is False. Defaults to None.
164
+
165
+ Returns:
166
+ str: Modified name.
167
+
168
+ """
169
+ if condition_boolean:
170
+ if text_to_append_if_condition_is_true is not None:
171
+ name += text_to_append_if_condition_is_true
172
+ else:
173
+ if text_to_append_if_condition_is_false is not None:
174
+ name += text_to_append_if_condition_is_false
175
+ return name
176
+
177
+
178
+ def smart_name_parser(full_file_path, ordered_output=known_parsers, appenders=None, replace_empty_by_none=False):
179
+ """
180
+ Parses the full file path and returns the specified output.
181
+
182
+ Args:
183
+ full_file_path (str): Full file path.
184
+ ordered_output (str or list, optional): Ordered list of output formats. Defaults to known_parsers.
185
+ appenders (str or list, optional): String or list of strings to append to the output. Defaults to None.
186
+ replace_empty_by_none (bool, optional): Replace empty strings by None. Defaults to False.
187
+
188
+ Returns:
189
+ str or list: Parsed output.
190
+
191
+ """
192
+ if full_file_path is None:
193
+ logger.error('Please specify an input file name')
194
+ return
195
+ if ordered_output is None:
196
+ logger.error('Parsing unspecified, nothing to do')
197
+ return
198
+
199
+ fixed_path = full_file_path.replace('\\\\', '/').replace('\\', '/')
200
+ filename0_without_path = os.path.basename(fixed_path)
201
+ filename0_without_ext, ext = os.path.splitext(filename0_without_path)
202
+ parent_dir_of_filename0 = os.path.dirname(fixed_path)
203
+
204
+ single_output = False
205
+ if isinstance(ordered_output, str):
206
+ single_output = True
207
+ ordered_output = [ordered_output]
208
+
209
+ sorted_output = []
210
+ for parser in ordered_output:
211
+ if parser not in known_parsers:
212
+ sorted_output.append(os.path.join(parent_dir_of_filename0, os.path.join(filename0_without_ext, parser)))
213
+ continue
214
+ if parser == 'parent':
215
+ sorted_output.append(parent_dir_of_filename0)
216
+ continue
217
+ if parser == 'short_no_ext':
218
+ sorted_output.append(filename0_without_ext)
219
+ continue
220
+ if parser == 'short_pop_all_exts':
221
+ extracted = filename0_without_ext
222
+ while '.' in extracted:
223
+ extracted, _ = os.path.splitext(extracted)
224
+ sorted_output.append(extracted)
225
+ if parser == 'full_no_ext' or parser == 'TA':
226
+ sorted_output.append(os.path.join(parent_dir_of_filename0, filename0_without_ext))
227
+ continue
228
+ if parser == 'short':
229
+ sorted_output.append(filename0_without_path)
230
+ continue
231
+ if parser == 'full':
232
+ sorted_output.append(full_file_path)
233
+ continue
234
+ if parser == 'ext':
235
+ sorted_output.append(ext)
236
+ continue
237
+ if parser == 'full_no_end_slash':
238
+ out = fixed_path
239
+ if out.endswith('/'):
240
+ out = out[:-1]
241
+ sorted_output.append(out)
242
+
243
+ if appenders is not None:
244
+ if not isinstance(appenders, list):
245
+ appenders = [appenders]
246
+ sorted_output = [os.path.join(txt, *appenders) for txt in sorted_output]
247
+
248
+ if replace_empty_by_none:
249
+ sorted_output = [replace_empty_string_by_none(input_string) for input_string in sorted_output]
250
+
251
+ if single_output:
252
+ return sorted_output[0]
253
+ return sorted_output
254
+
255
+
256
+ def get_input_file_and_output_folder(images_to_analyze, idx):
257
+ """
258
+ Returns the input file and output folder for a given index.
259
+
260
+ Args:
261
+ images_to_analyze (list): List of images to analyze.
262
+ idx (int): Index of the image to retrieve.
263
+
264
+ Returns:
265
+ tuple: Input file path and output folder path.
266
+
267
+ """
268
+ file_path_0 = images_to_analyze[idx]
269
+ filename0_without_ext = os.path.splitext(file_path_0)[0]
270
+ return file_path_0, filename0_without_ext
271
+
272
+
273
+ def get_input_files_and_output_folders(images_to_analyze, start_idx, incr=1):
274
+ """
275
+ Returns the input files and output folders for consecutive indices.
276
+
277
+ Args:
278
+ images_to_analyze (list): List of images to analyze.
279
+ start_idx (int): Starting index.
280
+ incr (int, optional): Increment value. Defaults to 1.
281
+
282
+ Returns:
283
+ tuple: Input file paths and output folder paths.
284
+
285
+ """
286
+ file_path_0 = images_to_analyze[start_idx]
287
+ file_path_1 = images_to_analyze[start_idx + incr]
288
+
289
+ filename0_without_ext = os.path.splitext(file_path_0)[0]
290
+ filename1_without_ext = os.path.splitext(file_path_1)[0]
291
+
292
+ return file_path_0, file_path_1, filename0_without_ext, filename1_without_ext
293
+
294
+
295
+ def get_list_of_files(path):
296
+ """
297
+ Returns a list of files in the given path.
298
+
299
+ Args:
300
+ path (str or list): Path to the directory or a list of file paths.
301
+
302
+ Returns:
303
+ list: List of file paths.
304
+
305
+ # Examples:
306
+ # >>> get_list_of_files('/path/to/files')
307
+ # ['/path/to/files/file1.txt', '/path/to/files/file2.txt', '/path/to/files/file3.txt']
308
+ #
309
+ # >>> get_list_of_files(['/path/to/files/file1.txt', '/path/to/files/file2.txt'])
310
+ # ['/path/to/files/file1.txt', '/path/to/files/file2.txt']
311
+
312
+ """
313
+ if isinstance(path, list):
314
+ return path
315
+
316
+ if not path.lower().endswith('.txt') and not path.lower().endswith('.lst'):
317
+ images_to_analyze = os.listdir(path)
318
+ images_to_analyze = [os.path.join(path, f) for f in images_to_analyze if os.path.isfile(os.path.join(path, f))]
319
+ images_to_analyze = natsorted(images_to_analyze)
320
+ else:
321
+ images_to_analyze = loadlist(path)
322
+
323
+ return images_to_analyze
324
+
325
+
326
+ def first_image_tracking(mask_t0, labels_t0, regprps=None, assigned_ids=None, seed=None):
327
+ """
328
+ Performs tracking on the first image.
329
+
330
+ Args:
331
+ mask_t0 (ndarray): Binary mask of the first image.
332
+ labels_t0 (ndarray): Labels of the first image.
333
+ regprps (list, optional): List of region properties. Defaults to None.
334
+ assigned_ids (list, optional): List of assigned IDs. Defaults to None.
335
+ seed (int, optional): Random seed. Defaults to None.
336
+
337
+ Returns:
338
+ ndarray: Tracked image.
339
+
340
+ """
341
+ tracks_t0 = np.zeros_like(mask_t0, dtype=np.uint32)
342
+
343
+ if regprps is None:
344
+ regprps = regionprops(labels_t0)
345
+
346
+ for iii, region in enumerate(regprps):
347
+ # create a random color and store it
348
+ if iii == 0:
349
+ new_col = get_unique_random_color_int24(forbidden_colors=assigned_ids, seed_random=seed,
350
+ assign_new_col_to_forbidden=True)
351
+ else:
352
+ new_col = get_unique_random_color_int24(forbidden_colors=assigned_ids, assign_new_col_to_forbidden=True)
353
+
354
+ tracks_t0[labels_t0 == iii + 1] = new_col
355
+
356
+ tracks_t0[labels_t0 == 0] = 0xFFFFFF
357
+ # save the image or return it
358
+ return tracks_t0 # this is the image # need copy it
359
+
360
+
361
+ def deduplicate_duplicated_cells_using_random_ids(RGB24, labels=None, background=0xFFFFFF, assigned_ids=None):
362
+ """
363
+ Deduplicates duplicated cells using random IDs.
364
+
365
+ Args:
366
+ RGB24 (ndarray): RGB image.
367
+ labels (ndarray, optional): Label image. Defaults to None.
368
+ background (int, optional): Background color. Defaults to 0xFFFFFF.
369
+ assigned_ids (list, optional): List of assigned IDs. Defaults to None.
370
+
371
+ Returns:
372
+ ndarray: Deduplicated RGB image.
373
+
374
+ """
375
+ if labels is None:
376
+ labels = measure.label(RGB24, connectivity=1, background=background)
377
+
378
+ cell_ids = []
379
+ for region in regionprops(labels):
380
+ cell_ids.append(RGB24[region.coords[0][0], region.coords[0][1]])
381
+
382
+ cell_ids_n_count = Counter(cell_ids)
383
+ duplicated_cells = {k: v for k, v in cell_ids_n_count.items() if v >= 2}
384
+
385
+ duplicated_cells_keys = list(duplicated_cells.keys())
386
+ for region in regionprops(labels):
387
+ id = RGB24[region.coords[0][0], region.coords[0][1]]
388
+ if id in duplicated_cells_keys:
389
+ duplication_count = duplicated_cells[id]
390
+ if duplication_count >= 2:
391
+ duplicated_cells[id] = duplication_count - 1
392
+ RGB24[labels == region.label] = get_unique_random_color_int24(forbidden_colors=assigned_ids,
393
+ assign_new_col_to_forbidden=True)
394
+ else:
395
+ duplicated_cells_keys.remove(id)
396
+
397
+ return RGB24
398
+
399
+
400
+ def assign_random_ID_to_missing_cells(RGB24img, labels, regprps=None, assigned_ids=None):
401
+ """
402
+ Assigns random IDs to missing cells in the image.
403
+
404
+ Args:
405
+ RGB24img (ndarray): RGB image.
406
+ labels (ndarray): Label image.
407
+ regprps (list, optional): List of region properties. Defaults to None.
408
+ assigned_ids (list, optional): List of assigned IDs. Defaults to None.
409
+
410
+ Returns:
411
+ ndarray: RGB image with assigned random IDs.
412
+
413
+ """
414
+ if regprps is None:
415
+ regprps = regionprops(labels)
416
+
417
+ for iii, region in enumerate(regprps):
418
+ color_of_first_pixel_of_potential_match = RGB24img[region.coords[0][0], region.coords[0][1]]
419
+
420
+ if color_of_first_pixel_of_potential_match == 0:
421
+ new_col = get_unique_random_color_int24(forbidden_colors=assigned_ids, assign_new_col_to_forbidden=True)
422
+ RGB24img[labels == labels[region.coords[0][0], region.coords[0][1]]] = new_col
423
+
424
+ return RGB24img
425
+
426
+
427
+ def get_lost_cells_between_first_and_second_set(first_set, second_set):
428
+ """
429
+ Returns the lost cells between the first and second set.
430
+
431
+ Args:
432
+ first_set (list or set): First set of cells.
433
+ second_set (list or set): Second set of cells.
434
+
435
+ Returns:
436
+ set: Set of lost cells.
437
+
438
+ Examples:
439
+ >>> get_lost_cells_between_first_and_second_set([1, 2, 3, 4, 5], [2, 4, 6, 8])
440
+ {1, 3, 5}
441
+
442
+ >>> get_lost_cells_between_first_and_second_set({1, 2, 3, 4, 5}, {2, 4, 6, 8})
443
+ {1, 3, 5}
444
+
445
+ """
446
+ set_t0 = first_set
447
+ if not isinstance(set_t0, set):
448
+ set_t0 = set(set_t0)
449
+ set_t1 = second_set
450
+ if not isinstance(set_t1, set):
451
+ set_t1 = set(set_t1)
452
+ return set_t0.difference(set_t1)
453
+
454
+
455
+ def get_common_cells(first_set, second_set):
456
+ """
457
+ Returns the common cells between the first and second set.
458
+
459
+ Args:
460
+ first_set (list or set): First set of cells.
461
+ second_set (list or set): Second set of cells.
462
+
463
+ Returns:
464
+ set: Set of common cells.
465
+
466
+ Examples:
467
+ >>> get_common_cells([1, 2, 3, 4, 5], [2, 4, 6, 8])
468
+ {2, 4}
469
+
470
+ >>> get_common_cells({1, 2, 3, 4, 5}, {2, 4, 6, 8})
471
+ {2, 4}
472
+
473
+ """
474
+ set_t0 = first_set
475
+ if not isinstance(set_t0, set):
476
+ set_t0 = set(set_t0)
477
+ set_t1 = second_set
478
+ if not isinstance(set_t1, set):
479
+ set_t1 = set(set_t1)
480
+ return set_t0.intersection(set_t1)
481
+
482
+
483
+ def get_cells_in_image(RGB24_img):
484
+ """
485
+ Returns the unique IDs of cells in the image.
486
+
487
+ Args:
488
+ RGB24_img (ndarray): RGB image.
489
+
490
+ Returns:
491
+ ndarray: Array of unique cell IDs.
492
+
493
+ """
494
+ unique_ids = np.unique(RGB24_img)
495
+ return unique_ids
496
+
497
+
498
+ def get_cells_in_image_n_fisrt_pixel(RGB24_img):
499
+ """
500
+ Returns the unique IDs of cells in the image and their corresponding first pixel indices.
501
+
502
+ Args:
503
+ RGB24_img (ndarray): RGB image.
504
+
505
+ Returns:
506
+ ndarray: Array of unique cell IDs.
507
+ ndarray: Array of indices of the first pixels of the cells.
508
+
509
+ """
510
+ u, indices = np.unique(RGB24_img, return_index=True)
511
+ return u, indices
512
+
513
+
514
+ def get_cells_in_image_n_count(RGB24_img):
515
+ """
516
+ Returns the unique IDs of cells in the image and their corresponding counts.
517
+
518
+ Args:
519
+ RGB24_img (ndarray): RGB image.
520
+
521
+ Returns:
522
+ ndarray: Array of unique cell IDs.
523
+ ndarray: Array of counts for each cell ID.
524
+
525
+ """
526
+ u, counts = np.unique(RGB24_img, return_counts=True)
527
+ return u, counts
528
+
529
+
530
+ def plot_triangles(img, coords, tri, inner_color, perimeter_color=None):
531
+ """
532
+ Plot the triangles of a cell on an image.
533
+
534
+ Args:
535
+ img (ndarray): Image to plot on.
536
+ coords (ndarray): Coordinates of the cell vertices.
537
+ tri (Delaunay): Delaunay triangulation of the cell.
538
+ inner_color (int): Inner color of the triangles.
539
+ perimeter_color (int, optional): Perimeter color of the triangles. Defaults to None.
540
+
541
+ """
542
+ for simplex in tri.simplices:
543
+ r = coords[simplex][:, 0] # get the y coords of the simplex
544
+ c = coords[simplex][:, 1] # get the x coords of the simplex
545
+ rr, cc = polygon(r, c)
546
+ img[rr, cc] = inner_color
547
+ if perimeter_color is not None:
548
+ rr, cc = polygon_perimeter(r, c)
549
+ img[rr, cc] = perimeter_color
550
+
551
+
552
+ def backup_file_with_date(source_file, verbose=False, append_time=True):
553
+ """
554
+ Bcakup a file and append the current date in 'yyyymmdd' format to it.
555
+
556
+ Args:
557
+ source_file (str): The path to the source file to be backed up.
558
+
559
+ Returns:
560
+ str: The path to the copied file with the date appended.
561
+ """
562
+ # Check if the source file exists
563
+ if os.path.exists(source_file):
564
+ # Get the current date in 'yyyymmdd' format
565
+
566
+ if append_time:
567
+ current_date = datetime.now().strftime('%Y%m%d_%H%M%S')
568
+ else:
569
+ current_date = datetime.now().strftime('%Y%m%d')
570
+
571
+ # Construct the new file name with the date appended
572
+ new_file_name = f"{source_file}.{current_date}"
573
+
574
+ if verbose:
575
+ print('creating a backup', source_file, new_file_name)
576
+
577
+ # Copy the source file to the destination with the new name
578
+ shutil.copy(source_file, new_file_name)
579
+
580
+ return new_file_name
581
+ else:
582
+ raise FileNotFoundError("Source file does not exist.")
583
+
584
+
585
+ def make_dirs_for_file_saving(save_name):
586
+ """
587
+ Create directories for file saving based on the given save_name.
588
+
589
+ Parameters:
590
+ - save_name: The name of the file to be saved.
591
+
592
+ Returns:
593
+ None
594
+ """
595
+
596
+ # Parse the parent folder name from the save_name using smart_name_parser
597
+ parent_folder = smart_name_parser(save_name, 'parent')
598
+
599
+ # Create the parent folder and any necessary intermediate directories
600
+ os.makedirs(parent_folder, exist_ok=True)
601
+
602
+ def open_file_with_default_handler(file_path):
603
+ """
604
+ Opens a file with the default system handler.
605
+
606
+ Args:
607
+ file_path (str): The path to the file to be opened.
608
+
609
+ Returns:
610
+ bool: True if the file was opened successfully, False otherwise.
611
+ """
612
+ if os.path.isfile(file_path):
613
+ try:
614
+ subprocess.run(['open', file_path], check=True)
615
+ return True
616
+ except subprocess.CalledProcessError as e:
617
+ print(f"Error: {e}")
618
+ return False
619
+ else:
620
+ print(f"The file '{file_path}' does not exist.")
621
+ return False
622
+
623
+ def open_file_with_default_app(file_path):
624
+ """
625
+ Opens a file using the default system application.
626
+
627
+ Parameters:
628
+ - file_path (str): The path to the file to be opened.
629
+ """
630
+
631
+ # Determine the platform
632
+ current_platform = platform.system()
633
+
634
+ # Open the file using the default system application
635
+ if current_platform == 'Windows':
636
+ os.startfile(file_path)
637
+ elif current_platform == 'Darwin': # macOS
638
+ os.system('open "{}"'.format(file_path))
639
+ elif current_platform == 'Linux':
640
+ os.system('xdg-open "{}"'.format(file_path))
641
+ else:
642
+ print("Unsupported operating system")
643
+
644
+
645
+ def create_temporary_file(extension=None, delete=True, return_file=True):
646
+ """
647
+ Create a temporary file with a specified file extension and automatic deletion on close.
648
+
649
+ Args:
650
+ extension (str): The desired file extension, including the dot (e.g., '.txt', '.csv').
651
+
652
+ Returns:
653
+ tempfile.NamedTemporaryFile: A NamedTemporaryFile object with the specified extension.
654
+
655
+ Example:
656
+ >>> with create_temporary_file() as temp_file:
657
+ ... temp_file.write(b"Hello, World!")
658
+ ... temp_file.seek(0)
659
+ ... data = temp_file.read()
660
+ ... print(data) # Output: b'Hello, World!'
661
+ 13
662
+ 0
663
+ b'Hello, World!'
664
+ """
665
+ if extension is not None and extension:
666
+ if not extension.startswith('.'):
667
+ extension = '.'+extension
668
+ temp_file = tempfile.NamedTemporaryFile(delete=delete, suffix=extension)
669
+ if return_file:
670
+ return temp_file
671
+ else:
672
+ return temp_file.name
673
+
674
+ # # maybe allow glob with exceptions
675
+ # def rm(file_path, exceptions=None):
676
+ # """
677
+ # Delete a file if it exists.
678
+ #
679
+ # Args:
680
+ # file_path (str): The path to the file you want to delete.
681
+ #
682
+ # Returns:
683
+ # str: A message indicating the result of the deletion.
684
+ #
685
+ # # Example:
686
+ # # >>> rm("example.txt")
687
+ # # >>> rm("nonexistent_file.txt")
688
+ # """
689
+ #
690
+ # if '*' in file_path:
691
+ # # run glob
692
+ #
693
+ #
694
+ # if os.path.exists(file_path):
695
+ # try:
696
+ # os.remove(file_path)
697
+ # except Exception as e:
698
+ # pass
699
+ def rm(file_path, exceptions=None):
700
+ """
701
+ Delete a file if it exists.
702
+
703
+ Args:
704
+ file_path (str): The path to the file you want to delete.
705
+ exceptions (list, optional): A list of file names to exclude from deletion. Default is None.
706
+
707
+ Returns:
708
+ str: A message indicating the result of the deletion.
709
+
710
+ # Example:
711
+ # >>> rm("example.txt")
712
+ # 'File 'example.txt' has been deleted.'
713
+ # >>> rm("nonexistent_file.txt")
714
+ # 'The file 'nonexistent_file.txt' does not exist.'
715
+ # >>> rm("*.txt", exceptions=["example.txt"])
716
+ # 'All matching files except ['example.txt'] have been deleted.'
717
+ """
718
+ if exceptions is not None:
719
+ if isinstance(exceptions,str):
720
+ exceptions = [exceptions]
721
+
722
+ if '*' in file_path:
723
+ # Use glob to create a list of files that match the pattern
724
+ files_to_delete = glob.glob(file_path)
725
+ if exceptions:
726
+ files_to_delete = [f for f in files_to_delete if os.path.basename(f) not in exceptions]
727
+ # if exceptions:
728
+ # files_to_delete = [f for f in files_to_delete if os.path.basename(f) not in exceptions]
729
+
730
+ if not files_to_delete:
731
+ # print('No files matching the pattern found or all were exceptions.')
732
+ return
733
+
734
+ deleted_files = []
735
+ for file_to_delete in files_to_delete:
736
+ try:
737
+ os.remove(file_to_delete)
738
+ deleted_files.append(file_to_delete)
739
+ except Exception as e:
740
+ pass
741
+
742
+ if deleted_files:
743
+ # return f'All matching files except {exceptions if exceptions else "none"} have been deleted.'
744
+ return
745
+ else:
746
+ # return f'No matching files were deleted due to exceptions or errors.'
747
+ return
748
+
749
+ elif os.path.exists(file_path):
750
+ try:
751
+ os.remove(file_path)
752
+ # return f"File '{file_path}' has been deleted."
753
+ return
754
+ except Exception as e:
755
+ pass
756
+ else:
757
+ # return f"The file '{file_path}' does not exist."
758
+ return
759
+
760
+
761
+ def is_file_more_recent(file1, file2):
762
+ """
763
+ Check if file1 was modified more recently than file2.
764
+
765
+ Parameters:
766
+ - file1: Path to the first file
767
+ - file2: Path to the second file
768
+
769
+ Returns:
770
+ - True if file1 is more recent than file2, False otherwise
771
+ """
772
+ try:
773
+ # Get the modification time of each file
774
+ time1 = os.path.getmtime(file1)
775
+ time2 = os.path.getmtime(file2)
776
+
777
+ # Compare the modification times
778
+ return time1 > time2
779
+ except FileNotFoundError:
780
+ print("One or both of the files do not exist.")
781
+ return False
782
+
783
+
784
+ def get_md5_hash(filename):
785
+ if not os.path.isfile(filename):
786
+ return None
787
+ hash_md5 = hashlib.md5()
788
+ with open(filename, 'rb') as f:
789
+ for chunk in iter(lambda: f.read(4096), b''):
790
+ hash_md5.update(chunk)
791
+ return hash_md5.hexdigest()
792
+
793
+ def get_sha256(filename):
794
+ return get_md5_hash(filename)
795
+
796
+ def get_file_size(path, return_size_in_mb=True):
797
+ size = os.path.getsize(path)
798
+ if return_size_in_mb:
799
+ size/= (1024*1024)
800
+ return size
801
+
802
+ def find_files_by_extension(folder_path, extension):
803
+ file_paths = []
804
+ for root, dirs, files in os.walk(folder_path):
805
+ for file in files:
806
+ if file.endswith(extension):
807
+ file_paths.append(os.path.join(root, file))
808
+ return file_paths
809
+
810
+
811
+ def merge_files(input_lst, extra_TA_name, output_file):
812
+
813
+ with open(output_file, 'w') as outfile:
814
+ for filename in input_lst:
815
+ if extra_TA_name is not None:
816
+ filename = smart_name_parser(filename,extra_TA_name)
817
+ # if filename.endswith(".txt"): # only process text files
818
+ # basename = os.path.splitext(filename)[0] # get the basename without extension
819
+ sep = None
820
+ with open(filename, 'r') as infile:
821
+ for line in infile:
822
+ if sep is None:
823
+ if ',' in line:
824
+ sep = ','
825
+ else:
826
+ sep='\t'
827
+ new_line = ''
828
+ if not '\n' in line:
829
+ new_line='\n'
830
+ outfile.write(f'{filename}{sep}{line}{new_line}')
831
+
832
+ def write_string_to_file(file_path, string):
833
+ make_dirs_for_file_saving(file_path)
834
+ # Open the file for writing
835
+ with open(file_path, 'w') as f:
836
+ # Write the string to the file
837
+ f.write(string)
838
+
839
+ def read_string_from_file(file_path):
840
+ # Open the file for reading
841
+ with open(file_path, 'r') as f:
842
+ # Read the string from the file
843
+ string = f.read()
844
+ return string
845
+
846
+
847
+
848
+ def get_consolidated_filename_from_parent(filename, parent_file):
849
+ # check if this is a consolidated file and if so try to find the consolidation name
850
+ if not filename:
851
+ return filename
852
+ if '.files' in filename:
853
+ # try to get it from the other file
854
+ # cut last files and add the parent stuff
855
+
856
+ if not is_string_a_list_string(filename):
857
+ # Split the file path at the last occurrence of '.files'
858
+ file_end = filename.rsplit('.files', 1)[-1]
859
+ corrected_filename = smart_name_parser(parent_file, 'full_no_ext')+'.files'+file_end
860
+ filename = corrected_filename
861
+ # print(corrected_filename)
862
+ else:
863
+ files = reload_string_list(filename)
864
+
865
+ corrected_files = []
866
+ for file in files:
867
+ file_end = file.rsplit('.files', 1)[-1]
868
+ corrected_filename = smart_name_parser(parent_file, 'full_no_ext') + '.files' + file_end
869
+ corrected_files.append(corrected_filename)
870
+
871
+ filename = str(corrected_files)
872
+
873
+ return filename
874
+
875
+
876
+
877
+
878
+ def _consolidate_single_file(file_path, save_folder, mock):
879
+ new_paths=[]
880
+ # Get the base name of the file
881
+ base_name = os.path.basename(file_path)
882
+
883
+ # here there can be an error for multi files --> just try to save them once and that's it
884
+
885
+ # Create a unique folder for each file
886
+ unique_id = str(uuid.uuid4())
887
+ unique_folder = os.path.join(save_folder, f"{unique_id}")
888
+ if not mock:
889
+ os.makedirs(unique_folder, exist_ok=True)
890
+
891
+ # Define the new path for the file
892
+ new_path = os.path.join(unique_folder, base_name)
893
+
894
+ # Copy the file to the new path
895
+ try:
896
+ if not mock:
897
+ shutil.copy2(file_path, new_path)
898
+ new_paths.append(new_path)
899
+ except:
900
+ print(f'file {file_path} does not exist -−> copy not possible')
901
+ new_paths.append(file_path) # keep the original path then (useful for reapplying the name to the files)
902
+
903
+ return new_paths
904
+
905
+
906
+
907
+ # this is a real file consolidation
908
+ def consolidate_files2(save_folder, files_to_consolidate, consolidated_files):
909
+ folders_to_delete = []
910
+ if os.path.exists(save_folder):
911
+ for folder in os.listdir(save_folder):
912
+ if os.path.isdir(os.path.join(save_folder, folder)):
913
+ folders_to_delete.append(folder)
914
+
915
+ # print('folders_to_delete before', folders_to_delete)
916
+
917
+ os.makedirs(save_folder, exist_ok=True)
918
+
919
+ for file_path, new_path in zip(files_to_consolidate, consolidated_files):
920
+ print(file_path, '->', new_path)
921
+
922
+ try:
923
+ folder_save = smart_name_parser(new_path, 'parent')
924
+ os.makedirs(folder_save, exist_ok=True)
925
+ # print('success',success)
926
+ # print(folder_save)
927
+ shutil.copy2(file_path, new_path)
928
+
929
+ # print(os.path.exists(new_path)) # this is supposed to exist but I
930
+ # print(new_path)
931
+ except IOError as e:
932
+ print("Unable to copy file. IOError({0}): {1}".format(e.errno, e.strerror))
933
+ print(f'file {file_path} does not exist -−> copy not possible')
934
+ except:
935
+ print("Unexpected error:", sys.exc_info()[0])
936
+ print(f'file {file_path} does not exist -−> copy not possible')
937
+
938
+ # print('folders_to_delete',folders_to_delete)
939
+
940
+ # somehow I delete all I build
941
+
942
+ if folders_to_delete:
943
+ # print('folders_to_delete inside', folders_to_delete)
944
+ for folder in folders_to_delete:
945
+ # print('deleting',os.path.join(save_folder, folder))
946
+ shutil.rmtree(os.path.join(save_folder, folder))
947
+
948
+
949
+ def consolidate_files(file_paths, save_folder, empty_folder=True, mock =True):
950
+ if mock:
951
+ empty_folder = False
952
+ # If empty_folder is True, collect the names of the folders to be deleted
953
+ folders_to_delete = []
954
+ if empty_folder and os.path.exists(save_folder):
955
+ for folder in os.listdir(save_folder):
956
+ if os.path.isdir(os.path.join(save_folder, folder)):
957
+ folders_to_delete.append(folder)
958
+ if not mock:
959
+ # Create the save folder if it doesn't exist
960
+ os.makedirs(save_folder, exist_ok=True)
961
+
962
+ new_paths = []
963
+ for file_path in file_paths:
964
+ # # Get the base name of the file
965
+ # base_name = os.path.basename(file_path)
966
+ #
967
+ # # here there can be an error for multi files --> just try to save them once and that's it
968
+ #
969
+ #
970
+ # # Create a unique folder for each file
971
+ # unique_id = str(uuid.uuid4())
972
+ # unique_folder = os.path.join(save_folder, f"{unique_id}")
973
+ # os.makedirs(unique_folder, exist_ok=True)
974
+ #
975
+ # # Define the new path for the file
976
+ # new_path = os.path.join(unique_folder, base_name)
977
+ #
978
+ # # Copy the file to the new path
979
+ # try:
980
+ # if not mock:
981
+ # shutil.copy2(file_path, new_path)
982
+ # new_paths.append(new_path)
983
+ # except:
984
+ # print(f'file {file_path} does not exist -−> copy not possible')
985
+ # new_paths.append(file_path) # keep the original path then (useful for reapplying the name to the files)
986
+
987
+ if not is_string_a_list_string(file_path):
988
+ consolidated_files = _consolidate_single_file(file_path, save_folder, mock)
989
+ new_paths.extend(consolidated_files)
990
+ else:
991
+ consolidated_files = []
992
+ lst_of_files = reload_string_list(file_path)
993
+ for f in lst_of_files:
994
+ consolidated_files.extend(_consolidate_single_file(f, save_folder, mock))
995
+ new_paths.append(str(consolidated_files))
996
+
997
+ # If empty_folder is True, delete the folders to be deleted
998
+ if empty_folder:
999
+ for folder in folders_to_delete:
1000
+ shutil.rmtree(os.path.join(save_folder, folder))
1001
+
1002
+ return file_paths, new_paths
1003
+
1004
+ def consolidate_files_from_paired_lists(file_paths, dest_list,save_folder, empty_folder=True):
1005
+ # If empty_folder is True, collect the names of the folders to be deleted
1006
+ folders_to_delete = []
1007
+ if empty_folder and os.path.exists(save_folder):
1008
+ for folder in os.listdir(save_folder):
1009
+ if os.path.isdir(os.path.join(save_folder, folder)):
1010
+ folders_to_delete.append(folder)
1011
+ # Create the save folder if it doesn't exist
1012
+ os.makedirs(save_folder, exist_ok=True)
1013
+
1014
+ new_paths=[]
1015
+ for iii, file_path in enumerate(file_paths):
1016
+ # Get the base name of the file
1017
+ # base_name = os.path.basename(file_path)
1018
+
1019
+ # Create a unique folder for each file
1020
+ unique_folder= smart_name_parser(file_path, 'parent')
1021
+ os.makedirs(unique_folder, exist_ok=True)
1022
+
1023
+ # Define the new path for the file
1024
+ new_path = dest_list[iii]
1025
+
1026
+ # Copy the file to the new path
1027
+ try:
1028
+ shutil.copy2(file_path, new_path)
1029
+ new_paths.append(new_path)
1030
+ except:
1031
+ print(f'file {file_path} does not exist -−> copy not possible')
1032
+ new_paths.append(file_path) # keep the original path then (useful for reapplying the name to the files)
1033
+
1034
+ # If empty_folder is True, delete the folders to be deleted
1035
+ if empty_folder:
1036
+ for folder in folders_to_delete:
1037
+ shutil.rmtree(os.path.join(save_folder, folder))
1038
+
1039
+ return file_paths, new_paths
1040
+
1041
+ def smartly_consolidate_files_to_reduce_dupes(full_list_of_filenames_to_consolidate, dest_folder):
1042
+ full_list_of_filenames_to_consolidate, consolidated_files = consolidate_files(full_list_of_filenames_to_consolidate, dest_folder)
1043
+ # now reduce the pairs so that we do not duplicate the same files and therfore minimize resources this si very importnat for crops and the same logic can be applied to minimize resources and loading
1044
+
1045
+ print('dabu',len(full_list_of_filenames_to_consolidate)==len(consolidated_files)) # ok here too
1046
+
1047
+
1048
+
1049
+ # flatten the lists if not flat to make things better
1050
+
1051
+ # if there are multiple files I need to flatten them --> TODO
1052
+
1053
+ full_list_of_filenames_to_consolidate = [elm if not is_string_a_list_string(elm) else reload_string_list(elm) for elm in full_list_of_filenames_to_consolidate]
1054
+ consolidated_files = [elm if not is_string_a_list_string(elm) else reload_string_list(elm) for elm in consolidated_files]
1055
+
1056
+ full_list_of_filenames_to_consolidate = flatten_list(full_list_of_filenames_to_consolidate)
1057
+ consolidated_files = flatten_list(consolidated_files)
1058
+
1059
+ print('dabu flattened',len(full_list_of_filenames_to_consolidate)==len(consolidated_files), len(full_list_of_filenames_to_consolidate),len(consolidated_files)) # ok here too
1060
+ print('full_list_of_filenames_to_consolidate',full_list_of_filenames_to_consolidate)
1061
+ print('consolidated_files',consolidated_files)
1062
+
1063
+ # TODO --> handle here the multi files too !!! -−> this will not be so easy because I need to loop over other loops -−> not so easy --> think of it
1064
+ final_version_of_consolidated_files = []
1065
+ # for elm in full_list_of_images:
1066
+ # idx = find_first_index(elm.filename,full_list_of_filenames_to_consolidate)
1067
+ #
1068
+ # if idx is not None and idx >=0:
1069
+ # final_version_of_consolidated_files.append(consolidated_files[idx])
1070
+ # else:
1071
+ # print(idx, elm.filename,'not found')
1072
+ for elm in full_list_of_filenames_to_consolidate:
1073
+ idx = find_first_index(elm,full_list_of_filenames_to_consolidate)
1074
+
1075
+ if idx is not None and idx >=0:
1076
+ final_version_of_consolidated_files.append(consolidated_files[idx])
1077
+ else:
1078
+ print(idx, elm.filename,'not found')
1079
+ return full_list_of_filenames_to_consolidate,final_version_of_consolidated_files
1080
+
1081
+ if __name__ == '__main__':
1082
+ import sys
1083
+
1084
+ if True:
1085
+ # Usage
1086
+ file_paths = ["/home/aigouy/Bureau/test.pdf", "/home/aigouy/Bureau/test_export.pdf",
1087
+ "/home/aigouy/Bureau/test.svg",
1088
+ '/home/aigouy/Bureau/test_consolidation.files/34a95ae3-ca74-47ff-b95b-3875593231ce/test.pdf']
1089
+ save_folder = "/home/aigouy/Bureau/test_consolidation.files"
1090
+ file_paths, new_paths = consolidate_files(file_paths, save_folder)
1091
+
1092
+ print(len(file_paths))
1093
+ print(len(new_paths))
1094
+ print(new_paths)
1095
+
1096
+ for f1, f2 in zip(file_paths, new_paths):
1097
+ print(f'{f1}-->{f2}')
1098
+
1099
+ sys.exit(0)
1100
+
1101
+ if True:
1102
+ files = '/media/teamPrudhomme/EqpPrudhomme2/Bernard/Apotome/Pour quantif Benoit/*.tif'
1103
+ list_of_files = loadlist(files, recursive=1)
1104
+ print(list_of_files)
1105
+ file = 'spots_count.txt'
1106
+ merge_files(list_of_files, file, os.path.join(smart_name_parser(files, 'parent'),file))
1107
+ file = 'spots.csv'
1108
+ merge_files(list_of_files, file, os.path.join(smart_name_parser(files, 'parent'),file))
1109
+
1110
+ sys.exit(0)
1111
+
1112
+ if True:
1113
+ # Example usage:
1114
+ file_path1 = "/F/genomic_resources/db_100_genomes/drosophila_only_with_gunu_human_readbale_names/100genomes_with_annots/0_suz_genome_us/D_suzukii.fasta.ndb"
1115
+ file_path2 = "/F/genomic_resources/db_100_genomes/drosophila_only_with_gunu_human_readbale_names/100genomes_with_annots/0_suz_genome_us/D_suzukii.fasta"
1116
+ file_path2 = "/F/genomic_resources/db_100_genomes/drosophila_only_with_gunu_human_readbale_names/100genomes_with_annots/0_suz_genome_us/D_suzukii.fasta.nin"
1117
+
1118
+ # file_path1, file_path2 = file_path2, file_path1
1119
+
1120
+ if is_file_more_recent(file_path1, file_path2):
1121
+ print(f"{file_path1} is more recent than {file_path2}")
1122
+ else:
1123
+ print(f"{file_path1} is not more recent than {file_path2}")
1124
+ sys.exit(0)
1125
+
1126
+ if True:
1127
+ tst_name = '/F/hiC_microC/haplotype_resolved_embryo/GSE121255_RAW/GSM3428927_2_4hrs-R2.dedup.pairs.txt.gz'
1128
+
1129
+ print(smart_name_parser(tst_name, 'short_pop_all_exts'))
1130
+
1131
+ tst_name = '/F/hiC_microC/haplotype_resolved_embryo/GSE121255_RAW/GSM3428927_2_4hrs-R2'
1132
+ print(smart_name_parser(tst_name, 'short_pop_all_exts'))
1133
+
1134
+ tst_name = '/F/hiC_microC/haplotype_resolved_embryo/GSE121255_RAW/GSM3428927_2_4hrs-R2.txt'
1135
+ print(smart_name_parser(tst_name, 'short_pop_all_exts'))
1136
+
1137
+ import sys
1138
+
1139
+ sys.exit(0)
1140
+
1141
+ if True:
1142
+ print(smart_name_parser('Série 10kb X1 Spot196 mut2 TgX malex.tif.tif', 'tutu'))
1143
+
1144
+ import sys
1145
+
1146
+ sys.exit(0)
1147
+
1148
+ if True:
1149
+ # these are the tests for the smart_name_parser
1150
+
1151
+ print(smart_name_parser('/this/is/a/test/of/your/system.tif', 'parent', appenders=['toto', 'tutu',
1152
+ 'tata.tif']))
1153
+ print(smart_name_parser('/this/is/a/test/of/your/system.tif', 'parent',
1154
+ appenders='tata.tif'))
1155
+ print(smart_name_parser('/this/is/a/test/of/your/system.tif', 'full_no_ext',
1156
+ appenders='tata.tif'))
1157
+ print(smart_name_parser('/this/is/a/test/of/your/system.tif', ['TA', 'parent'],
1158
+ appenders='tata.tif'))
1159
+
1160
+ print('smart_name_parser', smart_name_parser(
1161
+ '/E/Sample_images/sample_images_PA/mini/focused_Series012.png')) # ['/E/Sample_images/sample_images_PA/mini', '', 'focused_Series012', '/E/Sample_images/sample_images_PA/mini/focused_Series012', 'focused_Series012', '/E/Sample_images/sample_images_PA/mini/focused_Series012']
1162
+ print('smart_name_parser', smart_name_parser(
1163
+ '/E/Sample_images/sample_images_PA/mini/focused_Series012')) # ['/E/Sample_images/sample_images_PA/mini', '', 'focused_Series012', '/E/Sample_images/sample_images_PA/mini/focused_Series012', 'focused_Series012', '/E/Sample_images/sample_images_PA/mini/focused_Series012']
1164
+ print('smart_name_parser', smart_name_parser(
1165
+ 'focused_Series012.png')) # smart_name_parser ['', '.png', 'focused_Series012.png', 'focused_Series012', 'focused_Series012', 'focused_Series012.png']
1166
+ print('smart_name_parser',
1167
+ smart_name_parser('D:\\Sample_images\\sample_images_PA\\trash_test_mem\\mini\\focused_Series012.png'))
1168
+ print('smart_name_parser', smart_name_parser(
1169
+ 'D:\\Sample_images\\\\sample_images_PA/trash_test_mem\\mini\\focused_Series012.png')) # hybrid widows linux names
1170
+ print('smart_name_parser',
1171
+ smart_name_parser('D:\\Sample_images\\\\sample_images_PA/trash_test_mem\\mini\\focused_Series012'))
1172
+ print('smart_name_parser', smart_name_parser(''))
1173
+ print('smart_name_parser', smart_name_parser('', replace_empty_by_none=True))
1174
+ print('smart_name_parser', smart_name_parser(None))
1175
+ print('smart_name_parser',
1176
+ smart_name_parser('/E/Sample_images/sample_images_PA/mini/focused_Series012.png',
1177
+ ordered_output=[
1178
+ 'tracked_cells_resized.png'])) # retruns a TA name --> it is really cool!!!
1179
+ tracked_cells_resized, TA_path = smart_name_parser(
1180
+ '/E/Sample_images/sample_images_PA/mini/focused_Series012.png',
1181
+ ordered_output=['full_no_ext', 'tracked_cells_resized.png'])
1182
+ print('TADA', tracked_cells_resized, TA_path)
1183
+ tracked_cells_resized, TA_path = smart_name_parser(
1184
+ '/E/Sample_images/sample_images_PA/mini/focused_Series012.png',
1185
+ ordered_output=['TA', 'tracked_cells_resized.png'])
1186
+ print('TADA2', tracked_cells_resized, TA_path)
1187
+ import sys
1188
+
1189
+ sys.exit(0)
1190
+
1191
+ if True:
1192
+ # test of getting n consecutive images
1193
+ # also see how to handle None --> TODO
1194
+ img_list = loadlist('/E/Sample_images/sample_images_PA/mini/list.lst')
1195
+ print(img_list)
1196
+
1197
+ desired_images = get_n_input_files_and_output_folders(img_list, 1, -1, 1) # get one image before and after
1198
+
1199
+ print(desired_images)
1200
+ import sys
1201
+
1202
+ sys.exit(0)
1203
+
1204
+ # if True:
1205
+ # random_vx_images = (np.random.randint(2, size=(1024, 1024)) * 255).astype('uint8')
1206
+ # cell_labels = (np.random.randint(255, size=(1024, 1024))).astype('uint8')
1207
+ # vertices = np.where(random_vx_images == 255) # c'est
1208
+ # count_same = 0
1209
+ # count_different = 0
1210
+ #
1211
+ # start_all = timer()
1212
+ # for i in range(len(vertices[0])):
1213
+ # y = vertices[0][i]
1214
+ # x = vertices[1][i]
1215
+ # # ids = neighbors8((y, x), cell_labels).tolist() # celui ci est faux
1216
+ # ids2 = neighbors8_2((y, x), cell_labels)
1217
+ #
1218
+ # # if ids!=ids2:
1219
+ # # print(ids, ids2, ids==ids2)
1220
+ #
1221
+ # print('time', timer() - start_all)
1222
+ # # start_all = timer()
1223
+ # # for i in range(len(vertices[0])):
1224
+ # # y = vertices[0][i]
1225
+ # # x = vertices[1][i]
1226
+ # # ids = neighbors8((y, x), cell_labels).tolist() # celui ci est faux # --> keep my old way but fix its errors
1227
+ # # ids2 = neighbors8_2((y, x), cell_labels)
1228
+ # #
1229
+ # # if ids != ids2:
1230
+ # # print(ids, ids2, ids == ids2, y, x)
1231
+ # # count_different+=1
1232
+ # # else:
1233
+ # # count_same+=1
1234
+ # #
1235
+ # # print(count_same, count_different)
1236
+ # # print('time', timer() - start_all)
1237
+ #
1238
+ # # this one is much faster but why ???
1239
+ # start_all = timer()
1240
+ # for i in range(len(vertices[0])):
1241
+ # y = vertices[0][i]
1242
+ # x = vertices[1][i]
1243
+ # ids = neighbors8((y, x), cell_labels).tolist() # celui ci est faux # --> keep my old way but fix its errors
1244
+ # # ids2 = neighbors8_2((y, x), cell_labels)
1245
+ #
1246
+ # # if ids!=ids2:
1247
+ # # print(ids, ids2, ids==ids2)
1248
+ #
1249
+ # print('time', timer() - start_all)
1250
+
1251
+ cells_at_t0 = [0, 1, 2, 3, 4, 5, 6, 7, 128]
1252
+ cells_at_t1 = [1, 3, 4, 5, 128, 33, 24, 52]
1253
+
1254
+ print(get_lost_cells_between_first_and_second_set(cells_at_t0, cells_at_t1))
1255
+ print(get_lost_cells_between_first_and_second_set(cells_at_t1, cells_at_t0))
1256
+
1257
+ img = Img(
1258
+ '/E/Sample_images/segmentation_assistant/ovipo_uncropped/200709_armGFP_suz_46hAPF_ON.lif - Series011/tracked_cells_resized.tif')
1259
+ img = RGB_to_int24(img)
1260
+ start_all = timer()
1261
+ print(len(get_cells_in_image(img))) # ça marche et c'est super rapide en fait --> really good and fast
1262
+ print('time', timer() - start_all)
1263
+ # can get the first pixel of each using indices
1264
+
1265
+ start_all = timer()
1266
+ cells, first_px = get_cells_in_image_n_fisrt_pixel(
1267
+ img) # ça marche et c'est super rapide en fait --> really good and fast
1268
+ print(cells)
1269
+ print(first_px) # this is the ravel index
1270
+ print('time', timer() - start_all)
1271
+
1272
+ # --> 0.20 secs
1273
+ start_all = timer()
1274
+ cells, area = get_cells_in_image_n_count(img)
1275
+ print(cells)
1276
+ print(area)
1277
+ print('time', timer() - start_all)
1278
+
1279
+ # full self replacement of one image using == --> 14 secs
1280
+ start_all = timer()
1281
+ for cell in cells:
1282
+ img[img == cell] = cell
1283
+ print('time', timer() - start_all)
1284
+
1285
+ # start_all = timer()
1286
+ # for cell in cells:
1287
+ #
1288
+ # img[img == cell] = cell
1289
+ # print('time', timer() - start_all)
1290
+
1291
+ # encore plus lent et null --> 45 secs
1292
+ # start_all = timer()
1293
+ # for cell in cells:
1294
+ # np.where(img == cell, cell, img)
1295
+ # # img[img == cell] = cell
1296
+ # print('time', timer() - start_all)
1297
+
1298
+ # super slow --> do not use np.where in fact cause super slow
1299
+ start_all = timer()
1300
+ for cell in cells:
1301
+ cond = np.where(img == cell)
1302
+ img[cond] = cell
1303
+ print('time', timer() - start_all)
1304
+
1305
+ # print('neighbs length', len(ids))
1306
+
1307
+ # print(vertices)
1308
+ # if vertices[0].size != 0:
1309
+ # print('y', vertices[0][0])
1310
+ # if vertices[1].size != 0:
1311
+ # print('x', vertices[1][0])
1312
+ # if vertices[0].size + vertices[1].size != 0:
1313
+ # print('first vx', result[vertices[0][0], vertices[1][0]])
1314
+
1315
+ import importlib
1316
+ print(importlib.import_module("batoolset.files.tools")) #<module 'batoolset.files.tools' from '/home/aigouy/mon_prog/Python/epyseg_pkg/epyseg/files/tools.py'>
1317
+
1318
+ # rm('/E/Sample_images/cells_escaping_silencing_test_count/14,5kb T2A DsRed X2 B4 Tg/14,5kb T2A DsRed X2 B4 Tg 0001/wing_mask.tif')
1319
+ rm('/E/Sample_images/cells_escaping_silencing_test_count/14,5kb T2A DsRed X2 B4 Tg/14,5kb T2A DsRed X2 B4 Tg 0001/*.tif', exceptions=['veins_deep.tif','wing_cells.tif'])
1320
+ rm('/E/Sample_images/cells_escaping_silencing_test_count/14,5kb T2A DsRed X2 B4 Tg/14,5kb T2A DsRed X2 B4 Tg 0001/*.db', exceptions='spots.db')
1321
+