mwxlib 1.2.0__py3-none-any.whl → 1.2.3__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.

Potentially problematic release.


This version of mwxlib might be problematic. Click here for more details.

mwx/framework.py CHANGED
@@ -1,7 +1,7 @@
1
1
  #! python3
2
2
  """mwxlib framework.
3
3
  """
4
- __version__ = "1.2.0"
4
+ __version__ = "1.2.3"
5
5
  __author__ = "Kazuya O'moto <komoto@jeol.co.jp>"
6
6
 
7
7
  from contextlib import contextmanager
mwx/matplot2.py CHANGED
@@ -348,22 +348,22 @@ class MatplotPanel(wx.Panel):
348
348
  xbound = property(
349
349
  lambda self: np.array(self.axes.get_xbound()),
350
350
  lambda self,v: self.axes.set_xbound(v),
351
- doc="x-axis numerical bounds where lowerBound < upperBound)")
351
+ doc="X-axis numerical bounds where lowerBound < upperBound)")
352
352
 
353
353
  ybound = property(
354
354
  lambda self: np.array(self.axes.get_ybound()),
355
355
  lambda self,v: self.axes.set_ybound(v),
356
- doc="y-axis numerical bounds where lowerBound < upperBound)")
356
+ doc="Y-axis numerical bounds where lowerBound < upperBound)")
357
357
 
358
358
  xlim = property(
359
359
  lambda self: np.array(self.axes.get_xlim()),
360
360
  lambda self,v: self.axes.set_xlim(v),
361
- doc="x-axis range [left, right]")
361
+ doc="X-axis range [left, right]")
362
362
 
363
363
  ylim = property(
364
364
  lambda self: np.array(self.axes.get_ylim()),
365
365
  lambda self,v: self.axes.set_ylim(v),
366
- doc="y-axis range [bottom, top]")
366
+ doc="Y-axis range [bottom, top]")
367
367
 
368
368
  @property
369
369
  def ddpu(self):
mwx/matplot2g.py CHANGED
@@ -14,7 +14,7 @@ from scipy import ndimage as ndi
14
14
 
15
15
  from . import framework as mwx
16
16
  from .framework import Menu
17
- ## from .utilus import warn
17
+ from .utilus import warn
18
18
  from .utilus import funcall as _F
19
19
  from .controls import Clipboard
20
20
  from .matplot2 import MatplotPanel
@@ -88,7 +88,7 @@ def _to_image(src, cutoff=0, threshold=None, binning=1):
88
88
  if src.dtype == np.uint8: # RGB or gray image <uint8>
89
89
  return bins, (0, 255), src
90
90
 
91
- if hasattr(cutoff, '__iter__'): # cutoff vlim:list is specified.
91
+ if hasattr(cutoff, '__iter__'): # cutoff vlim: (vmin, vmax) is specified.
92
92
  a, b = cutoff
93
93
  elif cutoff > 0:
94
94
  a = np.percentile(src, cutoff)
@@ -129,7 +129,7 @@ class AxesImagePhantom:
129
129
  """
130
130
  def __init__(self, parent, buf, name, show=True,
131
131
  localunit=None, aspect=1.0, **attributes):
132
- self.__owner = parent
132
+ self.parent = parent
133
133
  self.__name = name
134
134
  self.__localunit = localunit or None # [+] value, no assertion
135
135
  self.__aspect_ratio = aspect
@@ -141,7 +141,7 @@ class AxesImagePhantom:
141
141
  threshold = self.parent.nbytes_threshold,
142
142
  )
143
143
  self.__bins = bins
144
- self.__vlim = vlim
144
+ self.__cuts = vlim
145
145
  self.__art = parent.axes.imshow(img,
146
146
  cmap = cm.gray,
147
147
  aspect = 'equal',
@@ -157,39 +157,6 @@ class AxesImagePhantom:
157
157
  def __eq__(self, x):
158
158
  return x is self.__art
159
159
 
160
- parent = property(lambda self: self.__owner)
161
- artist = property(lambda self: self.__art)
162
- name = property(lambda self: self.__name)
163
- buffer = property(lambda self: self.__buf) # buffer.setter is defined below.
164
- binning = property(lambda self: self.__bins)
165
-
166
- image = property(
167
- lambda self: self.__art.get_array(),
168
- doc="A displayed image array<uint8>.")
169
-
170
- vlim = property(
171
- lambda self: self.__vlim,
172
- doc="Image lower/upper values.")
173
-
174
- clim = property(
175
- lambda self: self.__art.get_clim(),
176
- lambda self,v: self.__art.set_clim(v),
177
- doc="Buffer lower/upper values.")
178
-
179
- attributes = property(
180
- lambda self: self.__attributes,
181
- doc="Miscellaneous info about the frame/buffer.")
182
-
183
- pathname = property(
184
- lambda self: self.__attributes.get('pathname'),
185
- lambda self,v: self.update_attributes({'pathname': v}),
186
- doc="A fullpath of buffer, when bounds to file.")
187
-
188
- annotation = property(
189
- lambda self: self.__attributes.get('annotation', ''),
190
- lambda self,v: self.update_attributes({'annotation': v}),
191
- doc="Annotation of the buffer.")
192
-
193
160
  def update_attributes(self, attr=None, **kwargs):
194
161
  """Update frame-specifc attributes.
