ipyvasp 0.8.5__py2.py3-none-any.whl → 0.8.7__py2.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.
ipyvasp/_lattice.py CHANGED
@@ -15,7 +15,7 @@ from matplotlib.collections import LineCollection
15
15
  from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
16
16
  import matplotlib.colors as mplc
17
17
 
18
- from ipywidgets import interactive
18
+ from ipywidgets import interactive, IntSlider
19
19
 
20
20
  # Inside packages import
21
21
  from .core import plot_toolkit as ptk
@@ -1635,13 +1635,13 @@ def filter_sites(poscar_data, func, tol = 0.01):
1635
1635
  pos = data['positions'][indices]
1636
1636
  qos = data['positions'][others] # need edge items to include
1637
1637
 
1638
- if qos.shape:
1638
+ if qos.size:
1639
1639
  qos = np.concatenate([[[i] for i in others], qos], axis=1) # need to keep index
1640
1640
  qos = np.array([qos + [0, *p] for p in product([-1,0,1],[-1,0,1],[-1,0,1])]).reshape((-1,4)) # all possible translations
1641
1641
  qos = qos[(qos[:,1:] < 1 + tol).all(axis=1) & (qos[:,1:] > -tol).all(axis=1)]# only in cell range
1642
1642
  qos = qos[[func(*q) for q in qos]] # masked only those are true
1643
1643
 
1644
- if qos.shape:
1644
+ if qos.size:
1645
1645
  pos = np.concatenate([pos, qos[:,1:]],axis=0)
1646
1646
 
1647
1647
  all_pos.append(pos)
