batoolset 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- batoolset/GUI/__init__.py +0 -0
- batoolset/GUI/list_gui.py +513 -0
- batoolset/GUI/multi_image_display.py +989 -0
- batoolset/GUI/open.py +325 -0
- batoolset/GUI/overlay_hints.py +45 -0
- batoolset/GUI/paint2.py +1345 -0
- batoolset/GUI/scrollablepaint.py +1152 -0
- batoolset/IJ_ROIs/__init__.py +0 -0
- batoolset/IJ_ROIs/tools.py +40 -0
- batoolset/PATH/__init__.py +0 -0
- batoolset/PATH/tools.py +79 -0
- batoolset/SQLite_tools/__init__.py +0 -0
- batoolset/SQLite_tools/tools.py +840 -0
- batoolset/__init__.py +0 -0
- batoolset/binary/__init__.py +0 -0
- batoolset/binary/tools.py +123 -0
- batoolset/binarytools/__init__.py +0 -0
- batoolset/binarytools/cell_center_detector.py +290 -0
- batoolset/clipboard_tools/__init__.py +0 -0
- batoolset/clipboard_tools/tools.py +7 -0
- batoolset/colors/__init__.py +0 -0
- batoolset/colors/colorgen.py +193 -0
- batoolset/colors/tools.py +22 -0
- batoolset/command_line/__init__.py +0 -0
- batoolset/command_line/tools.py +18 -0
- batoolset/dialogs/__init__.py +0 -0
- batoolset/dialogs/opensave.py +228 -0
- batoolset/dicts/__init__.py +0 -0
- batoolset/dicts/tools.py +299 -0
- batoolset/dims/__init__.py +0 -0
- batoolset/dims/tools.py +83 -0
- batoolset/draw/__init__.py +0 -0
- batoolset/draw/shapes/Position.py +183 -0
- batoolset/draw/shapes/__init__.py +0 -0
- batoolset/draw/shapes/automated_alignment_drawing_refactored.py +346 -0
- batoolset/draw/shapes/circle2d.py +99 -0
- batoolset/draw/shapes/compute_optimal_size_all_merged.py +317 -0
- batoolset/draw/shapes/ellipse2d.py +336 -0
- batoolset/draw/shapes/freehand2d.py +235 -0
- batoolset/draw/shapes/group.py +1830 -0
- batoolset/draw/shapes/image2d.py +2469 -0
- batoolset/draw/shapes/line2d.py +575 -0
- batoolset/draw/shapes/point2d.py +257 -0
- batoolset/draw/shapes/polygon2d.py +357 -0
- batoolset/draw/shapes/polyline2d.py +235 -0
- batoolset/draw/shapes/rect2d.py +388 -0
- batoolset/draw/shapes/rectangle2d.py +601 -0
- batoolset/draw/shapes/scalebar.py +304 -0
- batoolset/draw/shapes/serializablefont.py +126 -0
- batoolset/draw/shapes/serializableguiparams.py +10 -0
- batoolset/draw/shapes/square2d.py +103 -0
- batoolset/draw/shapes/textorientation.py +45 -0
- batoolset/draw/shapes/tools.py +467 -0
- batoolset/draw/shapes/transform2D.py +350 -0
- batoolset/draw/shapes/txt2d.py +550 -0
- batoolset/draw/widgets/__init__.py +0 -0
- batoolset/draw/widgets/col.py +343 -0
- batoolset/draw/widgets/image_group.py +248 -0
- batoolset/draw/widgets/image_organizer.py +96 -0
- batoolset/draw/widgets/paint.py +184 -0
- batoolset/draw/widgets/vectorial.py +257 -0
- batoolset/figure/__init__.py +0 -0
- batoolset/figure/alignment.py +814 -0
- batoolset/figure/column.py +1117 -0
- batoolset/figure/fig_tools.py +285 -0
- batoolset/figure/minimal_debugger_scale_etc.py +139 -0
- batoolset/figure/panel.py +697 -0
- batoolset/figure/row.py +852 -0
- batoolset/figure/user_selection.py +287 -0
- batoolset/files/__init__.py +0 -0
- batoolset/files/tools.py +1321 -0
- batoolset/images/__init__.py +0 -0
- batoolset/images/tools.py +81 -0
- batoolset/img.py +5216 -0
- batoolset/linux/__init__.py +0 -0
- batoolset/linux/tools.py +72 -0
- batoolset/lists/__init__.py +0 -0
- batoolset/lists/tools.py +436 -0
- batoolset/luts/__init__.py +0 -0
- batoolset/luts/lut_minimal_test.py +1207 -0
- batoolset/matplolib/__init__.py +0 -0
- batoolset/matplolib/tools.py +44 -0
- batoolset/np_tools/__init__.py +0 -0
- batoolset/np_tools/tools.py +252 -0
- batoolset/np_tools/trash.py +15 -0
- batoolset/pandas_tools/__init__.py +0 -0
- batoolset/pandas_tools/tools.py +880 -0
- batoolset/partials/__init__.py +0 -0
- batoolset/partials/tools.py +83 -0
- batoolset/plot_tools/__init__.py +0 -0
- batoolset/plot_tools/tools.py +70 -0
- batoolset/pyqt/__init__.py +0 -0
- batoolset/pyqt/tools.py +691 -0
- batoolset/re_tools/__init__.py +0 -0
- batoolset/re_tools/tools.py +35 -0
- batoolset/serialization/__init__.py +0 -0
- batoolset/serialization/tools.py +1192 -0
- batoolset/sets/__init__.py +0 -0
- batoolset/sets/tools.py +109 -0
- batoolset/settings/__init__.py +0 -0
- batoolset/settings/global_settings.py +134 -0
- batoolset/strings/__init__.py +0 -0
- batoolset/strings/tools.py +225 -0
- batoolset/ta/__init__.py +0 -0
- batoolset/ta/database/__init__.py +0 -0
- batoolset/ta/database/advanced_sql_plotter.py +1170 -0
- batoolset/ta/database/my_qt_table.py +79 -0
- batoolset/ta/database/preview_and_edit_sqlite_db.py +405 -0
- batoolset/ta/database/sql.py +2141 -0
- batoolset/ta/database/sql_column_name_dialog.py +122 -0
- batoolset/ta/measurements/TAmeasures.py +2226 -0
- batoolset/ta/measurements/__init__.py +0 -0
- batoolset/ta/measurements/measurements3D/__init__.py +0 -0
- batoolset/ta/measurements/measurements3D/get_point_on_surface_if_centroid_is_bad.py +175 -0
- batoolset/ta/measurements/measurements3D/height_map_to_projection.py +82 -0
- batoolset/ta/measurements/measurements3D/measures3D.py +208 -0
- batoolset/ta/measurements/measurements3D/triangulate.py +331 -0
- batoolset/ta/measurements/nematic.py +562 -0
- batoolset/ta/measurements/nematic_measurements.py +107 -0
- batoolset/ta/segmentation/__init__.py +0 -0
- batoolset/ta/segmentation/neo_wshed.py +314 -0
- batoolset/ta/selections/__init__.py +0 -0
- batoolset/ta/selections/selection.py +329 -0
- batoolset/ta/tracking/__init__.py +0 -0
- batoolset/ta/tracking/last_tracking_based_on_matching_or_on_translation_from_mermaid_warp.py +653 -0
- batoolset/ta/tracking/local_to_track_correspondance.py +138 -0
- batoolset/ta/tracking/rapid_detection_of_vertices.py +517 -0
- batoolset/ta/tracking/registration.py +108 -0
- batoolset/ta/tracking/swap_detector_and_fixer.py +296 -0
- batoolset/ta/tracking/track_correction.py +238 -0
- batoolset/ta/tracking/tracking_error_detector_and_fixer.py +3099 -0
- batoolset/ta/tracking/tracking_yet_another_approach_pyramidal_registration_n_neo_swapping_correction.py +725 -0
- batoolset/ta/utils/TA_tools.py +43 -0
- batoolset/ta/utils/__init__.py +0 -0
- batoolset/ta/utils/rps_tools.py +1783 -0
- batoolset/tests/__init__.py +0 -0
- batoolset/tests/rps_tools.py +51 -0
- batoolset/tests/tools.py +10 -0
- batoolset/tools/__init__.py +0 -0
- batoolset/tools/early_stopper_class.py +9 -0
- batoolset/tools/guided_data_recoverer.py +110 -0
- batoolset/tools/logger.py +100 -0
- batoolset/tools/mytimer.py +31 -0
- batoolset/tools/prompt_color.py +160 -0
- batoolset/tools/qthandler.py +118 -0
- batoolset/uitools/__init__.py +0 -0
- batoolset/uitools/blinker.py +56 -0
- batoolset/unsafe/__init__.py +0 -0
- batoolset/unsafe/tools.py +115 -0
- batoolset/utils/__init__.py +0 -0
- batoolset/utils/commontools.py +158 -0
- batoolset/utils/loadlist.py +728 -0
- batoolset/version.py +10 -0
- batoolset/xml/__init__.py +0 -0
- batoolset/xml/tools.py +65 -0
- batoolset/zip_tools/__init__.py +0 -0
- batoolset/zip_tools/tools.py +76 -0
- batoolset-0.1.0.dist-info/LICENSE +24 -0
- batoolset-0.1.0.dist-info/METADATA +45 -0
- batoolset-0.1.0.dist-info/RECORD +162 -0
- batoolset-0.1.0.dist-info/WHEEL +5 -0
- batoolset-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1152 @@
|
|
|
1
|
+
# channels seem be fixed --> cool
|
|
2
|
+
# finalize whsed and corrections --> make sure they are channel dependent
|
|
3
|
+
# check which channels are being restored by the new wshed within the paint arena
|
|
4
|
+
from batoolset.settings.global_settings import set_UI # set the UI to qtpy
|
|
5
|
+
set_UI()
|
|
6
|
+
import os
|
|
7
|
+
# in set image add sliders for D and Z --> see how I can do that --> or do it directly in paint ????
|
|
8
|
+
import traceback
|
|
9
|
+
import matplotlib.pyplot as plt
|
|
10
|
+
import numpy as np
|
|
11
|
+
from qtpy import QtWidgets, QtCore, QtGui
|
|
12
|
+
from qtpy.QtCore import QSize, Qt
|
|
13
|
+
from qtpy.QtGui import QPalette, QKeySequence, QPainter
|
|
14
|
+
from qtpy.QtWidgets import QScrollArea, QVBoxLayout, QWidget, QSpinBox, QComboBox, QToolBar, QStatusBar, QLabel, \
|
|
15
|
+
QHBoxLayout, QAction, QSlider
|
|
16
|
+
import qtawesome as qta
|
|
17
|
+
from qtpy.QtCore import Qt, QTimer
|
|
18
|
+
from batoolset.draw.shapes.freehand2d import Freehand2D
|
|
19
|
+
from batoolset.draw.shapes.image2d import Image2D
|
|
20
|
+
from batoolset.draw.shapes.rect2d import Rect2D
|
|
21
|
+
from batoolset.img import Img, int24_to_RGB, has_metadata
|
|
22
|
+
from batoolset.GUI.paint2 import Createpaintwidget
|
|
23
|
+
|
|
24
|
+
# TODO --> could maybe add icons just below scroll if needed to add actions
|
|
25
|
+
# j'arrive pas à creer un truc dejà self embedded
|
|
26
|
+
# make it also handle other stuff
|
|
27
|
+
|
|
28
|
+
# --> nb replace the Createpaintwidget in multi_image_display.py by this --> better in fact
|
|
29
|
+
# shall I do full screen ???
|
|
30
|
+
# TODO handle channels too if needed
|
|
31
|
+
# could store mask and memory of drawing here too --> maybe on mouse release ???
|
|
32
|
+
# avec des ctrl+Z et des ctrl+R
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# need zooms
|
|
36
|
+
#
|
|
37
|
+
|
|
38
|
+
class scrollable_paint(QWidget):
|
|
39
|
+
|
|
40
|
+
def __init__(self, custom_paint_panel=None):
|
|
41
|
+
super().__init__()
|
|
42
|
+
if custom_paint_panel is None:
|
|
43
|
+
self.paint = Createpaintwidget()
|
|
44
|
+
else:
|
|
45
|
+
self.paint = custom_paint_panel
|
|
46
|
+
layout = QVBoxLayout()
|
|
47
|
+
|
|
48
|
+
# delay dimensionality change update --> just to make sure it does not overwhelms the system upon slider change
|
|
49
|
+
# think about how to do that in a smart way -> maybe by changing the connect ???
|
|
50
|
+
# self.delayed_dimension_preview = QTimer()
|
|
51
|
+
# self.delayed_dimension_preview.setSingleShot(True)
|
|
52
|
+
# self.delayed_dimension_preview.timeout.connect(self.slider_dimension_value_changed)
|
|
53
|
+
self.dimension_sliders = []
|
|
54
|
+
self.is_width_for_alternating = True
|
|
55
|
+
# add the possibility to browse dimensions
|
|
56
|
+
self.dimensions_container = QVBoxLayout() # this will contain all the browsable dimensions of the image
|
|
57
|
+
# fake add sliders here
|
|
58
|
+
# self.dim_slider_with_label1 = self.create_dim_slider(dimension='d', max_dim=16)
|
|
59
|
+
# self.dimensions_container.addLayout(self.dim_slider_with_label1)
|
|
60
|
+
# self.dim_slider_with_label2 = self.create_dim_slider(dimension='c', max_dim=3)
|
|
61
|
+
# self.dimensions_container.addLayout(self.dim_slider_with_label2)
|
|
62
|
+
# self.dim_slider_with_label3 = self.create_dim_slider(dimension='t', max_dim=22)
|
|
63
|
+
# self.dimensions_container.addLayout(self.dim_slider_with_label3)
|
|
64
|
+
# each of the sliders will be assoc to a single dim --> TODO
|
|
65
|
+
# maybe remove the slider for channels ???
|
|
66
|
+
# same as the other with embed in scroll area
|
|
67
|
+
self.scrollArea = QScrollArea()
|
|
68
|
+
self.scrollArea.setBackgroundRole(QPalette.Dark)
|
|
69
|
+
self.scrollArea.setWidget(self.paint)
|
|
70
|
+
self.paint.scrollArea = self.scrollArea
|
|
71
|
+
layout.addLayout(self.dimensions_container)
|
|
72
|
+
layout.addWidget(self.scrollArea)
|
|
73
|
+
self.setLayout(layout)
|
|
74
|
+
status_bar = QStatusBar()
|
|
75
|
+
layout.addWidget(status_bar)
|
|
76
|
+
self.paint.statusBar = status_bar
|
|
77
|
+
self.add_shortcuts()
|
|
78
|
+
self.drawing_commands()
|
|
79
|
+
|
|
80
|
+
# this guy should handle the shortcuts it can and pass the rest to the other layer
|
|
81
|
+
def add_shortcuts(self):
|
|
82
|
+
# print('SHORTCUTS ADDED')
|
|
83
|
+
|
|
84
|
+
# if True:
|
|
85
|
+
# return
|
|
86
|
+
zoomPlus = QtWidgets.QShortcut("Ctrl+Shift+=", self)
|
|
87
|
+
zoomPlus.activated.connect(self.zoomIn)
|
|
88
|
+
zoomPlus.setContext(QtCore.Qt.ApplicationShortcut)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# that works and disconnects all
|
|
93
|
+
# zoomPlus.disconnect()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
zoomPlus2 = QtWidgets.QShortcut("Ctrl++", self)
|
|
98
|
+
zoomPlus2.activated.connect(self.zoomIn)
|
|
99
|
+
zoomPlus2.setContext(QtCore.Qt.ApplicationShortcut)
|
|
100
|
+
|
|
101
|
+
zoomMinus = QtWidgets.QShortcut("Ctrl+Shift+-", self)
|
|
102
|
+
zoomMinus.activated.connect(self.zoomOut)
|
|
103
|
+
zoomMinus.setContext(QtCore.Qt.ApplicationShortcut)
|
|
104
|
+
|
|
105
|
+
zoomMinus2 = QtWidgets.QShortcut("Ctrl+-", self)
|
|
106
|
+
zoomMinus2.activated.connect(self.zoomOut)
|
|
107
|
+
zoomMinus2.setContext(QtCore.Qt.ApplicationShortcut)
|
|
108
|
+
|
|
109
|
+
ctrl0 = QtWidgets.QShortcut("Ctrl+0", self)
|
|
110
|
+
ctrl0.activated.connect(self.zoom_reset)
|
|
111
|
+
ctrl0.setContext(QtCore.Qt.ApplicationShortcut)
|
|
112
|
+
|
|
113
|
+
self.ctrlS = QtWidgets.QShortcut("Ctrl+S", self)
|
|
114
|
+
self.ctrlS.activated.connect(self.paint.save)
|
|
115
|
+
self.ctrlS.setContext(QtCore.Qt.ApplicationShortcut)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
self.ctrlM = QtWidgets.QShortcut("Ctrl+M", self)
|
|
119
|
+
self.ctrlM.activated.connect(self.paint.ctrl_m_apply)
|
|
120
|
+
self.ctrlM.setContext(QtCore.Qt.ApplicationShortcut)
|
|
121
|
+
|
|
122
|
+
self.shrtM = QtWidgets.QShortcut("M", self)
|
|
123
|
+
self.shrtM.activated.connect(self.paint.m_apply)
|
|
124
|
+
self.shrtM.setContext(QtCore.Qt.ApplicationShortcut)
|
|
125
|
+
|
|
126
|
+
self.increase_contrastC = QtWidgets.QShortcut('C', self)
|
|
127
|
+
self.increase_contrastC.activated.connect(self.paint.increase_contrast)
|
|
128
|
+
self.increase_contrastC.setContext(QtCore.Qt.ApplicationShortcut)
|
|
129
|
+
|
|
130
|
+
# I can connect to progeny --> makes sense and really easy --> cool
|
|
131
|
+
self.enterShortcut = QtWidgets.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Return), self)
|
|
132
|
+
self.enterShortcut.activated.connect(self.paint.apply)
|
|
133
|
+
self.enterShortcut.setContext(QtCore.Qt.ApplicationShortcut)
|
|
134
|
+
|
|
135
|
+
self.enterShortcut2 = QtWidgets.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Enter), self)
|
|
136
|
+
self.enterShortcut2.activated.connect(self.paint.apply)
|
|
137
|
+
self.enterShortcut2.setContext(QtCore.Qt.ApplicationShortcut)
|
|
138
|
+
|
|
139
|
+
# en fait je peux aussi connecter des trucs au descendant --> pas bete et tres facile à faire!!!
|
|
140
|
+
|
|
141
|
+
# pkoi ça ne marche pas !!!
|
|
142
|
+
self.shiftEnterShortcut = QtWidgets.QShortcut("Shift+Enter", self)
|
|
143
|
+
self.shiftEnterShortcut.activated.connect(self.paint.shift_apply)
|
|
144
|
+
self.shiftEnterShortcut.setContext(QtCore.Qt.ApplicationShortcut)
|
|
145
|
+
#
|
|
146
|
+
self.shiftEnterShortcut2 = QtWidgets.QShortcut("Shift+Return", self)
|
|
147
|
+
self.shiftEnterShortcut2.activated.connect(self.paint.shift_apply)
|
|
148
|
+
self.shiftEnterShortcut2.setContext(QtCore.Qt.ApplicationShortcut)
|
|
149
|
+
|
|
150
|
+
self.ctrl_shift_S_grab_screen_shot = QtWidgets.QShortcut('Ctrl+Shift+S', self)
|
|
151
|
+
self.ctrl_shift_S_grab_screen_shot.activated.connect(self.paint.grab_screen_shot)
|
|
152
|
+
self.ctrl_shift_S_grab_screen_shot.setContext(QtCore.Qt.ApplicationShortcut)
|
|
153
|
+
|
|
154
|
+
self.supr = QtWidgets.QShortcut(QKeySequence(Qt.Key_Delete), self)
|
|
155
|
+
self.supr.activated.connect(self.paint.suppr_pressed)
|
|
156
|
+
self.supr.setContext(QtCore.Qt.ApplicationShortcut)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# peut etre faire un fullscreen shortcut --> can be useful
|
|
161
|
+
|
|
162
|
+
def enable_shortcuts(self):
|
|
163
|
+
self.disable_shortcuts()
|
|
164
|
+
self.ctrlS.activated.connect(self.paint.save)
|
|
165
|
+
self.ctrlM.activated.connect(self.paint.ctrl_m_apply)
|
|
166
|
+
self.shrtM.activated.connect(self.paint.m_apply)
|
|
167
|
+
self.enterShortcut.activated.connect(self.paint.apply)
|
|
168
|
+
self.enterShortcut2.activated.connect(self.paint.apply)
|
|
169
|
+
self.shiftEnterShortcut.activated.connect(self.paint.shift_apply)
|
|
170
|
+
self.shiftEnterShortcut2.activated.connect(self.paint.shift_apply)
|
|
171
|
+
|
|
172
|
+
def disable_shortcuts(self):
|
|
173
|
+
# TODO
|
|
174
|
+
try:
|
|
175
|
+
self.ctrlS.disconnect()
|
|
176
|
+
except:
|
|
177
|
+
pass
|
|
178
|
+
# TODO
|
|
179
|
+
try:
|
|
180
|
+
self.ctrlM.disconnect()
|
|
181
|
+
except:
|
|
182
|
+
pass
|
|
183
|
+
try:
|
|
184
|
+
self.shrtM.disconnect()
|
|
185
|
+
except:
|
|
186
|
+
pass
|
|
187
|
+
try:
|
|
188
|
+
self.enterShortcut.disconnect()
|
|
189
|
+
except:
|
|
190
|
+
pass
|
|
191
|
+
try:
|
|
192
|
+
self.enterShortcut2.disconnect()
|
|
193
|
+
except:
|
|
194
|
+
pass
|
|
195
|
+
try:
|
|
196
|
+
self.shiftEnterShortcut.disconnect()
|
|
197
|
+
except:
|
|
198
|
+
pass
|
|
199
|
+
try:
|
|
200
|
+
self.shiftEnterShortcut2.disconnect()
|
|
201
|
+
except:
|
|
202
|
+
pass
|
|
203
|
+
|
|
204
|
+
def enableMouseTracking(self):
|
|
205
|
+
self.paint.drawing_enabled = True
|
|
206
|
+
|
|
207
|
+
def disableMouseTracking(self):
|
|
208
|
+
self.paint.drawing_enabled = False
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
# def gather_indices_for_all_dimensions(self):
|
|
212
|
+
# loop through the content of an image ????
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
# ça marche --> ajouter fit to width ou fit to height
|
|
217
|
+
def fit_to_width_or_height(self):
|
|
218
|
+
if self.is_width_for_alternating:
|
|
219
|
+
self.fit_to_width()
|
|
220
|
+
else:
|
|
221
|
+
self.fit_to_height()
|
|
222
|
+
self.is_width_for_alternating = not self.is_width_for_alternating
|
|
223
|
+
|
|
224
|
+
# almost there but small bugs
|
|
225
|
+
def fit_to_width(self):
|
|
226
|
+
if self.paint.image is None:
|
|
227
|
+
return
|
|
228
|
+
# self.scrollArea = self.scroll_areas[nb]
|
|
229
|
+
width = self.scrollArea.width() - 2
|
|
230
|
+
width -= self.scrollArea.verticalScrollBar().sizeHint().width()
|
|
231
|
+
# height-=self.scrollArea.horizontalScrollBar().sizeHint().height()
|
|
232
|
+
width_im = self.paint.image.width()
|
|
233
|
+
scale = width / width_im
|
|
234
|
+
self.scaleImage(scale)
|
|
235
|
+
|
|
236
|
+
def fit_to_height(self, nb=0):
|
|
237
|
+
# paint = self.paints[nb]
|
|
238
|
+
if self.paint.image is None:
|
|
239
|
+
return
|
|
240
|
+
# scrollArea = self.scroll_areas[nb]
|
|
241
|
+
height = self.scrollArea.height() - 2
|
|
242
|
+
height -= self.scrollArea.horizontalScrollBar().sizeHint().height()
|
|
243
|
+
height_im = self.paint.image.height()
|
|
244
|
+
scale = height / height_im
|
|
245
|
+
self.scaleImage(scale)
|
|
246
|
+
|
|
247
|
+
def fit_to_window(self):
|
|
248
|
+
# compute best fit
|
|
249
|
+
# just get the size of the stuff and best fit it
|
|
250
|
+
# paint = self.paints[nb]
|
|
251
|
+
if self.paint.image is None:
|
|
252
|
+
return
|
|
253
|
+
|
|
254
|
+
# QScrollArea.ensureWidgetVisible(
|
|
255
|
+
# QScrollArea.ensureVisible
|
|
256
|
+
# QScrollArea.setWidgetResizable
|
|
257
|
+
# scrollArea = self.scroll_areas[nb]
|
|
258
|
+
width = self.scrollArea.width() - 2 # required to make sure bars not visible
|
|
259
|
+
height =self. scrollArea.height() - 2
|
|
260
|
+
|
|
261
|
+
# scale image that it fits in --> change scale
|
|
262
|
+
|
|
263
|
+
# width-=self.scrollArea.verticalScrollBar().sizeHint().width()
|
|
264
|
+
# height-=self.scrollArea.horizontalScrollBar().sizeHint().height()
|
|
265
|
+
|
|
266
|
+
height_im = self.paint.image.height()
|
|
267
|
+
width_im = self.paint.image.width()
|
|
268
|
+
scale = height / height_im
|
|
269
|
+
if width / width_im < scale:
|
|
270
|
+
scale = width / width_im
|
|
271
|
+
self.scaleImage(scale)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def zoomIn(self):
|
|
277
|
+
# 10% more each time
|
|
278
|
+
self.scaleImage(self.paint.scale + (self.paint.scale*10.0/100.0))# une hausse de 10% à chaque fois
|
|
279
|
+
|
|
280
|
+
def zoomOut(self):
|
|
281
|
+
# 10% less each time
|
|
282
|
+
self.scaleImage(self.paint.scale - (self.paint.scale*10.0/100.0))
|
|
283
|
+
|
|
284
|
+
def zoom_reset(self):
|
|
285
|
+
# resets zoom
|
|
286
|
+
self.scaleImage(1.0)
|
|
287
|
+
|
|
288
|
+
# pb this is redundant with the main GUI and not in sync --> can cause a lot of trouble --> dactivate for now
|
|
289
|
+
def full_screen(self):
|
|
290
|
+
if not self.isFullScreen():
|
|
291
|
+
self.fullscreen.setIcon(qta.icon('mdi.fullscreen-exit'))
|
|
292
|
+
self.fullscreen.setToolTip('Exit full screen')
|
|
293
|
+
self.showFullScreen()
|
|
294
|
+
# self.setWindowFlags(
|
|
295
|
+
# QtCore.Qt.Window |
|
|
296
|
+
# QtCore.Qt.CustomizeWindowHint |
|
|
297
|
+
# # QtCore.Qt.WindowTitleHint |
|
|
298
|
+
# # QtCore.Qt.WindowCloseButtonHint |
|
|
299
|
+
# QtCore.Qt.WindowStaysOnTopHint
|
|
300
|
+
# )
|
|
301
|
+
else:
|
|
302
|
+
# settings = QSettings()
|
|
303
|
+
# self.Stack.restoreGeometry(settings.value("geometry")) #.toByteArray()
|
|
304
|
+
self.fullscreen.setIcon(qta.icon('mdi.fullscreen'))
|
|
305
|
+
self.fullscreen.setToolTip('Enter full screen')
|
|
306
|
+
self.setWindowFlags(QtCore.Qt.Widget)
|
|
307
|
+
# # self.Stack.setWindowFlags(self.flags)
|
|
308
|
+
# self.grid.addWidget(self.Stack, 0,
|
|
309
|
+
# 0) # pas trop mal mais j'arrive pas à le remettre dans le truc principal
|
|
310
|
+
# # dirty hack to make it repaint properly --> obviously not all lines below are required but some are --> need test, the last line is key though
|
|
311
|
+
# self.grid.update()
|
|
312
|
+
# self.Stack.update()
|
|
313
|
+
# self.Stack.show()
|
|
314
|
+
# self.centralWidget().setLayout(self.grid)
|
|
315
|
+
# self.centralWidget().update()
|
|
316
|
+
# self.update()
|
|
317
|
+
self.show()
|
|
318
|
+
self.repaint()
|
|
319
|
+
# self.Stack.update()
|
|
320
|
+
# self.Stack.repaint()
|
|
321
|
+
# self.centralWidget().repaint()
|
|
322
|
+
|
|
323
|
+
def scaleImage(self, scale):
|
|
324
|
+
self.paint.set_scale(scale)
|
|
325
|
+
if self.paint.image is not None:
|
|
326
|
+
self.paint.resize(self.paint.scale * self.paint.image.size())
|
|
327
|
+
else:
|
|
328
|
+
self.paint.resize(QSize(0, 0))
|
|
329
|
+
self.paint.update()
|
|
330
|
+
|
|
331
|
+
# can maybe add pen stuff here --> simpler and easier
|
|
332
|
+
# need zoom buttons here too
|
|
333
|
+
'''
|
|
334
|
+
buttons/icons to add at some point
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
"Cell smaller than this value will be destroyed"
|
|
338
|
+
"small_cell_remover"
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
"/Icons/refresh.png"
|
|
342
|
+
"run 2 seeds watershed (click twice in a poorly segmented cell to have a the bond be created using the watershed algorithm)"
|
|
343
|
+
|
|
344
|
+
"/Icons/Knob Snapback.png"
|
|
345
|
+
"Undo"
|
|
346
|
+
|
|
347
|
+
"/Icons/Knob Valid Blue.png"
|
|
348
|
+
"remove small cells and apply correction"
|
|
349
|
+
|
|
350
|
+
"/Icons/Knob Valid Green.png"
|
|
351
|
+
"apply correction"
|
|
352
|
+
|
|
353
|
+
"/Icons/channels.png"
|
|
354
|
+
"Channel Selection"
|
|
355
|
+
"Channel to use for Watershed, polarity, recentering,...")
|
|
356
|
+
|
|
357
|
+
"/Icons/onebit_11.png"
|
|
358
|
+
"Save"
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
"/Icons/eye.png"
|
|
362
|
+
"View below the mask (lasts 2s)"
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
"/Icons/zoom in.png"
|
|
366
|
+
"Zoom +"
|
|
367
|
+
|
|
368
|
+
"/Icons/zoom out.png"
|
|
369
|
+
"Zoom -"
|
|
370
|
+
|
|
371
|
+
"/Icons/1in1.png"
|
|
372
|
+
"1:1 aspect ratio"
|
|
373
|
+
|
|
374
|
+
"/Icons/fit_2_screen.gif"
|
|
375
|
+
"Fit to panel"
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
"/Icons/double_diagonal_arrow.gif"
|
|
379
|
+
"Alternate between best fit in height or in width"
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
"/Icons/Import Picture Document.png"
|
|
383
|
+
"Send Current View To The System Clipboard"
|
|
384
|
+
|
|
385
|
+
"/Icons/pipet_small.png"
|
|
386
|
+
"Color pipet"
|
|
387
|
+
|
|
388
|
+
"Mask col"
|
|
389
|
+
"mask color"
|
|
390
|
+
|
|
391
|
+
"Correct Drift"
|
|
392
|
+
|
|
393
|
+
'''
|
|
394
|
+
|
|
395
|
+
# add shortcut for show hide mask and maybe also full screen --> not a good idea
|
|
396
|
+
|
|
397
|
+
def drawing_commands(self):
|
|
398
|
+
self.penSize = QSpinBox(objectName='penSize')
|
|
399
|
+
self.penSize.setToolTip('Change this value to change pen size')
|
|
400
|
+
self.penSize.setSingleStep(1)
|
|
401
|
+
self.penSize.setRange(1, 256)
|
|
402
|
+
self.penSize.setValue(3)
|
|
403
|
+
self.penSize.valueChanged.connect(self.penSizechange)
|
|
404
|
+
|
|
405
|
+
self.channels = QComboBox(objectName='channels')
|
|
406
|
+
self.channels.setToolTip('Select the channel of interest')
|
|
407
|
+
self.channels.addItem("merge")
|
|
408
|
+
# self.channels.addItem("0")
|
|
409
|
+
# self.channels.addItems(["1", "2", "3"])
|
|
410
|
+
self.channels.currentIndexChanged.connect(self.channelChange)
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
hlayout_of_toolbars = QHBoxLayout()
|
|
414
|
+
hlayout_of_toolbars.setAlignment(Qt.AlignLeft)
|
|
415
|
+
self.tb1 = QToolBar()
|
|
416
|
+
self.tb2 = QToolBar()
|
|
417
|
+
self.tb3 = QToolBar()
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
pencil_action = QAction(qta.icon('ei.pencil'), 'Pen Size', self)
|
|
421
|
+
pencil_action.setEnabled(False)
|
|
422
|
+
self.tb2.addAction(pencil_action)
|
|
423
|
+
# tb.addAction("sq...")
|
|
424
|
+
self.tb2.addWidget(self.penSize)
|
|
425
|
+
|
|
426
|
+
# toolButton = QToolButton()
|
|
427
|
+
# toolButton.setText("Draw")
|
|
428
|
+
# toolButton.setIcon(self.style().standardIcon(QStyle.SP_DriveFDIcon))
|
|
429
|
+
# tb.addWidget(toolButton)
|
|
430
|
+
|
|
431
|
+
# fa5.save
|
|
432
|
+
save_action = QAction(qta.icon('fa5.save'), 'Save mask', self)
|
|
433
|
+
save_action.triggered.connect(self.paint.save)
|
|
434
|
+
self.tb2.addAction(save_action)
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
# toolButton2 = QToolButton()
|
|
438
|
+
# toolButton2.setText("Draw")
|
|
439
|
+
# toolButton2.setIcon(self.style().standardIcon(QStyle.SP_DialogApplyButton))
|
|
440
|
+
# tb.addWidget(toolButton2)
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
show_hide_mask =QAction(qta.icon('fa.bullseye'), 'Show/hide mask (same as pressing "M")', self)
|
|
444
|
+
show_hide_mask.triggered.connect(self.paint.m_apply)
|
|
445
|
+
self.tb2.addAction(show_hide_mask)
|
|
446
|
+
|
|
447
|
+
apply_drawing = QAction(qta.icon('fa.check'), 'Apply drawing (same as pressing the "Enter" key)', self)
|
|
448
|
+
apply_drawing.triggered.connect(self.paint.apply)
|
|
449
|
+
self.tb2.addAction(apply_drawing)
|
|
450
|
+
|
|
451
|
+
# toolButton3 = QToolButton()
|
|
452
|
+
# toolButton3.setText("Draw")
|
|
453
|
+
# toolButton3.setIcon(self.style().standardIcon(QStyle.SP_DialogCancelButton))
|
|
454
|
+
# tb.addWidget(toolButton3)
|
|
455
|
+
|
|
456
|
+
# toolButton4 = QToolButton()
|
|
457
|
+
# toolButton4.setText("Draw")
|
|
458
|
+
# toolButton4.setIcon(self.style().standardIcon(QStyle.SP_DialogCloseButton))
|
|
459
|
+
# tb.addWidget(toolButton4)
|
|
460
|
+
|
|
461
|
+
# toolButton5 = QToolButton()
|
|
462
|
+
# toolButton5.setText("Draw")
|
|
463
|
+
# toolButton5.setIcon(self.style().standardIcon(QStyle.SP_TrashIcon))
|
|
464
|
+
# tb.addWidget(toolButton5)
|
|
465
|
+
|
|
466
|
+
# toolButton6 = QToolButton()
|
|
467
|
+
# toolButton6.setText("Draw")
|
|
468
|
+
# toolButton6.setIcon(self.style().standardIcon(QStyle.SP_ArrowBack))
|
|
469
|
+
# tb.addWidget(toolButton6)
|
|
470
|
+
|
|
471
|
+
# toolButton7 = QToolButton()
|
|
472
|
+
# toolButton7.setText("Draw")
|
|
473
|
+
# toolButton7.setIcon(self.style().standardIcon(QStyle.SP_BrowserReload))
|
|
474
|
+
# tb.addWidget(toolButton7)
|
|
475
|
+
|
|
476
|
+
self.small_cell_size = QSpinBox()
|
|
477
|
+
self.small_cell_size.setToolTip('Select the minimal pixel area for a cell to be considered as a cell.\nAny cell having an area less than this value will be removed.')
|
|
478
|
+
self.small_cell_size.setSingleStep(1)
|
|
479
|
+
self.small_cell_size.setRange(1, 1000000)
|
|
480
|
+
self.small_cell_size.setValue(10)
|
|
481
|
+
self.small_cell_size.valueChanged.connect(self.small_cell_size_changed)
|
|
482
|
+
|
|
483
|
+
self.tb2.addWidget(self.small_cell_size)
|
|
484
|
+
apply_rm_small_cells = QAction(qta.icon('mdi.check-underline'), 'Apply drawing and remove small cells (same as pressing "Shift+Enter")', self)
|
|
485
|
+
apply_rm_small_cells.triggered.connect(self.paint.shift_apply)# self.paint.shift_apply
|
|
486
|
+
self.tb2.addAction(apply_rm_small_cells)
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
# marche pas --> comment faire pr que ça marche...
|
|
493
|
+
local_reshed = QAction(qta.icon('mdi.reload'), 'Locally seeded watershed (same as pressing "Ctrl/Cmd + M")', self)
|
|
494
|
+
local_reshed.triggered.connect(self.paint.ctrl_m_apply)# self.paint.shift_apply
|
|
495
|
+
self.tb2.addAction(local_reshed)
|
|
496
|
+
# hgjhghj
|
|
497
|
+
|
|
498
|
+
# toolButton8 = QToolButton()
|
|
499
|
+
# toolButton8.setText("Zoom+")
|
|
500
|
+
# toolButton8.setIcon(qta.icon('ei.zoom-in')) # mdi.magnify-plus-outline --> marche aussi
|
|
501
|
+
# tb.addWidget(toolButton8)
|
|
502
|
+
|
|
503
|
+
# toolButton9 = QToolButton()
|
|
504
|
+
# toolButton9.setText("Zoom-")
|
|
505
|
+
# toolButton9.setIcon(qta.icon('ei.zoom-out'))
|
|
506
|
+
# tb.addWidget(toolButton9)
|
|
507
|
+
|
|
508
|
+
zoom_plus = QAction(qta.icon('ei.zoom-in'), 'Zoom+', self)
|
|
509
|
+
zoom_plus.triggered.connect(self.zoomIn)
|
|
510
|
+
self.tb1.addAction(zoom_plus)
|
|
511
|
+
|
|
512
|
+
zoom_minus = QAction(qta.icon('ei.zoom-out'), 'Zoom-', self)
|
|
513
|
+
zoom_minus.triggered.connect(self.zoomOut)
|
|
514
|
+
self.tb1.addAction(zoom_minus)
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
zoom_width_or_height = QAction(qta.icon('mdi.fit-to-page-outline'), 'Alternates between best fit in width and height', self)
|
|
518
|
+
zoom_width_or_height.triggered.connect(self.fit_to_width_or_height)
|
|
519
|
+
self.tb1.addAction(zoom_width_or_height)
|
|
520
|
+
|
|
521
|
+
zoom_0 = QAction(qta.icon('ei.resize-full'), 'Reset zoom', self)
|
|
522
|
+
zoom_0.triggered.connect(self.zoom_reset)
|
|
523
|
+
self.tb1.addAction(zoom_0)
|
|
524
|
+
|
|
525
|
+
# redundant with TA full screen and not in sync --> disable for now
|
|
526
|
+
# self.fullscreen = QtWidgets.QAction(qta.icon('mdi.fullscreen'), 'Full screen', self)
|
|
527
|
+
# self.fullscreen.setToolTip('Enter full screen')
|
|
528
|
+
# self.fullscreen.triggered.connect(self.full_screen)
|
|
529
|
+
# self.tb1.addAction(self.fullscreen)
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
# exit_fullscreen = QtWidgets.QAction(qta.icon('mdi.fullscreen'), 'Full screen', self)
|
|
535
|
+
# exit_fullscreen.triggered.connect(self.showFullScreen)
|
|
536
|
+
# self.tb1.addAction(fullscreen)
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
self.channel_label = QLabel('Channels:')
|
|
541
|
+
self.channel_label.setToolTip('Select the channel of interest')
|
|
542
|
+
self.tb3.addWidget(self.channel_label)
|
|
543
|
+
self.tb3.addWidget(self.channels)
|
|
544
|
+
|
|
545
|
+
# mdi.fullscreen
|
|
546
|
+
# mdi.fullscreen-exit
|
|
547
|
+
# ei.fullscreen --> a bit less good I find
|
|
548
|
+
# fa.bullseye
|
|
549
|
+
|
|
550
|
+
# could have show and hide mask here --> see how I can do that --> but do not delete it in fact
|
|
551
|
+
|
|
552
|
+
# self.layout().addWidget(self.tb1)
|
|
553
|
+
hlayout_of_toolbars.addWidget(self.tb2)
|
|
554
|
+
|
|
555
|
+
|
|
556
|
+
# self.tb2.addAction('toto')
|
|
557
|
+
# self.tb2.addAction('ttutu')
|
|
558
|
+
# self.tb2.addAction('tata')
|
|
559
|
+
hlayout_of_toolbars.addWidget(self.tb3)
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
# one for the zooms
|
|
563
|
+
# one for drawing and apply different things
|
|
564
|
+
# TODO do several toolbars to deactivate different levels of stuff
|
|
565
|
+
# and only allow save in the appropriate stuff
|
|
566
|
+
|
|
567
|
+
# self.tb3.addAction('toto')
|
|
568
|
+
# self.tb3.addAction('ttutu')
|
|
569
|
+
# self.tb3.addAction('tata')
|
|
570
|
+
hlayout_of_toolbars.addWidget(self.tb1)
|
|
571
|
+
|
|
572
|
+
self.layout().addLayout(hlayout_of_toolbars)
|
|
573
|
+
|
|
574
|
+
def get_selected_channel(self):
|
|
575
|
+
idx = self.channels.currentIndex()
|
|
576
|
+
if idx == 0:
|
|
577
|
+
return None
|
|
578
|
+
else:
|
|
579
|
+
return idx-1
|
|
580
|
+
|
|
581
|
+
# TODO also implement channel change directly within the display tool
|
|
582
|
+
# if merge is applied --> apply on average of all channels --> maybe not so smart an idea but ok to start with and better than what I do in TA
|
|
583
|
+
def channelChange(self, i):
|
|
584
|
+
# update displayed image depending on channel
|
|
585
|
+
# dqqsdqsdqsd
|
|
586
|
+
# pass
|
|
587
|
+
# try change channel if
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
# tODO --> need at least to reactivate a bit that
|
|
591
|
+
# pass
|
|
592
|
+
# print('in channel change') # needs a fix
|
|
593
|
+
meta = None
|
|
594
|
+
try:
|
|
595
|
+
meta = self.paint.raw_image.metadata
|
|
596
|
+
except:
|
|
597
|
+
pass
|
|
598
|
+
self.paint.set_display(self.get_image_to_display_including_all_dims(), metadata=meta)
|
|
599
|
+
self.paint.channelChange(i, skip_update_display=True)
|
|
600
|
+
|
|
601
|
+
# print('in channel change !!!')
|
|
602
|
+
# if self.img is not None:
|
|
603
|
+
# # print('in', self.img.metadata)
|
|
604
|
+
# if self.Stack.currentIndex() == 0:
|
|
605
|
+
# # need copy the image --> implement that
|
|
606
|
+
# # print(self.img[..., i].copy())
|
|
607
|
+
# # print(self.img[..., i])
|
|
608
|
+
# if i == 0:
|
|
609
|
+
# self.paint.setImage(self.img)
|
|
610
|
+
# # print('original', self.img.metadata)
|
|
611
|
+
# else:
|
|
612
|
+
# # print('modified0', self.img.metadata)
|
|
613
|
+
# channel_img = self.img.imCopy(c=i - 1) # it's here that it is affected
|
|
614
|
+
# # print('modified1', self.img.metadata)
|
|
615
|
+
# # print('modified2', channel_img.metadata)
|
|
616
|
+
# self.paint.setImage(channel_img)
|
|
617
|
+
# self.paint.update()
|
|
618
|
+
# else:
|
|
619
|
+
# # logger.error("Not implemented yet TODO add support for channels in 3D viewer")
|
|
620
|
+
# # sdqdqsdsqdqsd
|
|
621
|
+
# self.loadVolume()
|
|
622
|
+
# or reimplement that for multi channels !!!
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
# TODO maybe handle pen size change directly within the display --> can be useful by the way
|
|
627
|
+
def small_cell_size_changed(self):
|
|
628
|
+
self.paint.minimal_cell_size = self.small_cell_size.value()
|
|
629
|
+
|
|
630
|
+
# TODO maybe handle pen size change directly within the display --> can be useful by the way
|
|
631
|
+
def penSizechange(self):
|
|
632
|
+
self.paint.brushSize = self.penSize.value()
|
|
633
|
+
# self.update() # too slow if I update --> avoid
|
|
634
|
+
# self.l1.setFont(QFont("Arial", size))
|
|
635
|
+
|
|
636
|
+
def set_image(self, img):
|
|
637
|
+
# probably I need store raw image to avoid issues --> TODO ???
|
|
638
|
+
self.paint.set_image(img)# bug seems to be here
|
|
639
|
+
|
|
640
|
+
img = self.paint.raw_image
|
|
641
|
+
|
|
642
|
+
self.update_image_dimensions()
|
|
643
|
+
|
|
644
|
+
# need also update the dimensions if any
|
|
645
|
+
|
|
646
|
+
# print(type(img))
|
|
647
|
+
|
|
648
|
+
# else I need also reset channels
|
|
649
|
+
|
|
650
|
+
# if img is not None:
|
|
651
|
+
# if img.has_c():
|
|
652
|
+
self._update_channels(img=img)
|
|
653
|
+
# print('out')
|
|
654
|
+
# channels = self.paint.get_nb_channels()
|
|
655
|
+
# self._update_channels(channels)
|
|
656
|
+
# make it update also the channels
|
|
657
|
+
def _delete_layout_content(self, layout):
|
|
658
|
+
for i in reversed(range(layout.count())):
|
|
659
|
+
layout.itemAt(i).widget().setParent(None)
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
# centralized version of the thing
|
|
664
|
+
def get_image_to_display_including_all_dims(self):
|
|
665
|
+
# print('in get_image_to_display_including_all_dims')
|
|
666
|
+
# returns the image to be displayed --> takes into account all the dimensions at once
|
|
667
|
+
|
|
668
|
+
#
|
|
669
|
+
# if self.raw_image is not None:
|
|
670
|
+
# if i == 0:
|
|
671
|
+
# self.set_display(self.raw_image)
|
|
672
|
+
# self.channel = None
|
|
673
|
+
# # print('original', self.img.metadata)
|
|
674
|
+
# else:
|
|
675
|
+
# # print('modified0', self.img.metadata)
|
|
676
|
+
# # I need a hack when the image is single channel yet I need several masks for it !!!
|
|
677
|
+
# if self.multichannel_mode and i - 1 >= self.raw_image.shape[-1]:
|
|
678
|
+
# channel_img = self.raw_image.imCopy(c=0) # if out of bonds load the first channel
|
|
679
|
+
# else:
|
|
680
|
+
# channel_img = self.raw_image.imCopy(c=i - 1) # it's here that it is affected
|
|
681
|
+
# self.channel = i - 1
|
|
682
|
+
# # print('modified1', self.img.metadata)
|
|
683
|
+
# # print('modified2', channel_img.metadata)
|
|
684
|
+
# self.set_display(
|
|
685
|
+
# channel_img) # maybe do a set display instead rather --> easier to handle --> does a subest of the other
|
|
686
|
+
image_to_display = None
|
|
687
|
+
try:
|
|
688
|
+
# need change just the displayed image
|
|
689
|
+
if has_metadata(self.paint.raw_image) and self.paint.raw_image.metadata['dimensions']:
|
|
690
|
+
# change the respective dim
|
|
691
|
+
# need all the spinner values to be recovered in fact
|
|
692
|
+
# and send the stuff
|
|
693
|
+
# print('dimension exists', self.objectName(),'--> changing it')
|
|
694
|
+
|
|
695
|
+
# need gather all the dimensions --> TODO
|
|
696
|
+
dimensions = self.paint.raw_image.metadata['dimensions']
|
|
697
|
+
position_h = dimensions.index('h')
|
|
698
|
+
image_to_display = self.paint.raw_image
|
|
699
|
+
if position_h != 0:
|
|
700
|
+
# loop for all the dimensions before
|
|
701
|
+
# print('changing stuff')
|
|
702
|
+
for pos_dim in range(0, position_h):
|
|
703
|
+
dim = dimensions[pos_dim]
|
|
704
|
+
value_to_set = self.get_dim_value_by_name(dim)
|
|
705
|
+
if value_to_set == None:
|
|
706
|
+
continue
|
|
707
|
+
else:
|
|
708
|
+
image_to_display = image_to_display[value_to_set]
|
|
709
|
+
# if not dimensions[pos_dim]==self.sender().objectName():
|
|
710
|
+
# image_to_display = image_to_display[0]
|
|
711
|
+
# else:
|
|
712
|
+
# image_to_display = image_to_display[self.sender().value()]
|
|
713
|
+
# self.paint.set_display(image_to_display)
|
|
714
|
+
channel_to_display = self.get_selected_channel()
|
|
715
|
+
|
|
716
|
+
# if force dimensions --> I need a hack even if
|
|
717
|
+
# hack for GT image editor --> where nb of channels are forced and do not necessarily match the channels of the image --> is that smart to put that here ???
|
|
718
|
+
if channel_to_display is not None and 'c' in dimensions:
|
|
719
|
+
if self.paint.multichannel_mode and channel_to_display >= self.paint.raw_image.shape[-1]:
|
|
720
|
+
image_to_display = image_to_display[..., 0]
|
|
721
|
+
else:
|
|
722
|
+
image_to_display=image_to_display[...,channel_to_display]
|
|
723
|
+
# print(image_to_display.shape)
|
|
724
|
+
except:
|
|
725
|
+
traceback.print_exc()
|
|
726
|
+
return image_to_display
|
|
727
|
+
|
|
728
|
+
def update_image_dimensions(self):
|
|
729
|
+
self.dimension_sliders = []
|
|
730
|
+
|
|
731
|
+
for i in reversed(range(self.dimensions_container.count())):
|
|
732
|
+
# print(i)
|
|
733
|
+
# print(self.dimensions_container.itemAt(i))
|
|
734
|
+
# self.dimensions_container.itemAt(i).widget().setParent(None)
|
|
735
|
+
self._delete_layout_content(self.dimensions_container.itemAt(i))
|
|
736
|
+
|
|
737
|
+
if self.paint.raw_image is None:
|
|
738
|
+
return
|
|
739
|
+
|
|
740
|
+
# empty the content of the slider and refill it
|
|
741
|
+
try:
|
|
742
|
+
treat_channels_as_a_browsable_dimension = False
|
|
743
|
+
if has_metadata(self.paint.raw_image):
|
|
744
|
+
dimensions = self.paint.raw_image.get_dimensions_as_string()
|
|
745
|
+
|
|
746
|
+
# if not self.paint.raw_image.has_c():
|
|
747
|
+
# nb_of_sliders = len(
|
|
748
|
+
# self.paint.raw_image.shape) - 2 # or -3 it depends whether I wanna show all the channels at once or not ???
|
|
749
|
+
# else:
|
|
750
|
+
# nb_of_sliders = len(
|
|
751
|
+
# self.paint.raw_image.shape) - 2 # or -3 it depends whether I wanna show all the channels at once or not ???
|
|
752
|
+
|
|
753
|
+
# print(nb_of_sliders)
|
|
754
|
+
|
|
755
|
+
# create an image with plenty of sliders --> TODO
|
|
756
|
+
# make the handling of the image to be displayed directly by the code !!!
|
|
757
|
+
|
|
758
|
+
# then I need couple each slider to a dimension
|
|
759
|
+
|
|
760
|
+
# dimensions that must have a slider
|
|
761
|
+
# --> all dimensions but hw and maybe c must have a slider --> TODO
|
|
762
|
+
for dim in dimensions:
|
|
763
|
+
if dim == 'h' or dim == 'y' or dim == 'w' or dim == 'x' or (
|
|
764
|
+
not treat_channels_as_a_browsable_dimension and dim == 'c'):
|
|
765
|
+
# we skip dimensions
|
|
766
|
+
continue
|
|
767
|
+
# print(dim, 'must have an assoicated slider')
|
|
768
|
+
|
|
769
|
+
# print(self.paint.raw_image.shape, ' toto ', )
|
|
770
|
+
self.dimensions_container.addLayout(self.create_dim_slider(dimension=dim, max_dim=self.paint.raw_image.shape[dimensions.index(dim)]))
|
|
771
|
+
except:
|
|
772
|
+
traceback.print_exc()
|
|
773
|
+
|
|
774
|
+
def set_mask(self, mask):
|
|
775
|
+
self.paint.set_mask(mask)
|
|
776
|
+
|
|
777
|
+
def _update_channels(self, img):
|
|
778
|
+
selection = self.channels.currentIndex()
|
|
779
|
+
self.channels.disconnect()
|
|
780
|
+
self.channels.clear()
|
|
781
|
+
comboData = ['merge']
|
|
782
|
+
if img is not None:
|
|
783
|
+
try:
|
|
784
|
+
if img.has_c():
|
|
785
|
+
for i in range(img.get_dimension('c')):
|
|
786
|
+
comboData.append(str(i))
|
|
787
|
+
except:
|
|
788
|
+
# assume image has no channel and return None
|
|
789
|
+
# or assume last stuff is channel if image has more than 2
|
|
790
|
+
pass
|
|
791
|
+
# logger.debug('channels found ' + str(comboData))
|
|
792
|
+
self.channels.addItems(comboData)
|
|
793
|
+
# index = self.channels.findData(selection)
|
|
794
|
+
|
|
795
|
+
self.channels.currentIndexChanged.connect(self.channelChange)
|
|
796
|
+
# print("data", index)
|
|
797
|
+
if selection != -1 and selection < self.channels.count():
|
|
798
|
+
self.channels.setCurrentIndex(selection)
|
|
799
|
+
# self.channelChange(selection)
|
|
800
|
+
else:
|
|
801
|
+
self.channels.setCurrentIndex(0)
|
|
802
|
+
# self.channelChange(0)
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
def freeze(self, bool, level=1):
|
|
806
|
+
|
|
807
|
+
self.tb1.setEnabled(True)
|
|
808
|
+
self.tb2.setEnabled(True)
|
|
809
|
+
self.tb3.setEnabled(True)
|
|
810
|
+
|
|
811
|
+
if level == 1:
|
|
812
|
+
self.tb2.setEnabled(not bool)
|
|
813
|
+
elif level == 2:
|
|
814
|
+
self.tb2.setEnabled(not bool)
|
|
815
|
+
self.tb3.setEnabled(not bool)
|
|
816
|
+
|
|
817
|
+
if bool:
|
|
818
|
+
self.disable_shortcuts()
|
|
819
|
+
else:
|
|
820
|
+
self.enable_shortcuts()
|
|
821
|
+
# remove draw mode maybe and freeze shortcuts
|
|
822
|
+
|
|
823
|
+
def create_dim_slider(self, dimension=None, max_dim=1):
|
|
824
|
+
dim_slider_with_label1 = QHBoxLayout()
|
|
825
|
+
label_slider1 = QLabel()
|
|
826
|
+
if dimension is not None:
|
|
827
|
+
label_slider1.setText(dimension)
|
|
828
|
+
fake_dim_slider = QSlider(Qt.Horizontal)
|
|
829
|
+
fake_dim_slider.setMinimum(0)
|
|
830
|
+
fake_dim_slider.setMaximum(max_dim-1)
|
|
831
|
+
dim_slider_with_label1.addWidget(label_slider1)
|
|
832
|
+
dim_slider_with_label1.addWidget(fake_dim_slider)
|
|
833
|
+
# dim_slider_with_label1
|
|
834
|
+
# add a partial?
|
|
835
|
+
fake_dim_slider.valueChanged.connect(self.slider_dimension_value_changed)
|
|
836
|
+
# fake_dim_slider.valueChanged.connect(lambda x: self.delayed_dimension_preview.start(600))
|
|
837
|
+
fake_dim_slider.setObjectName(dimension)
|
|
838
|
+
self.dimension_sliders.append(fake_dim_slider)
|
|
839
|
+
return dim_slider_with_label1
|
|
840
|
+
|
|
841
|
+
def get_dim_value_by_name(self, label):
|
|
842
|
+
for slider in self.dimension_sliders:
|
|
843
|
+
if slider.objectName() == label:
|
|
844
|
+
return slider.value()
|
|
845
|
+
return None
|
|
846
|
+
|
|
847
|
+
# def get_dims_value_by_name(self, label):
|
|
848
|
+
# for slider in self.dimension_sliders:
|
|
849
|
+
# if slider.objectName() == label:
|
|
850
|
+
# return slider.value()
|
|
851
|
+
# return None
|
|
852
|
+
|
|
853
|
+
# p
|
|
854
|
+
def slider_dimension_value_changed(self):
|
|
855
|
+
# TODO --> do delay only if necessary
|
|
856
|
+
# self.delayed_dimension_preview.stop()
|
|
857
|
+
# self.delayed_dimension_preview.start(600)
|
|
858
|
+
|
|
859
|
+
# self.delayed_dimension_preview.timeout.connect
|
|
860
|
+
|
|
861
|
+
# if self.delayed_dimension_preview.dis
|
|
862
|
+
|
|
863
|
+
# TODO only allow this when the dimension changing is over
|
|
864
|
+
# if the dimension exists --> print it
|
|
865
|
+
# print(self.sender(), self.sender().objectName(), self.sender().value())
|
|
866
|
+
# print(self.sender(), self.sender().objectName())
|
|
867
|
+
# print(sender)
|
|
868
|
+
#
|
|
869
|
+
# try:
|
|
870
|
+
# # need change just the displayed image
|
|
871
|
+
# if self.paint.raw_image.metadata['dimensions']:
|
|
872
|
+
# # change the respective dim
|
|
873
|
+
# # need all the spinner values to be recovered in fact
|
|
874
|
+
# # and send the stuff
|
|
875
|
+
# # print('dimension exists', self.objectName(),'--> changing it')
|
|
876
|
+
#
|
|
877
|
+
# # need gather all the dimensions --> TODO
|
|
878
|
+
# dimensions = self.paint.raw_image.metadata['dimensions']
|
|
879
|
+
# position_h = dimensions.index('h')
|
|
880
|
+
# image_to_display = self.paint.raw_image
|
|
881
|
+
# if position_h!=0:
|
|
882
|
+
# # loop for all the dimensions before
|
|
883
|
+
# # print('changing stuff')
|
|
884
|
+
# for pos_dim in range(0,position_h):
|
|
885
|
+
# dim = dimensions[pos_dim]
|
|
886
|
+
# value_to_set = self.get_dim_value_by_name(dim)
|
|
887
|
+
# if value_to_set == None:
|
|
888
|
+
# continue
|
|
889
|
+
# else:
|
|
890
|
+
# image_to_display = image_to_display[value_to_set]
|
|
891
|
+
# # if not dimensions[pos_dim]==self.sender().objectName():
|
|
892
|
+
# # image_to_display = image_to_display[0]
|
|
893
|
+
# # else:
|
|
894
|
+
# # image_to_display = image_to_display[self.sender().value()]
|
|
895
|
+
# self.paint.set_display(image_to_display)
|
|
896
|
+
# except:
|
|
897
|
+
# traceback.print_exc()
|
|
898
|
+
|
|
899
|
+
try:
|
|
900
|
+
meta = None
|
|
901
|
+
try:
|
|
902
|
+
meta = self.paint.raw_image.metadata
|
|
903
|
+
except:
|
|
904
|
+
pass
|
|
905
|
+
# metadata is required to get the luts properly
|
|
906
|
+
self.paint.set_display(self.get_image_to_display_including_all_dims(), metadata=meta)
|
|
907
|
+
except:
|
|
908
|
+
traceback.print_exc()
|
|
909
|
+
|
|
910
|
+
# pass
|
|
911
|
+
|
|
912
|
+
# then have a single code to handle dynamically all the dimension changes !!! --> TODO
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
# pas mal faut juste voir ce que je peux faire
|
|
916
|
+
# peut etre permetre de mettre des custom panels
|
|
917
|
+
|
|
918
|
+
if __name__ == '__main__':
|
|
919
|
+
import sys
|
|
920
|
+
from qtpy.QtWidgets import QApplication
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
# hand drawing panel
|
|
924
|
+
if False:
|
|
925
|
+
|
|
926
|
+
# TODO add a main method so it can be called directly
|
|
927
|
+
# maybe just show a canvas and give it interesting props --> TODO --> really need fix that too!!!
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
# should probably have his own scroll bar embedded somewhere
|
|
931
|
+
|
|
932
|
+
app = QApplication(sys.argv)
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
# quite easy todo in fact
|
|
936
|
+
|
|
937
|
+
# no clue why it always works just once
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
# maybe make a scrollable TA paint that will handle and behave like that
|
|
941
|
+
# maybe handle also stacks at some point ---> see how
|
|
942
|
+
# --> almost all is ok now
|
|
943
|
+
class overriding_apply(Createpaintwidget):
|
|
944
|
+
# all seems ok now and functions as in TA
|
|
945
|
+
# just do the shift enter to get rid of small cells
|
|
946
|
+
|
|
947
|
+
# avec ça ça marche 100% à la TA ... --> cool --> maybe make it a TA drawing pad
|
|
948
|
+
def apply(self):
|
|
949
|
+
self.apply_drawing(minimal_cell_size=0)
|
|
950
|
+
|
|
951
|
+
def shift_apply(self):
|
|
952
|
+
# MEGA TODO IMPLEMENT SIZE within this stuff!!!
|
|
953
|
+
self.apply_drawing(minimal_cell_size=10)
|
|
954
|
+
|
|
955
|
+
def ctrl_m_apply(self):
|
|
956
|
+
self.manually_reseeded_wshed()
|
|
957
|
+
|
|
958
|
+
def save(self):
|
|
959
|
+
self.save_mask()
|
|
960
|
+
|
|
961
|
+
w = scrollable_paint(
|
|
962
|
+
custom_paint_panel=overriding_apply()) # ça marche --> permet de mettre des paint panels avec des proprietes particulieres --> assez facile en fait
|
|
963
|
+
# w.set_image('/E/Sample_images/sample_images_PA/mini (copie)/focused_Series012.png')
|
|
964
|
+
# w.set_mask('/E/Sample_images/sample_images_PA/mini (copie)/focused_Series012/handCorrection.png')
|
|
965
|
+
# w.set_image('/E/Sample_images/sample_images_PA/test_complete_wing_raphael/Optimized_projection_018.png')
|
|
966
|
+
# w.set_mask('/E/Sample_images/sample_images_PA/test_complete_wing_raphael/neo_mask.tif')
|
|
967
|
+
|
|
968
|
+
w.set_image('/D/VirtualBox/book_chapter_image_segmentation_final_2021/new_figs/dataset_1/minimal_demo_sample_simplified_bckup_before_messing_with_two_seg_errors/1.tif')
|
|
969
|
+
w.set_mask('/D/VirtualBox/book_chapter_image_segmentation_final_2021/new_figs/dataset_1/minimal_demo_sample_simplified_bckup_before_messing_with_two_seg_errors/1/handCorrection.tif')
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
# ça marche mais tt finalizer
|
|
973
|
+
# that seems to work
|
|
974
|
+
|
|
975
|
+
# w.freeze(True)
|
|
976
|
+
# w.freeze(False)
|
|
977
|
+
# w.freeze(True)
|
|
978
|
+
|
|
979
|
+
# all is so easy to do this way
|
|
980
|
+
|
|
981
|
+
# ça marche --> tres facile a tester
|
|
982
|
+
# --> how can I do a zoom
|
|
983
|
+
# ask whether self scroll or not --> if scrollable
|
|
984
|
+
|
|
985
|
+
# mask = w.get_mask()
|
|
986
|
+
#
|
|
987
|
+
# plt.imshow(mask)
|
|
988
|
+
# plt.show()
|
|
989
|
+
|
|
990
|
+
w.show()
|
|
991
|
+
sys.exit(app.exec_())
|
|
992
|
+
|
|
993
|
+
# vectorial panel for drawing ROIs --> that works --> keep this code cause very useful and many bug fix
|
|
994
|
+
# TODO try convert any ROIs to something like a contour using the pavlidis algo --> put this in rps tools
|
|
995
|
+
|
|
996
|
+
if True:
|
|
997
|
+
# TODO add a main method so it can be called directly
|
|
998
|
+
# maybe just show a canvas and give it interesting props --> TODO --> really need fix that too!!!
|
|
999
|
+
|
|
1000
|
+
# should probably have his own scroll bar embedded somewhere
|
|
1001
|
+
|
|
1002
|
+
app = QApplication(sys.argv)
|
|
1003
|
+
|
|
1004
|
+
|
|
1005
|
+
# quite easy todo in fact
|
|
1006
|
+
|
|
1007
|
+
# no clue why it always works just once
|
|
1008
|
+
|
|
1009
|
+
# maybe make a scrollable TA paint that will handle and behave like that
|
|
1010
|
+
# maybe handle also stacks at some point ---> see how
|
|
1011
|
+
# --> almost all is ok now
|
|
1012
|
+
class overriding_apply(Createpaintwidget):
|
|
1013
|
+
# all seems ok now and functions as in TA
|
|
1014
|
+
# just do the shift enter to get rid of small cells
|
|
1015
|
+
def m_apply(self):
|
|
1016
|
+
self.vdp.active = not self.vdp.active
|
|
1017
|
+
self.update()
|
|
1018
|
+
|
|
1019
|
+
# avec ça ça marche 100% à la TA ... --> cool --> maybe make it a TA drawing pad
|
|
1020
|
+
def apply(self):
|
|
1021
|
+
# self.apply_drawing(minimal_cell_size=0)
|
|
1022
|
+
pass
|
|
1023
|
+
|
|
1024
|
+
def shift_apply(self):
|
|
1025
|
+
# MEGA TODO IMPLEMENT SIZE within this stuff!!!
|
|
1026
|
+
# self.apply_drawing(minimal_cell_size=10)
|
|
1027
|
+
pass
|
|
1028
|
+
|
|
1029
|
+
def ctrl_m_apply(self):
|
|
1030
|
+
# print('seed')
|
|
1031
|
+
# self.manually_reseeded_wshed()
|
|
1032
|
+
pass
|
|
1033
|
+
|
|
1034
|
+
def save(self):
|
|
1035
|
+
# self.save_mask()
|
|
1036
|
+
print('saving ROIs')
|
|
1037
|
+
print(self.vdp.shapes)
|
|
1038
|
+
# create an image the save size as the displayed one and open it
|
|
1039
|
+
if self.raw_image is None:
|
|
1040
|
+
return
|
|
1041
|
+
if len(self.raw_image.shape)==2:
|
|
1042
|
+
black_image = np.zeros_like(self.raw_image, dtype=np.uint64)
|
|
1043
|
+
else:
|
|
1044
|
+
black_image = np.zeros(shape=(*self.raw_image[:-1],), dtype=np.uint64)
|
|
1045
|
+
# plt.imshow(black_image)
|
|
1046
|
+
# plt.show()
|
|
1047
|
+
# make it fill all the ROIs inside that
|
|
1048
|
+
im2d = Image2D(black_image)
|
|
1049
|
+
|
|
1050
|
+
for iii,shape in enumerate(self.vdp.shapes):
|
|
1051
|
+
# ideally need clone it and make it the enumerate color +1
|
|
1052
|
+
|
|
1053
|
+
shape.fill_color = iii+1
|
|
1054
|
+
shape.color = None
|
|
1055
|
+
# print(shape.fill_color)
|
|
1056
|
+
# print(type(shape), shape.fill_color)
|
|
1057
|
+
im2d.annotation.append(shape)
|
|
1058
|
+
|
|
1059
|
+
|
|
1060
|
+
|
|
1061
|
+
# im2d.annotation.extend(self.vdp.shapes)
|
|
1062
|
+
|
|
1063
|
+
# need clone the shape
|
|
1064
|
+
|
|
1065
|
+
# I need remove antialiasing
|
|
1066
|
+
im = im2d.save(None,quality=QPainter.NonCosmeticDefaultPen)
|
|
1067
|
+
im = im2d.convert_qimage_to_numpy(im)
|
|
1068
|
+
|
|
1069
|
+
# restore colors
|
|
1070
|
+
for shape in self.vdp.shapes:
|
|
1071
|
+
shape.fill_color = None
|
|
1072
|
+
shape.color = 0xFFFFFF
|
|
1073
|
+
|
|
1074
|
+
# faudrait tester en grandeur reelle pr voir si ça marche --> à faire !!!
|
|
1075
|
+
if True:
|
|
1076
|
+
# TODO just save the raw file in one channel not in many --> check the output by the way
|
|
1077
|
+
|
|
1078
|
+
# from skimage.measure import label
|
|
1079
|
+
# lab = label(im, connectivity=2, background=0)
|
|
1080
|
+
# im=lab
|
|
1081
|
+
|
|
1082
|
+
# I need remove antialiasing
|
|
1083
|
+
Img(im.astype(np.float64), dimensions='hwc').save('/E/Sample_images/sample_image_neurons_laurence_had/data_test/test_raw.tif')
|
|
1084
|
+
|
|
1085
|
+
plt.imshow(im)
|
|
1086
|
+
plt.show()
|
|
1087
|
+
|
|
1088
|
+
# what I need to do here now is to save in the folder of the parent à la TA --> can save it as neurons.tif maybe
|
|
1089
|
+
|
|
1090
|
+
|
|
1091
|
+
|
|
1092
|
+
|
|
1093
|
+
# def suppr_pressed(self):
|
|
1094
|
+
# # self.save_mask()
|
|
1095
|
+
# # print('suppr')
|
|
1096
|
+
# self.pa
|
|
1097
|
+
|
|
1098
|
+
|
|
1099
|
+
test = overriding_apply()
|
|
1100
|
+
test.vdp.shape_to_draw = Freehand2D
|
|
1101
|
+
|
|
1102
|
+
# test.vdp.shape_to_draw = Rect2D # ça ça marche --> bug is in the other then...
|
|
1103
|
+
|
|
1104
|
+
# there is a bug in the vectorial but no big deal probably
|
|
1105
|
+
|
|
1106
|
+
w = scrollable_paint(
|
|
1107
|
+
custom_paint_panel=test) # ça marche --> permet de mettre des paint panels avec des proprietes particulieres --> assez facile en fait
|
|
1108
|
+
# w.set_image('/E/Sample_images/sample_images_PA/mini (copie)/focused_Series012.png')
|
|
1109
|
+
# w.set_mask('/E/Sample_images/sample_images_PA/mini (copie)/focused_Series012/handCorrection.png')
|
|
1110
|
+
# w.set_image('/E/Sample_images/sample_images_PA/test_complete_wing_raphael/Optimized_projection_018.png')
|
|
1111
|
+
# w.set_mask('/E/Sample_images/sample_images_PA/test_complete_wing_raphael/neo_mask.tif')
|
|
1112
|
+
|
|
1113
|
+
test.vdp.active = True
|
|
1114
|
+
test.vdp.drawing_mode = True
|
|
1115
|
+
|
|
1116
|
+
# QApplication.setOverrideCursor(Qt.WaitCursor)
|
|
1117
|
+
# do lengthy process
|
|
1118
|
+
# QApplication.restoreOverrideCursor()
|
|
1119
|
+
|
|
1120
|
+
# w.set_image('/E/Sample_images/sample_images_FIJI/sample2.lsm')
|
|
1121
|
+
w.set_image('/E/Sample_images/sample_images_denoise_manue/29-1_lif/ON 290119.lif - Series001.tif')
|
|
1122
|
+
|
|
1123
|
+
# w.set_image('/E/Sample_images/sample_image_neurons_laurence_had/data_test/image.png')
|
|
1124
|
+
# w.set_mask('/D/VirtualBox/book_chapter_image_segmentation_final_2021/new_figs/dataset_1/minimal_demo_sample_simplified_bckup_before_messing_with_two_seg_errors/1/handCorrection.tif')
|
|
1125
|
+
|
|
1126
|
+
# w.setCursor(Qt.BlankCursor)
|
|
1127
|
+
|
|
1128
|
+
# ça marche mais tt finalizer
|
|
1129
|
+
# that seems to work
|
|
1130
|
+
|
|
1131
|
+
# w.freeze(True)
|
|
1132
|
+
# w.freeze(False)
|
|
1133
|
+
# w.freeze(True)
|
|
1134
|
+
|
|
1135
|
+
# we force the cursor to be visible --> set it by default
|
|
1136
|
+
# cursor = Qt.ArrowCursor
|
|
1137
|
+
# w.paint.setCursor(cursor)
|
|
1138
|
+
|
|
1139
|
+
# all is so easy to do this way
|
|
1140
|
+
|
|
1141
|
+
# ça marche --> tres facile a tester
|
|
1142
|
+
# --> how can I do a zoom
|
|
1143
|
+
# ask whether self scroll or not --> if scrollable
|
|
1144
|
+
|
|
1145
|
+
# mask = w.get_mask()
|
|
1146
|
+
#
|
|
1147
|
+
# plt.imshow(mask)
|
|
1148
|
+
# plt.show()
|
|
1149
|
+
|
|
1150
|
+
w.show()
|
|
1151
|
+
# w.setCursor(Qt.BlankCursor)
|
|
1152
|
+
sys.exit(app.exec_())
|