195
162
  The frame holds any attributes with dictionary
@@ -215,10 +182,70 @@ class AxesImagePhantom:
215
182
  if {'pathname', 'annotation'} & attr.keys():
216
183
  self.parent.handler('frame_updated', self)
217
184
 
185
+ def update_buffer(self, buf=None):
186
+ """Update buffer and the image (internal use only)."""
187
+ if buf is not None:
188
+ self.__buf = _to_buffer(buf)
189
+
190
+ bins, vlim, img = _to_image(self.__buf,
191
+ cutoff = self.parent.score_percentile,
192
+ threshold = self.parent.nbytes_threshold,
193
+ )
194
+ self.__bins = bins
195
+ self.__cuts = vlim
196
+ self.__art.set_array(img)
197
+ self.parent.handler('frame_modified', self)
198
+
199
+ def update_extent(self):
200
+ """Update logical extent of the image (internal use only)."""
201
+ h, w = self.__buf.shape[:2]
202
+ ux, uy = self.xy_unit
203
+ w *= ux/2
204
+ h *= uy/2
205
+ self.__art.set_extent((-w,w,-h,h))
206
+
218
207
  selector = _Property('Selector')
219
208
  markers = _Property('Markers')
220
209
  region = _Property('Region')
221
210
 
211
+ artist = property(
212
+ lambda self: self.__art)
213
+
214
+ binning = property(
215
+ lambda self: self.__bins,
216
+ doc="Binning value resulting from the score_percentile.")
217
+
218
+ cuts = property(
219
+ lambda self: self.__cuts,
220
+ doc="Lower/Upper cutoff values of the buffer.")
221
+
222
+ image = property(
223
+ lambda self: self.__art.get_array(),
224
+ doc="A displayed image array<uint8>.")
225
+
226
+ clim = property(
227
+ lambda self: self.__art.get_clim(),
228
+ lambda self,v: self.__art.set_clim(v),
229
+ doc="Lower/Upper color limit values of the buffer.")
230
+
231
+ attributes = property(
232
+ lambda self: self.__attributes,
233
+ doc="Miscellaneous info about the frame/buffer.")
234
+
235
+ pathname = property(
236
+ lambda self: self.__attributes.get('pathname'),
237
+ lambda self,v: self.update_attributes({'pathname': v}),
238
+ doc="A fullpath of buffer, when bounds to file.")
239
+
240
+ annotation = property(
241
+ lambda self: self.__attributes.get('annotation', ''),
242
+ lambda self,v: self.update_attributes({'annotation': v}),
243
+ doc="Annotation of the buffer.")
244
+
245
+ @property
246
+ def name(self):
247
+ return self.__name
248
+
222
249
  @name.setter
223
250
  def name(self, v):
224
251
  self.__name = v
@@ -278,28 +305,6 @@ class AxesImagePhantom:
278
305
  """Page number in the parent book."""
279
306
  return self.parent.index(self)
280
307
 
281
- def update_buffer(self, buf=None):
282
- """Update buffer and the image (internal use only)."""
283
- if buf is not None:
284
- self.__buf = _to_buffer(buf)
285
-
286
- bins, vlim, img = _to_image(self.__buf,
287
- cutoff = self.parent.score_percentile,
288
- threshold = self.parent.nbytes_threshold,
289
- )
290
- self.__bins = bins
291
- self.__vlim = vlim
292
- self.__art.set_array(img)
293
- self.parent.handler('frame_modified', self)
294
-
295
- def update_extent(self):
296
- """Update logical extent of the image (internal use only)."""
297
- h, w = self.__buf.shape[:2]
298
- ux, uy = self.xy_unit
299
- w *= ux/2
300
- h *= uy/2
301
- self.__art.set_extent((-w,w,-h,h))
302
-
303
308
  @property
304
309
  def roi(self):
305
310
  """Current buffer ROI (region of interest)."""
