mirror of https://github.com/abinit/abipy.git
Add abiopen FILE.json --panel
This commit is contained in:
parent
398ee0c219
commit
358d1387e7
|
@ -7,6 +7,7 @@ Release 0.8.0: xxxx-xx-xx
|
|||
* Add examples and flows for effective mass calculations
|
||||
* Add examples for quasi-harmonic calculations and post-processing tools
|
||||
* Add support for JSON files (including MSONable format) to abiopen.py
|
||||
Supports `--notebook`, `--panel` options such as `abiopen.py FILE.json --panel`
|
||||
* Improved support for EPH calculations.
|
||||
* Add `primitive` command to `abistruct.py` to get primitive structure from spglib
|
||||
|
||||
|
|
|
@ -226,7 +226,7 @@ class Structure(pymatgen.Structure, NotebookWriter):
|
|||
new = ncfile.read_structure(cls=cls)
|
||||
new.set_abi_spacegroup(AbinitSpaceGroup.from_ncreader(ncfile))
|
||||
|
||||
# Try to read indsym from file (added in 8.9.x)
|
||||
# Try to read indsym table from file (added in 8.9.x)
|
||||
indsym = ncfile.read_value("indsym", default=None)
|
||||
if indsym is not None:
|
||||
# Fortran --> C convention
|
||||
|
@ -2065,7 +2065,7 @@ class Structure(pymatgen.Structure, NotebookWriter):
|
|||
nbv.new_code_cell("print(structure)"),
|
||||
nbv.new_code_cell("print(structure.abi_string)"),
|
||||
nbv.new_code_cell("structure"),
|
||||
nbv.new_code_cell("print(structure.spglib_summary())"),
|
||||
nbv.new_code_cell("print(structure.spget_summary())"),
|
||||
nbv.new_code_cell("if structure.abi_spacegroup is not None: print(structure.abi_spacegroup)"),
|
||||
nbv.new_code_cell("print(structure.hsym_kpoints)"),
|
||||
nbv.new_code_cell("structure.plot_bz();"),
|
||||
|
|
|
@ -851,6 +851,18 @@ class ElectronBands(Has_Structure):
|
|||
"""True if time-reversal symmetry is used in the BZ sampling."""
|
||||
return has_timrev_from_kptopt(self.kptopt)
|
||||
|
||||
@lazy_property
|
||||
def supports_fermi_surface(self):
|
||||
"""
|
||||
True if the kpoints used for the energies can be employed to visualize Fermi surface.
|
||||
Fermi surface viewers require gamma-centered k-mesh.
|
||||
"""
|
||||
if self.kpoints.is_mpmesh:
|
||||
mpdivs, shifts = self.kpoints.mpdivs_shifts
|
||||
if shifts is not None and np.all(shifts == 0.0):
|
||||
return True
|
||||
return False
|
||||
|
||||
def kindex(self, kpoint):
|
||||
"""
|
||||
The index of the k-point in the internal list of k-points.
|
||||
|
|
|
@ -1542,6 +1542,13 @@ class FatBandsFile(AbinitNcFile, Has_Header, Has_Structure, Has_ElectronBands, N
|
|||
yield self.plot_pjdos_lview(show=False)
|
||||
yield self.plot_pjdos_typeview(show=False)
|
||||
|
||||
def get_panel(self):
|
||||
"""
|
||||
Build panel with widgets to interact with the |FatbandsFile| either in a notebook or in panel app.
|
||||
"""
|
||||
from abipy.panels.fatbands import FatBandsFilePanel
|
||||
return FatBandsFilePanel(self).get_panel()
|
||||
|
||||
def write_notebook(self, nbpath=None):
|
||||
"""
|
||||
Write a jupyter_ notebook to nbpath. If nbpath is None, a temporay file in the current
|
||||
|
@ -1587,9 +1594,10 @@ class FatBandsFile(AbinitNcFile, Has_Header, Has_Structure, Has_ElectronBands, N
|
|||
|
||||
if self.prtdos == 3 and self.ebands.kpoints.is_path:
|
||||
nb.cells.extend([
|
||||
nbv.new_markdown_cell("## L-DOSes with fatbands\n"
|
||||
"(require `prtdos=3`, `fbnc` must contain a k-path, "
|
||||
"`pjdosfile` is a `FATBANDS.nc` file with a BZ sampling)"),
|
||||
nbv.new_markdown_cell(
|
||||
"## L-DOSes with fatbands\n"
|
||||
"(require `prtdos=3`, `fbnc` must contain a k-path, "
|
||||
"`pjdosfile` is a `FATBANDS.nc` file with a BZ sampling)"),
|
||||
nbv.new_code_cell("fbnc.plot_fatbands_with_pjdos(pjdosfile=None, ylims=ylims, view='type');"),
|
||||
])
|
||||
|
||||
|
|
|
@ -479,6 +479,7 @@ class ElectronBandsTest(AbipyTest):
|
|||
with abilab.abiopen(abidata.ref_file("mgb2_kmesh181818_FATBANDS.nc")) as fbnc_kmesh:
|
||||
ebands = fbnc_kmesh.ebands
|
||||
str(ebands)
|
||||
assert ebands.supports_fermi_surface
|
||||
ebands.to_bxsf(self.get_tmpname(text=True))
|
||||
|
||||
# Test Ebands3d
|
||||
|
@ -525,6 +526,7 @@ class ElectronBandsFromRestApi(AbipyTest):
|
|||
|
||||
new_fermie = r.ebands_kpath.set_fermie_to_vbm()
|
||||
assert new_fermie == r.ebands_kpath.fermie
|
||||
assert not r.ebands_kpath.supports_fermi_surface
|
||||
|
||||
edos = r.ebands_kmesh.get_edos()
|
||||
new_fermie = r.ebands_kpath.set_fermie_from_edos(edos)
|
||||
|
|
|
@ -39,6 +39,9 @@ class TestElectronFatbands(AbipyTest):
|
|||
if self.has_nbformat():
|
||||
fbnc_kpath.write_notebook(nbpath=self.get_tmpname(text=True))
|
||||
|
||||
if self.has_panel():
|
||||
assert hasattr(fbnc_kpath.get_panel(), "show")
|
||||
|
||||
fbnc_kmesh = FatBandsFile(abidata.ref_file("mgb2_kmesh181818_FATBANDS.nc"))
|
||||
repr(fbnc_kmesh); str(fbnc_kmesh)
|
||||
assert fbnc_kmesh.ebands.kpoints.is_ibz
|
||||
|
|
|
@ -48,8 +48,8 @@ class PanelWithElectronBands(AbipyParameterized): #, metaclass=abc.ABCMeta):
|
|||
# - `fermie`: shift all eigenvalues to have zero energy at the Fermi energy (`self.fermie`).
|
||||
# - Number e.g e0=0.5: shift all eigenvalues to have zero energy at 0.5 eV
|
||||
# - None: Don't shift energies, equivalent to e0=0
|
||||
set_fermie_to_vbm = pnw.Checkbox(name="Set Fermie to VBM")
|
||||
|
||||
#set_fermie_to_vbm
|
||||
plot_ebands_btn = pnw.Button(name="Plot e-bands", button_type='primary')
|
||||
|
||||
# DOS plot.
|
||||
|
@ -58,19 +58,25 @@ class PanelWithElectronBands(AbipyParameterized): #, metaclass=abc.ABCMeta):
|
|||
edos_width = pnw.Spinner(name='e-DOS Gaussian broadening (eV)', value=0.2, step=0.05, start=1e-6, end=None)
|
||||
plot_edos_btn = pnw.Button(name="Plot e-DOS", button_type='primary')
|
||||
|
||||
# Fermi surface plot.
|
||||
fs_viewer = pnw.Select(name="FS viewer", options=["matplotlib", "xcrysden"])
|
||||
plot_fermi_surface_btn = pnw.Button(name="Plot Fermi surface", button_type='primary')
|
||||
|
||||
#@abc.abstractproperty
|
||||
#def ebands(self):
|
||||
# """Returns the |ElectronBands| object."""
|
||||
|
||||
def get_plot_ebands_widgets(self):
|
||||
"""Widgets to plot ebands."""
|
||||
return pn.Column(self.with_gaps,
|
||||
self.plot_ebands_btn)
|
||||
return pn.Column(self.with_gaps, self.set_fermie_to_vbm, self.plot_ebands_btn)
|
||||
|
||||
@param.depends('plot_ebands_btn.clicks')
|
||||
def on_plot_ebands_btn(self):
|
||||
"""Button triggering ebands plot."""
|
||||
if self.plot_ebands_btn.clicks == 0: return
|
||||
if self.set_fermie_to_vbm.value:
|
||||
self.ebands.set_fermie_to_vbm()
|
||||
|
||||
fig1 = self.ebands.plot(e0="fermie", ylims=None,
|
||||
with_gaps=self.with_gaps.value, max_phfreq=None, fontsize=8, **self.fig_kwargs)
|
||||
|
||||
|
@ -89,9 +95,37 @@ class PanelWithElectronBands(AbipyParameterized): #, metaclass=abc.ABCMeta):
|
|||
if self.plot_edos_btn.clicks == 0: return
|
||||
edos = self.ebands.get_edos(method=self.edos_method.value, step=self.edos_step.value, width=self.edos_width.value)
|
||||
fig = edos.plot(**self.fig_kwargs)
|
||||
#print(edos)
|
||||
return pn.Row(self._mp(fig), sizing_mode='scale_width')
|
||||
|
||||
def get_plot_fermi_surface_widgets(self):
|
||||
"""Widgets to compute e-DOS."""
|
||||
return pn.Column(self.fs_viewer, self.plot_fermi_surface_btn)
|
||||
|
||||
@param.depends('plot_fermi_surface_btn.clicks')
|
||||
def on_plot_fermi_surface_btn(self):
|
||||
if self.plot_fermi_surface_btn.clicks == 0: return
|
||||
if hasattr(self, "_eb3d"):
|
||||
eb3d = self._eb3d
|
||||
else:
|
||||
# Build ebands in full BZ.
|
||||
eb3d = self._eb3d = self.ebands.get_ebands3d()
|
||||
|
||||
if self.fs_viewer.value == "matplotlib":
|
||||
# Use matplotlib to plot isosurfaces corresponding to the Fermi level (default)
|
||||
# Warning: requires skimage package, rendering could be slow.
|
||||
fig = eb3d.plot_isosurfaces(e0="fermie", cmap=None, **self.fig_kwargs)
|
||||
return pn.Row(self._mp(fig), sizing_mode='scale_width')
|
||||
|
||||
elif self.fs_viewer.value == "xcrysden":
|
||||
# Alternatively, it's possible to export the data in xcrysden format
|
||||
# and then use `xcrysden --bxsf mgb2.bxsf`
|
||||
#eb3d.to_bxsf("mgb2.bxsf")
|
||||
# If you have mayavi installed, try:
|
||||
#eb3d.mvplot_isosurfaces()
|
||||
|
||||
else:
|
||||
raise ValueError("Invalid choice: %s" % self.fs_viewer.value)
|
||||
|
||||
|
||||
class BaseRobotPanel(AbipyParameterized):
|
||||
"""pass"""
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
"""Panels for interacting with FATBANDS files."""
|
||||
import param
|
||||
import panel as pn
|
||||
import panel.widgets as pnw
|
||||
import bokeh.models.widgets as bkw
|
||||
|
||||
from .core import PanelWithElectronBands, PanelWithEbandsRobot
|
||||
|
||||
|
||||
class FatBandsFilePanel(PanelWithElectronBands):
|
||||
"""
|
||||
Panel with widgets to interact with a |FatBandsFile|.
|
||||
"""
|
||||
def __init__(self, ncfile, **params):
|
||||
super().__init__(**params)
|
||||
self.ncfile = ncfile
|
||||
|
||||
@property
|
||||
def ebands(self):
|
||||
"""|ElectronBands|."""
|
||||
return self.ncfile.ebands
|
||||
|
||||
def get_panel(self):
|
||||
"""Return tabs with widgets to interact with the DDB file."""
|
||||
tabs = pn.Tabs(); app = tabs.append
|
||||
app(("Summary", pn.Row(bkw.PreText(text=self.ncfile.to_string(verbose=self.verbose),
|
||||
sizing_mode="scale_both"))))
|
||||
app(("e-Bands", pn.Row(self.get_plot_ebands_widgets(), self.on_plot_ebands_btn)))
|
||||
|
||||
# Add DOS tab only if k-sampling.
|
||||
if self.ncfile.ebands.kpoints.is_ibz:
|
||||
app(("e-DOS", pn.Row(self.get_plot_edos_widgets(), self.on_plot_edos_btn)))
|
||||
|
||||
if self.ncfile.ebands.supports_fermi_surface:
|
||||
# Fermi surface requires gamma-centered k-mesh
|
||||
app(("Fermi Surface", pn.Row(self.get_plot_fermi_surface_widgets(), self.on_plot_fermi_surface_btn)))
|
||||
|
||||
return tabs
|
||||
|
||||
|
||||
#class GsrRobotPanel(PanelWithEbandsRobot):
|
||||
# """
|
||||
# A Panel to interoperate with multiple GSR files.
|
||||
# """
|
||||
#
|
||||
# gsr_dataframe_btn = pnw.Button(name="Compute", button_type='primary')
|
||||
#
|
||||
# def __init__(self, robot, **params):
|
||||
# super().__init__(**params)
|
||||
# self.robot = robot
|
||||
#
|
||||
# @param.depends("gsr_dataframe_btn.clicks")
|
||||
# def on_gsr_dataframe_btn(self):
|
||||
# if self.gsr_dataframe_btn.clicks == 0: return
|
||||
# df = self.robot.get_dataframe(with_geo=True)
|
||||
# return pn.Column(self._df(df), sizing_mode='stretch_width')
|
||||
#
|
||||
# def get_panel(self):
|
||||
# """Return tabs with widgets to interact with the |GsrRobot|."""
|
||||
# tabs = pn.Tabs(); app = tabs.append
|
||||
# app(("Summary", pn.Row(bkw.PreText(text=self.robot.to_string(verbose=self.verbose),
|
||||
# sizing_mode="scale_both"))))
|
||||
# app(("e-Bands", pn.Row(self.get_ebands_plotter_widgets(), self.on_ebands_plotter_btn)))
|
||||
#
|
||||
# # Add e-DOS tab only if all ebands have k-sampling.
|
||||
# if all(abifile.ebands.kpoints.is_ibz for abifile in self.robot.abifiles):
|
||||
# app(("e-DOS", pn.Row(self.get_edos_plotter_widgets(), self.on_edos_plotter_btn)))
|
||||
#
|
||||
# app(("GSR-DataFrame", pn.Row(self.gsr_dataframe_btn, self.on_gsr_dataframe_btn)))
|
||||
#
|
||||
# return tabs
|
|
@ -28,9 +28,14 @@ class GsrFilePanel(PanelWithElectronBands):
|
|||
app(("e-Bands", pn.Row(self.get_plot_ebands_widgets(), self.on_plot_ebands_btn)))
|
||||
|
||||
# Add DOS tab only if k-sampling.
|
||||
if self.gsr.ebands.kpoints.is_ibz:
|
||||
kpoints = self.gsr.ebands.kpoints
|
||||
if kpoints.is_ibz:
|
||||
app(("e-DOS", pn.Row(self.get_plot_edos_widgets(), self.on_plot_edos_btn)))
|
||||
|
||||
if self.gsr.ebands.supports_fermi_surface:
|
||||
# Fermi surface requires gamma-centered k-mesh
|
||||
app(("Fermi Surface", pn.Row(self.get_plot_fermi_surface_widgets(), self.on_plot_fermi_surface_btn)))
|
||||
|
||||
return tabs
|
||||
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import bokeh.models.widgets as bkw
|
|||
|
||||
from abipy.panels.core import AbipyParameterized
|
||||
|
||||
|
||||
pn.config.js_files = {
|
||||
'$': 'https://code.jquery.com/jquery-3.4.1.slim.min.js',
|
||||
"clipboard": "https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js",
|
||||
|
@ -79,7 +80,7 @@ class StructurePanel(AbipyParameterized):
|
|||
@param.depends("viewer_btn.clicks")
|
||||
def view(self):
|
||||
if self.viewer_btn.clicks == 0: return
|
||||
return self.structure.nglview()
|
||||
#return self.structure.nglview()
|
||||
#import nglview as nv
|
||||
#view = nv.demo(gui=False)
|
||||
#return view
|
||||
|
@ -96,12 +97,12 @@ class StructurePanel(AbipyParameterized):
|
|||
spin_mode=self.label2mode[self.spin_mode.value],
|
||||
smearing=None)
|
||||
gs_inp.pop_vars(("charge", "chksymbreak"))
|
||||
gs_inp.set_vars(ecut="?? # depends on pseudos", nband="?? # depends on pseudos")
|
||||
|
||||
if self.gs_type.value == "relax":
|
||||
gs_inp.set_vars(optcell=2, ionmov=2, ecutsm=0.5, dilatmx=1.05)
|
||||
|
||||
gs_inp.set_mnemonics(False)
|
||||
#return gs_inp._repr_html_()
|
||||
return """
|
||||
<button class="btn btn-primary btn-sm" data-clipboard-target="#foobar"> Copy to clipboard </button>
|
||||
<div id="foobar"> %s </div>
|
||||
|
|
|
@ -87,7 +87,7 @@ Use `-v` to increase verbosity level (can be supplied multiple times e.g -vv).
|
|||
|
||||
JSON file are supported as well. In this case, abiopen.py tries to reconstruct python objects
|
||||
assuming JSON document in MSONable format and then invokes ipython with the `data` object.
|
||||
Use `-e` to print the JSON documenting without reconstructing python objects.
|
||||
Use `-e` or `--notebook` or `--panel` to print the JSON dictionary without reconstructing python objects.
|
||||
|
||||
Table mapping file extension to AbiPy object:
|
||||
|
||||
|
@ -133,8 +133,6 @@ def get_parser(with_epilog=False):
|
|||
help=("Set matplotlib interactive backend. "
|
||||
"Possible values: GTKAgg, GTK3Agg, GTK, GTKCairo, GTK3Cairo, WXAgg, WX, TkAgg, Qt4Agg, Qt5Agg, macosx."
|
||||
"See also: https://matplotlib.org/faq/usage_faq.html#what-is-a-backend."))
|
||||
#parser.add_argument('--pylustrator', action='store_true', default=False,
|
||||
# help="Style matplotlib plots with pylustrator. See https://pylustrator.readthedocs.io/en/latest/")
|
||||
|
||||
return parser
|
||||
|
||||
|
@ -178,11 +176,6 @@ def main():
|
|||
sns.set(context=options.seaborn, style='darkgrid', palette='deep',
|
||||
font='sans-serif', font_scale=1, color_codes=False, rc=None)
|
||||
|
||||
#if options.pylustrator:
|
||||
# # Start pylustrator to style matplotlib plots
|
||||
# import pylustrator
|
||||
# pylustrator.start()
|
||||
|
||||
if not os.path.exists(options.filepath):
|
||||
raise RuntimeError("%s: no such file" % options.filepath)
|
||||
|
||||
|
@ -272,18 +265,37 @@ Use `print(abifile)` to print the object.
|
|||
def handle_json(options):
|
||||
"""Handle JSON file."""
|
||||
|
||||
if not options.notebook:
|
||||
if options.notebook:
|
||||
# Visualize JSON document in jupyter
|
||||
cmd = "jupyter-lab %s" % options.filepath
|
||||
print("Executing:", cmd)
|
||||
process = subprocess.Popen(cmd.split(), shell=False) #, stdout=fd, stderr=fd)
|
||||
cprint("pid: %s" % str(process.pid), "yellow")
|
||||
return 0
|
||||
|
||||
elif options.panel:
|
||||
# Visualize JSON document in panel dashboard
|
||||
import json
|
||||
import panel as pn
|
||||
with open(options.filepath, "rt") as fh:
|
||||
d = json.load(fh)
|
||||
json_pane = pn.pane.JSON(d, name='JSON', height=300, width=500)
|
||||
app = pn.Row(json_pane.controls(jslink=True), json_pane)
|
||||
app.show()
|
||||
return 0
|
||||
|
||||
else:
|
||||
if options.print:
|
||||
# Print object to terminal.
|
||||
# Print python object to terminal.
|
||||
data = abilab.mjson_load(options.filepath)
|
||||
pprint(data, indent=4)
|
||||
return 0
|
||||
elif options.expose:
|
||||
# Pretty-print dict to terminal.
|
||||
import json
|
||||
with open(options.filepath, "rt") as fh:
|
||||
data = json.load(fh)
|
||||
pprint(data, indent=4)
|
||||
|
||||
return 0
|
||||
|
||||
data = abilab.mjson_load(options.filepath)
|
||||
|
@ -294,13 +306,6 @@ def handle_json(options):
|
|||
The object initialized from JSON (MSONable) is associated to the `data` python variable.
|
||||
""")
|
||||
|
||||
else:
|
||||
cmd = "jupyter-lab %s" % options.filepath
|
||||
print("Executing:", cmd)
|
||||
process = subprocess.Popen(cmd.split(), shell=False) #, stdout=fd, stderr=fd)
|
||||
cprint("pid: %s" % str(process.pid), "yellow")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
|
|
@ -110,6 +110,7 @@
|
|||
.. |MdfFile| replace:: :class:`abipy.electrons.bse.MdfFile`
|
||||
.. |DdbFile| replace:: :class:`abipy.dfpt.ddb.DdbFile`
|
||||
.. |HistFile| replace:: :class:`abipy.dynamics.hist.HistFile`
|
||||
.. |FatBandsFile| replace:: :class:`abipy.electrons.fatbands.FatBandsFile`
|
||||
.. |DielectricTensorGenerator| replace:: :class:`abipy.dfpt.ddb.DielectricTensorGenerator`
|
||||
.. |DdbRobot| replace:: :class:`abipy.dfpt.ddb.DdbRobot`
|
||||
.. |AnaddbNcFile| replace:: :class:`abipy.dfpt.anaddb.AnaddbNcFile`
|
||||
|
|
Loading…
Reference in New Issue