ipyvasp 0.8.9__py2.py3-none-any.whl → 0.9.1__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 +38 -91
- ipyvasp/_version.py +1 -1
- ipyvasp/core/serializer.py +11 -2
- ipyvasp/lattice.py +45 -22
- {ipyvasp-0.8.9.dist-info → ipyvasp-0.9.1.dist-info}/METADATA +1 -1
- {ipyvasp-0.8.9.dist-info → ipyvasp-0.9.1.dist-info}/RECORD +10 -10
- {ipyvasp-0.8.9.dist-info → ipyvasp-0.9.1.dist-info}/LICENSE +0 -0
- {ipyvasp-0.8.9.dist-info → ipyvasp-0.9.1.dist-info}/WHEEL +0 -0
- {ipyvasp-0.8.9.dist-info → ipyvasp-0.9.1.dist-info}/entry_points.txt +0 -0
- {ipyvasp-0.8.9.dist-info → ipyvasp-0.9.1.dist-info}/top_level.txt +0 -0
ipyvasp/_lattice.py
CHANGED
|
@@ -1440,65 +1440,34 @@ def _fix_sites(
|
|
|
1440
1440
|
labels = np.array(poscar_data.labels) # We need to store equivalent labels as well
|
|
1441
1441
|
out_dict = poscar_data.to_dict() # For output
|
|
1442
1442
|
|
|
1443
|
-
if
|
|
1443
|
+
if isinstance(translate, (int, np.integer, float)):
|
|
1444
1444
|
pos = pos + (translate - int(translate)) # Only translate in 0 - 1
|
|
1445
|
-
elif translate and len(translate) == 3:
|
|
1445
|
+
elif isinstance(translate,(tuple, list, np.ndarray)) and len(translate) == 3:
|
|
1446
1446
|
txyz = np.array([translate])
|
|
1447
1447
|
pos = pos + (txyz - txyz.astype(int))
|
|
1448
1448
|
|
|
1449
1449
|
# Fix coordinates of sites distributed on edges and faces
|
|
1450
|
-
|
|
1451
|
-
int
|
|
1452
|
-
|
|
1450
|
+
if getattr(poscar_data.metadata, 'eqv_fix', True): # no more fixing over there
|
|
1451
|
+
pos -= (pos > (1 - tol)).astype(int) # Move towards orign for common fixing like in joining POSCARs
|
|
1452
|
+
|
|
1453
1453
|
out_dict["positions"] = pos
|
|
1454
1454
|
out_dict["metadata"]["comment"] = "Modified by ipyvasp"
|
|
1455
1455
|
|
|
1456
1456
|
# Add equivalent sites on edges and faces if given,handle each sepecies separately
|
|
1457
|
-
if eqv_sites:
|
|
1457
|
+
if eqv_sites and getattr(poscar_data.metadata, 'eqv_fix', True):
|
|
1458
1458
|
new_dict, start = {}, 0
|
|
1459
1459
|
for k, v in out_dict["types"].items():
|
|
1460
1460
|
vpos = pos[v]
|
|
1461
1461
|
vlabs = labels[v]
|
|
1462
1462
|
inds = np.array(v)
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
), # Add 1 to y on modified and if within tol
|
|
1472
|
-
(
|
|
1473
|
-
((vpos[:, 2] + 1) < (tol + 1)),
|
|
1474
|
-
[[0, 0, 1]],
|
|
1475
|
-
), # Add 1 to z and if within tol
|
|
1476
|
-
(
|
|
1477
|
-
((vpos[:, 0:2] + 1) < (tol + 1)).all(axis=1),
|
|
1478
|
-
[[1, 1, 0]],
|
|
1479
|
-
), # Add 1 to x and y if within tol
|
|
1480
|
-
(
|
|
1481
|
-
((vpos[:, 1:3] + 1) < (tol + 1)).all(axis=1),
|
|
1482
|
-
[[0, 1, 1]],
|
|
1483
|
-
), # Add 1 to y and z if within tol
|
|
1484
|
-
(
|
|
1485
|
-
((vpos[:, [0, 2]] + 1) < (tol + 1)).all(axis=1),
|
|
1486
|
-
[[1, 0, 1]],
|
|
1487
|
-
), # Add 1 to x and z if within tol
|
|
1488
|
-
(
|
|
1489
|
-
((vpos + 1) < (tol + 1)).all(axis=1),
|
|
1490
|
-
[[1, 1, 1]],
|
|
1491
|
-
), # Add 1 to all if within tol
|
|
1492
|
-
]
|
|
1493
|
-
spos = [vpos[c] + op for c, op in cond_ops]
|
|
1494
|
-
slab = [vlabs[c] for c, op in cond_ops]
|
|
1495
|
-
sinds = [inds[c] for c, op in cond_ops]
|
|
1496
|
-
|
|
1497
|
-
new_dict[k] = {
|
|
1498
|
-
"pos": np.vstack([vpos, *spos]),
|
|
1499
|
-
"lab": np.hstack([vlabs, *slab]),
|
|
1500
|
-
"inds": np.hstack([inds, *sinds]),
|
|
1501
|
-
}
|
|
1463
|
+
|
|
1464
|
+
ivpos = np.concatenate([np.indices((len(vpos),)).reshape((-1,1)),vpos],axis=1) # track of indices
|
|
1465
|
+
ivpos = np.array([ivpos + [0, *p] for p in product([-1,0,1],[-1,0,1],[-1,0,1])]).reshape((-1,4))
|
|
1466
|
+
ivpos = ivpos[(ivpos[:,1:] > -tol).all(axis=1) & (ivpos[:,1:] < 1 + tol).all(axis=1)]
|
|
1467
|
+
ivpos = ivpos[ivpos[:,0].argsort()]
|
|
1468
|
+
idxs = ivpos[:,0].ravel().astype(int).tolist()
|
|
1469
|
+
|
|
1470
|
+
new_dict[k] = {"pos": ivpos[:,1:], "lab": vlabs[idxs], "inds": inds[idxs]}
|
|
1502
1471
|
new_dict[k]["range"] = range(start, start + len(new_dict[k]["pos"]))
|
|
1503
1472
|
start += len(new_dict[k]["pos"])
|
|
1504
1473
|
|
|
@@ -1594,9 +1563,7 @@ def _masked_data(poscar_data, func):
|
|
|
1594
1563
|
if not isinstance(func(0, 0, 0, 0), bool):
|
|
1595
1564
|
raise TypeError("`func` should return a boolean value.")
|
|
1596
1565
|
|
|
1597
|
-
eqv_inds
|
|
1598
|
-
if hasattr(poscar_data.metadata, "eqv_indices"):
|
|
1599
|
-
eqv_inds = tuple(poscar_data.metadata.eqv_indices)
|
|
1566
|
+
eqv_inds = tuple(getattr(poscar_data.metadata, "eqv_indices",[]))
|
|
1600
1567
|
|
|
1601
1568
|
pick = []
|
|
1602
1569
|
for i, pos in enumerate(poscar_data.positions):
|
|
@@ -1622,41 +1589,39 @@ def _filter_pairs(labels, pairs, dist, bond_length):
|
|
|
1622
1589
|
# Return all pairs otherwise
|
|
1623
1590
|
return pairs # None -> auto calculate bond_length, number -> use that number
|
|
1624
1591
|
|
|
1625
|
-
|
|
1626
1592
|
def filter_sites(poscar_data, func, tol = 0.01):
|
|
1627
1593
|
"""Filter sites based on a function that acts on index and fractional positions such as `lambda i,x,y,z: condition`.
|
|
1628
|
-
This may include equivalent sites, so it should be used for plotting purpose only, e.g. showing atoms on a plane.
|
|
1594
|
+
This may include equivalent sites, so it should be used for plotting purpose only, e.g. showing atoms on a plane.
|
|
1595
|
+
An attribute `source_indices` is added to metadata which is useful to pick other things such as `OUTCAR.ion_pot[POSCAR.filter(...).data.metadata.source_indices]`.
|
|
1596
|
+
|
|
1597
|
+
Note: If you are filtering a plane with more than one non-zero hkl like 110, you may first need to translate or set boundary on POSCAR to bring desired plane in full view to include all atoms.
|
|
1598
|
+
"""
|
|
1599
|
+
if hasattr(poscar_data.metadata, 'source_indices'):
|
|
1600
|
+
raise ValueError("Cannot filter an already filtered POSCAR data.")
|
|
1601
|
+
|
|
1602
|
+
poscar_data = _fix_sites(poscar_data, tol = tol, eqv_sites=True)
|
|
1629
1603
|
idxs = _masked_data(poscar_data, func)
|
|
1630
1604
|
data = poscar_data.to_dict()
|
|
1631
|
-
|
|
1605
|
+
eqvi = data['metadata'].pop('eqv_indices', []) # no need of this
|
|
1606
|
+
|
|
1607
|
+
all_pos, npos, eqv_labs, finds = [], [0,],[],[]
|
|
1632
1608
|
for value in poscar_data.types.values():
|
|
1633
|
-
indices = [i for i in value if i in idxs]
|
|
1634
|
-
|
|
1609
|
+
indices = [i for i in value if i in idxs] # search from value make sure only non-equivalent sites added
|
|
1610
|
+
finds.extend(eqvi[indices] if len(eqvi) else indices)
|
|
1611
|
+
eqv_labs.extend(poscar_data.labels[indices])
|
|
1635
1612
|
pos = data['positions'][indices]
|
|
1636
|
-
qos = data['positions'][others] # need edge items to include
|
|
1637
|
-
|
|
1638
|
-
if qos.size:
|
|
1639
|
-
qos = np.concatenate([[[i] for i in others], qos], axis=1) # need to keep index
|
|
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
|
-
qos = qos[(qos[:,1:] < 1 + tol).all(axis=1) & (qos[:,1:] > -tol).all(axis=1)]# only in cell range
|
|
1642
|
-
qos = qos[[func(*q) for q in qos]] # masked only those are true
|
|
1643
|
-
|
|
1644
|
-
if qos.size:
|
|
1645
|
-
pos = np.concatenate([pos, qos[:,1:]],axis=0)
|
|
1646
|
-
|
|
1647
1613
|
all_pos.append(pos)
|
|
1648
1614
|
npos.append(len(pos))
|
|
1649
1615
|
|
|
1650
1616
|
if not np.sum(npos):
|
|
1651
1617
|
raise ValueError("No sites found with given filter func!")
|
|
1652
1618
|
|
|
1653
|
-
if not 'prev_positions' in data['metadata']: # keep always the starting one
|
|
1654
|
-
data['metadata']['prev_positions'] = poscar_data.positions
|
|
1655
|
-
data['metadata']['prev_types'] = poscar_data.types
|
|
1656
|
-
|
|
1657
1619
|
data['positions'] = np.concatenate(all_pos, axis = 0)
|
|
1620
|
+
data['metadata']['source_indices'] = np.array(finds)
|
|
1621
|
+
data['metadata']['eqv_fix'] = False
|
|
1622
|
+
data['metadata']['eqv_labels'] = np.array(eqv_labs) # need these for compare to previous
|
|
1658
1623
|
|
|
1659
|
-
ranges = np.cumsum(
|
|
1624
|
+
ranges = np.cumsum(npos)
|
|
1660
1625
|
data['types'] = {key: range(i,j) for key, i,j in zip(data['types'],ranges[:-1],ranges[1:]) if range(i,j)} # avoid empty
|
|
1661
1626
|
return serializer.PoscarData(data)
|
|
1662
1627
|
|
|
@@ -2241,7 +2206,7 @@ def scale_poscar(poscar_data, scale=(1, 1, 1), tol=1e-2):
|
|
|
2241
2206
|
return serializer.PoscarData(new_poscar)
|
|
2242
2207
|
|
|
2243
2208
|
def set_boundary(poscar_data, a = [0,1], b = [0,1], c = [0,1]):
|
|
2244
|
-
"View atoms
|
|
2209
|
+
"View atoms in a given boundary along a,b,c directions."
|
|
2245
2210
|
for d, name in zip([a,b,c],'abc'):
|
|
2246
2211
|
if not isinstance(d,(list,tuple)) or len(d) != 2:
|
|
2247
2212
|
raise ValueError(f"{name} should be a list/tuple of type [min, max]")
|
|
@@ -2253,17 +2218,13 @@ def set_boundary(poscar_data, a = [0,1], b = [0,1], c = [0,1]):
|
|
|
2253
2218
|
for key, value in poscar_data.types.items():
|
|
2254
2219
|
pos = data['positions'][value]
|
|
2255
2220
|
for i, (l,h), shift in zip(range(3), [a,b,c],np.eye(3)):
|
|
2256
|
-
|
|
2257
|
-
pos = np.concatenate([pos, pos - shift],axis=0)
|
|
2258
|
-
|
|
2259
|
-
while pos[:,i].max() < np.ceil(h):
|
|
2260
|
-
pos = np.concatenate([pos, pos + shift],axis=0)
|
|
2261
|
-
|
|
2221
|
+
pos = np.concatenate([pos + shift*k for k in np.arange(np.floor(l), np.ceil(h))],axis=0)
|
|
2262
2222
|
pos = pos[(pos[:,i] >= l) & (pos[:,i] <= h)]
|
|
2263
2223
|
|
|
2264
2224
|
upos[key] = pos
|
|
2265
2225
|
|
|
2266
2226
|
data['positions'] = np.concatenate(list(upos.values()), axis = 0)
|
|
2227
|
+
data['metadata']['eqv_fix'] = False
|
|
2267
2228
|
|
|
2268
2229
|
ranges = np.cumsum([0, *[len(v) for v in upos.values()]])
|
|
2269
2230
|
data['types'] = {key: range(i,j) for key, i,j in zip(upos,ranges[:-1],ranges[1:])}
|
|
@@ -2293,20 +2254,6 @@ def rotate_poscar(poscar_data, angle_deg, axis_vec):
|
|
|
2293
2254
|
p_dict["metadata"]["comment"] = f"Modified by ipyvasp"
|
|
2294
2255
|
return serializer.PoscarData(p_dict)
|
|
2295
2256
|
|
|
2296
|
-
|
|
2297
|
-
def set_origin(poscar_data, origin):
|
|
2298
|
-
"""Set origin of POSCAR sites to a given position in fractional coordinates.
|
|
2299
|
-
The following example demonstrates the use of this function.
|
|
2300
|
-
|
|
2301
|
-
>>> import ipyvasp as ipv
|
|
2302
|
-
>>> poscar = ipv.POSCAR("POSCAR")
|
|
2303
|
-
>>> ax = poscar.splot_cell() # plot original cell
|
|
2304
|
-
>>> poscar_shifted = poscar.scale((3,3,3)).set_origin((1/3,1/3,1/3))
|
|
2305
|
-
>>> poscar_shifted.splot_lattice(ax=ax, plot_cell=False) # displays sites around original cell
|
|
2306
|
-
"""
|
|
2307
|
-
return _fix_sites(poscar_data, eqv_sites=False, origin=origin)
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
2257
|
def set_zdir(poscar_data, hkl, phi=0):
|
|
2311
2258
|
"""Set z-direction of POSCAR along a given hkl direction and returns new data.
|
|
2312
2259
|
|
|
@@ -2438,7 +2385,7 @@ def transform_poscar(poscar_data, transformation, fill_factor=2, tol=1e-2):
|
|
|
2438
2385
|
|
|
2439
2386
|
_p = range(-fill_factor, fill_factor + 1)
|
|
2440
2387
|
pos = np.concatenate([poscar_data.positions,[[i] for i,_ in enumerate(poscar_data.positions)]], axis=1) # keep track of index
|
|
2441
|
-
pos = np.concatenate([pos + [*p,0] for p in
|
|
2388
|
+
pos = np.concatenate([pos + [*p,0] for p in product(_p,_p,_p)],axis=0) # increaser by fill_factor^3
|
|
2442
2389
|
pos[:,:3] = to_basis(new_basis, poscar_data.to_cartesian(pos[:,:3])) # convert to coords in this and to points in new
|
|
2443
2390
|
pos = pos[(pos[:,:3] <= 1 - tol).all(axis=1) & (pos[:,:3] >= -tol).all(axis=1)]
|
|
2444
2391
|
pos = pos[pos[:,-1].argsort()] # sort for species
|
ipyvasp/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.
|
|
1
|
+
__version__ = "0.9.1"
|
ipyvasp/core/serializer.py
CHANGED
|
@@ -328,6 +328,15 @@ class PoscarData(Dict2Data):
|
|
|
328
328
|
def symbols(self):
|
|
329
329
|
"Returns the symbols of the atoms in the poscar data without numbers"
|
|
330
330
|
return np.array([lab.split()[0] for lab in self.labels])
|
|
331
|
+
|
|
332
|
+
def get_sites(self, type_or_indices, as_coords=False):
|
|
333
|
+
"Shortcut method for `POSCAR.data.positions[POSCAR.data.types['name']]` or with regular indexing."
|
|
334
|
+
points = self.coords if as_coords else self.positions
|
|
335
|
+
if isinstance(type_or_indices,str) and type_or_indices in self.types:
|
|
336
|
+
return points[self.types[type_or_indices]]
|
|
337
|
+
elif not isinstance(type_or_indices,(list,range,tuple)):
|
|
338
|
+
raise TypeError("type_or_indices should be a species type like 'Ga' or list-like of indices to pick positions.")
|
|
339
|
+
return points[type_or_indices]
|
|
331
340
|
|
|
332
341
|
def get_neighbors(self, k=5):
|
|
333
342
|
"""Get the k nearest neighbors of each atom (including itself) in the lattice.
|
|
@@ -390,7 +399,7 @@ class PoscarData(Dict2Data):
|
|
|
390
399
|
|
|
391
400
|
dists = []
|
|
392
401
|
for idx in idx1:
|
|
393
|
-
for trans in
|
|
402
|
+
for trans in product([-1,0,1],[-1,0,1],[-1,0,1]):
|
|
394
403
|
C = self.to_cartesian(self.positions[idx] + trans) # translate around to get lowest distance
|
|
395
404
|
|
|
396
405
|
dists = [
|
|
@@ -412,7 +421,7 @@ class PoscarData(Dict2Data):
|
|
|
412
421
|
for i in self.types[type1]:
|
|
413
422
|
for j in [k for k in self.types[type2] if k != i]:
|
|
414
423
|
a = self.coords[i]
|
|
415
|
-
bs = [self.to_cartesian(self.positions[j] + p) for p in
|
|
424
|
+
bs = [self.to_cartesian(self.positions[j] + p) for p in product([-1,0,1],[-1,0,1],[-1,0,1])]
|
|
416
425
|
ds = np.array([np.linalg.norm(a-b) for b in bs])
|
|
417
426
|
d = ds[ds > 0].min() # no same site distance
|
|
418
427
|
if min < d < max:
|
ipyvasp/lattice.py
CHANGED
|
@@ -85,6 +85,7 @@ def ngl_viewer(
|
|
|
85
85
|
plot_vectors=True,
|
|
86
86
|
dashboard=False,
|
|
87
87
|
origin=(0, 0, 0),
|
|
88
|
+
eqv_sites = True,
|
|
88
89
|
):
|
|
89
90
|
"""Display structure in Jupyter notebook using nglview.
|
|
90
91
|
|
|
@@ -135,7 +136,7 @@ def ngl_viewer(
|
|
|
135
136
|
|
|
136
137
|
# Only show equivalent sites if plotting cell, only shift origin otherwise
|
|
137
138
|
poscar = POSCAR( # don't change instance itself, make new one
|
|
138
|
-
data=plat._fix_sites(poscar.data, eqv_sites=
|
|
139
|
+
data=plat._fix_sites(poscar.data, eqv_sites=eqv_sites, origin=origin)
|
|
139
140
|
)
|
|
140
141
|
|
|
141
142
|
_types = poscar.data.types.to_dict()
|
|
@@ -187,7 +188,8 @@ def weas_viewer(poscar,
|
|
|
187
188
|
bond_length=None,
|
|
188
189
|
model_style = 1,
|
|
189
190
|
plot_cell=True,
|
|
190
|
-
origin = (0,0,0)
|
|
191
|
+
origin = (0,0,0),
|
|
192
|
+
eqv_sites = True,
|
|
191
193
|
):
|
|
192
194
|
"""
|
|
193
195
|
sizes : float or dict of type -> float
|
|
@@ -215,7 +217,7 @@ def weas_viewer(poscar,
|
|
|
215
217
|
|
|
216
218
|
# Only show equivalent sites if plotting cell, only shift origin otherwise
|
|
217
219
|
poscar = POSCAR( # don't change instance itself, make new one
|
|
218
|
-
data=plat._fix_sites(poscar.data, eqv_sites=
|
|
220
|
+
data=plat._fix_sites(poscar.data, eqv_sites=eqv_sites, origin=origin)
|
|
219
221
|
)
|
|
220
222
|
|
|
221
223
|
w = WeasWidget(from_ase=poscar.to_ase())
|
|
@@ -254,18 +256,18 @@ class _AutoRenderer:
|
|
|
254
256
|
_figw = None
|
|
255
257
|
_kws = {}
|
|
256
258
|
|
|
257
|
-
def __init__(self,
|
|
258
|
-
self._pc =
|
|
259
|
+
def __init__(self, pc_cls):
|
|
260
|
+
self._pc = pc_cls
|
|
259
261
|
|
|
260
262
|
def on(self, template=None):
|
|
261
263
|
"Enable auto rendering. In Jupyterlab, you can use `Create New View for Output` to drag a view on side."
|
|
262
264
|
self.off()
|
|
263
|
-
type(self)._figw = iplot2widget(self._pc.iplot_lattice(**self._kws), fig_widget=self._figw,template=template)
|
|
265
|
+
type(self)._figw = iplot2widget(self._pc._last.iplot_lattice(**self._kws), fig_widget=self._figw,template=template)
|
|
264
266
|
|
|
265
267
|
def ip_display(that):
|
|
266
268
|
iplot2widget(that.iplot_lattice(**self._kws), fig_widget=self._figw, template=template)
|
|
267
269
|
|
|
268
|
-
|
|
270
|
+
self._pc._ipython_display_ = ip_display
|
|
269
271
|
|
|
270
272
|
from ipywidgets import Button, VBox
|
|
271
273
|
btn = Button(description='Disable Auto Rendering',icon='close',layout={'width': 'max-content'})
|
|
@@ -279,14 +281,14 @@ class _AutoRenderer:
|
|
|
279
281
|
self._box.close()
|
|
280
282
|
type(self)._figw = None # no need to close figw, it raise warning, but now garbage collected
|
|
281
283
|
|
|
282
|
-
if hasattr(
|
|
283
|
-
del
|
|
284
|
+
if hasattr(self._pc, '_ipython_display_'):
|
|
285
|
+
del self._pc._ipython_display_
|
|
284
286
|
|
|
285
287
|
@_sig_kwargs(plat.iplot_lattice,('poscar_data',))
|
|
286
288
|
def update_params(self, **kwargs):
|
|
287
289
|
type(self)._kws = kwargs
|
|
288
|
-
if hasattr(
|
|
289
|
-
self._pc._ipython_display_()
|
|
290
|
+
if hasattr(self._pc, '_ipython_display_'):
|
|
291
|
+
self._pc._last._ipython_display_()
|
|
290
292
|
|
|
291
293
|
@property
|
|
292
294
|
def params(self):
|
|
@@ -302,7 +304,6 @@ class POSCAR:
|
|
|
302
304
|
def __init__(self, path=None, content=None, data=None):
|
|
303
305
|
"""
|
|
304
306
|
POSCAR class to contain data and related methods, data is PoscarData, json/tuple file/string.
|
|
305
|
-
Do not use `data` yourself, it's for operations on poscar.
|
|
306
307
|
|
|
307
308
|
Parameters
|
|
308
309
|
----------
|
|
@@ -312,14 +313,20 @@ class POSCAR:
|
|
|
312
313
|
|
|
313
314
|
Prefrence order: data > content > path
|
|
314
315
|
|
|
316
|
+
Note: During chained operations where functions are acting on index of sites, use `self.last` instead of `self` to point to latest POSCAR in chain.
|
|
317
|
+
|
|
318
|
+
```python
|
|
319
|
+
pc = POSCAR()
|
|
320
|
+
pc.filter_sites(lambda i,x,y,z: i in pc.data.types.Ga) # FINE
|
|
321
|
+
pc.set_boundary([-2,2]).filter_sites(lambda i,x,y,z: i in pc.data.types.Ga) # INCORRECT sites may be picked
|
|
322
|
+
pc.set_boundary([-2,2]).filter_sites(lambda i,x,y,z: i in pc.last.data.types.Ga) # PERFECT, pc.last is output of set_boundary
|
|
323
|
+
```
|
|
324
|
+
|
|
315
325
|
Tip: You can use `self.auto_renderer.on()` to keep doing opertions and visualize while last line of any cell is a POSCAR object.
|
|
316
326
|
"""
|
|
317
327
|
self._path = Path(path or "POSCAR") # Path to file
|
|
318
328
|
self._content = content
|
|
319
|
-
|
|
320
|
-
if not hasattr(self, '_renderer'): # Only once
|
|
321
|
-
type(self)._renderer = _AutoRenderer(self) # assign to class
|
|
322
|
-
self._renderer._pc = self # keep latest refrence there too, for update_params on right one
|
|
329
|
+
self.__class__._last = self # need this to access in lambda in chain operations
|
|
323
330
|
|
|
324
331
|
if data:
|
|
325
332
|
self._data = serializer.PoscarData.validated(data)
|
|
@@ -345,6 +352,19 @@ class POSCAR:
|
|
|
345
352
|
def path(self):
|
|
346
353
|
return self._path
|
|
347
354
|
|
|
355
|
+
@property
|
|
356
|
+
def last(self):
|
|
357
|
+
"""Points to last created POSCAR instance during chained operations!
|
|
358
|
+
|
|
359
|
+
```python
|
|
360
|
+
pc = POSCAR()
|
|
361
|
+
pc.filter_sites(lambda i,x,y,z: i in pc.data.types.Ga) # FINE
|
|
362
|
+
pc.set_boundary([-2,2]).filter_sites(lambda i,x,y,z: i in pc.data.types.Ga) # INCORRECT sites may be picked
|
|
363
|
+
pc.set_boundary([-2,2]).filter_sites(lambda i,x,y,z: i in pc.last.data.types.Ga) # PERFECT, pc.last is output set_boundary
|
|
364
|
+
```
|
|
365
|
+
"""
|
|
366
|
+
return self._last
|
|
367
|
+
|
|
348
368
|
@property
|
|
349
369
|
def auto_renderer(self):
|
|
350
370
|
"""A renderer for auto viewing POSCAR when at last line of cell.
|
|
@@ -356,6 +376,8 @@ class POSCAR:
|
|
|
356
376
|
In Jupyterlab, you can use `Create New View for Output` to drag a view on side.
|
|
357
377
|
In VS Code, you can open another view of Notebook to see it on side while doing operations.
|
|
358
378
|
"""
|
|
379
|
+
if not hasattr(self, '_renderer'):
|
|
380
|
+
self.__class__._renderer = _AutoRenderer(self.__class__) # assign to class
|
|
359
381
|
return self._renderer
|
|
360
382
|
|
|
361
383
|
def to_ase(self):
|
|
@@ -565,6 +587,11 @@ class POSCAR:
|
|
|
565
587
|
def data(self):
|
|
566
588
|
"Data object in POSCAR."
|
|
567
589
|
return self._data
|
|
590
|
+
|
|
591
|
+
@property
|
|
592
|
+
def metadata(self):
|
|
593
|
+
"Metadata associated with this POSCAR."
|
|
594
|
+
return self._data.metadata
|
|
568
595
|
|
|
569
596
|
def copy(self):
|
|
570
597
|
"Copy POSCAR object. It avoids accidental changes to numpy arrays in original object."
|
|
@@ -674,12 +701,8 @@ class POSCAR:
|
|
|
674
701
|
|
|
675
702
|
@_sub_doc(plat.filter_sites)
|
|
676
703
|
@_sig_kwargs(plat.filter_sites,("poscar_data",))
|
|
677
|
-
def filter_sites(self, func):
|
|
678
|
-
return self.__class__(data = plat.filter_sites(self.data, func))
|
|
679
|
-
|
|
680
|
-
@_sub_doc(plat.set_origin)
|
|
681
|
-
def set_origin(self, origin):
|
|
682
|
-
return self.__class__(data=plat.set_origin(self.data, origin=origin))
|
|
704
|
+
def filter_sites(self, func, tol=0.01):
|
|
705
|
+
return self.__class__(data = plat.filter_sites(self.data, func,tol=tol))
|
|
683
706
|
|
|
684
707
|
@_sub_doc(plat.rotate_poscar)
|
|
685
708
|
def rotate(self, angle_deg, axis_vec):
|
|
@@ -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=
|
|
5
|
-
ipyvasp/_version.py,sha256=
|
|
4
|
+
ipyvasp/_lattice.py,sha256=BqlDmokeYgdnWGw8YPGPRm3-wrgteUJg1R3YK9suMLY,102554
|
|
5
|
+
ipyvasp/_version.py,sha256=nowX8dTYmAqqc8x180AcV7Ru6brVwGyJwg9GfVedBCE,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=
|
|
9
|
+
ipyvasp/lattice.py,sha256=wz5CKv5YJbELvG2lbrYnXoT7u9R70Jkr_i3olE4Hx4I,30643
|
|
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
|
|
@@ -15,11 +15,11 @@ ipyvasp/widgets.py,sha256=fZ2b7EYYxuaAVfklnLa0VJ00U9Uyd7SqXrzt0hbLOvI,45400
|
|
|
15
15
|
ipyvasp/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
ipyvasp/core/parser.py,sha256=C3CaZsJbPME_ttYlYy4DXeOdL7dnkXs-cHRwFZL6bio,38058
|
|
17
17
|
ipyvasp/core/plot_toolkit.py,sha256=8t5svyWbOm-PS7ZvIptnK6F46kp6uwoGNdohPv5dQKA,35962
|
|
18
|
-
ipyvasp/core/serializer.py,sha256=
|
|
18
|
+
ipyvasp/core/serializer.py,sha256=_Ck51U_N6m4pTOkr3VxPtZumi8znrhneHjHuVtA7qDU,36661
|
|
19
19
|
ipyvasp/core/spatial_toolkit.py,sha256=8DBYTiBFWJ7OBKuvOPw7UoEVCyNjJhSW0OcudjYZvAw,14748
|
|
20
|
-
ipyvasp-0.
|
|
21
|
-
ipyvasp-0.
|
|
22
|
-
ipyvasp-0.
|
|
23
|
-
ipyvasp-0.
|
|
24
|
-
ipyvasp-0.
|
|
25
|
-
ipyvasp-0.
|
|
20
|
+
ipyvasp-0.9.1.dist-info/LICENSE,sha256=F3SO5RiAZOMfmMGf1KOuk2g_c4ObvuBJhd9iBLDgXoQ,1263
|
|
21
|
+
ipyvasp-0.9.1.dist-info/METADATA,sha256=1DwFCWMbumZTzK_LrDuuCTvlwinFEewM9RWGm-fa1oU,2420
|
|
22
|
+
ipyvasp-0.9.1.dist-info/WHEEL,sha256=iYlv5fX357PQyRT2o6tw1bN-YcKFFHKqB_LwHO5wP-g,110
|
|
23
|
+
ipyvasp-0.9.1.dist-info/entry_points.txt,sha256=C7m0Sjmr14wFjflCkWXLzr5N6-cQj8uJC9n82mUtzt8,44
|
|
24
|
+
ipyvasp-0.9.1.dist-info/top_level.txt,sha256=ftziWlMWu_1VpDP1sRTFrkfBnWxAi393HYDVu4wRhUk,8
|
|
25
|
+
ipyvasp-0.9.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|