@@ -315,9 +320,14 @@ class AxesImagePhantom:
315
320
  self.roi[:] = v # cannot broadcast input array into different shape
316
321
  self.update_buffer()
317
322
 
323
+ @property
324
+ def buffer(self):
325
+ return self.__buf
326
+
318
327
  @buffer.setter
319
328
  def buffer(self, v):
320
329
  self.update_buffer(v)
330
+ self.update_extent()
321
331
 
322
332
  def xytoc(self, x, y=None, nearest=True):
323
333
  """Convert xydata (x,y) -> data[(x,y)] value of neaerst pixel.
@@ -618,9 +628,6 @@ class GraphPlot(MatplotPanel):
618
628
  - aspect : aspect ratio
619
629
  - pathname : full path of the buffer file
620
630
  """
621
- if buf is None:
622
- return
623
-
624
631
  if isinstance(buf, str):
625
632
  buf = Image.open(buf)
626
633
 
@@ -687,9 +694,6 @@ class GraphPlot(MatplotPanel):
687
694
  j = self.index(j)
688
695
 
689
696
  buffers = [art.buffer for art in self.__Arts]
690
- if hasattr(j, '__iter__'):
691
- return [buffers[i] for i in j]
692
-
693
697
  return buffers[j] # j can also be slicing
694
698
 
695
699
  def __setitem__(self, j, v):
@@ -699,14 +703,14 @@ class GraphPlot(MatplotPanel):
699
703
  except ValueError:
700
704
  return self.load(v, name=j) # new buffer
701
705
 
702
- if hasattr(j, '__iter__') or isinstance(j, slice):
703
- raise ValueError("attempt to assign buffers into slice")
706
+ if isinstance(j, slice):
707
+ raise ValueError("attempt to assign buffers via slicing")
704
708
 
705
709
  if v is None:
706
- self.__delitem__(j)
710
+ raise ValueError("values must be buffers, not NoneType.")
707
711
  else:
708
712
  art = self.__Arts[j]
709
- art.update_buffer(v)
713
+ art.update_buffer(v) # update buffer
710
714
  art.update_extent()
711
715
  self.select(j)
712
716
 
@@ -714,9 +718,7 @@ class GraphPlot(MatplotPanel):
714
718
  if isinstance(j, str):
715
719
  j = self.index(j)
716
720
 
717
- if hasattr(j, '__iter__'):
718
- arts = [self.__Arts[i] for i in j]
719
- elif isinstance(j, slice):
721
+ if isinstance(j, slice):
720
722
  arts = self.__Arts[j]
721
723
  else:
722
724
  arts = [self.__Arts[j]]
@@ -784,16 +786,27 @@ class GraphPlot(MatplotPanel):
784
786
  if self.__Arts and self.__index is not None:
785
787
  return self.__Arts[self.__index]
786
788
 
787
- buffer = property(
788
- lambda self: self.frame and self.frame.buffer,
789
- lambda self,v: self.__setitem__(self.__index, v),
790
- lambda self: self.__delitem__(self.__index),
791
- doc="current buffer array")
789
+ @property
790
+ def buffer(self):
791
+ """Current buffer array."""
792
+ if self.frame:
793
+ return self.frame.buffer
794
+
795
+ @buffer.setter
796
+ def buffer(self, v):
797
+ if self.frame:
798
+ self.__setitem__(self.__index, v)
799
+ else:
800
+ self.load(v)
801
+
802
+ @property
803
+ def newbuffer(self):
804
+ """New buffer loader."""
805
+ return None
792
806
 
793
- newbuffer = property(
794
- lambda self: None,
795
- lambda self,v: self.load(v),
796
- doc="new buffer loader")
807
+ @newbuffer.setter
808
+ def newbuffer(self, v):
809
+ self.load(v)
797
810
 
798
811
  @property
799
812
  def unit(self):
@@ -951,7 +964,7 @@ class GraphPlot(MatplotPanel):
951
964
  data = frame.roi
952
965
  GraphPlot.clipboard_name = name
953
966
  GraphPlot.clipboard_data = data
954
- bins, vlim, img = _to_image(data, frame.vlim)
967
+ bins, vlim, img = _to_image(data, frame.cuts)
955
968
  Clipboard.imwrite(img)
956
969
  self.message("Write buffer to clipboard.")
957
970
  except Exception as e:
mwx/nutshell.py CHANGED
@@ -33,7 +33,8 @@ from .framework import CtrlInterface, AuiNotebook, Menu
33
33
 
34
34
 
35
35
  ## URL pattern (flag = re.M | re.A)
