batoolset 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. batoolset/GUI/__init__.py +0 -0
  2. batoolset/GUI/list_gui.py +513 -0
  3. batoolset/GUI/multi_image_display.py +989 -0
  4. batoolset/GUI/open.py +325 -0
  5. batoolset/GUI/overlay_hints.py +45 -0
  6. batoolset/GUI/paint2.py +1345 -0
  7. batoolset/GUI/scrollablepaint.py +1152 -0
  8. batoolset/IJ_ROIs/__init__.py +0 -0
  9. batoolset/IJ_ROIs/tools.py +40 -0
  10. batoolset/PATH/__init__.py +0 -0
  11. batoolset/PATH/tools.py +79 -0
  12. batoolset/SQLite_tools/__init__.py +0 -0
  13. batoolset/SQLite_tools/tools.py +840 -0
  14. batoolset/__init__.py +0 -0
  15. batoolset/binary/__init__.py +0 -0
  16. batoolset/binary/tools.py +123 -0
  17. batoolset/binarytools/__init__.py +0 -0
  18. batoolset/binarytools/cell_center_detector.py +290 -0
  19. batoolset/clipboard_tools/__init__.py +0 -0
  20. batoolset/clipboard_tools/tools.py +7 -0
  21. batoolset/colors/__init__.py +0 -0
  22. batoolset/colors/colorgen.py +193 -0
  23. batoolset/colors/tools.py +22 -0
  24. batoolset/command_line/__init__.py +0 -0
  25. batoolset/command_line/tools.py +18 -0
  26. batoolset/dialogs/__init__.py +0 -0
  27. batoolset/dialogs/opensave.py +228 -0
  28. batoolset/dicts/__init__.py +0 -0
  29. batoolset/dicts/tools.py +299 -0
  30. batoolset/dims/__init__.py +0 -0
  31. batoolset/dims/tools.py +83 -0
  32. batoolset/draw/__init__.py +0 -0
  33. batoolset/draw/shapes/Position.py +183 -0
  34. batoolset/draw/shapes/__init__.py +0 -0
  35. batoolset/draw/shapes/automated_alignment_drawing_refactored.py +346 -0
  36. batoolset/draw/shapes/circle2d.py +99 -0
  37. batoolset/draw/shapes/compute_optimal_size_all_merged.py +317 -0
  38. batoolset/draw/shapes/ellipse2d.py +336 -0
  39. batoolset/draw/shapes/freehand2d.py +235 -0
  40. batoolset/draw/shapes/group.py +1830 -0
  41. batoolset/draw/shapes/image2d.py +2469 -0
  42. batoolset/draw/shapes/line2d.py +575 -0
  43. batoolset/draw/shapes/point2d.py +257 -0
  44. batoolset/draw/shapes/polygon2d.py +357 -0
  45. batoolset/draw/shapes/polyline2d.py +235 -0
  46. batoolset/draw/shapes/rect2d.py +388 -0
  47. batoolset/draw/shapes/rectangle2d.py +601 -0
  48. batoolset/draw/shapes/scalebar.py +304 -0
  49. batoolset/draw/shapes/serializablefont.py +126 -0
  50. batoolset/draw/shapes/serializableguiparams.py +10 -0
  51. batoolset/draw/shapes/square2d.py +103 -0
  52. batoolset/draw/shapes/textorientation.py +45 -0
  53. batoolset/draw/shapes/tools.py +467 -0
  54. batoolset/draw/shapes/transform2D.py +350 -0
  55. batoolset/draw/shapes/txt2d.py +550 -0
  56. batoolset/draw/widgets/__init__.py +0 -0
  57. batoolset/draw/widgets/col.py +343 -0
  58. batoolset/draw/widgets/image_group.py +248 -0
  59. batoolset/draw/widgets/image_organizer.py +96 -0
  60. batoolset/draw/widgets/paint.py +184 -0
  61. batoolset/draw/widgets/vectorial.py +257 -0
  62. batoolset/figure/__init__.py +0 -0
  63. batoolset/figure/alignment.py +814 -0
  64. batoolset/figure/column.py +1117 -0
  65. batoolset/figure/fig_tools.py +285 -0
  66. batoolset/figure/minimal_debugger_scale_etc.py +139 -0
  67. batoolset/figure/panel.py +697 -0
  68. batoolset/figure/row.py +852 -0
  69. batoolset/figure/user_selection.py +287 -0
  70. batoolset/files/__init__.py +0 -0
  71. batoolset/files/tools.py +1321 -0
  72. batoolset/images/__init__.py +0 -0
  73. batoolset/images/tools.py +81 -0
  74. batoolset/img.py +5216 -0
  75. batoolset/linux/__init__.py +0 -0
  76. batoolset/linux/tools.py +72 -0
  77. batoolset/lists/__init__.py +0 -0
  78. batoolset/lists/tools.py +436 -0
  79. batoolset/luts/__init__.py +0 -0
  80. batoolset/luts/lut_minimal_test.py +1207 -0
  81. batoolset/matplolib/__init__.py +0 -0
  82. batoolset/matplolib/tools.py +44 -0
  83. batoolset/np_tools/__init__.py +0 -0
  84. batoolset/np_tools/tools.py +252 -0
  85. batoolset/np_tools/trash.py +15 -0
  86. batoolset/pandas_tools/__init__.py +0 -0
  87. batoolset/pandas_tools/tools.py +880 -0
  88. batoolset/partials/__init__.py +0 -0
  89. batoolset/partials/tools.py +83 -0
  90. batoolset/plot_tools/__init__.py +0 -0
  91. batoolset/plot_tools/tools.py +70 -0
  92. batoolset/pyqt/__init__.py +0 -0
  93. batoolset/pyqt/tools.py +691 -0
  94. batoolset/re_tools/__init__.py +0 -0
  95. batoolset/re_tools/tools.py +35 -0
  96. batoolset/serialization/__init__.py +0 -0
  97. batoolset/serialization/tools.py +1192 -0
  98. batoolset/sets/__init__.py +0 -0
  99. batoolset/sets/tools.py +109 -0
  100. batoolset/settings/__init__.py +0 -0
  101. batoolset/settings/global_settings.py +134 -0
  102. batoolset/strings/__init__.py +0 -0
  103. batoolset/strings/tools.py +225 -0
  104. batoolset/ta/__init__.py +0 -0
  105. batoolset/ta/database/__init__.py +0 -0
  106. batoolset/ta/database/advanced_sql_plotter.py +1170 -0
  107. batoolset/ta/database/my_qt_table.py +79 -0
  108. batoolset/ta/database/preview_and_edit_sqlite_db.py +405 -0
  109. batoolset/ta/database/sql.py +2141 -0
  110. batoolset/ta/database/sql_column_name_dialog.py +122 -0
  111. batoolset/ta/measurements/TAmeasures.py +2226 -0
  112. batoolset/ta/measurements/__init__.py +0 -0
  113. batoolset/ta/measurements/measurements3D/__init__.py +0 -0
  114. batoolset/ta/measurements/measurements3D/get_point_on_surface_if_centroid_is_bad.py +175 -0
  115. batoolset/ta/measurements/measurements3D/height_map_to_projection.py +82 -0
  116. batoolset/ta/measurements/measurements3D/measures3D.py +208 -0
  117. batoolset/ta/measurements/measurements3D/triangulate.py +331 -0
  118. batoolset/ta/measurements/nematic.py +562 -0
  119. batoolset/ta/measurements/nematic_measurements.py +107 -0
  120. batoolset/ta/segmentation/__init__.py +0 -0
  121. batoolset/ta/segmentation/neo_wshed.py +314 -0
  122. batoolset/ta/selections/__init__.py +0 -0
  123. batoolset/ta/selections/selection.py +329 -0
  124. batoolset/ta/tracking/__init__.py +0 -0
  125. batoolset/ta/tracking/last_tracking_based_on_matching_or_on_translation_from_mermaid_warp.py +653 -0
  126. batoolset/ta/tracking/local_to_track_correspondance.py +138 -0
  127. batoolset/ta/tracking/rapid_detection_of_vertices.py +517 -0
  128. batoolset/ta/tracking/registration.py +108 -0
  129. batoolset/ta/tracking/swap_detector_and_fixer.py +296 -0
  130. batoolset/ta/tracking/track_correction.py +238 -0
  131. batoolset/ta/tracking/tracking_error_detector_and_fixer.py +3099 -0
  132. batoolset/ta/tracking/tracking_yet_another_approach_pyramidal_registration_n_neo_swapping_correction.py +725 -0
  133. batoolset/ta/utils/TA_tools.py +43 -0
  134. batoolset/ta/utils/__init__.py +0 -0
  135. batoolset/ta/utils/rps_tools.py +1783 -0
  136. batoolset/tests/__init__.py +0 -0
  137. batoolset/tests/rps_tools.py +51 -0
  138. batoolset/tests/tools.py +10 -0
  139. batoolset/tools/__init__.py +0 -0
  140. batoolset/tools/early_stopper_class.py +9 -0
  141. batoolset/tools/guided_data_recoverer.py +110 -0
  142. batoolset/tools/logger.py +100 -0
  143. batoolset/tools/mytimer.py +31 -0
  144. batoolset/tools/prompt_color.py +160 -0
  145. batoolset/tools/qthandler.py +118 -0
  146. batoolset/uitools/__init__.py +0 -0
  147. batoolset/uitools/blinker.py +56 -0
  148. batoolset/unsafe/__init__.py +0 -0
  149. batoolset/unsafe/tools.py +115 -0
  150. batoolset/utils/__init__.py +0 -0
  151. batoolset/utils/commontools.py +158 -0
  152. batoolset/utils/loadlist.py +728 -0
  153. batoolset/version.py +10 -0
  154. batoolset/xml/__init__.py +0 -0
  155. batoolset/xml/tools.py +65 -0
  156. batoolset/zip_tools/__init__.py +0 -0
  157. batoolset/zip_tools/tools.py +76 -0
  158. batoolset-0.1.0.dist-info/LICENSE +24 -0
  159. batoolset-0.1.0.dist-info/METADATA +45 -0
  160. batoolset-0.1.0.dist-info/RECORD +162 -0
  161. batoolset-0.1.0.dist-info/WHEEL +5 -0
  162. batoolset-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,852 @@