@@ -1681,10 +1681,10 @@ def iplot_lattice(
1681
1681
 
1682
1682
  Parameters
1683
1683
  ----------
1684
- sizes : float or tuple
1685
- Size of sites. Either one int/float or list equal to type of ions.
1686
- colors : tuple
1687
- Sequence of colors for each type. Automatically generated if not provided.
1684
+ sizes : float or dict of type -> float
1685
+ Size of sites. Either one int/float or a mapping like {'Ga': 2, ...}.
1686
+ colors : color or dict of type -> color
1687
+ Mapping of colors like {'Ga': 'red, ...} or a single color. Automatically generated color for missing types.
1688
1688
  bond_length : float or dict
1689
1689
  Length of bond in Angstrom. Auto calculated if not provides. Can be a dict like {'Fe-O':3.2,...} to specify bond length between specific types.
1690
1690
  bond_kws : dict
@@ -1717,17 +1717,9 @@ def iplot_lattice(
1717
1717
  fig = go.Figure()
1718
1718
 
1719
1719
  uelems = poscar_data.types.to_dict()
1720
- if not isinstance(sizes, (list, tuple, np.ndarray)):
1721
- sizes = [sizes for elem in uelems.keys()]
1722
-
1723
- if colors and len(colors) != len(uelems.keys()):
1724
- print(
1725
- "Warning: Number of colors does not match number of atom types. Using default colors."
1726
- )
1727
-
1728
- if (colors is None) or len(colors) != len(uelems.keys()):
1729
- colors = [_atom_colors[elem] for elem in uelems.keys()]
1730
- colors = ["rgb({},{},{})".format(*[int(_c * 255) for _c in c]) for c in colors]
1720
+ _fcs = _fix_color_size(uelems, colors, sizes, 10, backend = 'plotly')
1721
+ sizes = [v['size'] for v in _fcs.values()]
1722
+ colors = [v['color'] for v in _fcs.values()]
1731
1723
 
1732
1724
  _colors = np.array([colors[i] for i, vs in enumerate(uelems.values()) for v in vs],dtype=object) # could be mixed color types
1733
1725
 
@@ -1854,6 +1846,33 @@ def _validate_label_func(fmt_label, parameter):
1854
1846
  elif not isinstance(test_out, str):
1855
1847
  raise ValueError("fmt_label must return a string or a list/tuple of length 2.")
1856
1848
 
1849
+ def _fix_color_size(types, colors, sizes, default_size, backend=None):
1850
+ cs = {key: {'color': _atom_colors.get(key, 'blue'), 'size': default_size} for key in types}
1851
+ for k in cs:
1852
+ if len(cs[k]['color']) == 3: # otherwise its blue
1853
+ if backend == 'plotly':
1854
+ cs[k]['color'] = "rgb({},{},{})".format(*[int(255*c) for c in cs[k]['color']])
1855
+ elif backend == 'ngl':
1856
+ cs[k]['color'] = mplc.to_hex(cs[k]['color'])
1857
+
1858
+ if isinstance(sizes,(int,float,np.integer)):
1859
+ for k in cs:
1860
+ cs[k]['size'] = sizes
1861
+ elif isinstance(sizes, dict):
1862
+ for k,v in sizes.items():
1863
+ cs[k]['size'] = v
1864
+ else:
1865
+ raise TypeError("sizes should be a single int/float or dict as {'Ga':10,'As':15,...}")
1866
+
1867
+ if isinstance(colors,dict):
1868
+ for k,v in colors.items():
1869
+ cs[k]['color'] = v
1870
+ elif colors is not None and isinstance(colors,(str,list,tuple,np.ndarray)):
1871
+ for k in cs:
1872
+ cs[k]['color'] = colors
1873
+ else:
1874
+ raise TypeError("colors should be a single valid color or dict as {'Ga':'red','As':'blue',...}")
1875
+ return cs
1857
1876
 
1858
1877
  # Cell
1859
1878
  def splot_lattice(
@@ -1880,10 +1899,10 @@ def splot_lattice(
1880
1899
  ----------
1881
1900
  plane : str
1882
1901
  Plane to plot. Either 'xy','xz','yz' or None for 3D plot.
1883
- sizes : float or tuple
1884
- Size of sites. Either one int/float or list equal to type of ions.
1885
- colors : tuple
1886
- Sequence of colors for each ion type. If None, automatically generated.
1902
+ sizes : float or dict of type -> float
1903
+ Size of sites. Either one int/float or a mapping like {'Ga': 2, ...}.
1904
+ colors : color or dict of type -> color
1905
+ Mapping of colors like {'Ga': 'red, ...} or a single color. Automatically generated color for missing types.
1887
1906
  bond_length : float or dict
1888
1907
  Length of bond in Angstrom. Auto calculated if not provides. Can be a dict like {'Fe-O':3.2,...} to specify bond length between specific types.
1889
1908
  alpha : float
@@ -1941,23 +1960,10 @@ def splot_lattice(
1941
1960
  print(f"Warning: Parameters {list(kwargs.keys())} are not used when `plot_cell = False`.")
1942
1961
 
1943
1962
  uelems = poscar_data.types.to_dict()
1944
- if not isinstance(sizes, (list, tuple, np.ndarray)):
1945
- if not isinstance(sizes, (int, float, np.integer)):
1946
- raise ValueError("sizes must be a number or a list/tuple of numbers.")
1947
- sizes = [sizes for _ in uelems]
1948
-
1949
- if len(sizes) != len(uelems):
1950
- raise ValueError(
1951
- f"Length of `sizes` must be equal to number of elements in POSCAR. Got {len(sizes)} sizes for {len(uelems)} elements."
1952
- )
1953
-
1954
- if colors and len(colors) != len(uelems.keys()):
1955
- print(
1956
- "Warning: Number of colors does not match number of atom types. Using default colors."
1957
- )
1958
1963
 
1959
- if (colors is None) or len(colors) != len(uelems.keys()):
1960
- colors = [_atom_colors[elem] for elem in uelems.keys()]
1964
+ _fcs = _fix_color_size(uelems, colors, sizes, 50)
1965
+ sizes = [v['size'] for v in _fcs.values()]
1966
+ colors = [v['color'] for v in _fcs.values()]
1961
1967
 
1962
1968
  # Before doing other stuff, create something for legend.
1963
1969
  if showlegend:
@@ -2691,8 +2697,12 @@ def deform_poscar(poscar_data, deformation):
2691
2697
  def view_poscar(poscar_data, **kwargs):
2692
2698
  "View a POSCAR in a jupyter notebook. kwargs are passed to splot_lattice. After setting a view, you can do view.f(**view.kwargs) to get same plot in a cell."
2693
2699
 
2694
- def view(elev=30, azim=30, roll=0):
2700
+ def view(elev, azim, roll):
2695
2701
  ax = splot_lattice(poscar_data, **kwargs)
2696
2702
  ax.view_init(elev=elev, azim=azim, roll=roll)
2703
+
2704
+ elev = IntSlider(description='elev', min=0,max=180,value=30, continuous_update=False)
2705
+ azim = IntSlider(description='azim', min=0,max=360,value=30, continuous_update=False)
2706
+ roll = IntSlider(description='roll', min=0,max=360,value=0, continuous_update=False)
2697
2707
 
2698
- return interactive(view, elev=(0, 180), azim=(0, 360), roll=(0, 360))
2708
+ return interactive(view, elev=elev, azim=azim, roll=roll)
ipyvasp/_version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.8.5"
1
+ __version__ = "0.8.7"
ipyvasp/lattice.py CHANGED
@@ -75,7 +75,7 @@ def download_structure(
75
75
  def ngl_viewer(
76
76
  poscar,
77
77
  colors=None,
78
- sizes=None,
78
+ sizes=0.5,
79
79
  plot_cell=True,
80
80
  linewidth=0.05,
81
81
  color=[0, 0, 0.2],
@@ -91,13 +91,12 @@ def ngl_viewer(
91
91
  Parameters
92
92
  ----------
93
93
  poscar : ipyvasp.POSCAR
94
- colors : list or str
95
- List of colors for each atom type. If str, use sames colors for all.
94
+ sizes : float or dict of type -> float
95
+ Size of sites. Either one int/float or a mapping like {'Ga': 2, ...}.
96
+ colors : color or sheme name or dict of type -> color
97
+ Mapping of colors like {'Ga': 'red, ...} or a single color. Automatically generated color for missing types.
96
98
  If `colors = 'element'`, then element colors from `nglview` will be used.
97
99
  You can use `nglview.color.COLOR_SCHEME` to see available color schemes to use.
98
- If colors is None, then default colors from ipyvasp will be used that are same in `[i,s]plot_lattice`.
99
- sizes : list
100
- List of sizes for each atom type.
101
100
  plot_cell : bool
102
101
  Plot unit cell. Default True.
103
102
  linewidth : float
@@ -136,31 +135,13 @@ def ngl_viewer(
136
135
 
137
136
  # Only show equivalent sites if plotting cell, only shift origin otherwise
138
137
  poscar = POSCAR( # don't change instance itself, make new one
139
- data=plat._fix_sites(
140
- poscar.data, eqv_sites=True if plot_cell else False, origin=origin
141
- )
138
+ data=plat._fix_sites(poscar.data, eqv_sites=True if plot_cell else False, origin=origin)
142
139
  )
143
140
 
144
- _types = list(poscar.data.types.keys())
145
- _sizes = [0.5 for _ in _types]
146
- _colors = [mcolors.to_hex(plat._atom_colors[e]) for e in _types]
147
-
148
- if sizes:
149
- if len(sizes) != len(_types):
150
- raise ValueError(
151
- "sizes must have the same length as the number of atom types."
152
- )
153
- _sizes = sizes
154
-
155
- if colors:
156
- if isinstance(colors, str):
157
- _colors = [colors for _ in _types] # All same color, may be 'element'
158
- else:
159
- if len(colors) != len(_types):
160
- raise ValueError(
161
- "colors must have the same length as the number of atom types."
162
- )
163
- _colors = [mcolors.to_hex(c) for c in colors]
141
+ _types = poscar.data.types.to_dict()
142
+ _fcs = plat._fix_color_size(_types,colors,sizes,0.5, backend='ngl')
143
+ _sizes = [v['size'] for v in _fcs.values()]
144
+ _colors = [v['color'] for v in _fcs.values()]
164
145
 
165
146
  view = nv.NGLWidget(
166
147
  nv.ASEStructure(poscar.to_ase()),
@@ -201,16 +182,19 @@ def ngl_viewer(
201
182
 
202
183
 
203
184
  def weas_viewer(poscar,
204
- sizes=None,
185
+ sizes=1,
205
186
  colors=None,
206
187
  bond_length=None,
207
188
  model_style = 1,
208
- plot_cell=True
189
+ plot_cell=True,
190
+ origin = (0,0,0)
209
191
  ):
210
192
  """
211
- colors : list or str
212
- List of colors for each atom type. If str, use 'VESTA','JMOL','CPK'.
213
- By default, ipyvasp colors are used.
193
+ sizes : float or dict of type -> float
194
+ Size of sites. Either one int/float or a mapping like {'Ga': 2, ...}.
195
+ colors : color, color scheme or dict of type -> color
196
+ Mapping of colors like {'Ga': 'red, ...} or a single color. Automatically generated color for missing types.
197
+ You can use color schemes as 'VESTA','JMOL','CPK'.
214
198
  sizes : list
215
199
  List of sizes for each atom type.
216
200
  model_type: int
@@ -221,18 +205,23 @@ def weas_viewer(poscar,
221
205
  Length of bond in Angstrom. Auto calculated if not provides. Can be a dict like {'Fe-O':3.2,...} to specify bond length between specific types.
222
206
 
223
207
  Returns a WeasWidget instance. You can use `.export_image`, `save_image` and other operations on it.
208
+ Read what you can do more with `WeasWidget` [here](https://weas-widget.readthedocs.io/en/latest/index.html).
224
209
  """
225
210
 
226
211
  from weas_widget import WeasWidget
227
212
 
228
213
  if len(poscar.data.positions) < 1:
229
214
  raise ValueError("Need at least 1 atom!")
215
+
216
+ # Only show equivalent sites if plotting cell, only shift origin otherwise
217
+ poscar = POSCAR( # don't change instance itself, make new one
218
+ data=plat._fix_sites(poscar.data, eqv_sites=True if plot_cell else False, origin=origin)
219
+ )
230
220
 
231
221
  w = WeasWidget(from_ase=poscar.to_ase())
232
- w.avr.show_bonded_atoms = True
222
+ w.avr.show_bonded_atoms = False if plot_cell else True # plot_cell fix atoms itself
233
223
  w.avr.model_style = model_style
234
- w.avr.show_cell = plot_cell
235
-
224
+ w.avr.show_cell = plot_cell
236
225
 
237
226
  if bond_length:
238
227
  if isinstance(bond_length,(int,float)):
@@ -242,40 +231,30 @@ def weas_viewer(poscar,
242
231
  elif isinstance(bond_length, dict):
243
232
  for key, value in bond_length.items():
244
233
  w.avr.bond.settings[key].update({'max': value})
245
-
246
- if sizes is not None:
247
- if not isinstance(sizes, (list,tuple)) or len(sizes) != len(poscar.data.types):
248
- raise ValueError(f"sizes should be list/tuple of same sizes as atom types = {len(poscar.data.types)}.")
249
- for key, value in zip(poscar.data.types,sizes):
250
- w.avr.species.settings[key].update({"radius": value})
251
234
 
252
- if colors is None:
253
- colors = [plat._atom_colors[key] for key in poscar.data.types]
254
-
255
- if isinstance(colors, str):
256
- if not colors in ['VESTA','JMOL','CPK']:
257
- raise ValueError("colors should be one of ['VESTA','JMOL','CPK'] if given as string!")
258
-
259
- w.avr.color_type = colors
235
+ _fcs = plat._fix_color_size(poscar.data.types.to_dict(), colors, sizes, 1)
260
236
 
261
- if not isinstance(colors, str):
262
- if not isinstance(colors, (list,tuple)) or len(colors) != len(poscar.data.types):
263
- raise ValueError(f"colors should be list/tuple of same sizes as atom types = {len(poscar.data.types)}.")
237
+ for key, value in _fcs.items():
238
+ w.avr.species.settings[key].update({"radius": value["size"]})
264
239
 
265
- colors = {key: value for key, value in zip(poscar.data.types,colors)}
240
+ if isinstance(colors, str) and colors in ['VESTA','JMOL','CPK']:
241
+ w.avr.color_type = colors
242
+ else:
243
+ colors = {key: value["color"] for key, value in _fcs.items()}
266
244
  for key,value in colors.items():
267
245
  w.avr.species.settings[key].update({"color": value})
268
246
  for (k1,c1), (k2,c2) in permutations(colors.items(),2):
269
247
  with suppress(KeyError):
270
248
  w.avr.bond.settings[f'{k1}-{k2}'].update({'color1':c1,'color2':c2})
271
-
249
+
272
250
  return w
273
251
 
274
252
 
275
253
  class POSCAR:
276
254
  _cb_instance = {} # Loads last clipboard data if not changed
277
255
  _mp_instance = {} # Loads last mp data if not changed
278
- _update_kws = {} # kwargs to pass to auto update figurewidget
256
+ _plotly_kws = {} # kwargs to pass to auto update figurewidget
257
+ _weas_kws = {}
279
258
 
280
259
  def __init__(self, path=None, content=None, data=None):
281
260
  """
@@ -365,6 +344,7 @@ class POSCAR:
365
344
  @_sub_doc(weas_viewer)
366
345
  @_sig_kwargs(weas_viewer, ("poscar",))
367
346
  def view_weas(self, **kwargs):
347
+ self.__class__._weas_kws = kwargs # attach to class, not self
368
348
  return weas_viewer(self, **kwargs)
369
349
 
370
350
 
@@ -376,17 +356,13 @@ class POSCAR:
376
356
 
377
357
  @_sub_doc(plat.iplot_lattice)
378
358
  @_sig_kwargs(plat.iplot_lattice, ("poscar_data",))
379
- def view_widget(self, **kwargs):
380
- self.__class__._update_kws = kwargs # attach to class, not self
359
+ def view_plotly(self, **kwargs):
360
+ self.__class__._plotly_kws = kwargs # attach to class, not self
381
361
  return iplot2widget(self.iplot_lattice(**kwargs))
382
362
 
383
- @_sig_kwargs(plat.iplot_lattice, ("poscar_data",))
384
- def update_widget(self, handle, **kwargs):
385
- """Update widget (if shown in notebook) after some operation on POSCAR with `handle` returned by `view_widget`
386
- kwargs are passed to `self.iplot_lattice` method.
387
- """
388
- kwargs = {**self.__class__._update_kws, **kwargs}
389
- iplot2widget(self.iplot_lattice(**kwargs), fig_widget=handle)
363
+ def update_plotly(self, handle):
364
+ "Update plotly widget (already shown in notebook) after some operation on POSCAR with `handle` returned by `view_plotly`."
365
+ iplot2widget(self.iplot_lattice(**self._plotly_kws), fig_widget=handle)
390
366
 
391
367
  @classmethod
392
368
  def from_file(cls, path):
@@ -530,11 +506,9 @@ class POSCAR:
530
506
 
531
507
 
532
508
  def update_weas(self, handle):
533
- """Send result of any operation to view on opened weas widget handle with default parameters becuase any operations
534
- can be incompatible with presious state of POSCAR. VESTA color scheme is used here.
509
+ """Send result of any operation to view on opened weas widget handle.
535
510
  Useful in Jupyterlab side panel to look operations results on POSCAR."""
536
- handle.from_ase(self.to_ase())
537
- handle.avr.color_type = 'VESTA'
511
+ handle.children = weas_viewer(self, **self._weas_kws).children # does not work properly otherwise
538
512
 
539
513
  @property
540
514
  def data(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ipyvasp
3
- Version: 0.8.5
3
+ Version: 0.8.7
4
4
  Summary: A processing tool for VASP DFT input/output processing in Jupyter Notebook.
5
5
  Home-page: https://github.com/massgh/ipyvasp
6
6
  Author: Abdul Saboor
@@ -1,12 +1,12 @@
1
1
  ipyvasp/__init__.py,sha256=7o41i5eYlNKg1Hsv0DLNFZ81GilxB02IXAJN-QiJQi0,1420
2
2
  ipyvasp/__main__.py,sha256=eJV1TZSiT8mC_VqAeksNnBI2I8mKMiPkEIlwikbtOjI,216
3
3
  ipyvasp/_enplots.py,sha256=D38paN8zqZgluNAwmCwcocd7-_h_T0HTGolI1eBkDes,37484
4
- ipyvasp/_lattice.py,sha256=-0Zo12xSPgwWy1TEPtrsX6iEBah6VhpH4GuZ7f98K8g,103373
5
- ipyvasp/_version.py,sha256=80NvSNse6emwcC7J2uzxIjsOMz3EsAiMsuAyJRp8sE0,23
4
+ ipyvasp/_lattice.py,sha256=AU_iQ4ZdJ0fEb8FxiADexOsVMp_zWJ11HLxBg_u9q7M,104022
5
+ ipyvasp/_version.py,sha256=ggGr8Eeuw9YZ1g40gSyKadNe96lor0upJSmlkeVHJlg,23
6
6
  ipyvasp/bsdos.py,sha256=ZtQji-W11UdFFicAoWZjlqVhI5tqYu_jpKyPPWKkeeo,30634
7
7
  ipyvasp/cli.py,sha256=aWFEVhNmnW8eSOp5uh95JaDwLQ9K9nlCQcbnOSuhWgw,6844
8
8
  ipyvasp/evals_dataframe.py,sha256=-sqxK7LPV6sYDO_XXmZ80FznOaXTkVdbqJKKvTUtMak,20637
9
- ipyvasp/lattice.py,sha256=ElvILd6TbIGvbH3jj5537EhHl6T5gx6rYhejNMGzyNs,28489
9
+ ipyvasp/lattice.py,sha256=HUMh1GYS8CbY7D4VssRQbOV-klm7pK6gnfUU_evwC0k,27752
10
10
  ipyvasp/misc.py,sha256=SZJ_ePUR2-HEKYTEpDHVRVE7zpIQVTCjiuw0BCC9UTU,2349
11
11
  ipyvasp/potential.py,sha256=tzA73c5lkp6ahLSJchMrU043-QWaOV0nIOUA7VMmfKQ,11408
12
12
  ipyvasp/surface.py,sha256=MjE5oB0wW6Pca_C-xu8rN6OMH7lUEeNPNyM7Kz_Im-8,23766
@@ -17,9 +17,9 @@ ipyvasp/core/parser.py,sha256=C3CaZsJbPME_ttYlYy4DXeOdL7dnkXs-cHRwFZL6bio,38058
17
17
  ipyvasp/core/plot_toolkit.py,sha256=cktbPZTJ4K0_6-vKYqtQ1xIIPZg-gHJY5793M9XoYQ0,35754
18
18
  ipyvasp/core/serializer.py,sha256=OsnYhlwt8O6UeJQMKmjp1-hwRjhxiqobV6bybfDECUY,35777
19
19
  ipyvasp/core/spatial_toolkit.py,sha256=8DBYTiBFWJ7OBKuvOPw7UoEVCyNjJhSW0OcudjYZvAw,14748
20
- ipyvasp-0.8.5.dist-info/LICENSE,sha256=F3SO5RiAZOMfmMGf1KOuk2g_c4ObvuBJhd9iBLDgXoQ,1263
21
- ipyvasp-0.8.5.dist-info/METADATA,sha256=zDQVItXjnjkNp9_9hmGBltvvx1m85_5NHlGKjmzvNms,2436
22
- ipyvasp-0.8.5.dist-info/WHEEL,sha256=iYlv5fX357PQyRT2o6tw1bN-YcKFFHKqB_LwHO5wP-g,110
23
- ipyvasp-0.8.5.dist-info/entry_points.txt,sha256=C7m0Sjmr14wFjflCkWXLzr5N6-cQj8uJC9n82mUtzt8,44
24
- ipyvasp-0.8.5.dist-info/top_level.txt,sha256=ftziWlMWu_1VpDP1sRTFrkfBnWxAi393HYDVu4wRhUk,8
25
- ipyvasp-0.8.5.dist-info/RECORD,,
20
+ ipyvasp-0.8.7.dist-info/LICENSE,sha256=F3SO5RiAZOMfmMGf1KOuk2g_c4ObvuBJhd9iBLDgXoQ,1263
21
+ ipyvasp-0.8.7.dist-info/METADATA,sha256=xAr8HFygxeP0mLIRR5Pqbb04UuUOoXGwr7rUq4uDy2I,2436
22
+ ipyvasp-0.8.7.dist-info/WHEEL,sha256=iYlv5fX357PQyRT2o6tw1bN-YcKFFHKqB_LwHO5wP-g,110
23
+ ipyvasp-0.8.7.dist-info/entry_points.txt,sha256=C7m0Sjmr14wFjflCkWXLzr5N6-cQj8uJC9n82mUtzt8,44
24
+ ipyvasp-0.8.7.dist-info/top_level.txt,sha256=ftziWlMWu_1VpDP1sRTFrkfBnWxAi393HYDVu4wRhUk,8
25
+ ipyvasp-0.8.7.dist-info/RECORD,,