36
- url_re = r"https?://[\w/:%#$&?()~.=+-]+"
36
+ ## url_re = r"https?://[\w/:%#$&?()~.=+-]+"
37
+ url_re = r"https?://[\w/:%#$&?~.=+-]+" # excluding ()
37
38
 
38
39
  ## no-file pattern
39
40
  nofile_re = r'[\/:*?"<>|]'
@@ -630,7 +631,7 @@ class EditorInterface(AutoCompInterfaceMixin, CtrlInterface):
630
631
 
631
632
  ## Custom indicators ([BUG] indicator=1 is reset when the buffer is udpated.)
632
633
  ## [10-11] filter_text
633
- ## [2] URL for load_file
634
+ ## [2] URL
634
635
  ## [3] match_paren
635
636
  self.IndicatorSetStyle(10, stc.STC_INDIC_TEXTFORE)
636
637
  self.IndicatorSetForeground(10, "red")
@@ -1725,16 +1726,15 @@ class Buffer(EditorInterface, EditWindow):
1725
1726
  self.__path = Path(fn)
1726
1727
  if self.__path.is_file():
1727
1728
  self.__mtime = self.__path.stat().st_mtime # update timestamp (modified time)
1729
+ elif re.match(url_re, fn):
1730
+ self.__mtime = -1
1728
1731
  else:
1729
- if re.match(url_re, fn):
1730
- self.__mtime = -1
1731
- else:
1732
- try:
1733
- self.__path.resolve(True) # Check if the path format is valid.
1734
- except FileNotFoundError:
1735
- self.__mtime = False
1736
- except Exception:
1737
- self.__mtime = None
1732
+ try:
1733
+ self.__path.resolve(True) # Check if the path format is valid.
1734
+ except FileNotFoundError:
1735
+ self.__mtime = False # valid path (but not found)
1736
+ except OSError:
1737
+ self.__mtime = None # *invalid path*
1738
1738
  if self.__filename != fn:
1739
1739
  self.__filename = fn
1740
1740
  self.update_caption()