1
+ # not so bad --> see how to add legends --> not so easy because I need to create various groups
2
+ # the ideal situtation would be to preview all the possible fusions and ask the user what should be done
3
+ # or offer a preview if user wants it and then ask him what to do
4
+ # otherwise fuse things
5
+ # NB add row names and column names to each image and offer the possibility to show or fuse them whenever necessary... --> will replace in an easier way the add labels around ... --> think if smart or not ???
6
+ # do the math also below
7
+ # see ho to handle row labels
8
+ # preview might be slow --> ask how to do things ????
9
+
10
+
11
+ # https://docs.python.org/2/library/operator.html
12
+
13
+ # TODO try remove row if possible to only handle panels
14
+ # in a way a figure can be a panel of panels --> if so the I would just have one element --> in fact that would really simplify things like crazy
15
+ # pas mal mais du coup faudrait pas packer par defaut ou bien si sauf si l'utilisateur veut pas
16
+ # peut être plus flexible --> supress fig and row just keep panel and make it more flexible
17
+ # faire un stacker(horizontal or vertical)
18
+ # that may work in a way
19
+ # seule difference est que le panel ne doit contenir que des images de même taille alors que la row non mais en gros la row est un panel de panel
20
+ # puis je appliquer la regle des rows aux panels
21
+ # --> j'ai besoin d'une orientation des le depart
22
+ # est ce que ça peut marcher --> peut etre
23
+ # should I put a warning if they don't have the same size initially --> ? think about it
24
+ # should I have linear panel and 2D panel and give them different rules panel1D panel2D #dans panel2D ttes les images doivent avoir la meme taille. Panel1D --> c'est un peu une row en fait
25
+
26
+ # panel1D --> orientation --> hor/ver
27
+ # panel2D --> more stuff and same size required
28
+ import os
29
+ from batoolset.settings.global_settings import set_UI # set the UI to qtpy
30
+ set_UI()
31
+ from qtpy import QtWidgets
32
+
33
+ from batoolset.draw.shapes.image2d import Image2D
34
+ from batoolset.draw.shapes.point2d import Point2D
35
+ from batoolset.draw.shapes.rect2d import Rect2D
36
+ from qtpy.QtCore import QPointF, QRectF
37
+ # logger
38
+ # from epyseg.ezfig import MyWidget
39
+ # from batoolset.figure import fig_tools
40
+ from batoolset.figure.alignment import alignTop, packX, updateBoudingRect, setToHeight, _brute_force_find_height
41
+ from batoolset.figure.fig_tools import get_master_bounds2, get_common_scaling_factor
42
+ from batoolset.tools.logger import TA_logger
43
+
44
+ logger = TA_logger()
45
+
46
+ # keep this in mind: https://stackoverflow.com/questions/34827132/changing-the-order-of-operation-for-add-mul-etc-methods-in-a-custom-c
47
+ # do rows and columns and no need to take images --> they just pack horiz or vertically and that's it each image or stuff handles itslef
48
+ # a row like that cannot be appended another row or can it --> yes in fact just add to it
49
+ # not a good idea to have rect2D and qrectF at the same time....
50
+ # Ideally choose one or allow a better sync between the two
51
+
52
+ class Row(Rect2D):
53
+
54
+ def __init__(self, *args, space=3, width=None):
55
+ super(QRectF, self).__init__()
56
+ self.images = []
57
+ for img in args:
58
+ # if isinstance(img, Row):
59
+ # self.images += img.images
60
+ # else:
61
+ # prevent adding images that could not be loaded
62
+ if img.isSet:
63
+ self.images.append(img)
64
+ # init super empty
65
+ # self.isSet = True # required to allow dragging
66
+ self.space = space
67
+ # why did not work ???
68
+ self.sameHeight(space=space)
69
+ self.widthInPixel = width
70
+ self.setToWidth(width)
71
+
72
+ # maybe also make the add a
73
+
74
+ def __mod__(self, other):
75
+ # formerly was a swap but in fact need better for a swap maybe == or <>
76
+ if isinstance(other, Row):
77
+ pos = self.get_P1()
78
+ other_pos = other.get_P1()
79
+ self.set_P1(other_pos)
80
+ other.set_P1(pos)
81
+ else:
82
+ logger.error('swapping not implemented yet for ' + str(type(other)))
83
+
84
+ def __ior__(self, other):
85
+ return self.__or__(other=other)
86
+
87
+ def __or__(self, other):
88
+ # print('called')
89
+ return self.__add__(other=other)
90
+ # formerly was a swap but in fact need better for a swap maybe == or <> moved to modulo for now
91
+ # if isinstance(other, Row):
92
+ # pos = self.get_P1()
93
+ # other_pos = other.get_P1()
94
+ # self.set_P1(other_pos)
95
+ # other.set_P1(pos)
96
+ # else:
97
+ # logger.error('swapping not implemented yet for ' + str(type(other)))
98
+
99
+ def __add__(self, other):
100
+ # print('here', other)
101
+ # from batoolset.figure.panel import Panel
102
+ if isinstance(other, Row):
103
+ # print(self.images)
104
+ # print(len(self.images))
105
+ # print(other.images)
106
+ # print(len(other.images))
107
+ P1 = self.get_P1()
108
+ final_width = self.width()
109
+ self.images = self.images + other.images
110
+
111
+ # self.sameHeight(space=self.space)
112
+ # self.setToHeight(self.height())
113
+ self.setToWidth(final_width)
114
+ self.set_P1(P1)
115
+ # elif isinstance(other, Image2D):
116
+ else:
117
+ P1 = self.get_P1()
118
+ final_width = self.width()
119
+ self.images.append(other)
120
+ # self.sameHeight(space=self.space)
121
+ # self.setToHeight(self.height())
122
+ self.setToWidth(final_width)
123
+ self.set_P1(P1)
124
+ # elif isinstance(other, Panel):
125
+ # self.images.append(other)
126
+ # self.sameHeight(space=self.space)
127
+ # self.setToWidth(self.widthInPixel)
128
+
129
+
130
+ return self
131
+
132
+ # def __truediv__(self, other):
133
+
134
+ def __floordiv__(self, other):
135
+ from batoolset.figure.column import Column
136
+ P1 = self.get_P1()
137
+ # final_height = self.height()
138
+ col = Column(self, other,
139
+ space=self.space) # the size of this stuff is way too big and way bigger than its components --> do not allow that
140
+ # col.setToHeight(final_height)
141
+ # need update the bounding rect
142
+ col.sameWidth(self.space)
143
+ # row.setToWidth(self.widthInPixel)
144
+ col.set_P1(P1)
145
+ return col
146
+
147
+ # TODO maybe make it smarter so that it also removes from lower panels
148
+ def __sub__(self, other):
149
+ if other in self.images:
150
+ self.images.remove(other)
151
+ self.setToWidth(self.widthInPixel)
152
+ return self
153
+
154
+ def is_empty(self):
155
+ if self.images is None or not self.images:
156
+ return True
157
+ return False
158
+
159
+ def __truediv__(self, other):
160
+ return self.__floordiv__(other=other)
161
+
162
+ def __len__(self):
163
+ if self.images is None:
164
+ return 0
165
+ return len(self.images)
166
+
167
+ # def setWidthInPixel(self, widthInPixel):
168
+ # self.widthInPixel = widthInPixel
169
+ # self.packX()
170
+
171
+ def packX(self, space=3):
172
+ last_x = 0
173
+ last_y = 0
174
+
175
+ for i in range(len(self.images)):
176
+ img = self.images[i]
177
+ if i != 0:
178
+ last_x += space
179
+ img.set_P1(last_x, img.get_P1().y())
180
+ last_x = img.boundingRect().x() + img.boundingRect().width()
181
+
182
+ self.updateBoudingRect()
183
+
184
+ def packY(self, space=3):
185
+ last_x = 0
186
+ last_y = 0
187
+
188
+ for i in range(len(self.images)):
189
+ img = self.images[i]
190
+ if i != 0:
191
+ last_y += space
192
+ img.set_P1(img.get_P1().x(), last_y)
193
+ # get all the bounding boxes and pack them with desired space in between
194
+ # get first point and last point in x
195
+ x = img.boundingRect().x()
196
+ y = img.boundingRect().y()
197
+ last_x = img.boundingRect().x() + img.boundingRect().width()
198
+ last_y = img.boundingRect().y() + img.boundingRect().height()
199
+ self.updateBoudingRect()
200
+
201
+ def updateBoudingRect(self):
202
+ '''updates the image bounding rect depending on content'''
203
+ x = None
204
+ y = None
205
+ x2 = None
206
+ y2 = None
207
+ for img in self:
208
+
209
+ # topLeft = img.get_P1()
210
+ topLeft = img.boundingRect().topLeft()
211
+ # print('comparison', img.boundingRect(), img.get_P1(), img) # the bug is here the various objects are not in sync !!!! --> do not allow that
212
+
213
+ if x is None:
214
+ x = topLeft.x()
215
+ if y is None:
216
+ y = topLeft.y()
217
+ x = min(topLeft.x(), x)
218
+ y = min(topLeft.y(), y)
219
+
220
+ # print(img, img.boundingRect(), type(img))
221
+ # print(img, img.boundingRect(), type(img), img.boundingRect().height())
222
+ if x2 is None:
223
+ x2 = topLeft.x() + img.boundingRect().width()
224
+ if y2 is None:
225
+ y2 = topLeft.y() + img.boundingRect().height()
226
+ x2 = max(topLeft.x() + img.boundingRect().width(), x2)
227
+ y2 = max(topLeft.y() + img.boundingRect().height(), y2)
228
+
229
+ self.setX(x)
230
+ self.setY(y)
231
+ self.setWidth(x2 - x)
232
+ self.setHeight(y2 - y)
233
+
234
+ # print('bounds from inside', self)
235
+ # bounds = get_master_bounds2(self.images)
236
+ # self.setX(bounds.x())
237
+ # self.setY(bounds.y())
238
+ # self.setWidth(bounds.width())
239
+ # self.setHeight(bounds.height())
240
+ # return bounds
241
+
242
+ # def boundingRect(self):
243
+ # return self.updateBoudingRect()
244
+ # return get_master_bounds2(self.images)
245
+
246
+ def setOrigin(self, *args):
247
+ self.set_P1(*args)
248
+
249
+ def set_P1(self, *args):
250
+ curP1 = self.get_P1()
251
+ Rect2D.set_P1(self, *args) # is this how you call super ???
252
+ newP1 = self.get_P1()
253
+ for img in self:
254
+ img.translate(newP1.x() - curP1.x(), newP1.y() - curP1.y())
255
+
256
+ self.updateBoudingRect()
257
+
258
+ def translate(self, *args):
259
+ if len(args) == 1:
260
+ point = args[0]
261
+ QRectF.translate(self, point.x(), point.y())
262
+ for img in self:
263
+ img.translate(point.x(), point.y())
264
+ else:
265
+ QRectF.translate(self, args[0], args[1])
266
+ for img in self:
267
+ img.translate(QPointF(args[0], args[1]))
268
+
269
+ def draw(self, painter, draw=True):
270
+ if draw:
271
+ painter.save()
272
+ if draw:
273
+ for img in self:
274
+ img.draw(painter, draw=draw)
275
+ painter.restore()
276
+
277
+ def fill(self, painter, draw=True):
278
+ if self.fill_color is None:
279
+ return
280
+ if draw:
281
+ painter.save()
282
+ if draw:
283
+ for img in self:
284
+ img.fill(painter, draw=draw)
285
+ painter.restore()
286
+
287
+ def drawAndFill(self, painter):
288
+ painter.save()
289
+ self.draw(painter, draw=True)
290
+ painter.restore()
291
+
292
+ def __iter__(self):
293
+ ''' Returns the Iterator object '''
294
+ self._index = -1
295
+ return self
296
+
297
+ def __next__(self):
298
+ '''' Returns the next image or panel in the row '''
299
+ self._index += 1
300
+ if self._index < len(self.images):
301
+ return self.images[self._index]
302
+ # End of Iteration
303
+ raise StopIteration
304
+
305
+ def __lshift__(self, other):
306
+ # move image left with respect to self
307
+ if isinstance(other, Image2D):
308
+ # swap the position of the two images and repack
309
+ if other in self.images:
310
+ pos = self.images.index(other)
311
+ if pos - 1 >= 0:
312
+ self.images[pos - 1], self.images[pos] = self.images[pos], self.images[pos - 1]
313
+ else:
314
+ return self
315
+ self.packX(self.space)
316
+ return self
317
+ else:
318
+ logger.error('not implemented yet swapping two objects ' + str(type(other)))
319
+
320
+ def __rshift__(self, other):
321
+ # move image left with respect to self
322
+ if isinstance(other, Image2D):
323
+ # swap the position of the two images and repack
324
+ if other in self.images:
325
+ pos = self.images.index(other)
326
+ if pos + 1 < len(self.images):
327
+ self.images[pos + 1], self.images[pos] = self.images[pos], self.images[pos + 1]
328
+ else:
329
+ return self
330
+ self.packX(self.space)
331
+ return self
332
+ else:
333
+ logger.error('not implemented yet swapping two objects ' + str(type(other)))
334
+
335
+ # en fait ne peut pas marcher faut faire row per row
336
+ def sameHeight(self, space):
337
+ if space is None:
338
+ space = 0
339
+ max_height = None
340
+ for img in self:
341
+ if max_height is None:
342
+ # print('TUTU',img)
343
+ # print('TUTA',img, img.boundingRect(), img.boundingRect().height)
344
+ # print('TOTO',img, img.boundingRect(), img.boundingRect().height())
345
+ max_height = img.boundingRect().height()
346
+ max_height = max(img.boundingRect().height(), max_height)
347
+ for img in self:
348
+ img.setToHeight(max_height)
349
+ # print('height after update', img.height())
350
+
351
+ self.packX(space)
352
+ self.alignTop(updateBounds=False)
353
+ self.updateBoudingRect()
354
+
355
+ # Aligns objects within the block
356
+ def arrangeRow(self):
357
+ self.alignTop()
358
+
359
+ # Align vectorial objects to the top
360
+ # in fact should align in y
361
+ def alignTop(self, updateBounds=False):
362
+ first_left = None
363
+ for img in self:
364
+ cur_pos = img.get_P1()
365
+ if first_left is None:
366
+ first_left = cur_pos
367
+ img.set_P1(cur_pos.x(), first_left.y())
368
+ if updateBounds:
369
+ self.updateMasterRect()
370
+
371
+ def get_shape_at_coord(self, x, y):
372
+ '''returns the shape under the mouse or None if none is found
373
+
374
+ :param x:
375
+ :param y:
376
+ :return:
377
+ '''
378
+ for img in self.images:
379
+ if img.boundingRect().contains(x, y):
380
+ return img
381
+ return None
382
+
383
+ # ça marche super mais cree un bug pour les objects vectoriels --> voir où est le bug dans le truc
384
+ # much smarter and mathematically correct set to width
385
+ # Forces the block to be of width (width_in_px)
386
+ def setToWidth(self, width_in_px):
387
+ # from timeit import default_timer as timer
388
+ # start = timer()
389
+ if width_in_px is None:
390
+ return
391
+
392
+ topleft = Point2D(self.boundingRect().topLeft())
393
+ self.sameHeight(self.space)
394
+
395
+ # print('setToWidth row 1', timer() - start)
396
+
397
+ # print('setToWidth row 2', timer() - start)
398
+ # alignTop(topleft, *self.images)
399
+ # print('setToWidth row 3', timer() - start)
400
+ # packX(self.space, topleft, *self.images)
401
+
402
+ # self.updateBoudingRect() # I should also updat the bounding rect of output -> that is my error
403
+
404
+ sizes = []
405
+ for elm in self:
406
+ sizes.append(elm.width())
407
+ # print("inner size", elm)
408
+
409
+ # new way to compute size --> much smarter than previous way --> start replace everywhere
410
+ # sizes
411
+ scaling = get_common_scaling_factor(sizes, width_in_px, self.space)
412
+ # print('scaling, ', scaling)
413
+ # need set to scale
414
+ # need
415
+
416
+ for elm in self:
417
+ # elm.setWidth(scaling*elm.width())
418
+ # elm.setHeight(scaling*elm.height())
419
+ try:
420
+ elm.scale *= scaling
421
+ except:
422
+ # scaling will not be working if elm has incompressible part --> need change scale again
423
+ # c'est pas ce que je veux en fait --> c'est vraiment le mettre à la width desiree en fait
424
+ elm.setToWidth(elm.width() * scaling)
425
+
426
+ # pb there is a bug and the image and stuff don't match definitely my new code is better and smarter
427
+ # this does noyt work but why ????
428
+ # need pack them in x
429
+ packX(self.space, None, *self.images)
430
+
431
+ # need check that it worked
432
+
433
+ # self.updateBoudingRect()
434
+ # in fact that does not work and solving the equations can be difficult when the initial guess is wrong --> so brute force find it
435
+
436
+
437
+ min_h = 10000000
438
+ max_h = 0
439
+ for elm in self:
440
+ height = elm.height()
441
+ # print('size of inner elm', )
442
+ min_h = min(min_h, height)
443
+ max_h = max(max_h, height)
444
+
445
+ if max_h-min_h > 0.05:
446
+ # closest = _brute_force_find_height(self, min_h - 1, max_h + 1, 1, width_in_px)
447
+
448
+ # TODO --> need do something for gigantic images --> TODO
449
+ # apparently this is painful with big images --> need a ratio
450
+ # closest = _brute_force_find_height(self, min_h - 1, max_h + 1, (max_h - min_h) / 10, width_in_px)
451
+ #
452
+ # if closest is not None:
453
+ # if closest[1] - width_in_px < 0.05:
454
+ # self.setToHeight(closest[2])
455
+ # return closest
456
+ # else:
457
+ # closest = _brute_force_find_height(self, min_h - 1, max_h + 1, 1, width_in_px)
458
+ #
459
+ # value = closest[1]
460
+ # closest = _brute_force_find_height(self, value - 1, value + 1, 1, width_in_px)
461
+
462
+
463
+ closest = _brute_force_find_height(self, min_h - 1, max_h + 1, 1, width_in_px)
464
+
465
+ # print('closest1', closest)
466
+ value = closest[1]
467
+ # for height in np.arange(value - 1, value + 1, 0.01):
468
+ # col1.setToHeight(height)
469
+ # print('bob', height, col1.width(), col1.height())
470
+ # if (col1.width() - desired_width) <= mn and col1.width() - desired_width >= 0:
471
+ # closest = (col1.width(), col1.height(), height)
472
+ # mn = col1.width() - desired_width
473
+
474
+ if closest[1]-width_in_px<0.05:
475
+ self.setToHeight(closest[2])
476
+ return closest
477
+
478
+ closest = _brute_force_find_height(self, value - 0.5, value + 0.5, 0.1, width_in_px)
479
+
480
+
481
+ # tres lent --> need skip steps if good enough
482
+ # --> pas mal et assez rapide --> pourrait faire n iterations
483
+ if closest[1]-width_in_px<0.05:
484
+ self.setToHeight(closest[2])
485
+ return closest
486
+
487
+ value = closest[1]
488
+ closest = _brute_force_find_height(self, value - 0.1, value + 0.1, 0.01, width_in_px) # almost perfect
489
+
490
+ # (128.00066196944778, 42.80999999999944, 42.80999999999944) --> solution est à peu pres ça --> comment la trouver
491
+ # (128.5352647965376, 43.0, 43) # ineteger search then refinement --> could search between max height and min height of the shape of the column
492
+ # (128.00066196944888, 42.80999999999984, 42.80999999999984)
493
+
494
+ # this is a very good estimate
495
+
496
+ self.setToHeight(closest[2])
497
+
498
+ self.set_P1(topleft)
499
+ self.updateBoudingRect()
500
+
501
+ # def get_equa(self):
502
+ # sqdsqdsqdsqd
503
+
504
+ # this is a really crappy method --> needs be changed
505
+ # is that always correct irrespective of content ???
506
+ # probably need to overwrite the set to scale of this
507
+ # Forces the block to be of width (width_in_px)
508
+ # def setToWidth_old(self, width_in_px):
509
+ # # from timeit import default_timer as timer
510
+ # # start = timer()
511
+ # if width_in_px is None:
512
+ # return
513
+ # # print('setToWidth row 1', timer() - start)
514
+ # topleft = Point2D(self.boundingRect().topLeft())
515
+ # # print('setToWidth row 2', timer() - start)
516
+ # alignTop(topleft, *self.images)
517
+ # # print('setToWidth row 3', timer() - start)
518
+ # packX(self.space, topleft, *self.images)
519
+ # # print('setToWidth row 4', timer() - start)
520
+ # # print('bounds before', updateBoudingRect(*self.images))
521
+ # setToWidth(self.space, width_in_px, *self.images)
522
+ # # print('setToWidth row 5', timer() - start)
523
+ # bounds = updateBoudingRect(*self.images)
524
+ # # print('bounds after', updateBoudingRect(*self.images))
525
+ # # print('setToWidth row 6', timer() - start)
526
+ #
527
+ # max_height = -1
528
+ #
529
+ # cur_height = bounds.height()
530
+ # cur_width = bounds.width()
531
+ # all_heights_are_the_same = True
532
+ # # print('setToWidth row 7', timer() - start)
533
+ # for img in self.images:
534
+ # max_height = max(max_height, img.boundingRect().height())
535
+ # # print('cur height', img.boundingRect().height(), img.boundingRect().width())
536
+ # if cur_height != max_height:
537
+ # all_heights_are_the_same = False
538
+ #
539
+ # if not all_heights_are_the_same:
540
+ # setToHeight(self.space, max_height, *self.images)
541
+ # bounds = updateBoudingRect(*self.images)
542
+ # all_heights_are_the_same = True
543
+ # else:
544
+ # bounds = updateBoudingRect(*self.images)
545
+ #
546
+ # sign = 1
547
+ # if bounds.width() >= width_in_px:
548
+ # sign = -1
549
+ #
550
+ # # print(bounds.width(), 'vs desired', width_in_px, 'sign', sign)
551
+ # #
552
+ # # print(all_heights_are_the_same)
553
+ # # print(bounds.width() != width_in_px)
554
+ # # print(abs(bounds.width()-width_in_px)>0.3)
555
+ #
556
+ #
557
+ # # print('setToWidth row 8', timer() - start)
558
+ # # dirty height/width fix for complex panels figure out the math for it and replace this code
559
+ # # TODO also speed this up so that the action is only faked and not really done (just done once at the end to gain time)
560
+ #
561
+ # # VERY DIRTY HERE --> need be hacked and replaced by new code
562
+ #
563
+ # if not all_heights_are_the_same or (bounds.width() != width_in_px and abs(bounds.width()-width_in_px)>0.3):
564
+ #
565
+ # # indeed this is super dirty code that need be replaced by the new code I have that doesn't use that
566
+ # # print('setToWidth row 9', timer() - start)
567
+ # while True:
568
+ # setToHeight(self.space, max_height, *self.images)
569
+ # bounds = updateBoudingRect(*self.images)
570
+ # if sign<0:
571
+ # if bounds.width() <= width_in_px:
572
+ # break
573
+ # else:
574
+ # if bounds.width() >= width_in_px:
575
+ # break
576
+ # max_height += 1 * sign
577
+ # # print('setToWidth row 10', timer() - start)
578
+ #
579
+ # if bounds.width() != width_in_px:
580
+ # if bounds.width() >= width_in_px:
581
+ # sign = -1
582
+ # else:
583
+ # sign = 1
584
+ # # what if i remove refine step
585
+ # #
586
+ # # print('setToWidth row 10', timer() - start)
587
+ # # max_height -= 1
588
+ # # print('max_height', max_height, updateBoudingRect(*self.images))
589
+ # while True:
590
+ # setToHeight(self.space, max_height, *self.images)
591
+ # bounds = updateBoudingRect(*self.images)
592
+ # if sign < 0:
593
+ # if bounds.width() <= width_in_px:
594
+ # break
595
+ # else:
596
+ # if bounds.width() >= width_in_px:
597
+ # break
598
+ # max_height += 0.25 *sign # critical step with this value --> timing is ok --> maybe ok for now
599
+ # # # print('setToWidth row 11', timer() - start)
600
+ #
601
+ # # print('setToWidth row 11', timer() - start)
602
+ # # print('setToWidth row 12', timer() - start)
603
+ #
604
+ #
605
+ # self.updateBoudingRect() # I should also updat the bounding rect of output -> that is my error
606
+ #
607
+ # # print('setToWidth row last', timer() - start)
608
+
609
+ # def setToWidth(self, width_in_px):
610
+ # if width_in_px is None:
611
+ # return
612
+ # topleft = Point2D(self.boundingRect().topLeft())
613
+ # alignTop(topleft, *self.images)
614
+ # # because can use relative width and height
615
+ # # packX(self.space, topleft, *self.images)# do I need that --> I guess not
616
+ # # just fake it in fact --> faster
617
+ # fakeSetToWidth(width_in_px, *self.images)
618
+ # # compute fake nounds
619
+ # bounds = fakeUpdateBoudingRect(*self.images)
620
+ #
621
+ #
622
+ # # need compute fake height too
623
+ # min_height = 100_000_000
624
+ #
625
+ # cur_height = bounds.height()
626
+ # cur_width = bounds.width()
627
+ # all_heights_are_the_same = True
628
+ # for img in self.images:
629
+ # min_height = min(min_height, img.boundingRect().height())
630
+ # if min_height<cur_height:
631
+ # all_heights_are_the_same=False
632
+ #
633
+ # # dirty height/width fix for complex panels figure out the math for it and replace this code
634
+ # # TODO also speed this up so that the action is only faked and not really done (just done once at the end to gain time)
635
+ # if not all_heights_are_the_same or cur_width!=width_in_px:
636
+ # while True:
637
+ # setToHeight(min_height, *self.images)
638
+ # bounds = updateBoudingRect(*self.images)
639
+ # if bounds.width() >= width_in_px:
640
+ # break
641
+ # min_height += 1
642
+ #
643
+ # min_height -= 1
644
+ # while True:
645
+ # min_height += 0.05
646
+ # setToHeight(min_height, *self.images)
647
+ # bounds = updateBoudingRect(*self.images)
648
+ # if bounds.width() >= width_in_px:
649
+ # break
650
+ #
651
+ # self.updateBoudingRect()
652
+
653
+ def setToHeight(self, height_in_px):
654
+ if height_in_px is None:
655
+ return
656
+ # # nb_cols = len(self)
657
+ # pure_image_height = (self.boundingRect().height()) - self.getIncompressibleHeight()
658
+ # # print(width_in_px, self.getIncompressibleWidth(), (nb_cols - 1.) * self.space )
659
+ # height_in_px -= self.getIncompressibleHeight()
660
+ # ratio = height_in_px / pure_image_height
661
+ # for img in self:
662
+ # img.setToHeight(img.boundingRect().height() * ratio)
663
+ # self.packX(self.space)
664
+ # self.updateBoudingRect()
665
+ topleft = Point2D(self.boundingRect().topLeft())
666
+ alignTop(topleft, *self.images)
667
+ setToHeight(self.space, height_in_px, *self.images)
668
+ self.updateBoudingRect()
669
+
670
+ # @return the block incompressible width
671
+ def getIncompressibleHeight(self):
672
+ return 0
673
+
674
+ # @return the block incompressible width
675
+ def getIncompressibleWidth(self):
676
+ if not self:
677
+ return 0
678
+ return (len(self) - 1.) * self.space
679
+
680
+ # can I pass an ignoring char if some images need be ignored
681
+ # probably need return the increment
682
+ def setLettering(self, letter):
683
+ # TODO implement increment
684
+ # set letter for increasing stuff # check if letter is string or letter or array if so do or do not increase letters
685
+ for img in self:
686
+ img.setLettering(letter)
687
+ # self.letter = letter
688
+
689
+ # return all the solvable equations
690
+ # all pairs of heights should be equal in a row
691
+ # think how to do that
692
+ # shall I actually build solvable equation sets ???
693
+ def get_equation(self):
694
+ # from sympy import nsolve, exp, Symbol
695
+ # TODO --> maybe get a width equation and a height one
696
+
697
+ # need get the equa of inner also
698
+ # maybe need even get the final equations to that I just append them all and get exactly what I need to solve
699
+ # how should I increment that
700
+ # UnevaluatedExpr(x + x)
701
+ if not self:
702
+ return None
703
+
704
+
705
+ # in fact all heights should be equal and the sum of width would also be equal --> I need both sets of equations in fact --> maybe just do the get equation
706
+ # maybe I should just append the equations
707
+ # append both x and y equations and do the maths with them --> put them into a solvable form
708
+ # what is the best way to do that ???
709
+ equas_w = []
710
+ equas_h = []
711
+ equas_to_solve = []
712
+ for img in self:
713
+ equa_w, equa_h, equa_to_solve = img.get_equation()
714
+
715
+ if equa_w:
716
+ equas_w.extend(equa_w)
717
+ if equa_h:
718
+ equas_h.extend(equa_h)
719
+ if equa_to_solve:
720
+ equas_to_solve.extend(equa_to_solve)
721
+
722
+ # do I need increment ??? --> maybe not or maybe yes
723
+ # fig_tools.common_value+=1
724
+ # do I need a formula there # that would be the sum of others
725
+ # final equation is a concatenate of all equa for width
726
+ # id(self) # to set the variable
727
+ # --> is there an additional factor that would handle the resize if they are all the same size ???
728
+
729
+ # in a row all heights need be the same --> must put the equas so that this is true
730
+ # and in fact just return one equation for a row the top most row that needs be resized
731
+
732
+
733
+ for iii in range(1, len(equas_h)):
734
+ # print(iii)
735
+ # first - sec = 0
736
+ equa = equas_h[0] - equas_h[iii]
737
+ equas_to_solve.append(equa)
738
+ # if len(equa_h)==1:
739
+ # equa = equa_h[0] - equa_h[1]
740
+ # equas_to_solve.append(equa)
741
+
742
+ final_equa = None
743
+ for equa in equas_w:
744
+ if final_equa is None:
745
+ final_equa = equa
746
+ else:
747
+ final_equa += equa
748
+
749
+ # see how I can do that
750
+ # variable = Symbol('a'+str(id(self)))
751
+ # final_equa
752
+
753
+ # this is the equation I want
754
+ final_equa += self.getIncompressibleWidth()
755
+ equas_to_solve.append(final_equa) # pb is that for this equa I need to add the width --> how to I do that
756
+ # this lists the variables in the formula --> do I don't need to store them separately
757
+ # print(final_equa.free_symbols) # returns all the variables contained in it
758
+
759
+ # since they all have same height I need just return one equation
760
+ return equas_w, [equas_h[0]], equas_to_solve
761
+
762
+ # make no sense ??? la height n'est pas la somme mais juste une des valeurs de la colonne --> c'est tout je pense en fait
763
+ # def get_height_equation(self):
764
+ # # TODO --> maybe get a width equation and a height one
765
+ #
766
+ # # need get the equa of inner also
767
+ # # maybe need even get the final equations to that I just append them all and get exactly what I need to solve
768
+ # # how should I increment that
769
+ # # UnevaluatedExpr(x + x)
770
+ # equas = []
771
+ # for img in self:
772
+ # equas.append(img.get_height_equation())
773
+ # # do I need increment ??? --> maybe not or maybe yes
774
+ # # fig_tools.common_value+=1
775
+ # # do I need a formula there # that would be the sum of others
776
+ # # final equation is a concatenate of all equa for width
777
+ # # id(self) # to set the variable
778
+ # # --> is there an additional factor that would handle the resize if they are all the same size ???
779
+ # final_equa = None
780
+ # for equa in equas:
781
+ # if final_equa is None:
782
+ # final_equa = equa
783
+ # else:
784
+ # final_equa += equa
785
+ #
786
+ # # see how I can do that
787
+ # # variable = Symbol('a'+str(id(self)))
788
+ # final_equa += self.getIncompressibleHeight() # useless because 0 but ok still
789
+ #
790
+ # # this lists the variables in the formula --> do I don't need to store them separately
791
+ # print(final_equa.free_symbols) # returns all the variables contained in it
792
+ #
793
+ # return final_equa
794
+
795
+
796
+ # # hack to make column hashable to be able to add it to a dict, see https://stackoverflow.com/questions/10994229/how-to-make-an-object-properly-hashable
797
+ # def __eq__(self, other):
798
+ # try:
799
+ # return hash(str(self)) == other.__hash__()
800
+ # except:
801
+ # return False
802
+ #
803
+ # # hack to make column hashable to be able to add it to a dict, see https://stackoverflow.com/questions/10994229/how-to-make-an-object-properly-hashable
804
+ # def __hash__(self):
805
+ # return hash(str(self))
806
+
807
+ # allow to duplicate object
808
+ def __copy__(self):
809
+ return self
810
+
811
+ def __deepcopy__(self, memo):
812
+ return self
813
+
814
+ if __name__ == '__main__':
815
+ img1 = Image2D('/E/Sample_images/counter/00.png')
816
+ img2 = Image2D('/E/Sample_images/counter/01.png')
817
+ img3 = Image2D('/E/Sample_images/counter/02.png')
818
+ img4 = Image2D('/E/Sample_images/counter/03.png')
819
+ # result = img1 + img2
820
+
821
+ row = Row(img1, img2)
822
+ row2 = Row(img3, img4)
823
+
824
+ # peut etre la aussi le scripting language sera la clef
825
+ # faire aussi un code de packing et de truc de ce style
826
+
827
+
828
+ # print(result)
829
+ result = row + row2
830
+ print(result)
831
+ result.sameHeight(3)
832
+ result.setToWidth(128)
833
+
834
+ print('equa', result.get_equation())
835
+ # print('equa2', result.get_height_equation())
836
+
837
+ print(result)
838
+
839
+ # preview([result])
840
+ # preview(result)
841
+
842
+ # not bad --> also do a
843
+ # by default add all to the image
844
+ # maybe have a 'list' command that can return the content of the IQL dict --> so that one can interact with them and one can also list the sub elements in EZFIG --> can be useful
845
+
846
+ # TODO --> do a show of the stuff so that one can see the stuff
847
+
848
+ # TODO --> do a plot of this
849
+ # --> maybe need open an ezfig window --> TODO
850
+
851
+ # find easy ways to letter and autoincrement sutff --> TODO
852
+ # maybe store all as a script --> easy to reexecute --> but need store all images in the desired format