mwxlib 1.7.13__py3-none-any.whl → 1.8.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.
- mwx/bookshelf.py +12 -12
- mwx/controls.py +22 -22
- mwx/framework.py +58 -55
- mwx/graphman.py +87 -74
- mwx/matplot2.py +40 -40
- mwx/matplot2g.py +197 -219
- mwx/matplot2lg.py +32 -32
- mwx/nutshell.py +94 -114
- mwx/plugins/ffmpeg_view.py +40 -33
- mwx/plugins/frame_listview.py +21 -31
- mwx/py/filling.py +4 -6
- mwx/utilus.py +13 -11
- mwx/wxmon.py +7 -9
- mwx/wxpdb.py +2 -1
- mwx/wxwil.py +2 -1
- mwx/wxwit.py +7 -11
- {mwxlib-1.7.13.dist-info → mwxlib-1.8.0.dist-info}/METADATA +1 -1
- mwxlib-1.8.0.dist-info/RECORD +28 -0
- mwxlib-1.7.13.dist-info/RECORD +0 -28
- {mwxlib-1.7.13.dist-info → mwxlib-1.8.0.dist-info}/WHEEL +0 -0
- {mwxlib-1.7.13.dist-info → mwxlib-1.8.0.dist-info}/top_level.txt +0 -0
mwx/matplot2g.py
CHANGED
|
@@ -13,7 +13,6 @@ from scipy import ndimage as ndi
|
|
|
13
13
|
|
|
14
14
|
from . import framework as mwx
|
|
15
15
|
from .framework import Menu
|
|
16
|
-
# from .utilus import warn
|
|
17
16
|
from .utilus import funcall as _F
|
|
18
17
|
from .controls import Clipboard
|
|
19
18
|
from .matplot2 import MatplotPanel
|
|
@@ -125,30 +124,35 @@ class AxesImagePhantom:
|
|
|
125
124
|
**kwargs: frame attributes
|
|
126
125
|
|
|
127
126
|
Note:
|
|
128
|
-
Due to the problem of performance,
|
|
129
|
-
the image pixel size could be reduced by binning.
|
|
127
|
+
Due to the problem of performance, the image pixel size could be reduced by binning.
|
|
130
128
|
"""
|
|
131
129
|
def __init__(self, parent, buf, name, show=True, **kwargs):
|
|
132
130
|
self.parent = parent
|
|
131
|
+
|
|
132
|
+
## Properties of the frame/image.
|
|
133
133
|
self.__name = name
|
|
134
134
|
self.__attributes = kwargs
|
|
135
|
+
self.__pathname = kwargs.get('pathname')
|
|
136
|
+
self.__annotation = kwargs.get('annotation', '')
|
|
135
137
|
self.__localunit = kwargs.get('localunit')
|
|
136
|
-
self.__center = kwargs.get('center',
|
|
137
|
-
|
|
138
|
+
self.__center = kwargs.get('center', [0, 0])
|
|
139
|
+
|
|
140
|
+
## Conditions for image loading.
|
|
138
141
|
self.__buf = _to_buffer(buf)
|
|
139
142
|
bins, vlim, img = _to_image(self.__buf,
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
+
cutoff=self.parent.score_percentile,
|
|
144
|
+
threshold=self.parent.nbytes_threshold,
|
|
145
|
+
)
|
|
143
146
|
self.__bins = bins
|
|
144
147
|
self.__cuts = vlim
|
|
145
148
|
self.__art = parent.axes.imshow(img,
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
cmap=cm.gray,
|
|
150
|
+
aspect='equal', # cf. aspect_ratio => xy_unit
|
|
151
|
+
interpolation='nearest',
|
|
152
|
+
visible=show,
|
|
153
|
+
picker=True,
|
|
154
|
+
)
|
|
155
|
+
self.aspect_ratio = 1
|
|
152
156
|
self.update_extent()
|
|
153
157
|
|
|
154
158
|
def __getattr__(self, attr):
|
|
@@ -159,29 +163,47 @@ class AxesImagePhantom:
|
|
|
159
163
|
return x is self.__art
|
|
160
164
|
|
|
161
165
|
def update_attr(self, attr):
|
|
162
|
-
"""Update frame-specifc attributes
|
|
163
|
-
|
|
164
|
-
annotation : aux info (also displayed as a message in the infobar)
|
|
165
|
-
center : frame.center defaults to (0, 0)
|
|
166
|
-
localunit : frame.unit
|
|
167
|
-
pathname : full path of the buffer file
|
|
168
|
-
"""
|
|
166
|
+
"""Update frame-specifc attributes."""
|
|
169
167
|
if not attr:
|
|
170
168
|
return
|
|
171
|
-
self.__attributes.update(attr)
|
|
172
169
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if '
|
|
177
|
-
self.
|
|
170
|
+
FLAG_ANNOTATION = 1
|
|
171
|
+
FLAG_UPDATE_EXTENT = 2
|
|
172
|
+
flag = 0
|
|
173
|
+
if 'pathname' in attr:
|
|
174
|
+
self.__pathname = attr['pathname']
|
|
175
|
+
flag |= FLAG_ANNOTATION
|
|
178
176
|
|
|
179
177
|
if 'annotation' in attr:
|
|
180
|
-
|
|
178
|
+
self.__annotation = attr['annotation']
|
|
181
179
|
if self.parent.frame is self:
|
|
182
|
-
self.parent.infobar.ShowMessage(
|
|
180
|
+
self.parent.infobar.ShowMessage(attr['annotation'])
|
|
181
|
+
flag |= FLAG_ANNOTATION
|
|
182
|
+
|
|
183
|
+
if 'center' in attr:
|
|
184
|
+
v = list(attr['center']) # for json format
|
|
185
|
+
if v != self.__center:
|
|
186
|
+
self.__center = v
|
|
187
|
+
flag |= FLAG_UPDATE_EXTENT
|
|
188
|
+
|
|
189
|
+
if 'localunit' in attr:
|
|
190
|
+
v = attr['localunit']
|
|
191
|
+
if v is None or np.isnan(v): # nan => None: undefined.
|
|
192
|
+
v = None
|
|
193
|
+
elif np.isinf(v):
|
|
194
|
+
raise ValueError("The unit value must not be inf")
|
|
195
|
+
elif v <= 0:
|
|
196
|
+
raise ValueError("The unit value must be greater than zero")
|
|
197
|
+
if v != self.__localunit:
|
|
198
|
+
self.__localunit = v
|
|
199
|
+
flag |= FLAG_UPDATE_EXTENT
|
|
200
|
+
|
|
201
|
+
self.__attributes.update(attr)
|
|
183
202
|
|
|
184
|
-
if
|
|
203
|
+
if flag & FLAG_UPDATE_EXTENT:
|
|
204
|
+
self.update_extent()
|
|
205
|
+
self.parent.canvas.draw_idle()
|
|
206
|
+
if flag:
|
|
185
207
|
self.parent.handler('frame_updated', self)
|
|
186
208
|
|
|
187
209
|
def update_buffer(self, buf=None):
|
|
@@ -190,9 +212,9 @@ class AxesImagePhantom:
|
|
|
190
212
|
self.__buf = _to_buffer(buf)
|
|
191
213
|
|
|
192
214
|
bins, vlim, img = _to_image(self.__buf,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
215
|
+
cutoff = self.parent.score_percentile,
|
|
216
|
+
threshold = self.parent.nbytes_threshold,
|
|
217
|
+
)
|
|
196
218
|
self.__bins = bins
|
|
197
219
|
self.__cuts = vlim
|
|
198
220
|
self.__art.set_array(img)
|
|
@@ -232,80 +254,44 @@ class AxesImagePhantom:
|
|
|
232
254
|
doc="Auxiliary info about the frame.")
|
|
233
255
|
|
|
234
256
|
pathname = property(
|
|
235
|
-
lambda self: self.
|
|
257
|
+
lambda self: self.__pathname,
|
|
236
258
|
lambda self, v: self.update_attr({'pathname': v}),
|
|
237
259
|
doc="Fullpath of the buffer, if bound to a file.")
|
|
238
260
|
|
|
239
261
|
annotation = property(
|
|
240
|
-
lambda self: self.
|
|
262
|
+
lambda self: self.__annotation,
|
|
241
263
|
lambda self, v: self.update_attr({'annotation': v}),
|
|
242
264
|
doc="Annotation of the buffer.")
|
|
243
265
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
266
|
+
center = property(
|
|
267
|
+
lambda self: self.__center,
|
|
268
|
+
lambda self, v: self.update_attr({'center': v}),
|
|
269
|
+
doc="Center coordinates of the frame in logical units.")
|
|
247
270
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
self.
|
|
251
|
-
|
|
271
|
+
localunit = property(
|
|
272
|
+
lambda self: self.__localunit,
|
|
273
|
+
lambda self, v: self.update_attr({'localunit': v}),
|
|
274
|
+
doc="Logical length per pixel in arbitrary units [u/pix], or None if not assigned.")
|
|
252
275
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
@property
|
|
258
|
-
def unit(self):
|
|
259
|
-
"""Logical length per pixel arb.unit [u/pix]."""
|
|
260
|
-
return self.__localunit or self.parent.unit
|
|
261
|
-
|
|
262
|
-
@unit.setter
|
|
263
|
-
def unit(self, v):
|
|
264
|
-
if v == self.__localunit: # no effect
|
|
265
|
-
return
|
|
266
|
-
if v is None or np.isnan(v): # nan => undefined
|
|
267
|
-
v = None
|
|
268
|
-
elif np.isinf(v):
|
|
269
|
-
raise ValueError("The unit value must not be inf")
|
|
270
|
-
elif v <= 0:
|
|
271
|
-
raise ValueError("The unit value must be greater than zero")
|
|
272
|
-
|
|
273
|
-
self.__localunit = v
|
|
274
|
-
self.__attributes['localunit'] = self.__localunit
|
|
275
|
-
self.update_extent()
|
|
276
|
-
self.parent.handler('frame_updated', self)
|
|
277
|
-
self.parent.canvas.draw_idle()
|
|
278
|
-
|
|
279
|
-
@unit.deleter
|
|
280
|
-
def unit(self):
|
|
281
|
-
self.unit = None
|
|
276
|
+
unit = property(
|
|
277
|
+
lambda self: self.__localunit or self.parent.unit,
|
|
278
|
+
lambda self, v: self.update_attr({'localunit': v}),
|
|
279
|
+
doc="Logical length per pixel in arbitrary units [u/pix].")
|
|
282
280
|
|
|
283
281
|
@property
|
|
284
282
|
def xy_unit(self):
|
|
285
|
-
u
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
def center(self):
|
|
290
|
-
"""Center of logical unit."""
|
|
291
|
-
return self.__center
|
|
292
|
-
|
|
293
|
-
@center.setter
|
|
294
|
-
def center(self, v):
|
|
295
|
-
self.__center = tuple(v)
|
|
296
|
-
self.__attributes['center'] = self.__center
|
|
297
|
-
self.update_extent()
|
|
298
|
-
self.parent.handler('frame_updated', self)
|
|
283
|
+
"""Logical length per pixel in arbitrary units [u/pix] for (X, Y) directions."""
|
|
284
|
+
u = self.unit
|
|
285
|
+
r = self.aspect_ratio
|
|
286
|
+
return (u, u) if r == 1 else (u, u * r)
|
|
299
287
|
|
|
300
288
|
@property
|
|
301
|
-
def
|
|
302
|
-
|
|
303
|
-
return self.__aspect_ratio
|
|
289
|
+
def name(self):
|
|
290
|
+
return self.__name
|
|
304
291
|
|
|
305
|
-
@
|
|
306
|
-
def
|
|
307
|
-
self.
|
|
308
|
-
self.update_extent()
|
|
292
|
+
@name.setter
|
|
293
|
+
def name(self, v):
|
|
294
|
+
self.__name = v
|
|
309
295
|
self.parent.handler('frame_updated', self)
|
|
310
296
|
|
|
311
297
|
@property
|
|
@@ -317,7 +303,7 @@ class AxesImagePhantom:
|
|
|
317
303
|
def roi(self):
|
|
318
304
|
"""Current buffer ROI (region of interest)."""
|
|
319
305
|
if self.parent.region.size:
|
|
320
|
-
nx, ny = self.xytopixel(
|
|
306
|
+
nx, ny = self.xytopixel(self.region)
|
|
321
307
|
sx = slice(max(0, nx[0]), nx[1]) # nx slice
|
|
322
308
|
sy = slice(max(0, ny[1]), ny[0]) # ny slice 反転 (降順)
|
|
323
309
|
return self.__buf[sy, sx]
|
|
@@ -326,7 +312,7 @@ class AxesImagePhantom:
|
|
|
326
312
|
@roi.setter
|
|
327
313
|
def roi(self, v):
|
|
328
314
|
if not self.parent.region.size:
|
|
329
|
-
|
|
315
|
+
raise ValueError("region is not selected.")
|
|
330
316
|
self.roi[:] = v # cannot broadcast input array into different shape
|
|
331
317
|
self.update_buffer()
|
|
332
318
|
|
|
@@ -393,43 +379,31 @@ class AxesImagePhantom:
|
|
|
393
379
|
|
|
394
380
|
@property
|
|
395
381
|
def selector_pix(self):
|
|
396
|
-
"""Selected points array [[x],[y]] in pixels."""
|
|
382
|
+
"""Selected points array [[x], [y]] in pixels."""
|
|
397
383
|
return self.xytopixel(self.selector)
|
|
398
384
|
|
|
399
385
|
@selector_pix.setter
|
|
400
386
|
def selector_pix(self, v):
|
|
401
387
|
self.selector = self.xyfrompixel(v)
|
|
402
388
|
|
|
403
|
-
@selector_pix.deleter
|
|
404
|
-
def selector_pix(self):
|
|
405
|
-
del self.selector
|
|
406
|
-
|
|
407
389
|
@property
|
|
408
390
|
def markers_pix(self):
|
|
409
|
-
"""Marked points data array [[x],[y]] in pixels."""
|
|
391
|
+
"""Marked points data array [[x], [y]] in pixels."""
|
|
410
392
|
return self.xytopixel(self.markers)
|
|
411
393
|
|
|
412
394
|
@markers_pix.setter
|
|
413
395
|
def markers_pix(self, v):
|
|
414
396
|
self.markers = self.xyfrompixel(v)
|
|
415
397
|
|
|
416
|
-
@markers_pix.deleter
|
|
417
|
-
def markers_pix(self):
|
|
418
|
-
del self.markers
|
|
419
|
-
|
|
420
398
|
@property
|
|
421
399
|
def region_pix(self):
|
|
422
|
-
"""Cropped points data array [l,r],[b,t] in pixels."""
|
|
400
|
+
"""Cropped points data array [[l,r], [b,t]] in pixels."""
|
|
423
401
|
return self.xytopixel(self.region)
|
|
424
402
|
|
|
425
403
|
@region_pix.setter
|
|
426
404
|
def region_pix(self, v):
|
|
427
405
|
self.region = self.xyfrompixel(v)
|
|
428
406
|
|
|
429
|
-
@region_pix.deleter
|
|
430
|
-
def region_pix(self):
|
|
431
|
-
del self.region
|
|
432
|
-
|
|
433
407
|
|
|
434
408
|
class GraphPlot(MatplotPanel):
|
|
435
409
|
"""Graph panel for 2D graph.
|
|
@@ -440,41 +414,41 @@ class GraphPlot(MatplotPanel):
|
|
|
440
414
|
def _draw(evt):
|
|
441
415
|
self.canvas.draw_idle()
|
|
442
416
|
|
|
443
|
-
self.handler.update({
|
|
417
|
+
self.handler.update({ # DNA<GraphPlot>
|
|
444
418
|
None : {
|
|
445
|
-
'frame_shown' : [
|
|
446
|
-
'frame_hidden' : [
|
|
447
|
-
'frame_loaded' : [
|
|
448
|
-
'frame_removed' : [
|
|
449
|
-
'frame_selected' : [
|
|
450
|
-
'frame_deselected' : [
|
|
451
|
-
'frame_modified' : [
|
|
452
|
-
'frame_updated' : [
|
|
453
|
-
'frame_cmapped' : [
|
|
454
|
-
'line_draw' : [
|
|
455
|
-
'line_drawn' : [
|
|
456
|
-
'line_move' : [
|
|
457
|
-
'line_moved' : [
|
|
458
|
-
'line_removed' : [
|
|
459
|
-
'mark_draw' : [
|
|
460
|
-
'mark_drawn' : [
|
|
461
|
-
'mark_removed' : [
|
|
462
|
-
'region_draw' : [
|
|
463
|
-
'region_drawn' : [
|
|
464
|
-
'region_removed' : [
|
|
465
|
-
'M-up pressed' : [
|
|
466
|
-
'M-down pressed' : [
|
|
467
|
-
'pageup pressed' : [
|
|
468
|
-
'pagedown pressed' : [
|
|
469
|
-
'home pressed' : [
|
|
470
|
-
'end pressed' : [
|
|
471
|
-
'M-a pressed' : [
|
|
472
|
-
'C-a pressed' : [
|
|
473
|
-
'C-i pressed' : [
|
|
474
|
-
'C-k pressed' : [
|
|
475
|
-
'C-S-k pressed' : [
|
|
476
|
-
'C-c pressed' : [
|
|
477
|
-
'C-v pressed' : [
|
|
419
|
+
'frame_shown' : [None, ], # show
|
|
420
|
+
'frame_hidden' : [None, ], # show
|
|
421
|
+
'frame_loaded' : [None, ], # load
|
|
422
|
+
'frame_removed' : [None, ], # del[] ! event arg is indices, not frames.
|
|
423
|
+
'frame_selected' : [None, ], # = focus_set
|
|
424
|
+
'frame_deselected' : [None, ], # = focus_kill
|
|
425
|
+
'frame_modified' : [None, _F(self.writeln)], # set[],load,roi => update_buffer
|
|
426
|
+
'frame_updated' : [None, _F(self.writeln)], # unit,name,ratio => update_extent
|
|
427
|
+
'frame_cmapped' : [None, _F(self.writeln)], # cmap
|
|
428
|
+
'line_draw' : [None, ],
|
|
429
|
+
'line_drawn' : [None, _draw],
|
|
430
|
+
'line_move' : [None, ],
|
|
431
|
+
'line_moved' : [None, _draw],
|
|
432
|
+
'line_removed' : [None, _draw],
|
|
433
|
+
'mark_draw' : [None, ],
|
|
434
|
+
'mark_drawn' : [None, _draw],
|
|
435
|
+
'mark_removed' : [None, _draw],
|
|
436
|
+
'region_draw' : [None, ],
|
|
437
|
+
'region_drawn' : [None, _draw],
|
|
438
|
+
'region_removed' : [None, _draw],
|
|
439
|
+
'M-up pressed' : [None, self.OnPageUp],
|
|
440
|
+
'M-down pressed' : [None, self.OnPageDown],
|
|
441
|
+
'pageup pressed' : [None, self.OnPageUp],
|
|
442
|
+
'pagedown pressed' : [None, self.OnPageDown],
|
|
443
|
+
'home pressed' : [None, _F(self.select, index=0)],
|
|
444
|
+
'end pressed' : [None, _F(self.select, index=-1)],
|
|
445
|
+
'M-a pressed' : [None, _F(self.fit_to_canvas)],
|
|
446
|
+
'C-a pressed' : [None, _F(self.fit_to_axes)],
|
|
447
|
+
'C-i pressed' : [None, _F(self.invert_cmap)],
|
|
448
|
+
'C-k pressed' : [None, _F(self.kill_buffer)],
|
|
449
|
+
'C-S-k pressed' : [None, _F(self.kill_all_buffers)],
|
|
450
|
+
'C-c pressed' : [None, _F(self.write_buffer_to_clipboard)],
|
|
451
|
+
'C-v pressed' : [None, _F(self.read_buffer_from_clipboard)],
|
|
478
452
|
},
|
|
479
453
|
NORMAL : {
|
|
480
454
|
'image_picked' : (NORMAL, self.OnImagePicked),
|
|
@@ -581,6 +555,7 @@ class GraphPlot(MatplotPanel):
|
|
|
581
555
|
'delete pressed' : (NORMAL, self.OnRegionRemove),
|
|
582
556
|
'space pressed' : (PAN, self.OnPanBegin),
|
|
583
557
|
'ctrl pressed' : (PAN, self.OnPanBegin),
|
|
558
|
+
'c pressed' : (REGION, self.OnRegionCenter),
|
|
584
559
|
'z pressed' : (ZOOM, self.OnZoomBegin),
|
|
585
560
|
'*Ldrag begin' : (REGION+DRAGGING, self.OnRegionDragBegin),
|
|
586
561
|
'Rbutton pressed' : (REGION, self.on_menu_lock),
|
|
@@ -618,7 +593,7 @@ class GraphPlot(MatplotPanel):
|
|
|
618
593
|
lambda v: v.Enable(self.frame is not None)),
|
|
619
594
|
|
|
620
595
|
(wx.ID_CLOSE_ALL, "&Kill all buffer\t(C-S-k)", "Kill buffers", _Icon(wx.ART_DELETE),
|
|
621
|
-
lambda v: self.
|
|
596
|
+
lambda v: self.kill_all_buffers(),
|
|
622
597
|
lambda v: v.Enable(self.frame is not None)),
|
|
623
598
|
]
|
|
624
599
|
|
|
@@ -628,14 +603,13 @@ class GraphPlot(MatplotPanel):
|
|
|
628
603
|
lambda v: self.select(s),
|
|
629
604
|
lambda v: v.Check(self.frame is not None and self.frame.name == s))
|
|
630
605
|
|
|
631
|
-
self.modeline.Bind(wx.EVT_CONTEXT_MENU,
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
self.modeline.Show(1)
|
|
636
|
-
self.Layout()
|
|
606
|
+
self.modeline.Bind(wx.EVT_CONTEXT_MENU,
|
|
607
|
+
lambda v: Menu.Popup(self, (_menu(j, art.name)
|
|
608
|
+
for j, art in enumerate(self.__Arts))))
|
|
637
609
|
|
|
610
|
+
self.modeline.Show()
|
|
638
611
|
self.writeln()
|
|
612
|
+
self.Layout()
|
|
639
613
|
|
|
640
614
|
def clear(self):
|
|
641
615
|
MatplotPanel.clear(self)
|
|
@@ -646,14 +620,14 @@ class GraphPlot(MatplotPanel):
|
|
|
646
620
|
## cf. self.figure.dpi = 80 dpi (0.3175 mm/pix)
|
|
647
621
|
self.__unit = 1.0
|
|
648
622
|
|
|
649
|
-
|
|
623
|
+
# <matplotlib.lines.Line2D>
|
|
650
624
|
(self.marked,) = self.axes.plot([], [], "r+", ms=8, mew=1,
|
|
651
625
|
picker=8)
|
|
652
626
|
self.__marksel = []
|
|
653
627
|
self.__markarts = []
|
|
654
628
|
self.marked.set_clip_on(False)
|
|
655
629
|
|
|
656
|
-
|
|
630
|
+
# <matplotlib.lines.Line2D>
|
|
657
631
|
(self.rected,) = self.axes.plot([], [], "r+--", ms=4, lw=3/4,
|
|
658
632
|
picker=4, alpha=0.8)
|
|
659
633
|
self.__rectsel = []
|
|
@@ -688,13 +662,13 @@ class GraphPlot(MatplotPanel):
|
|
|
688
662
|
if isinstance(buf, str):
|
|
689
663
|
buf = Image.open(buf)
|
|
690
664
|
|
|
691
|
-
|
|
665
|
+
path = kwargs.get('pathname')
|
|
692
666
|
paths = [art.pathname for art in self.__Arts]
|
|
693
667
|
names = [art.name for art in self.__Arts]
|
|
694
668
|
j = -1
|
|
695
|
-
if
|
|
696
|
-
if
|
|
697
|
-
j = paths.index(
|
|
669
|
+
if path:
|
|
670
|
+
if path in paths:
|
|
671
|
+
j = paths.index(path) # existing path
|
|
698
672
|
elif name in names:
|
|
699
673
|
j = names.index(name) # existing frame
|
|
700
674
|
if j != -1:
|
|
@@ -880,12 +854,12 @@ class GraphPlot(MatplotPanel):
|
|
|
880
854
|
|
|
881
855
|
@property
|
|
882
856
|
def unit(self):
|
|
883
|
-
"""Logical length per pixel
|
|
857
|
+
"""Logical length per pixel in arbitrary units [u/pix]."""
|
|
884
858
|
return self.__unit
|
|
885
859
|
|
|
886
860
|
@unit.setter
|
|
887
861
|
def unit(self, v):
|
|
888
|
-
if v == self.__unit: # no effect
|
|
862
|
+
if v == self.__unit: # no effect
|
|
889
863
|
return
|
|
890
864
|
if v is None or np.isnan(v) or np.isinf(v):
|
|
891
865
|
raise ValueError("The unit value must not be nan or inf")
|
|
@@ -902,7 +876,7 @@ class GraphPlot(MatplotPanel):
|
|
|
902
876
|
if self.frame:
|
|
903
877
|
del self[self.__index]
|
|
904
878
|
|
|
905
|
-
def
|
|
879
|
+
def kill_all_buffers(self):
|
|
906
880
|
del self[:]
|
|
907
881
|
|
|
908
882
|
def fit_to_axes(self):
|
|
@@ -962,21 +936,22 @@ class GraphPlot(MatplotPanel):
|
|
|
962
936
|
|
|
963
937
|
def trace_point(self, x, y, type=NORMAL):
|
|
964
938
|
"""Puts (override) a message of points x and y."""
|
|
939
|
+
if not hasattr(x, '__iter__'): # called from OnMotion
|
|
940
|
+
return self.trace_point([x], [y], type)
|
|
941
|
+
|
|
965
942
|
frame = self.frame
|
|
966
943
|
if frame:
|
|
967
|
-
if not hasattr(x, '__iter__'): # called from OnMotion
|
|
968
|
-
nx, ny = frame.xytopixel(x, y)
|
|
969
|
-
z = frame.xytoc(x, y)
|
|
970
|
-
self.message(f"[{nx:-4d},{ny:-4d}] ({x:-8.3f},{y:-8.3f}) value: {z}")
|
|
971
|
-
return
|
|
972
|
-
|
|
973
944
|
if len(x) == 0: # no selection
|
|
974
945
|
return
|
|
975
946
|
|
|
976
|
-
if len(x) == 1: # 1-selector trace point (called from
|
|
977
|
-
|
|
947
|
+
if len(x) == 1: # 1-selector trace point (called from markers.setter)
|
|
948
|
+
x, y = x[0], y[0]
|
|
949
|
+
z = frame.xytoc(x, y)
|
|
950
|
+
nx, ny = frame.xytopixel(x, y)
|
|
951
|
+
self.message(f"[{nx:-4d},{ny:-4d}] ({x:-8.3f},{y:-8.3f}) value: {z}")
|
|
952
|
+
return
|
|
978
953
|
|
|
979
|
-
if len(x) == 2: # 2-selector trace line (called from selector
|
|
954
|
+
if len(x) == 2: # 2-selector trace line (called from selector.setter)
|
|
980
955
|
nx, ny = frame.xytopixel(x, y)
|
|
981
956
|
dx = x[1] - x[0]
|
|
982
957
|
dy = y[1] - y[0]
|
|
@@ -985,11 +960,11 @@ class GraphPlot(MatplotPanel):
|
|
|
985
960
|
li = np.hypot(nx[1]-nx[0], ny[1]-ny[0])
|
|
986
961
|
self.message(f"[Line] Length: {li:.1f} pixel ({lu:g}u) Angle: {a:.1f} deg")
|
|
987
962
|
|
|
988
|
-
elif type == REGION: # N-selector trace polygon (called from region
|
|
963
|
+
elif type == REGION: # N-selector trace polygon (called from region.setter)
|
|
989
964
|
nx, ny = frame.xytopixel(x, y)
|
|
990
|
-
xo,
|
|
991
|
-
|
|
992
|
-
self.message(f"[Region] crop={
|
|
965
|
+
xo, xp = min(nx), max(nx)
|
|
966
|
+
yo, yp = min(ny), max(ny)
|
|
967
|
+
self.message(f"[Region] crop={xp-xo}:{yp-yo}:{xo}:{yo}") # (W:H:left:top)
|
|
993
968
|
|
|
994
969
|
def writeln(self):
|
|
995
970
|
"""Puts (override) attributes of current frame to the modeline."""
|
|
@@ -1086,7 +1061,7 @@ class GraphPlot(MatplotPanel):
|
|
|
1086
1061
|
## matplotlib interface.
|
|
1087
1062
|
## --------------------------------
|
|
1088
1063
|
|
|
1089
|
-
def on_pick(self, evt):
|
|
1064
|
+
def on_pick(self, evt): # <matplotlib.backend_bases.PickEvent>
|
|
1090
1065
|
"""Pickup image and other arts.
|
|
1091
1066
|
Called (maybe) after mouse buttons are pressed.
|
|
1092
1067
|
"""
|
|
@@ -1135,19 +1110,18 @@ class GraphPlot(MatplotPanel):
|
|
|
1135
1110
|
def on_picker_unlock(self, evt):
|
|
1136
1111
|
self.__isPicked = False
|
|
1137
1112
|
|
|
1138
|
-
def OnImagePicked(self, evt):
|
|
1113
|
+
def OnImagePicked(self, evt): # <matplotlib.backend_bases.PickEvent>
|
|
1139
1114
|
x = evt.mouseevent.xdata
|
|
1140
1115
|
y = evt.mouseevent.ydata
|
|
1141
1116
|
nx, ny = self.frame.xytopixel(x, y)
|
|
1142
|
-
x, y = self.frame.xyfrompixel(nx, ny)
|
|
1143
1117
|
evt.ind = (ny, nx)
|
|
1144
|
-
self.selector = (
|
|
1118
|
+
self.selector = self.frame.xyfrompixel(nx, ny)
|
|
1145
1119
|
|
|
1146
1120
|
def _inaxes(self, evt):
|
|
1147
1121
|
try:
|
|
1148
|
-
return evt.inaxes is not self.axes
|
|
1122
|
+
return evt.inaxes is not self.axes # <matplotlib.backend_bases.MouseEvent>
|
|
1149
1123
|
except AttributeError:
|
|
1150
|
-
return None
|
|
1124
|
+
return None # <wx._core.KeyEvent>
|
|
1151
1125
|
|
|
1152
1126
|
## --------------------------------
|
|
1153
1127
|
## Pan/Zoom actions (override).
|
|
@@ -1314,7 +1288,7 @@ class GraphPlot(MatplotPanel):
|
|
|
1314
1288
|
dots = np.hypot(x-xs[k], y-ys[k]) * self.ddpu[0]
|
|
1315
1289
|
self.__linesel = k if dots < 8 else None
|
|
1316
1290
|
|
|
1317
|
-
def OnLineDeselected(self, evt):
|
|
1291
|
+
def OnLineDeselected(self, evt): # <matplotlib.backend_bases.PickEvent>
|
|
1318
1292
|
self.__linesel = None
|
|
1319
1293
|
|
|
1320
1294
|
def OnLineDragBegin(self, evt):
|
|
@@ -1365,10 +1339,10 @@ class GraphPlot(MatplotPanel):
|
|
|
1365
1339
|
if self.selector.size and self.frame:
|
|
1366
1340
|
ux, uy = self.frame.xy_unit
|
|
1367
1341
|
du = {
|
|
1368
|
-
'up' : (
|
|
1369
|
-
'down' : (
|
|
1370
|
-
'left' : (-ux, 0
|
|
1371
|
-
'right' : (
|
|
1342
|
+
'up' : (0, +uy),
|
|
1343
|
+
'down' : (0, -uy),
|
|
1344
|
+
'left' : (-ux, 0),
|
|
1345
|
+
'right' : (+ux, 0),
|
|
1372
1346
|
}
|
|
1373
1347
|
self.selector += np.resize(du[evt.key], (2,1))
|
|
1374
1348
|
self.handler('line_move', self.frame)
|
|
@@ -1399,7 +1373,7 @@ class GraphPlot(MatplotPanel):
|
|
|
1399
1373
|
return
|
|
1400
1374
|
self.marked.set_data(x, y)
|
|
1401
1375
|
self.__marksel = []
|
|
1402
|
-
self.
|
|
1376
|
+
self.update_mark_art()
|
|
1403
1377
|
self.handler('mark_drawn', self.frame)
|
|
1404
1378
|
|
|
1405
1379
|
@markers.deleter
|
|
@@ -1407,7 +1381,7 @@ class GraphPlot(MatplotPanel):
|
|
|
1407
1381
|
if self.markers.size:
|
|
1408
1382
|
self.marked.set_data([], [])
|
|
1409
1383
|
self.__marksel = []
|
|
1410
|
-
self.
|
|
1384
|
+
self.update_mark_art()
|
|
1411
1385
|
self.handler('mark_removed', self.frame)
|
|
1412
1386
|
|
|
1413
1387
|
def get_current_mark(self):
|
|
@@ -1421,7 +1395,7 @@ class GraphPlot(MatplotPanel):
|
|
|
1421
1395
|
if j:
|
|
1422
1396
|
xm[j], ym[j] = x, y
|
|
1423
1397
|
self.marked.set_data(xm, ym)
|
|
1424
|
-
self.
|
|
1398
|
+
self.update_mark_art(j, xm[j], ym[j])
|
|
1425
1399
|
else:
|
|
1426
1400
|
n = len(xm)
|
|
1427
1401
|
k = len(x) if hasattr(x, '__iter__') else 1
|
|
@@ -1429,7 +1403,7 @@ class GraphPlot(MatplotPanel):
|
|
|
1429
1403
|
xm, ym = np.append(xm, x), np.append(ym, y)
|
|
1430
1404
|
self.marked.set_data(xm, ym)
|
|
1431
1405
|
self.marked.set_visible(1)
|
|
1432
|
-
self.
|
|
1406
|
+
self.update_mark_art()
|
|
1433
1407
|
self.selector = (x, y)
|
|
1434
1408
|
|
|
1435
1409
|
def del_current_mark(self):
|
|
@@ -1441,9 +1415,9 @@ class GraphPlot(MatplotPanel):
|
|
|
1441
1415
|
self.marked.set_data(xm, ym)
|
|
1442
1416
|
n = len(xm)
|
|
1443
1417
|
self.__marksel = [j[-1] % n] if n > 0 else []
|
|
1444
|
-
self.
|
|
1418
|
+
self.update_mark_art()
|
|
1445
1419
|
|
|
1446
|
-
def
|
|
1420
|
+
def update_mark_art(self, *args):
|
|
1447
1421
|
if args:
|
|
1448
1422
|
for k, x, y in zip(*args):
|
|
1449
1423
|
art = self.__markarts[k] # art の再描画処理をして終了
|
|
@@ -1458,11 +1432,11 @@ class GraphPlot(MatplotPanel):
|
|
|
1458
1432
|
xm, ym = self.marked.get_data(orig=0)
|
|
1459
1433
|
for k, (x, y) in enumerate(zip(xm[:N], ym[:N])):
|
|
1460
1434
|
self.__markarts.append(
|
|
1461
|
-
self.axes.annotate(k,
|
|
1435
|
+
self.axes.annotate(k, # <matplotlib.text.Annotation>
|
|
1462
1436
|
xy=(x,y), xycoords='data',
|
|
1463
1437
|
xytext=(6,6), textcoords='offset points',
|
|
1464
1438
|
bbox=dict(boxstyle="round", fc=(1,1,1,), ec=(1,0,0,)),
|
|
1465
|
-
color='red', size=7,
|
|
1439
|
+
color='red', size=7, # fontsize=8,
|
|
1466
1440
|
)
|
|
1467
1441
|
)
|
|
1468
1442
|
self.trace_point(*self.get_current_mark(), type=MARK)
|
|
@@ -1473,28 +1447,28 @@ class GraphPlot(MatplotPanel):
|
|
|
1473
1447
|
if not self.__marksel and len(xs) > 0:
|
|
1474
1448
|
self.set_current_mark(xs, ys)
|
|
1475
1449
|
self.handler('mark_drawn', self.frame)
|
|
1476
|
-
self.
|
|
1450
|
+
self.update_mark_art()
|
|
1477
1451
|
|
|
1478
1452
|
def OnMarkRemove(self, evt):
|
|
1479
1453
|
if self.__marksel:
|
|
1480
1454
|
self.del_current_mark()
|
|
1481
1455
|
self.handler('mark_removed', self.frame)
|
|
1482
1456
|
|
|
1483
|
-
def OnMarkSelected(self, evt):
|
|
1457
|
+
def OnMarkSelected(self, evt): # <matplotlib.backend_bases.PickEvent>
|
|
1484
1458
|
k = evt.ind[0]
|
|
1485
1459
|
if evt.mouseevent.key == 'shift': # 多重マーカー選択
|
|
1486
1460
|
if k not in self.__marksel:
|
|
1487
1461
|
self.__marksel += [k]
|
|
1488
1462
|
else:
|
|
1489
1463
|
self.__marksel = [k]
|
|
1490
|
-
self.
|
|
1464
|
+
self.update_mark_art()
|
|
1491
1465
|
self.selector = self.get_current_mark()
|
|
1492
1466
|
if self.selector.shape[1] > 1:
|
|
1493
1467
|
self.handler('line_drawn', self.frame) # 多重マーカー選択時
|
|
1494
1468
|
|
|
1495
|
-
def OnMarkDeselected(self, evt):
|
|
1469
|
+
def OnMarkDeselected(self, evt): # <matplotlib.backend_bases.PickEvent>
|
|
1496
1470
|
self.__marksel = []
|
|
1497
|
-
self.
|
|
1471
|
+
self.update_mark_art()
|
|
1498
1472
|
|
|
1499
1473
|
def OnMarkDragBegin(self, evt):
|
|
1500
1474
|
if not self.frame or self._inaxes(evt):
|
|
@@ -1519,10 +1493,10 @@ class GraphPlot(MatplotPanel):
|
|
|
1519
1493
|
if j and self.frame:
|
|
1520
1494
|
ux, uy = self.frame.xy_unit
|
|
1521
1495
|
du = {
|
|
1522
|
-
'up' : (
|
|
1523
|
-
'down' : (
|
|
1524
|
-
'left' : (-ux, 0
|
|
1525
|
-
'right' : ( ux, 0
|
|
1496
|
+
'up' : (0, uy),
|
|
1497
|
+
'down' : (0, -uy),
|
|
1498
|
+
'left' : (-ux, 0),
|
|
1499
|
+
'right' : ( ux, 0),
|
|
1526
1500
|
}
|
|
1527
1501
|
p = self.get_current_mark() + np.resize(du[evt.key], (2,1))
|
|
1528
1502
|
self.set_current_mark(*p)
|
|
@@ -1562,13 +1536,13 @@ class GraphPlot(MatplotPanel):
|
|
|
1562
1536
|
|
|
1563
1537
|
@property
|
|
1564
1538
|
def region(self):
|
|
1565
|
-
"""Cropped rectangle points data array [l,r],[b,t]."""
|
|
1539
|
+
"""Cropped rectangle points data array [[l,r], [b,t]]."""
|
|
1566
1540
|
x, y = self.rected.get_data(orig=0)
|
|
1567
1541
|
if len(x) and len(y):
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
return np.array(((
|
|
1571
|
-
return np.resize(0., (2,0))
|
|
1542
|
+
l, r = min(x), max(x)
|
|
1543
|
+
b, t = min(y), max(y)
|
|
1544
|
+
return np.array(((l,r), (b,t)))
|
|
1545
|
+
return np.resize(0., (2, 0))
|
|
1572
1546
|
|
|
1573
1547
|
@region.setter
|
|
1574
1548
|
def region(self, v):
|
|
@@ -1597,8 +1571,6 @@ class GraphPlot(MatplotPanel):
|
|
|
1597
1571
|
l,r,b,t = self.frame.get_extent()
|
|
1598
1572
|
xa, xb = min(x), max(x)
|
|
1599
1573
|
ya, yb = min(y), max(y)
|
|
1600
|
-
# if (xa < l or xb > r) or (ya < b or yb > t):
|
|
1601
|
-
# return
|
|
1602
1574
|
## Modify range so that it does not exceed the extent.
|
|
1603
1575
|
w, h = xb-xa, yb-ya
|
|
1604
1576
|
if xa < l: xa, xb = l, l+w
|
|
@@ -1609,15 +1581,15 @@ class GraphPlot(MatplotPanel):
|
|
|
1609
1581
|
y = [ya, ya, yb, yb, ya]
|
|
1610
1582
|
self.rected.set_data(x, y)
|
|
1611
1583
|
self.rected.set_visible(1)
|
|
1612
|
-
self.
|
|
1584
|
+
self.update_rect_art()
|
|
1613
1585
|
|
|
1614
1586
|
def del_current_rect(self):
|
|
1615
1587
|
self.__rectsel = []
|
|
1616
1588
|
self.rected.set_data([], [])
|
|
1617
1589
|
self.rected.set_visible(0)
|
|
1618
|
-
self.
|
|
1590
|
+
self.update_rect_art()
|
|
1619
1591
|
|
|
1620
|
-
def
|
|
1592
|
+
def update_rect_art(self, *args):
|
|
1621
1593
|
if args:
|
|
1622
1594
|
art = self.__rectarts # art の再描画処理をして終了
|
|
1623
1595
|
art.xy = args
|
|
@@ -1638,6 +1610,12 @@ class GraphPlot(MatplotPanel):
|
|
|
1638
1610
|
self.trace_point(x, y, type=REGION)
|
|
1639
1611
|
self.draw(self.rected)
|
|
1640
1612
|
|
|
1613
|
+
def OnRegionCenter(self, evt):
|
|
1614
|
+
if self.region.size and self.frame:
|
|
1615
|
+
(l,r), (b,t) = self.region
|
|
1616
|
+
c = np.array(((l+r)/2, (b+t)/2))
|
|
1617
|
+
self.region += self.frame.center - c[:,None]
|
|
1618
|
+
|
|
1641
1619
|
def OnRegionAppend(self, evt):
|
|
1642
1620
|
xs, ys = self.selector
|
|
1643
1621
|
if len(xs) > 0 and self.frame:
|
|
@@ -1645,7 +1623,7 @@ class GraphPlot(MatplotPanel):
|
|
|
1645
1623
|
xs = (xs.min()-ux/2, xs.max()+ux/2)
|
|
1646
1624
|
ys = (ys.max()+uy/2, ys.min()-uy/2)
|
|
1647
1625
|
self.set_current_rect(xs, ys)
|
|
1648
|
-
self.
|
|
1626
|
+
self.update_rect_art()
|
|
1649
1627
|
self.handler('region_drawn', self.frame)
|
|
1650
1628
|
|
|
1651
1629
|
def OnRegionRemove(self, evt):
|
|
@@ -1654,18 +1632,18 @@ class GraphPlot(MatplotPanel):
|
|
|
1654
1632
|
self.handler('region_removed', self.frame)
|
|
1655
1633
|
self.set_wxcursor(wx.CURSOR_ARROW)
|
|
1656
1634
|
|
|
1657
|
-
def OnRegionSelected(self, evt):
|
|
1635
|
+
def OnRegionSelected(self, evt): # <matplotlib.backend_bases.PickEvent>
|
|
1658
1636
|
k = evt.ind[0]
|
|
1659
1637
|
x = evt.mouseevent.xdata
|
|
1660
1638
|
y = evt.mouseevent.ydata
|
|
1661
1639
|
xs, ys = evt.artist.get_data(orig=0)
|
|
1662
1640
|
dots = np.hypot(x-xs[k], y-ys[k]) * self.ddpu[0]
|
|
1663
1641
|
self.__rectsel = [k] if dots < 8 else [0,1,2,3,4] # リージョンの全選択
|
|
1664
|
-
self.
|
|
1642
|
+
self.update_rect_art()
|
|
1665
1643
|
|
|
1666
|
-
def OnRegionDeselected(self, evt):
|
|
1644
|
+
def OnRegionDeselected(self, evt): # <matplotlib.backend_bases.PickEvent>
|
|
1667
1645
|
self.__rectsel = []
|
|
1668
|
-
self.
|
|
1646
|
+
self.update_rect_art()
|
|
1669
1647
|
self.set_wxcursor(wx.CURSOR_ARROW)
|
|
1670
1648
|
|
|
1671
1649
|
def OnRegionDragBegin(self, evt):
|
|
@@ -1723,10 +1701,10 @@ class GraphPlot(MatplotPanel):
|
|
|
1723
1701
|
if j and self.frame:
|
|
1724
1702
|
ux, uy = self.frame.xy_unit
|
|
1725
1703
|
du = {
|
|
1726
|
-
'up' : (
|
|
1727
|
-
'down' : (
|
|
1728
|
-
'left' : (-ux, 0
|
|
1729
|
-
'right' : ( ux, 0
|
|
1704
|
+
'up' : (0, uy),
|
|
1705
|
+
'down' : (0, -uy),
|
|
1706
|
+
'left' : (-ux, 0),
|
|
1707
|
+
'right' : ( ux, 0),
|
|
1730
1708
|
}
|
|
1731
1709
|
dp = du[evt.key]
|
|
1732
1710
|
p = self.get_current_rect().T
|