@@ -1751,10 +1751,11 @@ class Buffer(EditorInterface, EditWindow):
1751
1751
  """
1752
1752
  try:
1753
1753
  return self.__path.stat().st_mtime - self.__mtime
1754
- except Exception:
1755
- if isinstance(self.__mtime, float): # path not resolved.
1756
- self.__mtime = False
1757
- return self.__mtime
1754
+ except FileNotFoundError:
1755
+ self.__mtime = False # valid path (but not found)
1756
+ except OSError:
1757
+ pass
1758
+ return self.__mtime
1758
1759
 
1759
1760
  @property
1760
1761
  def need_buffer_save(self):
@@ -1962,20 +1963,20 @@ class Buffer(EditorInterface, EditWindow):
1962
1963
  ## Processing text selection, dragging, or dragging+
1963
1964
  evt.Skip()
1964
1965
  return
1966
+
1965
1967
  pos = evt.Position
1968
+ self.goto_char(pos) # Clear selection
1966
1969
  i = 2
1967
1970
  if self.IndicatorValueAt(i, pos): # [C-indic click]
1968
1971
  p = self.IndicatorStart(i, pos)
1969
1972
  q = self.IndicatorEnd(i, pos)
1970
1973
  url = self.GetTextRange(p, q).strip()
1971
- self.message("URL {!r}".format(url))
1972
1974
  if wx.GetKeyState(wx.WXK_SHIFT): # [C-S-indic click]
1973
1975
  import webbrowser
1974
1976
  return webbrowser.open(url)
1975
1977
  else:
1976
1978
  ## Note: post-call for the confirmation dialog.
1977
1979
  wx.CallAfter(self.parent.load_file, url)
1978
- self.anchor = pos # Clear selection
1979
1980
 
1980
1981
  def on_modified(self, buf):
1981
1982
  """Called when the buffer is modified."""
@@ -2416,8 +2417,8 @@ class EditorBook(AuiNotebook, CtrlInterface):
2416
2417
  buf._load_textfile(res.text, filename)
2417
2418
  self.swap_buffer(buf, lineno)
2418
2419
  return True
2419
- return False
2420
- ## raise Exception("The requested URL was not found", filename)
2420
+ ## raise Exception("URL not found:", filename)
2421
+ res.raise_for_status() # raise HTTP error
2421
2422
  if buf._load_file(filename):
2422
2423
  self.swap_buffer(buf, lineno)
2423
2424
  return True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mwxlib
3
- Version: 1.2.0
3
+ Version: 1.2.3
4
4
  Summary: A wrapper of matplotlib and wxPython (phoenix)
5
5
  Home-page: https://github.com/komoto48g/mwxlib
6
6
  Author: Kazuya O'moto
@@ -1,14 +1,14 @@
1
1
  mwx/__init__.py,sha256=pS7ZG8QKRypiFFiaWAq_opBB6I_1viZ0zUMk2TbjzE0,667
2
2
  mwx/bookshelf.py,sha256=b_TMDaNIzLHoL0xbbqb3tt0BnRvhLAqaCn_pBdrigZw,7523
3
3
  mwx/controls.py,sha256=X4zx2h6oggUsQxi2PRk4RUsJieYTmcAPIvWwaz-ysTI,48107
4
- mwx/framework.py,sha256=8QHKtncqf_ip6BkcVA9CFttFFsjw4EgxEkT9efltECg,76125
4
+ mwx/framework.py,sha256=wXI4nzQcG0NV3c5ne4io9HJ1y7jd7xbjB_cOao8HKsU,76125
5
5
  mwx/graphman.py,sha256=RqD0W9I2BvJ3Q2kyMiyyg4n-T4-_x7PDuCI5bGAg5k4,70110
6
6
  mwx/images.py,sha256=oxCn0P-emiWujSS2gUgU5TUnr5cPjix2jBcjOBDr24I,48701
7
- mwx/matplot2.py,sha256=RuVWXC2A_qgZRNmBBptbHDn5MyxaWBqp3ru4bP_lDE0,33150
8
- mwx/matplot2g.py,sha256=dBAODQvSM_yf2uQUCrRO03ZOK3MycR8lEXTJfRXDlbY,64432
7
+ mwx/matplot2.py,sha256=Zwte-wwzCg_OHzsBniVgKdaNLzsvJaa1gc0n7VdAqxw,33150
8
+ mwx/matplot2g.py,sha256=tShPGy7whj51yvANja-MDmjfxiLubQ1C6rCsBZ0DAnY,64473
9
9
  mwx/matplot2lg.py,sha256=JRWjWnLJUytbSq6wxs4P0gbVUr3xoLSF6Wwqd5V_pJI,27404
10
10
  mwx/mgplt.py,sha256=8mXbHpCmm7lz3XbAxOg7IVC7DaSGBEby1UfTlMl9kjk,5604
11
- mwx/nutshell.py,sha256=qPMOa4froZAhslacI2Oz_Xhe99zU6ucgh42zwe3sKxQ,140838
11
+ mwx/nutshell.py,sha256=7nQ7UUFM9kvjDjHNUEdOkkeqZPiU6zOERwamqBdJpQs,140856
12
12
  mwx/testsuite.py,sha256=kiM3-BVhr42LRRN7xG7pYl3at8o2vnypWSxD8KRvA7c,1228
13
13
  mwx/utilus.py,sha256=HFvP682SyeSp8yNfUrdUXPhWdLuWVlsUSg6LqNBJOT8,37451
14
14
  mwx/wxmon.py,sha256=yzWqrbY6LzpfRwQeytYUeqFhFuLVm_XEvrVAL_k0HBQ,12756
@@ -22,8 +22,8 @@ mwx/plugins/frame_listview.py,sha256=gowjQ-ARNonMkDSXkQgPKq4U9YBJ-vQ0jK2krBVOdCs
22
22
  mwx/plugins/line_profile.py,sha256=zzm6_7lnAnNepLbh07ordp3nRWDFQJtu719ZVjrVf8s,819
23
23
  mwx/py/__init__.py,sha256=xykgfOytOwNuvXsfkLoumFZSTN-iBsHOjczYXngjmUE,12
24
24
  mwx/py/filling.py,sha256=fumUG1F5M9TL-Dfqni4G85uk7TmvnUunTbdcPDV0vfo,16857
25
- mwxlib-1.2.0.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
26
- mwxlib-1.2.0.dist-info/METADATA,sha256=0hdCtq1FWS8gy0i8hVk3Yslu0L7fmOp9ZBoxc0QVIlQ,7258
27
- mwxlib-1.2.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
28
- mwxlib-1.2.0.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
29
- mwxlib-1.2.0.dist-info/RECORD,,
25
+ mwxlib-1.2.3.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
26
+ mwxlib-1.2.3.dist-info/METADATA,sha256=2sSF51qYRi78w0McPUzYn2yr9H1ISRKXMfvWSB-ATls,7258
27
+ mwxlib-1.2.3.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
28
+ mwxlib-1.2.3.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
29
+ mwxlib-1.2.3.dist-info/RECORD,,
File without changes