mwxlib 1.2.5__py3-none-any.whl → 1.2.8__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.5"
4
+ __version__ = "1.2.8"
5
5
  __author__ = "Kazuya O'moto <komoto@jeol.co.jp>"
6
6
 
7
7
  from contextlib import contextmanager
mwx/graphman.py CHANGED
@@ -1410,7 +1410,7 @@ class Frame(mwx.Frame):
1410
1410
  frames = self.load_buffer(paths, view)
1411
1411
  if frames:
1412
1412
  for frame in frames:
1413
- frame.update_attributes(res.get(frame.name))
1413
+ frame.update_attr(res.get(frame.name))
1414
1414
 
1415
1415
  n = len(frames)
1416
1416
  self.message(
@@ -1486,14 +1486,16 @@ class Frame(mwx.Frame):
1486
1486
  res.update(eval(i.read())) # read res <dict>
1487
1487
 
1488
1488
  for name, attr in tuple(res.items()):
1489
- fn = os.path.join(savedir, name)
1490
- if not os.path.exists(fn): # search by relpath (dir+name)
1491
- fn = attr.get('pathname')
1492
- if not os.path.exists(fn): # check & pop missing files
1493
- res.pop(name)
1494
- mis.update({name:attr})
1489
+ fn = os.path.join(savedir, name) # search by relpath (dir / name)
1490
+ if os.path.exists(fn):
1491
+ attr.update(pathname=fn) # if found, update pathname
1495
1492
  else:
1496
- attr.update(pathname=fn)
1493
+ fn = attr.get('pathname') # if not found, try pathname
1494
+ if fn.startswith(r'\\'):
1495
+ warn(f"The pathnme of {fn!r} contains network path, "
1496
+ f"so the search may take long time.", stacklevel=3)
1497
+ if not os.path.exists(fn):
1498
+ mis[name] = res.pop(name) # pop missing items
1497
1499
  except FileNotFoundError:
1498
1500
  pass
1499
1501
  except Exception as e:
@@ -1540,7 +1542,7 @@ class Frame(mwx.Frame):
1540
1542
  res, mis = self.read_attributes(fn)
1541
1543
  savedirs[savedir] = res
1542
1544
  results = savedirs[savedir]
1543
- frame.update_attributes(results.get(frame.name))
1545
+ frame.update_attr(results.get(frame.name))
1544
1546
  return frames
1545
1547
 
1546
1548
  def save_frame(self, path=None, frame=None):
mwx/matplot2g.py CHANGED
@@ -118,25 +118,22 @@ class AxesImagePhantom:
118
118
  """Phantom of frame facade
119
119
 
120
120
  Args:
121
- buf : buffer
122
- name : buffer name
123
- show : show immediately when loaded
124
- aspect : initial aspect ratio
125
- localunit : initial localunit
126
- attributes : additional info:dict
121
+ buf : buffer
122
+ name : buffer name
123
+ show : show immediately when loaded
124
+ **kwargs: frame attributes
127
125
 
128
126
  Note:
129
127
  Due to the problem of performance,
130
128
  the image pixel size could be reduced by binning.
131
129
  """
132
- def __init__(self, parent, buf, name, show=True,
133
- localunit=None, aspect=1.0, **attributes):
130
+ def __init__(self, parent, buf, name, show=True, **kwargs):
134
131
  self.parent = parent
135
132
  self.__name = name
136
- self.__localunit = localunit or None # [+] value, no assertion
137
- self.__aspect_ratio = aspect
138
- self.__attributes = attributes
139
- self.__attributes['localunit'] = self.__localunit
133
+ self.__attributes = kwargs
134
+ self.__localunit = kwargs.get('localunit')
135
+ self.__center = kwargs.get('center', (0, 0))
136
+ self.__aspect_ratio = 1
140
137
  self.__buf = _to_buffer(buf)
141
138
  bins, vlim, img = _to_image(self.__buf,
142
139
  cutoff = self.parent.score_percentile,
@@ -151,7 +148,7 @@ class AxesImagePhantom:
151
148
  visible = show,
152
149
  picker = True,
153
150
  )
154
- self.update_extent() # this determines the aspect ratio
151
+ self.update_extent()
155
152
 
156
153
  def __getattr__(self, attr):
157
154
  return getattr(self.__art, attr)
@@ -160,22 +157,23 @@ class AxesImagePhantom:
160
157
  ## Called in `on_pick` and `__contains__` to check objects in.
161
158
  return x is self.__art
162
159
 
163
- def update_attributes(self, attr=None, **kwargs):
164
- """Update frame-specifc attributes.
165
- The frame holds any attributes with dictionary
166
- There are some keys which acts as the value setter when given,
167
- `annotation` also shows the message with infobar
168
- `localunit` also updates the frame.unit
160
+ def update_attr(self, attr):
161
+ """Update frame-specifc attributes:
162
+
163
+ annotation : aux info (also displayed as a message in the infobar)
164
+ center : frame.center defaults to (0, 0)
165
+ localunit : frame.unit
166
+ pathname : full path of the buffer file
169
167
  """
170
- attr = attr or {}
171
- attr.update(kwargs)
168
+ if not attr:
169
+ return
172
170
  self.__attributes.update(attr)
173
171
 
174
172
  if 'localunit' in attr:
175
- self.unit = attr['localunit']
173
+ self.unit = attr['localunit'] # => [frame_updated]
176
174
 
177
- if 'aspect' in attr:
178
- self.aspect_ratio = attr['aspect']
175
+ if 'center' in attr:
176
+ self.center = attr['center'] # => [frame_updated]
179
177
 
180
178
  if 'annotation' in attr:
181
179
  v = attr['annotation']
@@ -205,7 +203,8 @@ class AxesImagePhantom:
205
203
  ux, uy = self.xy_unit
206
204
  w *= ux/2
207
205
  h *= uy/2
208
- self.__art.set_extent((-w,w,-h,h))
206
+ cx, cy = self.center
207
+ self.__art.set_extent((cx-w, cx+w, cy-h, cy+h))
209
208
 
210
209
  selector = _Property('Selector')
211
210
  markers = _Property('Markers')
@@ -233,16 +232,16 @@ class AxesImagePhantom:
233
232
 
234
233
  attributes = property(
235
234
  lambda self: self.__attributes,
236
- doc="Miscellaneous info about the frame/buffer.")
235
+ doc="Auxiliary info about the frame.")
237
236
 
238
237
  pathname = property(
239
238
  lambda self: self.__attributes.get('pathname'),
240
- lambda self,v: self.update_attributes({'pathname': v}),
239
+ lambda self,v: self.update_attr({'pathname': v}),
241
240
  doc="Fullpath of the buffer, if bound to a file.")
242
241
 
243
242
  annotation = property(
244
243
  lambda self: self.__attributes.get('annotation', ''),
245
- lambda self,v: self.update_attributes({'annotation': v}),
244
+ lambda self,v: self.update_attr({'annotation': v}),
246
245
  doc="Annotation of the buffer.")
247
246
 
248
247
  @property
@@ -265,17 +264,16 @@ class AxesImagePhantom:
265
264
 
266
265
  @unit.setter
267
266
  def unit(self, v):
267
+ if v == self.__localunit: # no effect
268
+ return
268
269
  if v is None or np.isnan(v): # nan => undefined
269
- v = self.parent.unit
270
- self.__localunit = None
270
+ v = None
271
271
  elif np.isinf(v):
272
272
  raise ValueError("The unit value must not be inf")
273
273
  elif v <= 0:
274
274
  raise ValueError("The unit value must be greater than zero")
275
- else:
276
- if v == self.__localunit: # no effect when v is localunit
277
- return
278
- self.__localunit = v
275
+
276
+ self.__localunit = v
279
277
  self.__attributes['localunit'] = self.__localunit
280
278
  self.update_extent()
281
279
  self.parent.handler('frame_updated', self)
@@ -290,6 +288,18 @@ class AxesImagePhantom:
290
288
  u = self.__localunit or self.parent.unit
291
289
  return (u, u * self.__aspect_ratio)
292
290
 
291
+ @property
292
+ def center(self):
293
+ """Center of logical unit."""
294
+ return self.__center
295
+
296
+ @center.setter
297
+ def center(self, v):
298
+ self.__center = tuple(v)
299
+ self.__attributes['center'] = self.__center
300
+ self.update_extent()
301
+ self.parent.handler('frame_updated', self)
302
+
293
303
  @property
294
304
  def aspect_ratio(self):
295
305
  """Aspect ratio of logical unit."""
@@ -297,9 +307,7 @@ class AxesImagePhantom:
297
307
 
298
308
  @aspect_ratio.setter
299
309
  def aspect_ratio(self, v):
300
- if v == self.__aspect_ratio:
301
- return
302
- self.__aspect_ratio = v or 1.0
310
+ self.__aspect_ratio = v or 1
303
311
  self.update_extent()
304
312
  self.parent.handler('frame_updated', self)
305
313
 
@@ -624,12 +632,7 @@ class GraphPlot(MatplotPanel):
624
632
  name : buffer name (default to *temp*).
625
633
  pos : Insertion position in the frame list.
626
634
  show : Show immediately when loaded.
627
-
628
635
  **kwargs: frame attributes.
629
-
630
- - localunit : localunit
631
- - aspect : aspect ratio
632
- - pathname : full path of the buffer file
633
636
  """
634
637
  if isinstance(buf, str):
635
638
  buf = Image.open(buf)
@@ -645,8 +648,8 @@ class GraphPlot(MatplotPanel):
645
648
  j = names.index(name) # existing frame
646
649
  if j != -1:
647
650
  art = self.__Arts[j]
648
- art.update_buffer(buf) # => [frame_modified]
649
- art.update_attributes(kwargs) # => [frame_updated] localunit => [canvas_draw]
651
+ art.update_buffer(buf) # => [frame_modified]
652
+ art.update_attr(kwargs) # => [frame_updated] localunit => [canvas_draw]
650
653
  art.update_extent()
651
654
  if show:
652
655
  self.select(j)
@@ -697,17 +700,19 @@ class GraphPlot(MatplotPanel):
697
700
  j = self.index(j)
698
701
 
699
702
  buffers = [art.buffer for art in self.__Arts]
703
+ if hasattr(j, '__iter__'):
704
+ return [buffers[i] for i in j]
700
705
  return buffers[j] # j can also be slicing
701
706
 
702
707
  def __setitem__(self, j, v):
703
708
  if v is None:
704
- raise ValueError("values must be buffers, not NoneType.")
709
+ raise ValueError("values must be buffers, not NoneType")
705
710
 
706
711
  if isinstance(j, str):
707
712
  return self.load(v, name=j) # update buffer or new buffer
708
713
 
709
- if isinstance(j, slice):
710
- raise ValueError("attempt to assign buffers via slicing")
714
+ if isinstance(j, slice) or hasattr(j, '__iter__'):
715
+ raise ValueError("attempt to assign buffers via slicing or iterator")
711
716
 
712
717
  art = self.__Arts[j]
713
718
  art.update_buffer(v) # update buffer
@@ -718,7 +723,9 @@ class GraphPlot(MatplotPanel):
718
723
  if isinstance(j, str):
719
724
  j = self.index(j)
720
725
 
721
- if isinstance(j, slice):
726
+ if hasattr(j, '__iter__'):
727
+ arts = [self.__Arts[i] for i in j]
728
+ elif isinstance(j, slice):
722
729
  arts = self.__Arts[j]
723
730
  else:
724
731
  arts = [self.__Arts[j]]
@@ -815,13 +822,13 @@ class GraphPlot(MatplotPanel):
815
822
 
816
823
  @unit.setter
817
824
  def unit(self, v):
825
+ if v == self.__unit: # no effect unless unit changes
826
+ return
818
827
  if v is None or np.isnan(v) or np.isinf(v):
819
828
  raise ValueError("The unit value must not be nan or inf")
820
829
  elif v <= 0:
821
830
  raise ValueError("The unit value must be greater than zero")
822
831
  else:
823
- if v == self.__unit: # no effect unless unit changes
824
- return
825
832
  self.__unit = v
826
833
  for art in self.__Arts:
827
834
  art.update_extent()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mwxlib
3
- Version: 1.2.5
3
+ Version: 1.2.8
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,11 +1,11 @@
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=5PCy3zguDRuwYl89P9tOCUU7xAGUETs944qZBy5MS9g,48146
4
- mwx/framework.py,sha256=c0o6IXrdgvfpnPXHPNYU7isqzOydXwtiMY7-qRXMFyQ,76125
5
- mwx/graphman.py,sha256=RqD0W9I2BvJ3Q2kyMiyyg4n-T4-_x7PDuCI5bGAg5k4,70110
4
+ mwx/framework.py,sha256=aWRouIUMqBCH3Uv1FpGC6GKfbwb79fSV_e23Limhx-E,76125
5
+ mwx/graphman.py,sha256=sKwPy31H4lwtShTAui_6upe_Ys2-MwBHhdFq-3onBNE,70328
6
6
  mwx/images.py,sha256=oxCn0P-emiWujSS2gUgU5TUnr5cPjix2jBcjOBDr24I,48701
7
7
  mwx/matplot2.py,sha256=Zwte-wwzCg_OHzsBniVgKdaNLzsvJaa1gc0n7VdAqxw,33150
8
- mwx/matplot2g.py,sha256=ywvu5-QAIgv4jc1kalNYgVGcl4RoY9Y1Dx1qtteaqXk,64195
8
+ mwx/matplot2g.py,sha256=ceeAjFkrDz49aSLo_9dIWZZd4HhnSjxe8u9G_ipBHek,64195
9
9
  mwx/matplot2lg.py,sha256=JRWjWnLJUytbSq6wxs4P0gbVUr3xoLSF6Wwqd5V_pJI,27404
10
10
  mwx/mgplt.py,sha256=8mXbHpCmm7lz3XbAxOg7IVC7DaSGBEby1UfTlMl9kjk,5604
11
11
  mwx/nutshell.py,sha256=7nQ7UUFM9kvjDjHNUEdOkkeqZPiU6zOERwamqBdJpQs,140856
@@ -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.5.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
26
- mwxlib-1.2.5.dist-info/METADATA,sha256=HZpDkw3rpf_1eFrLWB4UFT2sGfuJQ0nDV7cUyWuot-w,7258
27
- mwxlib-1.2.5.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
28
- mwxlib-1.2.5.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
29
- mwxlib-1.2.5.dist-info/RECORD,,
25
+ mwxlib-1.2.8.dist-info/LICENSE,sha256=PGtRKCaTkmUDlBQwpptJAxJtdqxIUtAmdBsaT9nUVkA,1091
26
+ mwxlib-1.2.8.dist-info/METADATA,sha256=FKLkLzB6CRVzJ0JFJdYx3ngDSQR5aHxMm0HdQL5feTA,7258
27
+ mwxlib-1.2.8.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
28
+ mwxlib-1.2.8.dist-info/top_level.txt,sha256=SI1Mh118AstnUFGPNq5aMNKiAnVNmZk1S9Ij-OwAEpY,4
29
+ mwxlib-1.2.8.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.7.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5