ipyvasp 1.0.9__py2.py3-none-any.whl → 1.1.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 +63 -40
- ipyvasp/_version.py +1 -1
- ipyvasp/core/serializer.py +41 -0
- {ipyvasp-1.0.9.dist-info → ipyvasp-1.1.1.dist-info}/METADATA +1 -1
- {ipyvasp-1.0.9.dist-info → ipyvasp-1.1.1.dist-info}/RECORD +9 -9
- {ipyvasp-1.0.9.dist-info → ipyvasp-1.1.1.dist-info}/LICENSE +0 -0
- {ipyvasp-1.0.9.dist-info → ipyvasp-1.1.1.dist-info}/WHEEL +0 -0
- {ipyvasp-1.0.9.dist-info → ipyvasp-1.1.1.dist-info}/entry_points.txt +0 -0
- {ipyvasp-1.0.9.dist-info → ipyvasp-1.1.1.dist-info}/top_level.txt +0 -0
ipyvasp/_lattice.py
CHANGED
|
@@ -231,6 +231,21 @@ def periodic_table(selection=None):
|
|
|
231
231
|
ax.set(xlim=[-0.6,17.6],ylim=[9.6,-0.6]) # to show borders correctly
|
|
232
232
|
return ax
|
|
233
233
|
|
|
234
|
+
def _write_text(dest, text: str, *, encoding: str = "utf-8") -> None:
|
|
235
|
+
"Write unicode text either to a path-like destination or to a writable text stream."
|
|
236
|
+
# Treat file-like objects (streams) first (avoid Path("CON") / weird Windows devices, etc.)
|
|
237
|
+
if hasattr(dest, "write") and callable(getattr(dest, "write")):
|
|
238
|
+
dest.write(text)
|
|
239
|
+
# Best-effort flush (sys.stdout has it, StringIO doesn't need it)
|
|
240
|
+
flush = getattr(dest, "flush", None)
|
|
241
|
+
if callable(flush):
|
|
242
|
+
flush()
|
|
243
|
+
return
|
|
244
|
+
|
|
245
|
+
# Otherwise treat as a filesystem path
|
|
246
|
+
path = Path(dest)
|
|
247
|
+
with path.open("w", encoding=encoding) as f:
|
|
248
|
+
f.write(text)
|
|
234
249
|
|
|
235
250
|
def write_poscar(poscar_data, outfile=None, selective_dynamics=None, overwrite=False, comment="", scale=None, system=None):
|
|
236
251
|
"""Writes POSCAR data to a file or returns string
|
|
@@ -285,19 +300,18 @@ def write_poscar(poscar_data, outfile=None, selective_dynamics=None, overwrite=F
|
|
|
285
300
|
pos_list = [f"{p} {s}" for p, s in zip(pos_list, sd)]
|
|
286
301
|
|
|
287
302
|
out_str += "\n".join(pos_list)
|
|
288
|
-
if outfile:
|
|
289
|
-
|
|
290
|
-
if
|
|
291
|
-
|
|
292
|
-
f.write(out_str)
|
|
293
|
-
|
|
294
|
-
elif overwrite and path.is_file():
|
|
295
|
-
with path.open("w", encoding="utf-8") as f:
|
|
296
|
-
f.write(out_str)
|
|
303
|
+
if outfile is not None:
|
|
304
|
+
# If it's a writable stream (sys.stdout, StringIO, open file handle), write directly.
|
|
305
|
+
if hasattr(outfile, "write") and callable(getattr(outfile, "write")):
|
|
306
|
+
_write_text(outfile, out_str)
|
|
297
307
|
else:
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
)
|
|
308
|
+
# Otherwise treat as path-like with overwrite protection.
|
|
309
|
+
path = Path(outfile)
|
|
310
|
+
if path.exists() and not overwrite:
|
|
311
|
+
raise FileExistsError(
|
|
312
|
+
f"{str(path)!r} exists, can not overwrite; use overwrite=True."
|
|
313
|
+
)
|
|
314
|
+
_write_text(path, out_str)
|
|
301
315
|
else:
|
|
302
316
|
print(out_str)
|
|
303
317
|
|
|
@@ -555,9 +569,8 @@ class InvokeMaterialsProject:
|
|
|
555
569
|
return f"Structure(unit={self.unit},mp_id={self.mp_id!r},symbol={self.symbol!r},crystal={self.crystal!r},cif='{self._cif[:10]}...')"
|
|
556
570
|
|
|
557
571
|
def write_cif(self, outfile=None):
|
|
558
|
-
if
|
|
559
|
-
|
|
560
|
-
f.write(self._cif)
|
|
572
|
+
if outfile is not None:
|
|
573
|
+
_write_text(outfile, self._cif)
|
|
561
574
|
else:
|
|
562
575
|
print(self._cif)
|
|
563
576
|
|
|
@@ -640,12 +653,12 @@ def get_kpath(
|
|
|
640
653
|
ibzkpt : PathLike
|
|
641
654
|
Path to ibzkpt file, required for HSE calculations.
|
|
642
655
|
outfile : PathLike
|
|
643
|
-
Path/to/file to write kpoints.
|
|
656
|
+
Path/to/file to write kpoints. Use sys.stdout to print to console.
|
|
644
657
|
rec_basis : array_like
|
|
645
658
|
Reciprocal basis 3x3 array to use for calculating uniform points.
|
|
646
659
|
|
|
647
660
|
|
|
648
|
-
If `outfile = None`,
|
|
661
|
+
If `outfile = None`, kpoints array (Nx3) is returned.
|
|
649
662
|
"""
|
|
650
663
|
if isinstance(kpoints, str):
|
|
651
664
|
kpoints = _str2kpoints(kpoints)
|
|
@@ -766,10 +779,9 @@ def get_kpath(
|
|
|
766
779
|
)
|
|
767
780
|
out_str = "{}\n{}".format(top_str, out_str)
|
|
768
781
|
if outfile != None:
|
|
769
|
-
|
|
770
|
-
f.write(out_str)
|
|
782
|
+
_write_text(outfile, out_str)
|
|
771
783
|
else:
|
|
772
|
-
return
|
|
784
|
+
return points # return points for any processing by user.
|
|
773
785
|
|
|
774
786
|
|
|
775
787
|
# Cell
|
|
@@ -799,12 +811,12 @@ def get_kmesh(
|
|
|
799
811
|
ibzkpt : PathLike
|
|
800
812
|
Path to ibzkpt file, required for HSE calculations.
|
|
801
813
|
outfile : PathLike
|
|
802
|
-
Path/to/file to write kpoints.
|
|
814
|
+
Path/to/file to write kpoints. Use sys.stdout to print to console.
|
|
803
815
|
endpoint : bool
|
|
804
816
|
Default True, include endpoints in mesh at edges away from origin.
|
|
805
817
|
|
|
806
818
|
|
|
807
|
-
If `outfile = None`,
|
|
819
|
+
If `outfile = None`, kpoints array (Nx3) is returned.
|
|
808
820
|
|
|
809
821
|
"""
|
|
810
822
|
if len(args) not in [1, 3]:
|
|
@@ -879,10 +891,9 @@ def get_kmesh(
|
|
|
879
891
|
)
|
|
880
892
|
out_str = "{}\n{}".format(top_str, out_str)
|
|
881
893
|
if outfile != None:
|
|
882
|
-
|
|
883
|
-
f.write(out_str)
|
|
894
|
+
_write_text(outfile, out_str)
|
|
884
895
|
else:
|
|
885
|
-
return
|
|
896
|
+
return points # return points for any processing by user.
|
|
886
897
|
|
|
887
898
|
|
|
888
899
|
# Cell
|
|
@@ -898,6 +909,7 @@ def splot_bz(
|
|
|
898
909
|
shade=True,
|
|
899
910
|
alpha=0.4,
|
|
900
911
|
zoffset=0,
|
|
912
|
+
center=(0,0,0),
|
|
901
913
|
**kwargs,
|
|
902
914
|
):
|
|
903
915
|
"""Plots matplotlib's static figure of BZ/Cell. You can also plot in 2D on a 3D axes.
|
|
@@ -926,8 +938,9 @@ def splot_bz(
|
|
|
926
938
|
alpha : float
|
|
927
939
|
Opacity of filling in range [0,1]. Increase for clear viewpoint.
|
|
928
940
|
zoffset : float
|
|
929
|
-
Only used if plotting in 2D over a 3D axis. Default is 0. Any plane 'xy','yz' etc.
|
|
930
|
-
|
|
941
|
+
Only used if plotting in 2D over a 3D axis. Default is 0. Any plane 'xy','yz' etc can be offset to it's own normal.
|
|
942
|
+
center : (3,) array_like
|
|
943
|
+
Translation of origin in *basis coordinates* (fractional along the plotted basis). Use this to tile BZ with help of ``BrZoneData.tile`` fuction.
|
|
931
944
|
|
|
932
945
|
kwargs are passed to `plt.plot` or `Poly3DCollection` if `fill=True`.
|
|
933
946
|
|
|
@@ -951,6 +964,17 @@ def splot_bz(
|
|
|
951
964
|
if v not in [0, 1, 2]:
|
|
952
965
|
raise ValueError(f"`vectors` expects values in [0,1,2], got {vectors!r}")
|
|
953
966
|
|
|
967
|
+
if not isinstance(center, (tuple, list, np.ndarray)) or len(center) != 3:
|
|
968
|
+
raise ValueError("`center` must be a 3-sequence like (0,0,0) in basis coordinates.")
|
|
969
|
+
try:
|
|
970
|
+
center = np.array(center, dtype=float).reshape(3)
|
|
971
|
+
except Exception as e:
|
|
972
|
+
raise ValueError(f"`center` must be numeric, got {center!r}") from e
|
|
973
|
+
|
|
974
|
+
origin = to_R3(bz_data.basis, [center])[0] # (3,) cartesian shift
|
|
975
|
+
bz_data = bz_data.copy()
|
|
976
|
+
bz_data.vertices[:,:] += origin # apply on view, assignment is restricted
|
|
977
|
+
|
|
954
978
|
name = kwargs.pop("label", None) # will set only on single line
|
|
955
979
|
kwargs.pop("zdir", None) # remove , no need
|
|
956
980
|
is_subzone = hasattr(bz_data, "_specials") # For subzone
|
|
@@ -1020,13 +1044,14 @@ def splot_bz(
|
|
|
1020
1044
|
|
|
1021
1045
|
if vectors and not is_subzone:
|
|
1022
1046
|
s_basis = to_plane(normals[plane], bz_data.basis[(vectors,)])
|
|
1047
|
+
s_origin = to_plane(normals[plane], [origin]*len(vectors))
|
|
1023
1048
|
|
|
1024
1049
|
for k, b in zip(vectors, s_basis):
|
|
1025
1050
|
x, y = b[idxs[plane]]
|
|
1026
1051
|
l = r" ${}_{} $".format(_label, k + 1)
|
|
1027
1052
|
l = l + "\n" if y < 0 else "\n" + l
|
|
1028
1053
|
ha = "right" if x < 0 else "left"
|
|
1029
|
-
xyz = 0.8 * b + z0 if is3d else np.array([0.8 * x, 0.8 * y])
|
|
1054
|
+
xyz = 0.8 * b + z0 + s_origin[0] if is3d else np.array([0.8 * x, 0.8 * y]) + s_origin[0, idxs[plane]]
|
|
1030
1055
|
ax.text(
|
|
1031
1056
|
*xyz, l, va="center", ha=ha, clip_on=True
|
|
1032
1057
|
) # must clip to have limits of axes working.
|
|
@@ -1034,7 +1059,7 @@ def splot_bz(
|
|
|
1034
1059
|
*(xyz / 0.8), color="w", s=0.0005
|
|
1035
1060
|
) # Must be to scale below arrow.
|
|
1036
1061
|
if is3d:
|
|
1037
|
-
XYZ, UVW = (np.ones_like(s_basis) * z0).T, s_basis.T
|
|
1062
|
+
XYZ, UVW = (np.ones_like(s_basis) * z0 + s_origin).T, s_basis.T
|
|
1038
1063
|
quiver3d(
|
|
1039
1064
|
*XYZ,
|
|
1040
1065
|
*UVW,
|
|
@@ -1045,10 +1070,8 @@ def splot_bz(
|
|
|
1045
1070
|
mutation_scale=7,
|
|
1046
1071
|
)
|
|
1047
1072
|
else:
|
|
1048
|
-
s_zero = [0 for _ in s_basis] # either 3 or 2.
|
|
1049
1073
|
ax.quiver(
|
|
1050
|
-
|
|
1051
|
-
s_zero,
|
|
1074
|
+
*s_origin[:, idxs[plane]].T,
|
|
1052
1075
|
*s_basis[:, idxs[plane]].T,
|
|
1053
1076
|
lw=0.7,
|
|
1054
1077
|
color=color,
|
|
@@ -1115,9 +1138,9 @@ def splot_bz(
|
|
|
1115
1138
|
|
|
1116
1139
|
if vectors and not is_subzone:
|
|
1117
1140
|
for k, v in enumerate(0.35 * bz_data.basis):
|
|
1118
|
-
ax.text(*v, r"${}_{}$".format(_label, k + 1), va="center", ha="center")
|
|
1141
|
+
ax.text(*(v + origin), r"${}_{}$".format(_label, k + 1), va="center", ha="center")
|
|
1119
1142
|
|
|
1120
|
-
XYZ, UVW = [
|
|
1143
|
+
XYZ, UVW = np.array([origin] * 3).T, 0.3 * bz_data.basis.T
|
|
1121
1144
|
quiver3d(
|
|
1122
1145
|
*XYZ, *UVW, C="k", L=0.7, ax=ax, arrowstyle="-|>", mutation_scale=7
|
|
1123
1146
|
)
|
|
@@ -1136,7 +1159,7 @@ def splot_bz(
|
|
|
1136
1159
|
ax.set_zlabel(label.format("z"))
|
|
1137
1160
|
|
|
1138
1161
|
if vname == "b": # These needed for splot_kpath internally
|
|
1139
|
-
type(bz_data)._splot_kws = dict(plane=plane, zoffset=zoffset, ax=ax)
|
|
1162
|
+
type(bz_data)._splot_kws = dict(plane=plane, zoffset=zoffset, ax=ax, shift=origin)
|
|
1140
1163
|
|
|
1141
1164
|
return ax
|
|
1142
1165
|
|
|
@@ -1144,7 +1167,7 @@ def splot_bz(
|
|
|
1144
1167
|
def splot_kpath(
|
|
1145
1168
|
bz_data, kpoints, labels=None, fmt_label=lambda x: (x, {"color": "blue"}), **kwargs
|
|
1146
1169
|
):
|
|
1147
|
-
"""Plot k-path over
|
|
1170
|
+
"""Plot k-path over last plotted BZ. It will take ``ax``, ``plane`` and ``zoffset`` internally from most recent call to ``splot_bz``/``bz.splot``.
|
|
1148
1171
|
|
|
1149
1172
|
Parameters
|
|
1150
1173
|
----------
|
|
@@ -1170,9 +1193,9 @@ def splot_kpath(
|
|
|
1170
1193
|
if not np.ndim(kpoints) == 2 and np.shape(kpoints)[-1] == 3:
|
|
1171
1194
|
raise ValueError("kpoints must be 2D array of shape (N,3)")
|
|
1172
1195
|
|
|
1173
|
-
plane, ax, zoffset = [
|
|
1196
|
+
plane, ax, zoffset, shift = [
|
|
1174
1197
|
bz_data._splot_kws.get(attr, default) # class level attributes
|
|
1175
|
-
for attr, default in zip(["plane", "ax", "zoffset"], [None, None, 0])
|
|
1198
|
+
for attr, default in zip(["plane", "ax", "zoffset", "shift"], [None, None, 0,np.array([0.0, 0.0, 0.0])])
|
|
1176
1199
|
]
|
|
1177
1200
|
|
|
1178
1201
|
ijk = [0, 1, 2]
|
|
@@ -1208,9 +1231,9 @@ def splot_kpath(
|
|
|
1208
1231
|
if fmt_label is None:
|
|
1209
1232
|
fmt_label = lambda x: (x, {"color": "blue"})
|
|
1210
1233
|
|
|
1211
|
-
_validate_label_func(fmt_label,labels[0])
|
|
1234
|
+
_validate_label_func(fmt_label,labels[0])
|
|
1212
1235
|
|
|
1213
|
-
coords = bz_data.to_cartesian(kpoints)
|
|
1236
|
+
coords = bz_data.to_cartesian(kpoints) + shift
|
|
1214
1237
|
if _zoffset and plane:
|
|
1215
1238
|
normal = (
|
|
1216
1239
|
[0, 0, 1] if plane in "xyx" else [0, 1, 0] if plane in "xzx" else [1, 0, 0]
|
ipyvasp/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.
|
|
1
|
+
__version__ = "1.1.1"
|
ipyvasp/core/serializer.py
CHANGED
|
@@ -765,10 +765,51 @@ class BrZoneData(Dict2Data):
|
|
|
765
765
|
d = self.copy().to_dict()
|
|
766
766
|
d.update({"faces": faces, "vertices": vertices, "_specials": specials})
|
|
767
767
|
return self.__class__(d)
|
|
768
|
+
|
|
769
|
+
def tile(self, nxyz, filter=None):
|
|
770
|
+
"""Create a tiled array of BZ centers for visualization.
|
|
771
|
+
|
|
772
|
+
Parameters
|
|
773
|
+
----------
|
|
774
|
+
nxyz : list or tuple of 3 ints
|
|
775
|
+
Number of tiles along each cartesian direction [nx, ny, nz].
|
|
776
|
+
Must be 3 positive integers.
|
|
777
|
+
filter : callable, optional
|
|
778
|
+
Function filter(x,y,z) that takes cartesian coordinates and returns bool.
|
|
779
|
+
|
|
780
|
+
Returns
|
|
781
|
+
-------
|
|
782
|
+
numpy.ndarray
|
|
783
|
+
Array of shape (N, 3) containing BZ center positions in fractional coordinates.
|
|
784
|
+
|
|
785
|
+
Examples
|
|
786
|
+
--------
|
|
787
|
+
>>> centers = bz_data.tile([3, 3, 3])
|
|
788
|
+
>>> centers = bz_data.tile([5, 5, 1], filter=lambda x,y,z: x**2 + y**2 <= 2**2)
|
|
789
|
+
"""
|
|
790
|
+
if not isinstance(nxyz, (list, tuple, np.ndarray)) or len(nxyz) != 3:
|
|
791
|
+
raise ValueError("nxyz must be a list/tuple/array of 3 integers")
|
|
792
|
+
|
|
793
|
+
for i, n in enumerate(nxyz):
|
|
794
|
+
if not isinstance(n, int) or n < 1:
|
|
795
|
+
raise ValueError(f"nxyz[{i}] must be a positive integer")
|
|
796
|
+
|
|
797
|
+
xyz = self.to_cartesian(np.indices(np.ceil(nxyz).astype(int)).reshape((3,-1)).T)
|
|
798
|
+
# Apply filter if provided
|
|
799
|
+
if filter is not None:
|
|
800
|
+
if not callable(filter):
|
|
801
|
+
raise TypeError("filter must be callable")
|
|
802
|
+
|
|
803
|
+
mask = np.array([filter(x, y, z) for x, y, z in xyz])
|
|
804
|
+
xyz = xyz[mask]
|
|
805
|
+
|
|
806
|
+
# Convert to fractional coordinates and return
|
|
807
|
+
return self.to_fractional(xyz)
|
|
768
808
|
|
|
769
809
|
|
|
770
810
|
class CellData(Dict2Data):
|
|
771
811
|
splot, iplot = _methods_imported()
|
|
812
|
+
tile = BrZoneData.tile
|
|
772
813
|
_req_keys = ("basis", "faces", "vertices")
|
|
773
814
|
|
|
774
815
|
def __init__(self, d):
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
ipyvasp/__init__.py,sha256=pzTqeKuf6sN2GQmaexmMgG677ggT3sxIFyQDXq_2whU,1422
|
|
2
2
|
ipyvasp/__main__.py,sha256=eJV1TZSiT8mC_VqAeksNnBI2I8mKMiPkEIlwikbtOjI,216
|
|
3
3
|
ipyvasp/_enplots.py,sha256=gJ7S9WBmrxvDEbmoccDRaJG01kpx9oNlRf7mozigbgY,37872
|
|
4
|
-
ipyvasp/_lattice.py,sha256=
|
|
5
|
-
ipyvasp/_version.py,sha256=
|
|
4
|
+
ipyvasp/_lattice.py,sha256=Lh-ip60M6APUckR4I0bQ6GMN2aaY7gpkA1Z0uuFt1A4,108117
|
|
5
|
+
ipyvasp/_version.py,sha256=KGJQJ23MnEKMR2yQigWuN5Fj9B4JRjsenwhmGe0cwAA,23
|
|
6
6
|
ipyvasp/bsdos.py,sha256=hVHpxkdT2ImRsxwFvMSMHxRSo4LqDM90DnUhwTP8vcs,32192
|
|
7
7
|
ipyvasp/cli.py,sha256=-Lf-qdTvs7WyrA4ALNLaoqxMjLsZkXdPviyQps3ezqg,6880
|
|
8
8
|
ipyvasp/evals_dataframe.py,sha256=n2iSH4D4ZbrxlAV4yDTVHbcl3ycfD0zfQYmTBcxjfkE,20789
|
|
@@ -15,11 +15,11 @@ ipyvasp/widgets.py,sha256=Bpa4Y3Eopk_ZPFsVetfysClZP2q_2ONvmOwUol9vVGI,53154
|
|
|
15
15
|
ipyvasp/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
ipyvasp/core/parser.py,sha256=o-uHyL_w9W0pmxoSt3JmLwwmmT3WRHlHSs_NoiHO-hs,39401
|
|
17
17
|
ipyvasp/core/plot_toolkit.py,sha256=aURiPAu0tWTNctuA9LMEL3CfraRgAOyTJURzDrrO0r0,36232
|
|
18
|
-
ipyvasp/core/serializer.py,sha256=
|
|
18
|
+
ipyvasp/core/serializer.py,sha256=9xuLfl9LtUXPxTX2_zRs7nvfZsZOZN00bnxErAxDA5w,40065
|
|
19
19
|
ipyvasp/core/spatial_toolkit.py,sha256=dXowREhiFzBvvr5f_bApzFhf8IzjH2E2Ix90oCBUetY,14885
|
|
20
|
-
ipyvasp-1.
|
|
21
|
-
ipyvasp-1.
|
|
22
|
-
ipyvasp-1.
|
|
23
|
-
ipyvasp-1.
|
|
24
|
-
ipyvasp-1.
|
|
25
|
-
ipyvasp-1.
|
|
20
|
+
ipyvasp-1.1.1.dist-info/LICENSE,sha256=F3SO5RiAZOMfmMGf1KOuk2g_c4ObvuBJhd9iBLDgXoQ,1263
|
|
21
|
+
ipyvasp-1.1.1.dist-info/METADATA,sha256=WVjTyiCpM9SmXs2S9u6CTtwdrfWhSYaY8-S4fY7EiSU,3218
|
|
22
|
+
ipyvasp-1.1.1.dist-info/WHEEL,sha256=Kh9pAotZVRFj97E15yTA4iADqXdQfIVTHcNaZTjxeGM,110
|
|
23
|
+
ipyvasp-1.1.1.dist-info/entry_points.txt,sha256=aU-gGjQG2Q8XfxDlNc_8__cwfp8WG2K5ZgFPInTm2jg,45
|
|
24
|
+
ipyvasp-1.1.1.dist-info/top_level.txt,sha256=ftziWlMWu_1VpDP1sRTFrkfBnWxAi393HYDVu4wRhUk,8
|
|
25
|
+
ipyvasp-1.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|