batoolset-gui 0.2.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 (74) hide show
  1. batoolset/GUI/__init__.py +0 -0
  2. batoolset/GUI/customdialog.py +136 -0
  3. batoolset/GUI/exception_handler.py +74 -0
  4. batoolset/GUI/list_gui.py +514 -0
  5. batoolset/GUI/multi_image_display.py +1038 -0
  6. batoolset/GUI/open.py +325 -0
  7. batoolset/GUI/overlay_hints.py +45 -0
  8. batoolset/GUI/paint2.py +1369 -0
  9. batoolset/GUI/scrollablepaint.py +1165 -0
  10. batoolset/dialogs/__init__.py +0 -0
  11. batoolset/dialogs/opensave.py +228 -0
  12. batoolset/drawings/__init__.py +0 -0
  13. batoolset/drawings/math_text.py +294 -0
  14. batoolset/drawings/pdf_svg_renderer.py +376 -0
  15. batoolset/drawings/shapes/Position.py +183 -0
  16. batoolset/drawings/shapes/__init__.py +0 -0
  17. batoolset/drawings/shapes/automated_alignment_drawing_refactored.py +346 -0
  18. batoolset/drawings/shapes/circle2d.py +99 -0
  19. batoolset/drawings/shapes/compute_optimal_size_all_merged.py +328 -0
  20. batoolset/drawings/shapes/ellipse2d.py +336 -0
  21. batoolset/drawings/shapes/freehand2d.py +235 -0
  22. batoolset/drawings/shapes/group.py +1985 -0
  23. batoolset/drawings/shapes/image2d.py +3157 -0
  24. batoolset/drawings/shapes/line2d.py +579 -0
  25. batoolset/drawings/shapes/point2d.py +257 -0
  26. batoolset/drawings/shapes/polygon2d.py +357 -0
  27. batoolset/drawings/shapes/polyline2d.py +235 -0
  28. batoolset/drawings/shapes/rect2d.py +388 -0
  29. batoolset/drawings/shapes/rectangle2d.py +601 -0
  30. batoolset/drawings/shapes/scalebar.py +310 -0
  31. batoolset/drawings/shapes/serializablefont.py +133 -0
  32. batoolset/drawings/shapes/serializableguiparams.py +14 -0
  33. batoolset/drawings/shapes/square2d.py +102 -0
  34. batoolset/drawings/shapes/test_publication_style.py +220 -0
  35. batoolset/drawings/shapes/textorientation.py +45 -0
  36. batoolset/drawings/shapes/tools.py +467 -0
  37. batoolset/drawings/shapes/transform2D.py +350 -0
  38. batoolset/drawings/shapes/txt2d.py +615 -0
  39. batoolset/drawings/svg_clip_renderer.py +247 -0
  40. batoolset/drawings/svg_embed.py +165 -0
  41. batoolset/drawings/svg_text_renderer.py +183 -0
  42. batoolset/drawings/widgets/__init__.py +0 -0
  43. batoolset/drawings/widgets/col.py +343 -0
  44. batoolset/drawings/widgets/image_group.py +248 -0
  45. batoolset/drawings/widgets/image_organizer.py +96 -0
  46. batoolset/drawings/widgets/paint.py +184 -0
  47. batoolset/drawings/widgets/vectorial.py +256 -0
  48. batoolset/figure/__init__.py +0 -0
  49. batoolset/figure/alignment.py +822 -0
  50. batoolset/figure/column.py +1117 -0
  51. batoolset/figure/fig_tools.py +285 -0
  52. batoolset/figure/minimal_debugger_scale_etc.py +139 -0
  53. batoolset/figure/panel.py +697 -0
  54. batoolset/figure/row.py +852 -0
  55. batoolset/figure/user_selection.py +287 -0
  56. batoolset/icons/__init__.py +0 -0
  57. batoolset/icons/tools.py +248 -0
  58. batoolset/luts/__init__.py +0 -0
  59. batoolset/luts/lut_minimal_test.py +1308 -0
  60. batoolset/luts/lutcreatorfromformula.py +209 -0
  61. batoolset/luts/luteditor.py +243 -0
  62. batoolset/pyqts/__init__.py +0 -0
  63. batoolset/pyqts/pleasewaitdialog.py +14 -0
  64. batoolset/pyqts/tools.py +760 -0
  65. batoolset/serializations/__init__.py +0 -0
  66. batoolset/serializations/tools.py +1338 -0
  67. batoolset/theme.py +647 -0
  68. batoolset/uis/__init__.py +0 -0
  69. batoolset/uis/blinker.py +56 -0
  70. batoolset_gui-0.2.0.dist-info/METADATA +54 -0
  71. batoolset_gui-0.2.0.dist-info/RECORD +74 -0
  72. batoolset_gui-0.2.0.dist-info/WHEEL +5 -0
  73. batoolset_gui-0.2.0.dist-info/licenses/LICENSE +24 -0
  74. batoolset_gui-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1038 @@
