ipyvasp 0.8.8__tar.gz → 0.9.0__tar.gz
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-0.8.8 → ipyvasp-0.9.0}/PKG-INFO +1 -1
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/_lattice.py +26 -63
- ipyvasp-0.9.0/ipyvasp/_version.py +1 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/core/serializer.py +10 -6
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/lattice.py +13 -6
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp.egg-info/PKG-INFO +1 -1
- ipyvasp-0.8.8/ipyvasp/_version.py +0 -1
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/LICENSE +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/README.md +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/__init__.py +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/__main__.py +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/_enplots.py +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/bsdos.py +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/cli.py +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/core/__init__.py +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/core/parser.py +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/core/plot_toolkit.py +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/core/spatial_toolkit.py +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/evals_dataframe.py +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/misc.py +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/potential.py +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/utils.py +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp/widgets.py +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp.egg-info/SOURCES.txt +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp.egg-info/dependency_links.txt +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp.egg-info/entry_points.txt +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp.egg-info/requires.txt +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/ipyvasp.egg-info/top_level.txt +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/setup.cfg +0 -0
- {ipyvasp-0.8.8 → ipyvasp-0.9.0}/setup.py +0 -0
|
@@ -1447,9 +1447,9 @@ def _fix_sites(
|
|
|
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 not hasattr(poscar_data.metadata, 'source_indices'): # 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
|
|
|
@@ -1460,45 +1460,14 @@ def _fix_sites(
|
|
|
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 set(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
|
|
|
@@ -1622,41 +1591,35 @@ def _filter_pairs(labels, pairs, dist, bond_length):
|
|
|
1622
1591
|
# Return all pairs otherwise
|
|
1623
1592
|
return pairs # None -> auto calculate bond_length, number -> use that number
|
|
1624
1593
|
|
|
1625
|
-
|
|
1626
1594
|
def filter_sites(poscar_data, func, tol = 0.01):
|
|
1627
1595
|
"""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.
|
|
1596
|
+
This may include equivalent sites, so it should be used for plotting purpose only, e.g. showing atoms on a plane.
|
|
1597
|
+
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]`.
|
|
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
|
-
all_pos, npos = [], []
|
|
1605
|
+
all_pos, npos, eqv_labs, finds = [], [0,],[],[]
|
|
1632
1606
|
for value in poscar_data.types.values():
|
|
1633
|
-
indices = [i for i in value if i in idxs]
|
|
1634
|
-
|
|
1607
|
+
indices = [i for i in value if i in idxs] # search from value make sure only non-equivalent sites added
|
|
1608
|
+
finds.extend(poscar_data.metadata.eqv_indices[indices])
|
|
1609
|
+
eqv_labs.extend(poscar_data.labels[indices])
|
|
1635
1610
|
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
1611
|
all_pos.append(pos)
|
|
1648
1612
|
npos.append(len(pos))
|
|
1649
1613
|
|
|
1650
1614
|
if not np.sum(npos):
|
|
1651
1615
|
raise ValueError("No sites found with given filter func!")
|
|
1652
1616
|
|
|
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
1617
|
data['positions'] = np.concatenate(all_pos, axis = 0)
|
|
1618
|
+
data['metadata']['source_indices'] = np.array(finds)
|
|
1619
|
+
data['metadata']['eqv_labels'] = np.array(eqv_labs) # need these for compare to previous
|
|
1620
|
+
data['metadata'].pop('eqv_indices', None) # no need of this
|
|
1658
1621
|
|
|
1659
|
-
ranges = np.cumsum(
|
|
1622
|
+
ranges = np.cumsum(npos)
|
|
1660
1623
|
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
1624
|
return serializer.PoscarData(data)
|
|
1662
1625
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.9.0"
|
|
@@ -422,7 +422,9 @@ class PoscarData(Dict2Data):
|
|
|
422
422
|
|
|
423
423
|
|
|
424
424
|
def get_bond_data(self, site_indices, k = 5):
|
|
425
|
-
"Returns a DataFrame with bonds angle, bond length, vector positions etc. that can be used for plotting.
|
|
425
|
+
"""Returns a DataFrame with bonds angle, bond length, vector positions etc. that can be used for plotting.
|
|
426
|
+
t_a and t_b are translation vectors to get them near selected sites. You can use `POSCAR.translate` if somehow need nearest coordinates.
|
|
427
|
+
"""
|
|
426
428
|
if k < 3:
|
|
427
429
|
raise ValueError("k >= 3 is required!")
|
|
428
430
|
|
|
@@ -434,16 +436,18 @@ class PoscarData(Dict2Data):
|
|
|
434
436
|
for j in js:
|
|
435
437
|
bs = np.array([self.to_cartesian(self.positions[j] + p) for p in product([-1,0,1],[-1,0,1],[-1,0,1])])
|
|
436
438
|
ds = np.array([np.linalg.norm(a-b) for b in bs])
|
|
437
|
-
|
|
439
|
+
b = bs[ds.argsort()][0]
|
|
440
|
+
t = tuple((self.to_fractional(b) - self.positions[j]).astype(int)) # keep track of translation vector
|
|
441
|
+
nears.append((j, b, t))
|
|
438
442
|
|
|
439
|
-
for (m,b),(n, c) in combinations(nears,2):
|
|
440
|
-
v1, v2 = b-a, c-a
|
|
443
|
+
for (m,b,t1),(n, c,t2) in combinations(nears,2):
|
|
444
|
+
v1, v2 = b - a, c - a
|
|
441
445
|
n1, n2 = np.linalg.norm(v1), np.linalg.norm(v2)
|
|
442
446
|
name = '-'.join(self.symbols[[m,i,n]])
|
|
443
447
|
angle = np.degrees(np.arccos(v1.dot(v2)/(n1*n2)))
|
|
444
|
-
out.append([name, m,i,n, angle, n1, n2,
|
|
448
|
+
out.append([name, m,i,n, angle, n1, n2, t1,t2])
|
|
445
449
|
|
|
446
|
-
columns = 'bond a o b angle d_ao d_bo
|
|
450
|
+
columns = 'bond a o b angle d_ao d_bo t_a t_b'.split()
|
|
447
451
|
return DataFrame(out, columns=columns)
|
|
448
452
|
|
|
449
453
|
def to_fractional(self, coords):
|
|
@@ -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())
|
|
@@ -293,7 +295,7 @@ class _AutoRenderer:
|
|
|
293
295
|
return self._kws.copy() # avoid messing original
|
|
294
296
|
|
|
295
297
|
def __repr__(self):
|
|
296
|
-
return f"AutoRenderer({self._kws})"
|
|
298
|
+
return f"AutoRenderer(params = {self._kws})"
|
|
297
299
|
|
|
298
300
|
class POSCAR:
|
|
299
301
|
_cb_instance = {} # Loads last clipboard data if not changed
|
|
@@ -565,6 +567,11 @@ class POSCAR:
|
|
|
565
567
|
def data(self):
|
|
566
568
|
"Data object in POSCAR."
|
|
567
569
|
return self._data
|
|
570
|
+
|
|
571
|
+
@property
|
|
572
|
+
def metadata(self):
|
|
573
|
+
"Metadata associated with this POSCAR."
|
|
574
|
+
return self._data.metadata
|
|
568
575
|
|
|
569
576
|
def copy(self):
|
|
570
577
|
"Copy POSCAR object. It avoids accidental changes to numpy arrays in original object."
|
|
@@ -674,8 +681,8 @@ class POSCAR:
|
|
|
674
681
|
|
|
675
682
|
@_sub_doc(plat.filter_sites)
|
|
676
683
|
@_sig_kwargs(plat.filter_sites,("poscar_data",))
|
|
677
|
-
def filter_sites(self, func):
|
|
678
|
-
return self.__class__(data = plat.filter_sites(self.data, func))
|
|
684
|
+
def filter_sites(self, func, tol=0.01):
|
|
685
|
+
return self.__class__(data = plat.filter_sites(self.data, func,tol=tol))
|
|
679
686
|
|
|
680
687
|
@_sub_doc(plat.set_origin)
|
|
681
688
|
def set_origin(self, origin):
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.8.8"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|