ipyvasp 0.9.6__py2.py3-none-any.whl → 0.9.8__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 +54 -43
- ipyvasp/_version.py +1 -1
- ipyvasp/bsdos.py +29 -5
- ipyvasp/core/parser.py +4 -1
- ipyvasp/core/serializer.py +16 -8
- ipyvasp/lattice.py +10 -10
- ipyvasp/widgets.py +1 -1
- {ipyvasp-0.9.6.dist-info → ipyvasp-0.9.8.dist-info}/METADATA +1 -1
- {ipyvasp-0.9.6.dist-info → ipyvasp-0.9.8.dist-info}/RECORD +13 -13
- {ipyvasp-0.9.6.dist-info → ipyvasp-0.9.8.dist-info}/LICENSE +0 -0
- {ipyvasp-0.9.6.dist-info → ipyvasp-0.9.8.dist-info}/WHEEL +0 -0
- {ipyvasp-0.9.6.dist-info → ipyvasp-0.9.8.dist-info}/entry_points.txt +0 -0
- {ipyvasp-0.9.6.dist-info → ipyvasp-0.9.8.dist-info}/top_level.txt +0 -0
ipyvasp/_lattice.py
CHANGED
|
@@ -6,6 +6,7 @@ import requests as req
|
|
|
6
6
|
import inspect
|
|
7
7
|
from itertools import combinations, product
|
|
8
8
|
from functools import lru_cache
|
|
9
|
+
from typing import NamedTuple
|
|
9
10
|
|
|
10
11
|
from scipy.spatial import ConvexHull, KDTree
|
|
11
12
|
import plotly.graph_objects as go
|
|
@@ -238,7 +239,7 @@ def write_poscar(poscar_data, outfile=None, selective_dynamics=None, overwrite=F
|
|
|
238
239
|
----------
|
|
239
240
|
outfile : PathLike
|
|
240
241
|
selective_dynamics : callable
|
|
241
|
-
If given, should be a function like `f(
|
|
242
|
+
If given, should be a function like `f(a) -> (a.p < 1/4)` or `f(a) -> (a.x < 1/4, a.y < 1/4, a.z < 1/4)`
|
|
242
243
|
which turns on/off selective dynamics for each atom based in each dimension.
|
|
243
244
|
See `ipyvasp.POSCAR.data.get_selective_dynamics` for more info.
|
|
244
245
|
overwrite: bool
|
|
@@ -1192,8 +1193,11 @@ def splot_kpath(
|
|
|
1192
1193
|
labels = [
|
|
1193
1194
|
"[{0:5.2f}, {1:5.2f}, {2:5.2f}]".format(x, y, z) for x, y, z in kpoints
|
|
1194
1195
|
]
|
|
1196
|
+
|
|
1197
|
+
if fmt_label is None:
|
|
1198
|
+
fmt_label = lambda x: (x, {"color": "blue"})
|
|
1195
1199
|
|
|
1196
|
-
_validate_label_func(fmt_label,
|
|
1200
|
+
_validate_label_func(fmt_label,labels[0])
|
|
1197
1201
|
|
|
1198
1202
|
coords = bz_data.to_cartesian(kpoints)
|
|
1199
1203
|
if _zoffset and plane:
|
|
@@ -1565,25 +1569,49 @@ def _get_bond_length(poscar_data, bond_length=None):
|
|
|
1565
1569
|
) # Add 5% margin over mean distance, this covers same species too, and in multiple species, this will stop bonding between same species.
|
|
1566
1570
|
|
|
1567
1571
|
|
|
1568
|
-
|
|
1569
|
-
"
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
+
class _Atom(NamedTuple):
|
|
1573
|
+
"Object passed to POSCAR operations `func` where atomic sites are modified. Additinal property p -> array([x,y,z])."
|
|
1574
|
+
symbol : str
|
|
1575
|
+
index : int
|
|
1576
|
+
x : float
|
|
1577
|
+
y : float
|
|
1578
|
+
z : float
|
|
1579
|
+
|
|
1580
|
+
@property
|
|
1581
|
+
def p(self): return np.array([self.x,self.y,self.z]) # for robust operations
|
|
1582
|
+
|
|
1583
|
+
class _AtomLabel(str):
|
|
1584
|
+
"Object passed to `fmt_label` in plotting. `number` and `symbol` are additional attributes and `to_latex` is a method."
|
|
1585
|
+
@property
|
|
1586
|
+
def number(self): return int(self.split()[1])
|
|
1587
|
+
@property
|
|
1588
|
+
def symbol(self): return self.split()[0]
|
|
1589
|
+
def to_latex(self): return "{}$_{{{}}}$".format(*self.split())
|
|
1572
1590
|
|
|
1573
|
-
|
|
1591
|
+
def _validate_func(func):
|
|
1592
|
+
if not callable(func):
|
|
1593
|
+
raise ValueError("`func` must be a callable function with single parameter `Atom(symbol,index,x,y,z)`.")
|
|
1594
|
+
|
|
1595
|
+
if len(inspect.signature(func).parameters) != 1:
|
|
1574
1596
|
raise ValueError(
|
|
1575
|
-
"`func` takes exactly
|
|
1597
|
+
"`func` takes exactly 1 argument: `Atom(symbol,index,x,y,z)` in fractional coordinates"
|
|
1598
|
+
)
|
|
1599
|
+
|
|
1600
|
+
ret = func(_Atom('',0,0,0,0))
|
|
1601
|
+
if not isinstance(ret, (bool, np.bool_)):
|
|
1602
|
+
raise ValueError(
|
|
1603
|
+
f"`func` must be a function that returns a bool, got {type(ret)}."
|
|
1576
1604
|
)
|
|
1577
1605
|
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1606
|
+
def _masked_data(poscar_data, func):
|
|
1607
|
+
"Returns indices of sites which satisfy the func."
|
|
1608
|
+
_validate_func(func)
|
|
1581
1609
|
eqv_inds = tuple(getattr(poscar_data.metadata, "eqv_indices",[]))
|
|
1582
1610
|
|
|
1583
1611
|
pick = []
|
|
1584
1612
|
for i, pos in enumerate(poscar_data.positions):
|
|
1585
1613
|
idx = eqv_inds[i] if eqv_inds else i # map to original index
|
|
1586
|
-
if func(idx, *pos):
|
|
1614
|
+
if func(_Atom(poscar_data.symbols[i], idx, *pos)): # symbols based on i, not eqv_idx
|
|
1587
1615
|
pick.append(i)
|
|
1588
1616
|
return pick # could be duplicate indices
|
|
1589
1617
|
|
|
@@ -1604,8 +1632,8 @@ def _filter_pairs(labels, pairs, dist, bond_length):
|
|
|
1604
1632
|
# Return all pairs otherwise
|
|
1605
1633
|
return pairs # None -> auto calculate bond_length, number -> use that number
|
|
1606
1634
|
|
|
1607
|
-
def
|
|
1608
|
-
"""Filter sites based on a function that acts on
|
|
1635
|
+
def filter_atoms(poscar_data, func, tol = 0.01):
|
|
1636
|
+
"""Filter atomic sites based on a function that acts on an atom such as `lambda a: (a.p < 1/2).all()`. `p` is additional property to get array([x,y,z]) togther.
|
|
1609
1637
|
This may include equivalent sites, so it should be used for plotting purpose only, e.g. showing atoms on a plane.
|
|
1610
1638
|
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]`.
|
|
1611
1639
|
|
|
@@ -1804,13 +1832,13 @@ def iplot_lattice(
|
|
|
1804
1832
|
return fig
|
|
1805
1833
|
|
|
1806
1834
|
|
|
1807
|
-
def _validate_label_func(fmt_label,
|
|
1835
|
+
def _validate_label_func(fmt_label,label):
|
|
1808
1836
|
if not callable(fmt_label):
|
|
1809
1837
|
raise ValueError("fmt_label must be a callable function.")
|
|
1810
1838
|
if len(inspect.signature(fmt_label).parameters.values()) != 1:
|
|
1811
|
-
raise ValueError("fmt_label must have only one argument.")
|
|
1839
|
+
raise ValueError("fmt_label must have only one argument that accepts a str like 'Ga 1'.")
|
|
1812
1840
|
|
|
1813
|
-
test_out = fmt_label(
|
|
1841
|
+
test_out = fmt_label(_AtomLabel(label))
|
|
1814
1842
|
if isinstance(test_out, (list, tuple)):
|
|
1815
1843
|
if len(test_out) != 2:
|
|
1816
1844
|
raise ValueError(
|
|
@@ -1903,7 +1931,7 @@ def splot_lattice(
|
|
|
1903
1931
|
bond_kws : dict
|
|
1904
1932
|
Keyword arguments to pass to `LineCollection`/`Line3DCollection` for plotting bonds.
|
|
1905
1933
|
fmt_label : callable
|
|
1906
|
-
If given, each site label is passed to it
|
|
1934
|
+
If given, each site label is passed to it as a subclass of str 'Ga 1' with extra attributes `symbol` and `number` and a method `to_latex`, e.g. `lambda lab: lab.to_latex()`.
|
|
1907
1935
|
It must return a string or a list/tuple of length 2 with first item as label and second item as dictionary of keywords to pass to `plt.text`.
|
|
1908
1936
|
plot_cell : bool
|
|
1909
1937
|
Default is True, plot unit cell with default settings.
|
|
@@ -1935,7 +1963,7 @@ def splot_lattice(
|
|
|
1935
1963
|
pairs = _filter_pairs(labels, pairs, dist, bond_length)
|
|
1936
1964
|
|
|
1937
1965
|
if fmt_label is not None:
|
|
1938
|
-
_validate_label_func(fmt_label,
|
|
1966
|
+
_validate_label_func(fmt_label,labels[0])
|
|
1939
1967
|
|
|
1940
1968
|
if plot_cell:
|
|
1941
1969
|
bz_data = serializer.CellData(
|
|
@@ -2002,7 +2030,7 @@ def splot_lattice(
|
|
|
2002
2030
|
)
|
|
2003
2031
|
if fmt_label:
|
|
2004
2032
|
for i, coord in enumerate(coords):
|
|
2005
|
-
lab, textkws = fmt_label(labels[i]), {}
|
|
2033
|
+
lab, textkws = fmt_label(_AtomLabel(labels[i])), {}
|
|
2006
2034
|
if isinstance(lab, (list, tuple)):
|
|
2007
2035
|
lab, textkws = lab
|
|
2008
2036
|
ax.text(*coord, lab, **textkws)
|
|
@@ -2027,7 +2055,7 @@ def splot_lattice(
|
|
|
2027
2055
|
if fmt_label:
|
|
2028
2056
|
labels = [labels[i] for i in zorder] # Reorder labels
|
|
2029
2057
|
for i, coord in enumerate(coords[zorder]):
|
|
2030
|
-
lab, textkws = fmt_label(labels[i]), {}
|
|
2058
|
+
lab, textkws = fmt_label(_AtomLabel(labels[i])), {}
|
|
2031
2059
|
if isinstance(lab, (list, tuple)):
|
|
2032
2060
|
lab, textkws = lab
|
|
2033
2061
|
ax.text(*coord[[ix, iy]], lab, **textkws)
|
|
@@ -2512,24 +2540,8 @@ def add_atoms(poscar_data, name, positions):
|
|
|
2512
2540
|
return serializer.PoscarData(data) # Return new POSCAR
|
|
2513
2541
|
|
|
2514
2542
|
|
|
2515
|
-
def _validate_func(func, nargs, return_type):
|
|
2516
|
-
if not callable(func):
|
|
2517
|
-
raise ValueError("`func` must be a callable function.")
|
|
2518
|
-
|
|
2519
|
-
if len(inspect.signature(func).parameters) != nargs:
|
|
2520
|
-
raise ValueError(
|
|
2521
|
-
f"`func` must be a function with {nargs} arguments, got {len(inspect.signature(func).parameters)}."
|
|
2522
|
-
)
|
|
2523
|
-
ret = func(*range(nargs))
|
|
2524
|
-
if not isinstance(ret, return_type):
|
|
2525
|
-
raise ValueError(
|
|
2526
|
-
f"`func` must be a function that returns {return_type}, got {type(ret)}."
|
|
2527
|
-
)
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
2543
|
def replace_atoms(poscar_data, func, name):
|
|
2531
|
-
"""Replace atoms satisfying a `func(
|
|
2532
|
-
_validate_func(func, 4, bool)
|
|
2544
|
+
"""Replace atoms satisfying a `func(atom) -> bool` with a new `name`. Like `lambda a: a.symbol == 'Ga'`"""
|
|
2533
2545
|
data = poscar_data.to_dict() # Copy data to avoid modifying original
|
|
2534
2546
|
mask = _masked_data(poscar_data, func)
|
|
2535
2547
|
new_types = {**{k: [] for k in poscar_data.types.keys()}, name: []}
|
|
@@ -2570,19 +2582,18 @@ def sort_poscar(poscar_data, new_order):
|
|
|
2570
2582
|
|
|
2571
2583
|
return serializer.PoscarData(data)
|
|
2572
2584
|
|
|
2573
|
-
|
|
2574
2585
|
def remove_atoms(poscar_data, func, fillby=None):
|
|
2575
|
-
"""Remove atoms that satisfy `func(
|
|
2586
|
+
"""Remove atoms that satisfy `func(atom) -> bool` on their fractional coordinates like `lambda a: all(a.p < 1/2)`. `p` is additional property to get array([x,y,z]) togther.
|
|
2576
2587
|
If `fillby` is given, it will fill the removed atoms with atoms from fillby POSCAR.
|
|
2577
2588
|
|
|
2578
2589
|
.. note::
|
|
2579
2590
|
The coordinates of fillby POSCAR are transformed to basis of given POSCAR, before filling.
|
|
2580
2591
|
So a good filling is only guaranteed if both POSCARs have smaller lattice mismatch.
|
|
2581
2592
|
"""
|
|
2582
|
-
_validate_func(func
|
|
2593
|
+
_validate_func(func) # need to validate for fillbay
|
|
2583
2594
|
data = poscar_data.to_dict() # Copy data to avoid modifying original
|
|
2584
2595
|
positions = data["positions"]
|
|
2585
|
-
mask = _masked_data(poscar_data, lambda
|
|
2596
|
+
mask = _masked_data(poscar_data, lambda s: not func(s))
|
|
2586
2597
|
|
|
2587
2598
|
new_types = {k: [] for k in poscar_data.types.keys()}
|
|
2588
2599
|
for k, vs in data["types"].items():
|
|
@@ -2601,7 +2612,7 @@ def remove_atoms(poscar_data, func, fillby=None):
|
|
|
2601
2612
|
|
|
2602
2613
|
def keep_pos(i, x, y, z): # keep positions in basis of given data
|
|
2603
2614
|
u, v, w = to_basis(poscar_data.basis, to_R3(fillby.basis, [[x, y, z]]))[0]
|
|
2604
|
-
return bool(func(u, v, w))
|
|
2615
|
+
return bool(func(_Atom('', 0, u, v, w)))
|
|
2605
2616
|
|
|
2606
2617
|
mask = _masked_data(fillby, keep_pos)
|
|
2607
2618
|
N_prev = len(data["positions"]) # before filling
|
ipyvasp/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.9.
|
|
1
|
+
__version__ = "0.9.8"
|
ipyvasp/bsdos.py
CHANGED
|
@@ -35,7 +35,8 @@ from ._enplots import (
|
|
|
35
35
|
def _format_input(projections, sys_info):
|
|
36
36
|
"""
|
|
37
37
|
Format input spins, atoms, orbs and labels according to selected `projections`.
|
|
38
|
-
For example: {'Ga-s':(0,[
|
|
38
|
+
For example: {'Ga-s':(0,[0]),'Ga-px+py':(0,[2,3]),'Ga-all':(0,'all')} #for Ga in GaAs, to pick Ga-1, use [0] instead of 0 at first place
|
|
39
|
+
or {'Ga-s':('Ga','s'),'Ga-px+py':(0,'px+py'),'all-d':('all','d')}
|
|
39
40
|
In case of 3 items in tuple, the first item is spin index, the second is atoms, the third is orbs.
|
|
40
41
|
"""
|
|
41
42
|
if not isinstance(projections, dict):
|
|
@@ -53,6 +54,11 @@ def _format_input(projections, sys_info):
|
|
|
53
54
|
) # will be error if two ranges there to compare for max
|
|
54
55
|
norbs = len(sys_info.orbs)
|
|
55
56
|
|
|
57
|
+
orbs_map = {} # total if components given
|
|
58
|
+
if 'px' in sys_info.orbs: orbs_map['p'] = range(1,4)
|
|
59
|
+
if 'dxy' in sys_info.orbs: orbs_map['d'] = range(4,9)
|
|
60
|
+
if 'f0' in sys_info.orbs: orbs_map['f'] = range(9,16)
|
|
61
|
+
|
|
56
62
|
# Set default values for different situations
|
|
57
63
|
spins, atoms, orbs, labels = [], [], [], []
|
|
58
64
|
|
|
@@ -78,6 +84,24 @@ def _format_input(projections, sys_info):
|
|
|
78
84
|
)
|
|
79
85
|
|
|
80
86
|
spins.append(S) # Only add spins if given
|
|
87
|
+
|
|
88
|
+
if isinstance(A,str):
|
|
89
|
+
if A.lower() == 'all':
|
|
90
|
+
A = range(max_ind + 1)
|
|
91
|
+
else:
|
|
92
|
+
if not A in sys_info.types.keys():
|
|
93
|
+
raise KeyError(f"type {A!r} not found. Available are {list(sys_info.types.keys())}, 'all', or indexing with integeres/list of intergers.")
|
|
94
|
+
A = sys_info.types[A]
|
|
95
|
+
|
|
96
|
+
if isinstance(B,str):
|
|
97
|
+
if B.lower() == 'all':
|
|
98
|
+
B = range(norbs)
|
|
99
|
+
else:
|
|
100
|
+
B = {b:[sys_info.orbs.index(b)] if b in sys_info.orbs else orbs_map.get(b,[]) for b in (a.strip() for a in B.split('+'))}
|
|
101
|
+
for key, value in B.items():
|
|
102
|
+
if not value:
|
|
103
|
+
raise KeyError(f"orbital {key!r} not found. Available are {sys_info.orbs}, 'all' or indexing with integers/list of intergers")
|
|
104
|
+
B = list(sorted(set([i for b in B.values() for i in b]))) # flatten
|
|
81
105
|
|
|
82
106
|
if not isinstance(A, (int, np.integer, list, tuple, range)):
|
|
83
107
|
raise TypeError(f"{A!r} is not an integer or list/tuple/range of integers.")
|
|
@@ -129,7 +153,7 @@ def _format_input(projections, sys_info):
|
|
|
129
153
|
|
|
130
154
|
if spins and len(atoms) != len(spins):
|
|
131
155
|
raise ValueError(
|
|
132
|
-
"You should provide spin for each projection or none at all. If not provided, spin is picked from corresponding eigenvalues (up/down) for all projections."
|
|
156
|
+
"You should provide spin for each projection or none at all. If not provided, spin is picked from corresponding eigenvalues (up/down) for all projections using 'spin' parameter explicity."
|
|
133
157
|
)
|
|
134
158
|
|
|
135
159
|
uatoms = np.unique(
|
|
@@ -139,7 +163,7 @@ def _format_input(projections, sys_info):
|
|
|
139
163
|
uorbs = tuple(uorbs) if len(uorbs) < norbs else -1 # -1 means all orbitals
|
|
140
164
|
uatoms = tuple(uatoms) if len(uatoms) == (max_ind + 1) else -1 # -1 means all atoms
|
|
141
165
|
uspins = tuple(spins)
|
|
142
|
-
|
|
166
|
+
|
|
143
167
|
return (spins, uspins), (atoms, uatoms), (orbs, uorbs), labels
|
|
144
168
|
|
|
145
169
|
|
|
@@ -154,8 +178,8 @@ bands : list/tuple
|
|
|
154
178
|
List of indices of bands. If given, this ovverides elim."""
|
|
155
179
|
_proj_doc = """projections : dict
|
|
156
180
|
Mapping from str -> [atoms, orbs]. Use dict to select specific projections,
|
|
157
|
-
e.g. {'Ga-s':
|
|
158
|
-
are callable, they must accept two arguments evals/tdos, occs/idos of from data and
|
|
181
|
+
e.g. {'Ga-s':(0,[0]),'Ga-px+py':(0,[2,3]),'Ga-all':(0,'all')} or {'Ga-s':('Ga','s'),'Ga-px+py':(0,'px+py'),'all-d':('all','d')}.
|
|
182
|
+
If values of the dict are callable, they must accept two arguments evals/tdos, occs/idos of from data and
|
|
159
183
|
should return array of shape[1:] (all but spin dimension)."""
|
|
160
184
|
|
|
161
185
|
|
ipyvasp/core/parser.py
CHANGED
|
@@ -204,7 +204,10 @@ class Vasprun(DataSource):
|
|
|
204
204
|
else False
|
|
205
205
|
)
|
|
206
206
|
info_dict["EFERMI"] = float(
|
|
207
|
-
ET.fromstring(next(
|
|
207
|
+
ET.fromstring(next(chain(
|
|
208
|
+
self.read("<i.*efermi", "</i>"), # not always there but this is correct one
|
|
209
|
+
self.read("<i.*EFERMI", "</i>") # zero, always there in start
|
|
210
|
+
))).text
|
|
208
211
|
)
|
|
209
212
|
info_dict["NEDOS"] = int(
|
|
210
213
|
ET.fromstring(next(self.read("<i.*NEDOS", "</i>"))).text
|
ipyvasp/core/serializer.py
CHANGED
|
@@ -329,6 +329,11 @@ class PoscarData(Dict2Data):
|
|
|
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
331
|
|
|
332
|
+
@property
|
|
333
|
+
def sites(self):
|
|
334
|
+
"Returns data with types mapped to their positions."
|
|
335
|
+
return Dict2Data({k: self.positions[v] for k,v in self.types.items()})
|
|
336
|
+
|
|
332
337
|
@property
|
|
333
338
|
def G(self):
|
|
334
339
|
"""Return metric tensor to be used with fractional coordinates.
|
|
@@ -342,6 +347,7 @@ class PoscarData(Dict2Data):
|
|
|
342
347
|
|
|
343
348
|
def metric(self, points):
|
|
344
349
|
"""Shortcut for `np.linalg.norm(self.to_cartesian(points),axis=<1 or 0>)`. `points` are assumed as fractional coordinates in `self.basis`.
|
|
350
|
+
You can compute metric from any point other than origin by just subtracting that point, e.g. `points - 0.5` will get metric from center of cell (1/2,1/2,1/2).
|
|
345
351
|
"""
|
|
346
352
|
return np.linalg.norm(self.to_cartesian(points),axis=1 if np.ndim(points) == 2 else 0)
|
|
347
353
|
|
|
@@ -487,26 +493,28 @@ class PoscarData(Dict2Data):
|
|
|
487
493
|
"""
|
|
488
494
|
Returns a dictionary of {'Ga 1': 'T T T', 'As 1': 'T F F',...} for each atom in the poscar data.
|
|
489
495
|
|
|
490
|
-
`func` should be a callable like `
|
|
496
|
+
`func` should be a callable like `func(Atom(symbol,index,x,y,z)) -> (bool, bool, bool)` which turns on/off selective dynamics for each atom based in each dimension.
|
|
491
497
|
|
|
492
498
|
You can visualize selective dynamics sites by their labels as follows:
|
|
493
499
|
|
|
494
500
|
|
|
495
501
|
>>> poscar = POSCAR.from_file('POSCAR')
|
|
496
|
-
>>> sd = poscar.data.get_selective_dynamics(lambda
|
|
502
|
+
>>> sd = poscar.data.get_selective_dynamics(lambda a: (True, False, True) if a.index % 2 == 0 else (False, True, False)) # Just an example
|
|
497
503
|
>>> poscar.splot_lattice(..., fmt_label = lambda lab: sd[lab]) # This will label sites as T T T, F F F, ... and so so on
|
|
498
504
|
"""
|
|
499
505
|
if not callable(func):
|
|
500
506
|
raise TypeError(
|
|
501
|
-
"`func` should be a callable
|
|
507
|
+
"`func` should be a callable with one paramter `Atom(symbol,index, x,y,z)`"
|
|
502
508
|
)
|
|
503
509
|
|
|
504
|
-
if len(inspect.signature(func).parameters) !=
|
|
510
|
+
if len(inspect.signature(func).parameters) != 1:
|
|
505
511
|
raise ValueError(
|
|
506
|
-
"`func` should be a callable function with
|
|
512
|
+
"`func` should be a callable function with one paramter `Atom(symbol,index, x,y,z)` in fractional coordinates."
|
|
507
513
|
)
|
|
514
|
+
|
|
515
|
+
from .._lattice import _Atom # avoids circular import
|
|
508
516
|
|
|
509
|
-
test_output = func(0, 0, 0, 0)
|
|
517
|
+
test_output = func(_Atom('',0, 0, 0, 0))
|
|
510
518
|
if (
|
|
511
519
|
not isinstance(test_output, (list, tuple, np.ndarray))
|
|
512
520
|
or len(test_output) != 3
|
|
@@ -516,13 +524,13 @@ class PoscarData(Dict2Data):
|
|
|
516
524
|
)
|
|
517
525
|
|
|
518
526
|
for out in test_output:
|
|
519
|
-
if not isinstance(out, bool):
|
|
527
|
+
if not isinstance(out, (bool,np.bool_)):
|
|
520
528
|
raise ValueError(
|
|
521
529
|
"`func` should return boolean values in list/tuple/array like (True, False, True)"
|
|
522
530
|
)
|
|
523
531
|
|
|
524
532
|
sd_list = [
|
|
525
|
-
" ".join("T" if s else "F" for s in func(i, *p))
|
|
533
|
+
" ".join("T" if s else "F" for s in func(_Atom(self.symbols[i],i, *p)))
|
|
526
534
|
for i, p in enumerate(self.positions)
|
|
527
535
|
]
|
|
528
536
|
labels = np.array(
|
ipyvasp/lattice.py
CHANGED
|
@@ -317,9 +317,9 @@ class POSCAR:
|
|
|
317
317
|
|
|
318
318
|
```python
|
|
319
319
|
pc = POSCAR()
|
|
320
|
-
pc.
|
|
321
|
-
pc.set_boundary([-2,2]).
|
|
322
|
-
pc.set_boundary([-2,2]).
|
|
320
|
+
pc.filter_atoms(lambda a: a.index in pc.data.types.Ga) # FINE
|
|
321
|
+
pc.set_boundary([-2,2]).filter_atoms(lambda a: a.index in pc.data.types.Ga) # INCORRECT sites picked
|
|
322
|
+
pc.set_boundary([-2,2]).filter_atoms(lambda a: a.index in pc.last.data.types.Ga) # PERFECT, pc.last is output of set_boundary
|
|
323
323
|
```
|
|
324
324
|
|
|
325
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.
|
|
@@ -358,9 +358,9 @@ class POSCAR:
|
|
|
358
358
|
|
|
359
359
|
```python
|
|
360
360
|
pc = POSCAR()
|
|
361
|
-
pc.
|
|
362
|
-
pc.set_boundary([-2,2]).
|
|
363
|
-
pc.set_boundary([-2,2]).
|
|
361
|
+
pc.filter_atoms(lambda a: a.index in pc.data.types.Ga) # FINE
|
|
362
|
+
pc.set_boundary([-2,2]).filter_atoms(lambda a: a.index in pc.data.types.Ga) # INCORRECT sites picked
|
|
363
|
+
pc.set_boundary([-2,2]).filter_atoms(lambda a: a.index in pc.last.data.types.Ga) # PERFECT, pc.last is output of set_boundary
|
|
364
364
|
```
|
|
365
365
|
"""
|
|
366
366
|
return self._last
|
|
@@ -699,10 +699,10 @@ class POSCAR:
|
|
|
699
699
|
def set_boundary(self, a = [0,1], b=[0,1],c=[0,1]):
|
|
700
700
|
return self.__class__(data = plat.set_boundary(self.data, a=a,b=b,c=c))
|
|
701
701
|
|
|
702
|
-
@_sub_doc(plat.
|
|
703
|
-
@_sig_kwargs(plat.
|
|
704
|
-
def
|
|
705
|
-
return self.__class__(data = plat.
|
|
702
|
+
@_sub_doc(plat.filter_atoms)
|
|
703
|
+
@_sig_kwargs(plat.filter_atoms,("poscar_data",))
|
|
704
|
+
def filter_atoms(self, func, tol=0.01):
|
|
705
|
+
return self.__class__(data = plat.filter_atoms(self.data, func,tol=tol))
|
|
706
706
|
|
|
707
707
|
@_sub_doc(plat.rotate_poscar)
|
|
708
708
|
def rotate(self, angle_deg, axis_vec):
|
ipyvasp/widgets.py
CHANGED
|
@@ -181,7 +181,7 @@ class Files:
|
|
|
181
181
|
return self.__class__(files, exclude=exclude,dirs_only=dirs_only,files_only=files_only)
|
|
182
182
|
|
|
183
183
|
def summarize(self, func, **kwargs):
|
|
184
|
-
"Apply a func(
|
|
184
|
+
"Apply a func(path) -> dict and create a dataframe."
|
|
185
185
|
return summarize(self._files,func, **kwargs)
|
|
186
186
|
|
|
187
187
|
def load_results(self):
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
ipyvasp/__init__.py,sha256=rlorju9arMtHw1QRYPljday-PyZWJdSCxg4lw3g6t0Q,1409
|
|
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=
|
|
6
|
-
ipyvasp/bsdos.py,sha256=
|
|
4
|
+
ipyvasp/_lattice.py,sha256=ixvvaMgOjSWFrvJGQC5K9jmq9lfTwrLArYq7Pas7ars,104984
|
|
5
|
+
ipyvasp/_version.py,sha256=4eQCGJV2-GRHX8FlvA_4etK0E4LFj2or592J4aePZoA,23
|
|
6
|
+
ipyvasp/bsdos.py,sha256=JvYvHLqMp3eVaJ0amD-9kxp7FehQIFq3WFUxsO5dj0Q,31794
|
|
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=YA0_wuB_tU5_GyUybRddoOhTwYqG2_-NyKxQe74hm0w,30627
|
|
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
|
|
13
13
|
ipyvasp/utils.py,sha256=rVyD5SkO_Y7ok5W-fJeQys9X8pLLbDK7VOgbAbcE4WU,14227
|
|
14
|
-
ipyvasp/widgets.py,sha256=
|
|
14
|
+
ipyvasp/widgets.py,sha256=izqe1dffMWJrfojKM5RuqABCmjhNQAIjM3aoJ9tga0w,46605
|
|
15
15
|
ipyvasp/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
ipyvasp/core/parser.py,sha256=
|
|
16
|
+
ipyvasp/core/parser.py,sha256=TmRoIhyIGJ4nr32tb1MAAy5clUZh0CQh-2hP8mnTaVc,38221
|
|
17
17
|
ipyvasp/core/plot_toolkit.py,sha256=3RoPsND5gPssBSfS5H4TjoZ2Qz7B97vpxeKadc2cRRs,36046
|
|
18
|
-
ipyvasp/core/serializer.py,sha256=
|
|
18
|
+
ipyvasp/core/serializer.py,sha256=TW14A4rVveTOS0FDmAMjhUVFqraYgXRChnk4ZLVWQKI,38110
|
|
19
19
|
ipyvasp/core/spatial_toolkit.py,sha256=8DBYTiBFWJ7OBKuvOPw7UoEVCyNjJhSW0OcudjYZvAw,14748
|
|
20
|
-
ipyvasp-0.9.
|
|
21
|
-
ipyvasp-0.9.
|
|
22
|
-
ipyvasp-0.9.
|
|
23
|
-
ipyvasp-0.9.
|
|
24
|
-
ipyvasp-0.9.
|
|
25
|
-
ipyvasp-0.9.
|
|
20
|
+
ipyvasp-0.9.8.dist-info/LICENSE,sha256=F3SO5RiAZOMfmMGf1KOuk2g_c4ObvuBJhd9iBLDgXoQ,1263
|
|
21
|
+
ipyvasp-0.9.8.dist-info/METADATA,sha256=T989kNkzu5aHPsir63uvMsbigxzrcJwpMu76uH3WypM,2420
|
|
22
|
+
ipyvasp-0.9.8.dist-info/WHEEL,sha256=iYlv5fX357PQyRT2o6tw1bN-YcKFFHKqB_LwHO5wP-g,110
|
|
23
|
+
ipyvasp-0.9.8.dist-info/entry_points.txt,sha256=C7m0Sjmr14wFjflCkWXLzr5N6-cQj8uJC9n82mUtzt8,44
|
|
24
|
+
ipyvasp-0.9.8.dist-info/top_level.txt,sha256=ftziWlMWu_1VpDP1sRTFrkfBnWxAi393HYDVu4wRhUk,8
|
|
25
|
+
ipyvasp-0.9.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|