1
+ # TODO need handle tracking and need break buttons to stop the loop
2
+ from batoolset.settings.global_settings import set_UI # set the UI to qtpy
3
+ set_UI()# none of the label drawings is great --> ignore t for now or maybe add it to the vectorial draw pane but do not allow edit and save of this and move it with the image!!!
4
+ import traceback
5
+ from functools import partial
6
+ import numpy as np
7
+ from qtpy import QtWidgets, QtGui, QtCore
8
+ from qtpy.QtCore import QRect, Qt, QSize,QTimer
9
+ from qtpy.QtGui import QPalette
10
+ from qtpy.QtWidgets import QApplication, QGridLayout, QScrollArea, QLabel, QVBoxLayout, QDialog, QStyle, \
11
+ QStyleOptionTitleBar, QMessageBox, QDialogButtonBox
12
+ # from deprecated_demos.ta.wshed import Wshed
13
+ from batoolset.ta.segmentation.neo_wshed import wshed
14
+ # from batoolset.drawings.widgets.paint import Createpaintwidget
15
+ from batoolset.img import Img, RGB_to_int24
16
+ from batoolset.drawings.shapes.rect2d import Rect2D
17
+
18
+ # TODO add shortcuts to zoom and so on so that I can handle it better
19
+ # TODO maybe store the raw image in it
20
+
21
+ # in fact that is maybe already what I want!!!
22
+ # but I may also want to draw on it with a pen --> should have everything
23
+
24
+ # draw_mode= None #'pen' #'rect'
25
+
26
+ # fit to window or not
27
+ # maybe whatever happens the scroll should fit to window size
28
+
29
+ # NB in TA that works exactly as I want it !!!
30
+
31
+
32
+ # ok I finally have it
33
+ # implement all the zooms, crops, etc...
34
+ # --> TODO
35
+
36
+
37
+ # TODO --> maybe add a title
38
+ # TODO maybe offer to set a title in setimage --> can be a good idea
39
+ # faire un get image also
40
+ # faire un get mask
41
+ # ...
42
+ # faire un get shapes --> pas mal
43
+ # peut etre aussi permettre le right click pr supprimer des images
44
+
45
+
46
+ # TODO allow scroll all or zoom all at the same time or not!!!
47
+ # TODO allow support for shortcuts
48
+ # if sync shortcuts are for all, if not they are for the in focus stuff --> TODO
49
+
50
+ # vraiment tres bon mais à finaliser!!!
51
+
52
+ # TODO add labels --> would be really cool in a way
53
+ # maybe also add labels on the image ???
54
+
55
+ # TODO allow add labels on the sides --> like a table --> can be really useful!!!
56
+ from batoolset.GUI.paint2 import Createpaintwidget
57
+ from batoolset.ta.tracking.local_to_track_correspondance import add_localID_to_trackID_correspondance_in_DB
58
+ from batoolset.files.tools import smart_name_parser
59
+ from batoolset.ta.tracking.track_correction import swap_tracks, connect_tracks
60
+ from batoolset.tools.logger import TA_logger # logging
61
+
62
+ logger = TA_logger()
63
+
64
+ class ImgDisplayWindow(QDialog):
65
+
66
+ # replace preview only by a drawing mode --> TODO
67
+ # TODO try several displays at once then sync all
68
+ def __init__(self, parent_window=None, draw_mode=None, default_width=512, default_height=512, nb_rows=1, nb_cols=1,
69
+ synced=True , lst=None, cur_frame_idx=None, auto_contrast_for_all=False):
70
+ super().__init__(parent=parent_window)
71
+ self.auto_contrast_for_all = auto_contrast_for_all
72
+ self.default_width = default_width
73
+ self.default_height = default_height
74
+ self.nb_rows = nb_rows
75
+ self.nb_cols = nb_cols
76
+ self.draw_mode = draw_mode
77
+ self.synced = synced
78
+ self.initUI()
79
+ self.lst = lst
80
+ self.cur_frame_idx = cur_frame_idx
81
+
82
+
83
+
84
+ # self.last_propagated_mouse_event = None
85
+
86
+ # override the QDialoog keyPressEvent to prevent it from stealing the return key from the drawing panels
87
+ def keyPressEvent(self, event):
88
+
89
+ # print('key intercepted ') # can I pass it to the paint in focus ??? next ????
90
+
91
+ if event.key() in (Qt.Key_Return, Qt.Key_Enter):
92
+ self.apply()
93
+ return
94
+
95
+
96
+ #
97
+ # else:
98
+ #
99
+ # print('in there')
100
+ # idx = self.get_idx_of_widget_under_mouse()
101
+ # # dirty hack to transfer shortcut to child
102
+ # if idx != -1:
103
+ # print('passing')
104
+ # # print('applying in', idx)
105
+ # if idx in [0,1,2]:
106
+ # print('forwarding')
107
+ # self.paints[idx].keyPressEvent(event)
108
+ super().keyPressEvent(event)
109
+
110
+ def initUI(self):
111
+ self.is_width_for_alternating = True
112
+ self.scale = 1.0
113
+ self.scroll_areas = []
114
+ self.paints = []
115
+ self.labels = []
116
+ # TODO should I also store the labels ???
117
+
118
+ layout = QGridLayout()
119
+ layout.setSpacing(0)
120
+ layout.setContentsMargins(0, 0, 0, 0)
121
+
122
+ # maybe set one master that can propagate the event to all others
123
+
124
+ # TODO draw a label directly on the scrollpane --> need override its paint method
125
+ # if self.label is not None:
126
+ # # formato
127
+ # canvasPainter.setPen(QColor("Green"))
128
+ # canvasPainter.setFont(QFont('Helvetica', 48))
129
+ # print('drawing text')
130
+ # canvasPainter.drawText(50, 50, self.label)
131
+
132
+ for jjj in range(self.nb_rows):
133
+ for iii in range(self.nb_cols):
134
+
135
+ # ça marche pas mal est ce plus simple outside ????
136
+ # or add a label directly on the image at various position just by drawing it in the paint window --> can also be very interesting!!!
137
+ main_container = QVBoxLayout()
138
+ # need store this in arrays
139
+ # scrollArea = QScrollArea()
140
+ scrollArea = QScrollArea()
141
+
142
+ # maybe add a vertical stuff above
143
+
144
+ # try add a Qlabel on top of it to label things up
145
+
146
+ label = QLabel('')
147
+ self.labels.append(label)
148
+
149
+ scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
150
+ scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
151
+
152
+ # ui->scrollArea->verticalScrollBar()->isVisible();
153
+ # self.setMouseTracking(not self.preview_only) # I was doing crazy stuff here --> rather keep the draing mode in the inner object --> much simpler to handle
154
+
155
+ paint = Createpaintwidget()
156
+
157
+ # we only allow the three first images to be changed contrast
158
+ if self.auto_contrast_for_all:
159
+ # print('increasing cobntrast here')
160
+ if iii<3 and jjj==0:
161
+ paint.auto_contrast = self.auto_contrast_for_all
162
+ # if paint.auto_contrast_for_all:
163
+ # paint.increase_contrast()
164
+ # print('inside set_image', self.auto_contrast_for_all)
165
+
166
+
167
+ paint.vdp.active = False
168
+ paint.vdp.drawing_mode = True
169
+
170
+ paint.force_cursor_visible = True # required to force activate cursor to be visible
171
+ if self.synced:
172
+ paint.propagate_mouse_move = True
173
+ paint.propagate_mouse_event = self.mouse_move_multihandler
174
+
175
+ # code to override apply
176
+ if True:
177
+ if jjj == 0:
178
+ # save a function with its partial
179
+ paint.apply = partial(self.custom_apply, paint)
180
+ elif jjj == 1:
181
+ paint.apply = partial(self.get_colors_drawn_over, paint)
182
+ else:
183
+ paint.vdp.drawing_mode = False
184
+
185
+
186
+ if self.draw_mode == 'rect':
187
+ paint.vdp.active = True
188
+ paint.vdp.shape_to_draw = Rect2D
189
+ # removing this makes it paint drawable --> really easy in fact
190
+ # print(self.draw_mode is not None)
191
+ paint.setMouseTracking(self.draw_mode is not None) # KEEP IMPORTANT
192
+ paint.drawing = False # is that useful, I don't like it --> make it better
193
+
194
+ # print(self.paint.hasMouseTracking())
195
+ # self.paint.drawing = False # why always true
196
+ # self.paint.mouseMoveEvent = self.mouseMoveEvent
197
+ # self.paint.mousePressEvent = self.mousePressEvent
198
+ # self.paint.mouseReleaseEvent = self.mouseReleaseEvent
199
+
200
+ # self.prev_width = 192
201
+ # self.prev_height = 192
202
+
203
+ scrollArea.setGeometry(QRect(0, 0, self.default_width, self.default_height))
204
+ scrollArea.setBackgroundRole(QPalette.Dark)
205
+ scrollArea.setWidgetResizable(
206
+ False) # allows it to resize when the parent window is resized --> force a new repaint
207
+
208
+ if self.synced:
209
+ scrollArea.verticalScrollBar().valueChanged.connect(self.scroll_vertically_together)
210
+ scrollArea.horizontalScrollBar().valueChanged.connect(self.scroll_horizontally_together)
211
+
212
+ scrollArea.setWidget(paint)
213
+ paint.scrollArea = scrollArea
214
+ # self.paint.setBaseSize(512,512)
215
+
216
+ self.scroll_areas.append(scrollArea)
217
+ self.paints.append(paint)
218
+
219
+ self.setGeometry(QRect(0, 0, self.default_width, self.default_height))
220
+
221
+ main_container.addWidget(label)
222
+ main_container.addWidget(scrollArea)
223
+
224
+ # layout.addWidget(scrollArea,jjj,iii)
225
+ layout.addLayout(main_container, jjj, iii)
226
+ # self.setFixedSize(self.size()) # I actually want it resizable and upon resize change image size accordingly
227
+
228
+ # see how to define scrollarea size in the window --> that is really key though --> I think I have a bug maybe check in top TA
229
+ # add shortcuts --> needs love
230
+ # if self.synced:
231
+ self.add_shortcuts() # ça marche --> mais à améliorer if in sync remove self stuff
232
+ self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
233
+
234
+ # dirty way of doing this but ok!!!
235
+ self.buttonBox.button(QDialogButtonBox.Ok).setText("Next")
236
+ self.buttonBox.button(QDialogButtonBox.Cancel).setText("Stop")
237
+
238
+ self.buttonBox.accepted.connect(self.accept_if_clicked)
239
+ self.buttonBox.rejected.connect(self.reject)
240
+
241
+
242
+
243
+ # self.buttonBox.button(QDialogButtonBox.Ok).setAutoDefault(False)
244
+ # self.buttonBox.button(QDialogButtonBox.Cancel).setAutoDefault(False)
245
+ # self.buttonBox.button(QDialogButtonBox.Ok).setDefault(False)
246
+ # self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(False)
247
+
248
+
249
+
250
+ layout.addWidget(self.buttonBox)
251
+
252
+ self.setLayout(layout)
253
+
254
+ # dirty hack to ignore enter pressed
255
+ def accept_if_clicked(self):
256
+ if not self.buttonBox.button(QDialogButtonBox.Ok).hasFocus():
257
+ return
258
+ return self.accept()
259
+
260
+
261
+ def get_colors_drawn_over(self, paint):
262
+ mask = paint.get_user_drawing()
263
+ # print('I was called')
264
+ if mask is None:
265
+ return
266
+ # print(mask)
267
+
268
+
269
+ # need get all the colors of the raw image that correspond to user selection
270
+ selected_colors =paint.get_raw_image()[mask!=0]
271
+ selected_colors = RGB_to_int24(selected_colors)
272
+
273
+ selected_colors =set(selected_colors.ravel().tolist())
274
+ if 0xFFFFFF in selected_colors:
275
+ selected_colors.remove(0xFFFFFF)
276
+ selected_colors = list(selected_colors)
277
+
278
+ # print('colors', selected_colors) #.ravel()
279
+ #neee=d get the colors as RGB single values --> convert the output to RGB
280
+
281
+
282
+
283
+ # ned convert to
284
+
285
+
286
+ # plt.imshow(mask)
287
+ # plt.show()
288
+
289
+ # paint.set_mask(None)# reset the mask
290
+ # paint.set_mask(None)
291
+ # paint.reset_user_drawing()
292
+ # paint.raw_user_drawing.fill(QtCore.Qt.transparent)
293
+
294
+ # this is the only way I found to reset the user drawing but this is dirty and I must find a better way
295
+ paint.set_mask(np.zeros_like(mask))
296
+
297
+
298
+ # marche pas...Why ?
299
+ # paint.raw_user_drawing = QtGui.QImage(paint.imageDraw.size(), QtGui.QImage.Format_ARGB32)
300
+ # paint.raw_user_drawing.fill(QtCore.Qt.transparent) # somehow this is really required to have an empty image otherwise it is not --> ??? why
301
+
302
+ # test = paint.get_user_drawing()
303
+ # plt.imshow(test)
304
+ # plt.show()
305
+ # update drawing after user input has been reset
306
+
307
+ paint.update()
308
+ return selected_colors
309
+
310
+ def custom_apply(self, paint):
311
+ # print('you called me', paint, filename)
312
+ # print(QtGui.QImageWriter.supportedImageFormats())
313
+ # save as tiff ???
314
+
315
+ # drawn_img = paint.imageDraw
316
+
317
+ # ça marche mais c'est vraiment juste le dessin --> faudrait donc que je passe le masque entier en mask et pas seulement ça --> voir ds TA comment faire en fait et aussi faire que le mask et le wshed tourne là dedans en fait car smarter
318
+
319
+ # drawn_img.save("/E/Sample_images/sample_images_PA/trash/image.png", "PNG", -1)
320
+ # drawn_img.save("/E/Sample_images/sample_images_PA/trash/image.tif", "TIF", -1)
321
+ # print('saving',"/E/Sample_images/sample_images_PA/trash/image.tif")
322
+ # print(drawn_img)
323
+
324
+ # nb will only work for red pen !!!! --> do not allow to change pen color
325
+ mask = paint.get_mask()
326
+ if mask is None:
327
+ return
328
+ # TODO would need to run the wshed on it --> finally fix or recode my wshed can be done with numba
329
+
330
+ # ça marche en fait maintenant --> utiliser ça du coup!!!
331
+ # d'ailleurs verif ce code et le nettoyer une bonne fois pr toute et le mettre dans paint et dans mask d'ailleurs...
332
+ # if nothing is saved image become compeletely full of white
333
+ mask = wshed(mask, seeds='mask')
334
+
335
+ # print('saving filename',filename)
336
+ # plt.imshow(mask[...,2])
337
+ # plt.show()
338
+ # Img(mask, dimensions='hw').save(filename)
339
+
340
+ # update the mask
341
+ # nb maybe only save on demand each ??? --> think what is the best way to do that
342
+ paint.set_mask(mask)
343
+
344
+
345
+ # Img(img, dimensions='hwc').save(filename, mode='raw')
346
+
347
+ def mouse_move_multihandler(self, event):
348
+ # pb is I need get the sender not to send it it all
349
+ # very dirty and infinite loop --> see how to do that for all
350
+ # print('toto', self, event)
351
+ # just get it to draw the cursor --> no infinite propagation then
352
+ # if event == self.last_propagated_mouse_event:
353
+ # return
354
+ # idx = self.get_idx_of_widget_under_mouse()
355
+ # print(idx)
356
+ # copied_event = event
357
+ # if event.type() == QEvent.MouseMove:
358
+ # copied_event = event.pos()
359
+ # copied_event = event.copy()
360
+
361
+ # copied_event = QMouseEvent()
362
+ # self.receiver.move(event.pos())
363
+ for iii, paint in enumerate(self.paints):
364
+ try:
365
+ # if iii != idx:
366
+ # MEGA TODO: SUPER ULTIMATE DIRTY HACK FOR MOUSE EVENT PROPAGATION THROUGH PAINT WIDGETS THINK ABOUT A SMARTER WAY TO DO THAT IN THE FUTURE yet ok for now...
367
+ paint.propagate_mouse_move = False
368
+ # paint.mouseMove(copied_event) #Event( event)
369
+ # paint.mouseMoveEvent(copied_event) #Event( event)
370
+ paint.mouseMoveEvent(event) # Event( event)
371
+ paint.propagate_mouse_move = True
372
+ # self.last_propagated_mouse_event = event
373
+ except:
374
+ traceback.print_exc()
375
+ pass
376
+
377
+
378
+ # could add the same shortcuts within individual panels
379
+ def add_shortcuts(self):
380
+ # if True:
381
+ # return
382
+ zoomPlus = QtWidgets.QShortcut("Ctrl+Shift+=", self)
383
+ zoomPlus.activated.connect(self.zoomIn)
384
+ zoomPlus.setContext(QtCore.Qt.ApplicationShortcut)
385
+
386
+ zoomPlus2 = QtWidgets.QShortcut("Ctrl++", self)
387
+ zoomPlus2.activated.connect(self.zoomIn)
388
+ zoomPlus2.setContext(QtCore.Qt.ApplicationShortcut)
389
+
390
+ zoomMinus = QtWidgets.QShortcut("Ctrl+Shift+-", self)
391
+ zoomMinus.activated.connect(self.zoomOut)
392
+ zoomMinus.setContext(QtCore.Qt.ApplicationShortcut)
393
+
394
+ zoomMinus2 = QtWidgets.QShortcut("Ctrl+-", self)
395
+ zoomMinus2.activated.connect(self.zoomOut)
396
+ zoomMinus2.setContext(QtCore.Qt.ApplicationShortcut)
397
+
398
+ # dirty reimplementation of the shortcuts --> TODO recode that better some day --> but ok for now
399
+ enterShortcut = QtWidgets.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Return), self)
400
+ enterShortcut.activated.connect(self.apply)
401
+ enterShortcut.setContext(QtCore.Qt.ApplicationShortcut)
402
+
403
+ enterShortcut2 = QtWidgets.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Enter), self)
404
+ enterShortcut2.activated.connect(self.apply)
405
+ enterShortcut2.setContext(QtCore.Qt.ApplicationShortcut)
406
+
407
+ shrtM = QtWidgets.QShortcut("M", self)
408
+ shrtM.activated.connect(self.m_apply)
409
+ shrtM.setContext(QtCore.Qt.ApplicationShortcut)
410
+
411
+ ctrlM = QtWidgets.QShortcut("Ctrl+M", self)
412
+ ctrlM.activated.connect(self.ctrl_m_apply)
413
+ ctrlM.setContext(QtCore.Qt.ApplicationShortcut)
414
+
415
+ # pkoi ça ne marche pas !!!
416
+ shiftEnterShortcut = QtWidgets.QShortcut("Shift+Enter", self)
417
+ shiftEnterShortcut.activated.connect(self.shift_apply)
418
+ shiftEnterShortcut.setContext(QtCore.Qt.ApplicationShortcut)
419
+ #
420
+ shiftEnterShortcut2 = QtWidgets.QShortcut("Shift+Return", self)
421
+ shiftEnterShortcut2.activated.connect(self.shift_apply)
422
+ shiftEnterShortcut2.setContext(QtCore.Qt.ApplicationShortcut)
423
+
424
+
425
+
426
+ def take_intelligent_decision_for_track_editing_based_on_user_selection(self, selected_cells_prev, selected_cells_cur, selected_cells_next):
427
+ # if selected_cells_prev is not None and selected_cells_prev:
428
+ # # check how many cells have been selected and take action depending in the stuff
429
+ # pass
430
+ # if selected_cells_cur is not None and selected_cells_cur:
431
+ # pass
432
+ # if selected_cells_next is not None and selected_cells_next:
433
+ # pass
434
+ if selected_cells_next is None:
435
+ selected_cells_next = []
436
+ if selected_cells_prev is None:
437
+ selected_cells_prev = []
438
+ if selected_cells_cur is None:
439
+ selected_cells_cur = []
440
+
441
+ if len(selected_cells_prev) + len(selected_cells_cur) + len(selected_cells_next) != 2:
442
+ # print('Error: ')
443
+ if len(selected_cells_prev) + len(selected_cells_cur) + len(selected_cells_next) < 2:
444
+ # not enough cells --> need add more
445
+ self._show_warning_msage(text='Not enough cells drawn over, please click on exactly two cells')
446
+ return
447
+
448
+ # print(len(selected_cells_prev) + len(selected_cells_cur) + len(selected_cells_next))
449
+ # print(selected_cells_next, selected_cells_prev, selected_cells_cur)
450
+ self._show_warning_msage()
451
+ return
452
+
453
+ # the user has drawn properly over the image --> some decision can be taken then
454
+ # --> do the stuff
455
+
456
+ # sqsqdsqsqdqsdqsdqsd
457
+
458
+ # if both are in the same then do swap otherwise try connect cells
459
+ # I also need to know the current frame --> TODO
460
+
461
+ # I need have the list and the current frame
462
+
463
+ try:
464
+ path_to_cur_track = smart_name_parser(self.lst[self.cur_frame_idx], 'tracked_cells_resized.tif')
465
+ except:
466
+ path_to_cur_track = None
467
+ try:
468
+ path_to_next_track = smart_name_parser(self.lst[self.cur_frame_idx+1], 'tracked_cells_resized.tif')
469
+ except:
470
+ path_to_next_track = None
471
+ try:
472
+ path_to_prev_track = smart_name_parser(self.lst[self.cur_frame_idx-1], 'tracked_cells_resized.tif')
473
+ except:
474
+ path_to_prev_track = None
475
+
476
+ something_changed = False
477
+ if len(selected_cells_cur) == 2:
478
+ # launch a swap starting from the current image onwards
479
+ # start swapping fropm current idx onwards
480
+ something_changed = True
481
+ swap_tracks(self.lst, self.cur_frame_idx, selected_cells_cur[0],selected_cells_cur[1])
482
+ # check the images that need be reloaded and update them
483
+ # I need update cur and next image
484
+ if path_to_cur_track is not None:
485
+ img = Img(path_to_cur_track)
486
+ self.paints[4].set_image(img)
487
+ if path_to_next_track is not None:
488
+ img = Img(path_to_next_track)
489
+ self.paints[5].set_image(img)
490
+
491
+ # need reload two images
492
+ if len(selected_cells_next) == 2:
493
+ something_changed = True
494
+ swap_tracks(self.lst, self.cur_frame_idx+1, selected_cells_next[0], selected_cells_next[1])
495
+
496
+ if path_to_next_track is not None:
497
+ img = Img(path_to_next_track)
498
+ self.paints[5].set_image(img)
499
+
500
+ if len(selected_cells_prev) == 2:
501
+ something_changed = True
502
+ swap_tracks(self.lst, self.cur_frame_idx-1, selected_cells_prev[0], selected_cells_prev[1])
503
+
504
+ if path_to_prev_track is not None:
505
+ img = Img(path_to_prev_track)
506
+ self.paints[3].set_image(img)
507
+ if path_to_cur_track is not None:
508
+ img = Img(path_to_cur_track)
509
+ self.paints[4].set_image(img)
510
+ if path_to_next_track is not None:
511
+ img = Img(path_to_next_track)
512
+ self.paints[5].set_image(img)
513
+
514
+
515
+ if len(selected_cells_cur)==1:
516
+ if len(selected_cells_prev)==1:
517
+ something_changed = True
518
+ connect_tracks(self.lst, self.cur_frame_idx, selected_cells_cur[0],selected_cells_prev[0])
519
+ if path_to_cur_track is not None:
520
+ img = Img(path_to_cur_track)
521
+ self.paints[4].set_image(img)
522
+ if path_to_next_track is not None:
523
+ img = Img(path_to_next_track)
524
+ self.paints[5].set_image(img)
525
+
526
+ if len(selected_cells_next)==1:
527
+ something_changed = True
528
+ connect_tracks(self.lst, self.cur_frame_idx+1, selected_cells_cur[0],selected_cells_next[0])
529
+
530
+ if path_to_next_track is not None:
531
+ img = Img(path_to_next_track)
532
+ self.paints[5].set_image(img)
533
+ else:
534
+ logger.error('Please try to connect tracks across two consecutive frames, not between images distant from one another')
535
+
536
+ # TODO better check the something changed to avoid unnecessary db updates that may be lengthy
537
+ if something_changed:
538
+ # need update the track to local ID correpsondace
539
+ add_localID_to_trackID_correspondance_in_DB(self.lst)
540
+
541
+
542
+
543
+ def shift_apply(self):
544
+ idx = self.get_idx_of_widget_under_mouse()
545
+ # dirty hack to transfer shortcut to child
546
+ if idx != -1:
547
+ # print('applying in', idx)
548
+ if idx in [0,1,2]:
549
+ self.paints[idx].apply_drawing(minimal_cell_size=10)
550
+
551
+
552
+ # full of bugs --> deactivate it here ????
553
+ def ctrl_m_apply(self):
554
+ idx = self.get_idx_of_widget_under_mouse()
555
+ # dirty hack to transfer shortcut to child
556
+ if idx != -1:
557
+ # print('applying in', idx)
558
+ if idx in [0, 1, 2]:
559
+ try:
560
+ self.paints[idx].manually_reseeded_wshed()
561
+ except:
562
+ traceback.print_exc()
563
+
564
+
565
+ def m_apply(self):
566
+ idx = self.get_idx_of_widget_under_mouse()
567
+ # dirty hack to transfer shortcut to child
568
+ if idx != -1:
569
+ # print('applying in', idx)
570
+ if idx in [0,1,2]:
571
+ self.paints[idx].m_apply()
572
+
573
+
574
+
575
+
576
+ # ça marche mais c'est super dirty je pense ???? en plus pr je ne sais quelle raison marche pas avec enter
577
+ # ça fera
578
+ def apply(self):
579
+ # print('apply method to override in main')
580
+ idx = self.get_idx_of_widget_under_mouse()
581
+ # dirty hack to transfer shortcut to child
582
+ if idx != -1:
583
+ # print('applying in', idx)
584
+ if idx not in [3,4,5]:
585
+ self.paints[idx].apply()
586
+ else:
587
+ # get swaps from all the images and take action if makes sense
588
+ # or warn for errors
589
+ selected_cells_prev = []
590
+ selected_cells_cur = []
591
+ selected_cells_next = []
592
+ if len(self.paints) >= 4:
593
+ selected_cells_prev = self.paints[3].apply()
594
+ if len(self.paints) >= 5:
595
+ selected_cells_cur = self.paints[4].apply()
596
+ if len(self.paints) >= 6:
597
+ selected_cells_next = self.paints[5].apply()
598
+
599
+ self.take_intelligent_decision_for_track_editing_based_on_user_selection(selected_cells_prev, selected_cells_cur, selected_cells_next)
600
+
601
+ def _show_warning_msage(self, text='Too many cells for track correction please just draw over two cells, no more...'):
602
+ msg = QMessageBox()
603
+ msg.setIcon(QMessageBox.Critical)
604
+ msg.setText("Error")
605
+ msg.setInformativeText(text)
606
+ msg.setWindowTitle("Error")
607
+ # msg.setDetailedText("Detailed explanation of the error: .......") # TODO maybe add more some day
608
+ retval = msg.exec_()
609
+ # in case I would need to do something with the retval but I gss I do
610
+
611
+
612
+ # print()
613
+ # allows the bars to scroll together --> quite good in fact
614
+ # do it also for horiz
615
+ def scroll_vertically_together(self, event):
616
+ # print(event)
617
+ for scrollbar in self.scroll_areas:
618
+ scrollbar.verticalScrollBar().setValue(event)
619
+
620
+ def scroll_horizontally_together(self, event):
621
+ # print(event)
622
+ for scrollbar in self.scroll_areas:
623
+ scrollbar.horizontalScrollBar().setValue(event)
624
+
625
+ def set_last_scroll(self, last_scroll_position):
626
+ def apply_scroll():
627
+ for scrollbar in self.scroll_areas:
628
+ scrollbar.horizontalScrollBar().setValue(last_scroll_position[0])
629
+ scrollbar.verticalScrollBar().setValue(last_scroll_position[1])
630
+ # Defer to the next event loop cycle
631
+ QTimer.singleShot(0, apply_scroll) # this is required for the scroll pos to be updated even though the dialog is not showing
632
+
633
+ def set_labels(self, *args):
634
+ for iii, label in enumerate(args):
635
+ self.set_label(label, nb=iii)
636
+
637
+ def set_images(self, *args):
638
+ for iii, img in enumerate(args):
639
+ self.set_image(img, nb=iii)
640
+
641
+ def set_label(self, label, nb=0):
642
+ if label is not None:
643
+ self.labels[nb].setText(label)
644
+ else:
645
+ self.labels[nb].setText('')
646
+ # paint = self.paints[nb]
647
+ # paint.vdp.shapes.clear()
648
+ # paint.set_image(img) # bug is here
649
+ # if img is None:
650
+ # paint.scale = self.scale = paint.vdp.scale = 1. # will that work ??? remove global scale ???
651
+ # else:
652
+ # max_size = min(self.prev_width / img.get_width(), self.prev_height / img.get_height())
653
+ # self.paint.scale = self.scale = self.paint.vdp.scale = max_size
654
+
655
+ # TODO handle scale nicely here
656
+ # also allow drawing over the image
657
+
658
+ # if paint.image is not None:
659
+ # paint.resize(self.scale * paint.image.size())
660
+ # self.scrollArea.resize(self.scale * self.paint.image.size())
661
+ # self.scrollArea.resize(self.size())
662
+
663
+ # print('self.paint.hasMouseTracking()', self.paint.hasMouseTracking())# how come it can track if no mouse tracking ???
664
+
665
+
666
+
667
+ # should I offer a crop of the image --> maybe also make it to store the relevant raw data --> can be very useful
668
+ # do a clear also for the image
669
+ def set_image(self, img, nb=0):
670
+
671
+ paint = self.paints[nb]
672
+ paint.vdp.shapes.clear()
673
+ paint.set_image(img) # bug is here
674
+
675
+
676
+
677
+ if img is None:
678
+ paint.scale = self.scale = paint.vdp.scale = 1. # will that work ??? remove global scale ???
679
+ # else:
680
+ # max_size = min(self.prev_width / img.get_width(), self.prev_height / img.get_height())
681
+ # self.paint.scale = self.scale = self.paint.vdp.scale = max_size
682
+
683
+ # TODO handle scale nicely here
684
+ # also allow drawing over the image
685
+
686
+ if False:
687
+ if paint.image is not None:
688
+ paint.resize(self.scale * paint.image.size())
689
+ # self.scrollArea.resize(self.scale * self.paint.image.size())
690
+ # self.scrollArea.resize(self.size())
691
+
692
+ if paint.auto_contrast:
693
+ # print('increasing contrast')
694
+ paint.increase_contrast()
695
+
696
+
697
+ # print('self.paint.hasMouseTracking()', self.paint.hasMouseTracking())# how come it can track if no mouse tracking ???
698
+
699
+
700
+
701
+ # clear image
702
+ def clear(self, nb=0):
703
+ self.set_image(None, nb=nb)
704
+ # print(self.size())
705
+ # self.scrollArea.resize(self.size())
706
+ size = self.size()
707
+ scrollArea = self.scroll_areas[nb]
708
+ scrollArea.setGeometry(QRect(0, 0, size.width(), size.height()))
709
+ paint = self.paints[nb]
710
+ paint.setGeometry(
711
+ QRect(0, 0, self.default_width - 2, self.default_height - 2)) # force all black and no scrollbars ---> ok
712
+ # self.scale = 1.
713
+
714
+ # ça marche --> ajouter fit to width ou fit to height
715
+ def fit_to_width_or_height(self):
716
+ if self.is_width_for_alternating:
717
+ self.fit_to_width()
718
+ else:
719
+ self.fit_to_height()
720
+ self.is_width_for_alternating = not self.is_width_for_alternating
721
+
722
+ # almost there but small bugs
723
+ def fit_to_width(self, nb=0):
724
+ paint = self.paints[nb]
725
+ if paint.image is None:
726
+ return
727
+ scrollArea = self.scroll_areas[nb]
728
+ width = scrollArea.width() - 2
729
+ width -= scrollArea.verticalScrollBar().sizeHint().width()
730
+ # height-=self.scrollArea.horizontalScrollBar().sizeHint().height()
731
+ width_im = paint.image.width()
732
+ scale = width / width_im
733
+ self.scaleImage(scale, nb=nb)
734
+
735
+ def fit_to_height(self, nb=0):
736
+ paint = self.paints[nb]
737
+ if paint.image is None:
738
+ return
739
+ scrollArea = self.scroll_areas[nb]
740
+ height = scrollArea.height() - 2
741
+ height -= scrollArea.horizontalScrollBar().sizeHint().height()
742
+ height_im = paint.image.height()
743
+ scale = height / height_im
744
+ self.scaleImage(scale, nb=nb)
745
+
746
+ def fit_to_window(self, nb=0):
747
+ # compute best fit
748
+ # just get the size of the stuff and best fit it
749
+ paint = self.paints[nb]
750
+ if paint.image is None:
751
+ return
752
+
753
+ # QScrollArea.ensureWidgetVisible(
754
+ # QScrollArea.ensureVisible
755
+ # QScrollArea.setWidgetResizable
756
+ scrollArea = self.scroll_areas[nb]
757
+ width = scrollArea.width() - 2 # required to make sure bars not visible
758
+ height = scrollArea.height() - 2
759
+
760
+ # scale image that it fits in --> change scale
761
+
762
+ # width-=self.scrollArea.verticalScrollBar().sizeHint().width()
763
+ # height-=self.scrollArea.horizontalScrollBar().sizeHint().height()
764
+
765
+ height_im = paint.image.height()
766
+ width_im = paint.image.width()
767
+ scale = height / height_im
768
+ if width / width_im < scale:
769
+ scale = width / width_im
770
+ self.scaleImage(scale, nb=nb)
771
+
772
+ # don't want a factor
773
+ def scaleImage(self, scale, nb=0):
774
+ paint = self.paints[nb]
775
+ self.scale = scale
776
+ if paint.image is not None:
777
+ paint.resize(self.scale * paint.image.size())
778
+ else:
779
+ # no image set size to 0, 0 --> scroll pane will auto adjust
780
+ paint.resize(QSize(0, 0))
781
+ # self.scale -= factor # reset zoom
782
+
783
+ paint.scale = self.scale
784
+ paint.vdp.scale = self.scale
785
+ paint.update()
786
+
787
+ # self.adjustScrollBar(self.scrollArea.horizontalScrollBar(), factor)
788
+ # self.adjustScrollBar(self.scrollArea.verticalScrollBar(), factor)
789
+
790
+ # self.zoomInAct.setEnabled(self.scale < self.max_scaling_factor)
791
+ # self.zoomOutAct.setEnabled(self.scale > self.min_scaling_factor)
792
+
793
+ # synced version of scale
794
+ def scale_image_all(self, scale):
795
+ for img_nb in range(len(self.paints)):
796
+ self.scaleImage(scale, nb=img_nb)
797
+
798
+ #
799
+ # def fitToWindow(self):
800
+ # # TODO most likely a bug there because calls self.defaultSize that resets the scale --> MAKE NO SENSE
801
+ # fitToWindow = self.fitToWindowAct.isChecked()
802
+ # self.scrollArea.setWidgetResizable(fitToWindow)
803
+ # if not fitToWindow:
804
+ # self.defaultSize()
805
+
806
+ def zoomIn(self):
807
+ if self.synced:
808
+ self.scale_image_all(scale=self.scale + 0.1)
809
+ else:
810
+ idx = self.get_idx_of_widget_under_mouse()
811
+ if idx != -1:
812
+ self.scaleImage(self.scale + 0.1, nb=idx)
813
+ # get index
814
+
815
+ def zoomOut(self):
816
+ if self.synced:
817
+ self.scale_image_all(scale=self.scale - 0.1)
818
+ else:
819
+ idx = self.get_idx_of_widget_under_mouse()
820
+ if idx != -1:
821
+ self.scaleImage(self.scale - 0.1, nb=idx)
822
+
823
+ # get the index of the image under the mouse!!
824
+ def get_idx_of_widget_under_mouse(self):
825
+ pos = QtGui.QCursor.pos()
826
+ widget = QApplication.widgetAt(pos)
827
+ for iii, paint in enumerate(self.paints):
828
+ if widget == paint:
829
+ return iii
830
+ for iii, scrollarea in enumerate(self.scroll_areas):
831
+ if widget == scrollarea:
832
+ return iii
833
+ return -1
834
+
835
+ def get_paints(self):
836
+ return self.paints
837
+
838
+ def get_scrolls(self):
839
+ return self.scroll_areas
840
+
841
+ @staticmethod
842
+ def display(parent=None, draw_mode=None, default_width=512, default_height=512, nb_rows=1, nb_cols=1, synced=True,
843
+ images=None, labels=None, lst=None, cur_frame_idx=None, auto_contrast_for_all=False,last_scroll_position=None, last_scale=None): #, last_zoom=None
844
+
845
+
846
+
847
+ dialog = ImgDisplayWindow(parent, draw_mode=draw_mode, default_width=default_width,
848
+ default_height=default_height, nb_cols=nb_cols, nb_rows=nb_rows, synced=synced, lst=lst, cur_frame_idx=cur_frame_idx,auto_contrast_for_all=auto_contrast_for_all)
849
+ # dialog.showFullScreen() # pas mal mais vraiment full screen --> can cause trouble --> maybe change this some day
850
+
851
+ # show dialog full screen without maximizing, see # https://stackoverflow.com/questions/15702470/how-to-make-a-window-that-occupies-the-full-screen-without-maximising
852
+ titleBarHeight = dialog.style().pixelMetric(
853
+ QStyle.PM_TitleBarHeight,
854
+ QStyleOptionTitleBar(),
855
+ dialog
856
+ )
857
+
858
+ try:
859
+ geometry = QtWidgets.QDesktopWidget().availableGeometry()
860
+ geometry.setHeight(geometry.height() - (titleBarHeight * 2))
861
+ except:
862
+ from qtpy.QtGui import QGuiApplication
863
+ geometry = QGuiApplication.primaryScreen().geometry()
864
+
865
+ dialog.setGeometry(geometry)
866
+ # end show full screen without maximizing
867
+
868
+ if images is not None:
869
+ dialog.set_images(*images)
870
+
871
+ if labels is not None:
872
+ dialog.set_labels(*labels)
873
+
874
+
875
+ # dialog.set_
876
+
877
+ if last_scroll_position is not None:
878
+ dialog.set_last_scroll(last_scroll_position)
879
+
880
+ if last_scale is not None:
881
+ dialog.scale_image_all(scale=last_scale)
882
+
883
+ # this stuff is rest here
884
+ result = dialog.exec_()
885
+ augment = dialog.get_paints()
886
+
887
+ # Get last scroll positions from the source scroll area (so that we can reapply it for new sets of images)
888
+ scrolls = dialog.get_scrolls()
889
+ h_value = scrolls[0].horizontalScrollBar().value()
890
+ v_value = scrolls[0].verticalScrollBar().value()
891
+ last_scroll_position = [h_value, v_value]
892
+ last_scale = dialog.scale
893
+ # last_zoom =
894
+
895
+ return (augment, last_scroll_position, last_scale,result == QDialog.Accepted)
896
+
897
+
898
+ # does not work
899
+ # class labelled_scrollarea(QScrollArea):
900
+ #
901
+ # def __init__(self):
902
+ # super().__init__()
903
+ #
904
+ # # def paintEvent(self, event):
905
+ # # # ne marche pas car l'autre truc ecrit par dessus
906
+ # # # super().paintEvent(event)
907
+ # # super(labelled_scrollarea, self).paintEvent(event)
908
+ # #
909
+ # # # self.viewport().paintEvent(event)
910
+ # # # pb the widget overrides that --> need first paint it then call that
911
+ # # # print('inside')
912
+ # # painter = QtGui.QPainter(self.viewport())
913
+ # # # this will never work here --> really need be done in the other painter
914
+ # #
915
+ # # # painter = QPainter()
916
+ # # # painter.begin(self.viewport())
917
+ # # # self.drawRectangles(qp)
918
+ # # # painter.end()
919
+ # #
920
+ # # # painter = QPainter(self.viewport()) # If a widget has a viewport, you have to pass that to the QPainter constructor: https://stackoverflow.com/questions/12226930/overriding-qpaintevents-in-pyqt
921
+ # # # painter = QPainter(self) # If a widget has a viewport, you have to pass that to the QPainter constructor: https://stackoverflow.com/questions/12226930/overriding-qpaintevents-in-pyqt
922
+ # # # painter.setRenderHint(QPainter.Antialiasing)
923
+ # # painter.setPen(Qt.darkRed)
924
+ # # rectangle = QRectF(10.0, 20.0, 80.0, 60.0)
925
+ # # painter.drawRect(rectangle)
926
+ # #
927
+ # # painter.setPen(QColor("Green"))
928
+ # # painter.setFont(QFont('Helvetica', 48))
929
+ # # # print('drawing text')
930
+ # # painter.drawText(50, 50, 'this is a test of your system')
931
+ # #
932
+ # # painter.end()
933
+ # #
934
+ # # # scrollArea.paintEvent = paintEvent
935
+
936
+
937
+ if __name__ == '__main__':
938
+ # TODO --> last thing todo is to apply several 'apply' methods for each of the paint methods --> maybe simply override them ???
939
+
940
+ # TODO allow unknown number of files, sort of on demand creation --> clear and restore all paints and scrolls
941
+ # move most of the commands to the image panel itself
942
+ # allow crops
943
+ # add shortcuts
944
+ # offer synchronous pointer maybe ???
945
+ # offer drift maybe ???
946
+ # store the image directly in the object --> much smarter and easier to retrieve (maybe handle Z and or t stacks also from within)
947
+ # would be perfect to see corrections
948
+ # for corrections maybe first do the human one fully then try to automate things with automated solutions with accept of reject à la tinder --> TODO
949
+ # already showing the three original images with masks, the three tracks and the scores with prev and next for the current as well as new and lost cells should do most of the job
950
+ # later I can try automated corrections but quite ok already
951
+ # NB IDEALLY THE SCALE SHOULD ALSO BE SAVED DIRECTLY IN THE THING THAT DISPLAYS IMAGES
952
+
953
+ if True:
954
+ # try open this as a dialog
955
+ import sys
956
+
957
+ app = QApplication(sys.argv)
958
+ # TODO find a way to synchronize the mouse for all
959
+
960
+ # find a way to propagate mouse events from one to all
961
+ # ok = ImgDisplayWindow.display(draw_mode='pen', nb_cols=5, images=[
962
+ # Img('/E/Sample_images/sample_images_PA/egg_chambers/120404_division_EcadKI.lif - Series006_RGB_manual_proj.png'),
963
+ # Img('/E/Sample_images/sample_images_PA/mini10_fake_swaps/focused_Series012.png'),
964
+ # Img('/E/Sample_images/sample_images_PA/egg_chambers/120404_division_EcadKI.lif - Series006_RGB_manual_proj.png'),
965
+ # Img('/E/Sample_images/sample_images_PA/mini10_fake_swaps/focused_Series012.png'), None])
966
+
967
+ lst = ['/E/Sample_images/sample_images_PA/mini_different_nb_of_channels/focused_Series012.png', '/E/Sample_images/sample_images_PA/mini_different_nb_of_channels/focused_Series014.png', '/E/Sample_images/sample_images_PA/mini_different_nb_of_channels/focused_Series016.png']
968
+
969
+ augment, ok = ImgDisplayWindow.display(draw_mode='pen', nb_rows=3, nb_cols=3, images=[
970
+ # Img('/E/Sample_images/sample_images_PA/mini_different_nb_of_channels/focused_Series012.png'),#Img('/E/Sample_images/sample_images_PA/mini_different_nb_of_channels/focused_Series012/handCorrection.tif')],
971
+ Img('/F/Confocal_le_bivic/181023_ON_tila_SC_EcadKI_around16H_APF/predict/Image6.tif'),#Img('/E/Sample_images/sample_images_PA/mini_different_nb_of_channels/focused_Series012/handCorrection.tif')],
972
+ Img('/E/Sample_images/sample_images_PA/mini_different_nb_of_channels/focused_Series014.png'),
973
+ Img('/E/Sample_images/sample_images_PA/mini_different_nb_of_channels/focused_Series016.png'),
974
+ Img('/E/Sample_images/sample_images_PA/mini_different_nb_of_channels/focused_Series012/tracked_cells_resized.tif'),
975
+ Img('/E/Sample_images/sample_images_PA/mini_different_nb_of_channels/focused_Series014/tracked_cells_resized.tif'),
976
+ Img('/E/Sample_images/sample_images_PA/mini_different_nb_of_channels/focused_Series016/tracked_cells_resized.tif'), None],
977
+ labels=['test1', 'test2', 'test3', None], lst=lst, cur_frame_idx=1, auto_contrast_for_all=True)
978
+ print(augment, ok)
979
+ sys.exit(0)
980
+
981
+ if False:
982
+ # pas
983
+
984
+ # TODO essayer le multidisplay
985
+ # avec un set pr bcp de choses
986
+
987
+ # ok in fact that is already a great popup window --> can I further improve it ???
988
+
989
+ # just for a test
990
+ app = QApplication(sys.argv)
991
+ ex = ImgDisplayWindow(nb_rows=2, nb_cols=2)
992
+ # ex = ImgDisplayWindow(preview_only=True)
993
+ # img = Img('/home/aigouy/mon_prog/Python/Deep_learning/unet/data/membrane/test/11.png')
994
+ # img = Img('/home/aigouy/mon_prog/Python/Deep_learning/unet/data/membrane/test/122.png')
995
+ # img = Img('/home/aigouy/mon_prog/Python/data/3D_bicolor_ovipo.tif')
996
+ # img = Img('/home/aigouy/mon_prog/Python/data/Image11.lsm')
997
+ # img = Img('/home/aigouy/mon_prog/Python/data/lion.jpeg')
998
+ # img = Img('/home/aigouy/mon_prog/Python/data/epi_test.png')
999
+
1000
+ img = Img(
1001
+ '/E/Sample_images/sample_images_PA/egg_chambers/120404_division_EcadKI.lif - Series006_RGB_manual_proj.png')
1002
+ ex.set_image(img)
1003
+
1004
+ # test = QRectF(None, None, 128, 128)
1005
+ ex.scaleImage(
1006
+ 22) # ça marche faudra finalizer des trucs mais pas mal déjà --> tt mettre en interne dans ma classe d'intéret --> I'm almost done
1007
+ # store image inside and also give it more options
1008
+ ex.fit_to_window() # ça marche mais pb avec la taille des barres --> voir comment faire et tricher
1009
+ ex.fit_to_height()
1010
+ ex.fit_to_width()
1011
+
1012
+ # ça marche pas mal et en plus c'est simple!!!
1013
+ ex.fit_to_width_or_height()
1014
+ ex.fit_to_width_or_height()
1015
+ ex.fit_to_width_or_height()
1016
+ ex.fit_to_width_or_height()
1017
+
1018
+ # img = Img('/E/Sample_images/sample_images_PA/mini10_fake_swaps/focused_Series012.png')
1019
+ ex.set_image(img)
1020
+ ex.clear()
1021
+
1022
+ ex.set_image(img, nb=0)
1023
+ img = Img('/E/Sample_images/sample_images_PA/mini10_fake_swaps/focused_Series012.png')
1024
+ ex.set_image(img, nb=3)
1025
+
1026
+ ex.scale_image_all(0.3)
1027
+ ex.scaleImage(1, nb=3) # tt marche et en plus vraiment pas mal --> je vais adorer ce truc à la fin!!!
1028
+
1029
+ # ça a l'air de marcher --> just allow or disallow sync
1030
+ # ex.set_image(None)
1031
+ ex.show()
1032
+ app.exec_()
1033
+
1034
+ # all of the things seem ok !!!
1035
+
1036
+ # all is ok for now
1037
+ # maybe add ROIs to zoom on a region of the image
1038
+ # maybe stor all in the image because it is easier to handle !!!