Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
python${{ matrix.python-version }} -m pip install -r requirements/ubuntu-latest_py${{ matrix.python-version }}_extras.txt
python${{ matrix.python-version }} -m pip install --upgrade pip
python${{ matrix.python-version }} -m pip install --no-deps .[server,test]
python${{ matrix.python-version }} -m pip install lobsterpy
- name: Test modules
run: python${{ matrix.python-version }} -m pytest --cov=crystal_toolkit --cov-report=xml tests
- name: Test example apps
Expand Down
1 change: 1 addition & 0 deletions crystal_toolkit/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "2020.8.15.dev2217"
114 changes: 114 additions & 0 deletions crystal_toolkit/apps/examples/cohp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import os
import warnings

import dash
import numpy as np
from pymatgen.core import Structure
from pymatgen.electronic_structure.cohp import CompleteCohp
from pymatgen.io.lobster.inputs import Lobsterin
from pymatgen.io.lobster.outputs import (
Bandoverlaps,
Charge,
Doscar,
Icohplist,
Lobsterout,
MadelungEnergies,
)
from pymatgen.io.vasp.outputs import Vasprun

import crystal_toolkit.components as ctc
from crystal_toolkit.helpers.layouts import H3, Container
from crystal_toolkit.settings import SETTINGS


class CustomVasprun(Vasprun):
Copy link

@esoteric-ephemera esoteric-ephemera Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this class, I would recommend against copying all of Vasprun.final_energy:

class CustomVasprun(Vasprun):

    @property
    def final_energy(self):
        return float(super().final_energy)

"""Override final_energy property without unitized decorator"""

def __init__(self, filename, **kwargs):
super().__init__(filename, **kwargs)

@property
def final_energy(self) -> float:
"""Final energy from the VASP run."""

try:
final_istep = self.ionic_steps[-1]
total_energy = final_istep["e_0_energy"]

# Fix a bug in vasprun.xml.
# See https://www.vasp.at/forum/viewtopic.php?f=3&t=16942
final_estep = final_istep["electronic_steps"][-1]
electronic_energy_diff = (
final_estep["e_0_energy"] - final_estep["e_fr_energy"]
)
total_energy_bugfix = np.round(
electronic_energy_diff + final_istep["e_fr_energy"], 8
)
if np.abs(total_energy - total_energy_bugfix) > 1e-7:
return total_energy_bugfix

return total_energy

except (IndexError, KeyError):
warnings.warn(
"Calculation does not have a total energy. Possibly a GW or similar kind of run. Infinity is returned.",
stacklevel=2,
)
return float("inf")


calc_dir = "path/to/your/lobster/output" # Replace with your actual path

icohplist_obj = Icohplist(
filename=f"{calc_dir}/ICOHPLIST.lobster.gz", are_cobis=False, are_coops=False
)

completecohp_obj = CompleteCohp.from_file(
filename=f"{calc_dir}/COHPCAR.lobster.gz",
structure_file=f"{calc_dir}/CONTCAR.gz",
fmt="LOBSTER",
are_cobis=False,
are_coops=False,
)

charge_obj = Charge(filename=f"{calc_dir}/CHARGE.lobster.gz")
madelung_obj = MadelungEnergies(filename=f"{calc_dir}/MadelungEnergies.lobster.gz")
lob_dos = Doscar(
doscar=f"{calc_dir}/DOSCAR.LSO.lobster.gz", structure_file=f"{calc_dir}/CONTCAR.gz"
)

vasprun_obj = CustomVasprun(filename=f"{calc_dir}/vasprun.xml.gz")
structure_obj = Structure.from_file(f"{calc_dir}/CONTCAR.gz")
lobsterin_obj = Lobsterin.from_file(f"{calc_dir}/lobsterin.gz")
lobsterout_obj = Lobsterout(filename=f"{calc_dir}/lobsterout.gz")
# Include band overlaps file if it exists available
bandoverlaps_obj = (
Bandoverlaps(filename=f"{calc_dir}/bandOverlaps.lobster.gz")
if os.path.exists(f"{calc_dir}/bandOverlaps.lobster.gz")
else None
)

cohp_component = ctc.CohpAndDosComponent(
density_of_states=lob_dos.completedos,
charge_obj=charge_obj,
icohplist_obj=icohplist_obj,
completecohp_obj=completecohp_obj,
madelung_obj=madelung_obj,
vasprun_obj=vasprun_obj,
structure_obj=structure_obj,
lobsterin_obj=lobsterin_obj,
lobsterout_obj=lobsterout_obj,
bandoverlaps_obj=bandoverlaps_obj,
mpid="mp-xxx",
disable_callbacks=False,
)

# example layout to demonstrate capabilities of component
layout = Container([H3("COHP and Density of States Example"), cohp_component.layout()])

app = dash.Dash(assets_folder=SETTINGS.ASSETS_PATH, prevent_initial_callbacks=True) #

ctc.register_crystal_toolkit(app, layout=layout)

if __name__ == "__main__":
app.run(debug=True, port=8051)
9 changes: 5 additions & 4 deletions crystal_toolkit/components/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
BandstructureAndDosComponent,
BandstructureAndDosPanelComponent,
)

# from crystal_toolkit.components.transformations.rattle import (
# MonteCarloRattleTransformationComponent,
# )
from crystal_toolkit.components.cohp import CohpAndDosComponent
from crystal_toolkit.components.diffraction import XRayDiffractionComponent
from crystal_toolkit.components.diffraction_tem import TEMDiffractionComponent
from crystal_toolkit.components.fermi_surface import FermiSurfaceComponent
Expand Down Expand Up @@ -33,10 +38,6 @@
from crystal_toolkit.components.transformations.grainboundary import (
GrainBoundaryTransformationComponent,
)

# from crystal_toolkit.components.transformations.rattle import (
# MonteCarloRattleTransformationComponent,
# )
from crystal_toolkit.components.transformations.slab import SlabTransformationComponent
from crystal_toolkit.components.transformations.substitution import (
SubstitutionTransformationComponent,
Expand Down
Loading
Loading