Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Structure graphs #63

Merged
merged 52 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
6a66c87
initial rough draft
naik-aakash Aug 23, 2022
eb45aa7
add structure_graph module
naik-aakash Aug 23, 2022
ad74c3c
removed unwanted comments
naik-aakash Aug 23, 2022
91e1548
minor changes
naik-aakash Aug 24, 2022
b051f1b
added ICOHP bonding-antibonding properties
naik-aakash Aug 24, 2022
0278753
removed redundant methods, renamed graphobject class,option to switch…
naik-aakash Aug 25, 2022
35dd472
fix linting
naik-aakash Aug 25, 2022
6b2cec3
rename "ICOHP_bond_key" to "bond_label"
naik-aakash Aug 25, 2022
6359234
added test case
naik-aakash Aug 26, 2022
04a4096
removed blank space
naik-aakash Aug 26, 2022
8dff9a2
Merge branch 'main' into structure_graphs
naik-aakash Sep 23, 2022
cc9d6e7
Merge branch 'main' into structure_graphs
JaGeo Nov 1, 2022
074c871
Update graph.py
naik-aakash Nov 1, 2022
7d45f13
Update graph.py
naik-aakash Nov 1, 2022
7885eae
Merge branch 'JaGeo:main' into structure_graphs
naik-aakash Apr 17, 2023
613da7b
update doc strings
naik-aakash Apr 17, 2023
9cc12cf
doc strings
naik-aakash Apr 17, 2023
7dfa7ba
fix add_additional_data_sg not initialized
naik-aakash Apr 17, 2023
7f60606
Merge branch 'JaGeo:main' into structure_graphs
naik-aakash Apr 25, 2023
33fda06
Merge branch 'JaGeo:main' into structure_graphs
naik-aakash May 13, 2023
7b114d1
Merge branch 'JaGeo:main' into structure_graphs
naik-aakash May 18, 2023
94aa13f
run black
naik-aakash May 22, 2023
e69e0b7
Merge branch 'JaGeo:main' into structure_graphs
naik-aakash Jun 5, 2023
26d55ae
Merge branch 'JaGeo:main' into structure_graphs
naik-aakash Jun 5, 2023
544e8a9
Merge branch 'JaGeo:main' into structure_graphs
naik-aakash Jun 30, 2023
7f7258a
fix exception for cation-anion
naik-aakash Jun 30, 2023
cb915d2
Merge branch 'JaGeo:main' into structure_graphs
naik-aakash Aug 11, 2023
eed80ae
remove redundant cohpcar file reading, add cutoff parameter
naik-aakash Aug 25, 2023
e6c6a1f
update workflow to show missing line numbers coverage
naik-aakash Aug 25, 2023
472c405
exclude test_*.py files from coverage
naik-aakash Aug 25, 2023
4f90dc4
fix workflow error
naik-aakash Aug 25, 2023
30bdf25
add missing paramters to lobsterneighbors
naik-aakash Aug 25, 2023
8dcdb44
resolve merge conflicts
naik-aakash Sep 8, 2023
3fa39f5
Merge branch 'JaGeo:main' into structure_graphs
naik-aakash Sep 13, 2023
017c50e
Update docs/source/conf.py
naik-aakash Sep 13, 2023
d3c193f
Update docs/source/conf.py
naik-aakash Sep 13, 2023
c0f3c56
add more description to Lobstergraph class
naik-aakash Sep 13, 2023
deab80a
fix typo
naik-aakash Sep 13, 2023
283dfa0
Merge branch 'JaGeo:main' into structure_graphs
naik-aakash Sep 13, 2023
466b9d8
reolve merge conflicts
naik-aakash Sep 13, 2023
e07aa20
Add example
JaGeo Sep 13, 2023
64b108a
Merge branch 'structure_graphs' of github.com:naik-aakash/LobsterPy i…
naik-aakash Sep 13, 2023
442288e
resolve merge conflict
JaGeo Sep 13, 2023
d3e1828
Merge branch 'structure_graphs' of github.com:naik-aakash/LobsterPy i…
naik-aakash Sep 13, 2023
8045c75
resolve merge conflict
JaGeo Sep 13, 2023
af44445
fix failing test due to test file update
naik-aakash Sep 14, 2023
49d3912
Merge branch 'structure_graphs' of github.com:naik-aakash/LobsterPy i…
naik-aakash Sep 14, 2023
e59f506
resolve conflicts
naik-aakash Sep 14, 2023
6f2d8c5
2nd attempt to fix
naik-aakash Sep 14, 2023
27142fc
run black
naik-aakash Sep 14, 2023
091aa42
fix numerical issues in test for NaCl sg
naik-aakash Sep 14, 2023
a1383f0
resolve conflicts
naik-aakash Sep 14, 2023
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
7 changes: 5 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@

# -- Project information -----------------------------------------------------

project = "Lobsterpy"
copyright = "2022, Janine George"

project = "LobsterPy"
copyright = "2022-2023, LobsterPy Development Team"
author = "Janine George"


Expand Down Expand Up @@ -49,6 +50,7 @@
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.

exclude_patterns = ["../../lobsterpy/test",
"../../lobsterpy/cohp/test",
"../../lobsterpy/plotting/test",
Expand All @@ -57,6 +59,7 @@
".DS_Store",
]


def run_apidoc(_):
import subprocess
import glob
Expand Down
Binary file added examples/NaCl_comp_range/CHARGE.lobster.gz
Binary file not shown.
Binary file added examples/NaCl_comp_range/COHPCAR.lobster.gz
Binary file not shown.
Binary file added examples/NaCl_comp_range/ICOBILIST.lobster.gz
Binary file not shown.
Binary file added examples/NaCl_comp_range/ICOHPLIST.lobster.gz
Binary file not shown.
Binary file added examples/NaCl_comp_range/ICOOPLIST.lobster.gz
Binary file not shown.
Binary file added examples/NaCl_comp_range/MadelungEnergies.lobster.gz
Binary file not shown.
Binary file added examples/NaCl_comp_range/POSCAR.gz
Binary file not shown.
15 changes: 15 additions & 0 deletions examples/example_script_NaCl_Structure_graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from lobsterpy.structuregraph.graph import LobsterGraph

graph_NaCl_all = LobsterGraph(
path_to_poscar="./NaCl_comp_range/POSCAR.gz",
path_to_charge="./NaCl_comp_range/CHARGE.lobster.gz",
path_to_cohpcar="./NaCl_comp_range/COHPCAR.lobster.gz",
path_to_icohplist="./NaCl_comp_range/ICOHPLIST.lobster.gz",
add_additional_data_sg=True,
path_to_icooplist="./NaCl_comp_range/ICOOPLIST.lobster.gz",
path_to_icobilist="./NaCl_comp_range/ICOBILIST.lobster.gz",
path_to_madelung="./NaCl_comp_range/MadelungEnergies.lobster.gz",
which_bonds="all",
start=None,
)
print(graph_NaCl_all.sg)
Binary file modified lobsterpy/TestData/CdF_comp_range/ICOBILIST.lobster.gz
100755 → 100644
Binary file not shown.
Binary file modified lobsterpy/TestData/CdF_comp_range/ICOOPLIST.lobster.gz
100755 → 100644
Binary file not shown.
Binary file not shown.
Binary file modified lobsterpy/TestData/NaCl_comp_range/ICOBILIST.lobster.gz
100755 → 100644
Binary file not shown.
Binary file modified lobsterpy/TestData/NaCl_comp_range/ICOHPLIST.lobster.gz
Binary file not shown.
Binary file modified lobsterpy/TestData/NaCl_comp_range/ICOOPLIST.lobster.gz
100755 → 100644
Binary file not shown.
Binary file not shown.
Empty file.
178 changes: 178 additions & 0 deletions lobsterpy/structuregraph/graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Copyright (c) lobsterpy development team
# Distributed under the terms of a BSD 3-Clause "New" or "Revised" License

"""
This package provides the modules for generating graph objects using lobsterpy data
"""

from typing import Optional
from pymatgen.core.structure import Structure
from pymatgen.io.lobster.lobsterenv import LobsterNeighbors
from pymatgen.io.lobster.outputs import Charge
from lobsterpy.cohp.analyze import Analysis


class LobsterGraph:
"""
Class to generate structure graph objects with bonding data from Lobster

Attributes:
sg: return structure_graph object
"""

def __init__(
self,
path_to_poscar: str,
path_to_charge: str,
path_to_cohpcar: str,
path_to_icohplist: str,
path_to_madelung: str,
add_additional_data_sg=True,
path_to_icooplist: Optional[str] = None,
path_to_icobilist: Optional[str] = None,
which_bonds: str = "all",
cutoff_icohp: float = 0.10,
start: str = None,
):
"""
This class will return structure graph objects with bonding information from Lobster data.
Mode of automatic bonding analysis can be “cation-anion” or “all” bonds. The strongest bond is
determined based on the ICOHPs. The coordination environments are determined based on
cutoff_icohp *ICOHPs values. If the path of ICOBILIST (ICOOPLIST) is provided, the ICOBI (ICOOP)
values corresponding to relevant bond labels obtained from the ICOHPLIST are also added as edge properties
to the structure graph objects. The Mulliken and Loewdin charges are added as node properties to
the structure graph objects.


Args:
path_to_poscar: path to POSCAR (e.g., "POSCAR")
path_to_charge: path to CHARGE.lobster (e.g., "CHARGE.lobster")
path_to_cohpcar: path to COHPCAR.lobster (e.g., "COHPCAR.lobster")
path_to_icohplist: path to ICOHPLIST.lobster (e.g., "ICOHPLIST.lobster")
path_to_icooplist: path to ICOOPLIST.lobster (e.g., "ICOOPLIST.lobster")
path_to_icobilist: path to ICOBILIST.lobster (e.g., "ICOBILIST.lobster")
path_to_madelung: path to MadelungEnergies.lobster (e.g., "MadelungEnergies.lobster")
cutoff_icohp : only bonds that are stronger than cutoff_icohp*strongest ICOHP will be considered
add_additional_data_sg: (bool) if True will add the information from ICOOPLIST.lobster
and ICOBILIST.lobster based on ICOHPLIST.lobster relevant bond
which_bonds: selects which kind of bonds are analyzed. "all" is the default
start: start energy for bonding antibonding percent integration
"""
if add_additional_data_sg:
self.add_additional_data_sg = add_additional_data_sg
if path_to_icooplist is not None and path_to_icobilist is not None:
self.path_to_icooplist = path_to_icooplist
self.path_to_icobilist = path_to_icobilist
else:
raise ValueError(
"add_additional_data_sg is set to True."
"Please provide path_to_icooplist and path_to_icobilist"
)
else:
self.add_additional_data_sg = add_additional_data_sg

self.path_to_poscar = path_to_poscar
self.path_to_charge = path_to_charge
self.path_to_cohpcar = path_to_cohpcar
self.path_to_icohplist = path_to_icohplist
self.path_to_madelung = path_to_madelung
self.which_bonds = which_bonds
self.cutoff_icohp = cutoff_icohp

if self.which_bonds == "all":
self.additional_condition = 0
elif self.which_bonds == "cation-anion":
self.additional_condition = 1
else:
raise ValueError(
"Only accepted values are 'all' and 'cation-anion'."
"Please check the input parameters of which_bonds arg"
)
self.start = start

self.sg = self.get_decorated_sg()

def get_decorated_sg(self):
"""
Method to generate graph object decorated with bonding data from lobsterpy
Returns:
structure graph object
"""
if self.add_additional_data_sg:
chemenvlobster = LobsterNeighbors(
are_coops=False,
filename_ICOHP=self.path_to_icohplist,
perc_strength_ICOHP=self.cutoff_icohp,
structure=Structure.from_file(self.path_to_poscar),
additional_condition=self.additional_condition,
filename_CHARGE=self.path_to_charge,
add_additional_data_sg=self.add_additional_data_sg,
filename_blist_sg1=self.path_to_icobilist,
id_blist_sg1="ICOBI",
filename_blist_sg2=self.path_to_icooplist,
id_blist_sg2="ICOOP",
valences_from_charges=True,
adapt_extremum_to_add_cond=True,
)

else:
chemenvlobster = LobsterNeighbors(
are_coops=False,
filename_ICOHP=self.path_to_icohplist,
perc_strength_ICOHP=self.cutoff_icohp,
structure=Structure.from_file(self.path_to_poscar),
additional_condition=self.additional_condition,
filename_CHARGE=self.path_to_charge,
add_additional_data_sg=self.add_additional_data_sg,
valences_from_charges=True,
adapt_extremum_to_add_cond=True,
)

# Adds Mulliken and Löwdin charges as site properties to structure object (node properties)
decorated_structure = Charge(self.path_to_charge).get_structure_with_charges(
JaGeo marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Owner

Choose a reason for hiding this comment

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

Isn't the charge information already in LobsterNeighbors or the Analysis object or anything else?

Copy link
Collaborator Author

@naik-aakash naik-aakash Sep 13, 2023

Choose a reason for hiding this comment

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

Oh yes, I just looked up into get_structure_with_charges method, I infact do not need to reinitialize the charge object just for that method. Thanks for the suggestion. Will implement the changes soon

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ops, we cannot, Lobsterpy only has Mulliken charges, Loewdin Charges are not part of Analysis object

Copy link
Owner

Choose a reason for hiding this comment

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

I see! Thanks for checking!

self.path_to_poscar
)

# Create the structure graph object decorated with site and edge properties based on ICOHP/ICOBI/ICOOP data
lobster_env = chemenvlobster.get_bonded_structure(
structure=decorated_structure, decorate=True, edge_properties=True
)

# Initialize automating bonding analysis from Lobsterpy based on ICOHP
analyze = Analysis(
Copy link
Owner

Choose a reason for hiding this comment

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

Isn't LobsterNeighbors part of the Analysis object? Can't you reuse this? I think we are currently running the same code multiple times which could be really slow.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Indeed LobsterNeighbors is part of Analysis object which can be reused, but as it is not initialized with ICOOP and ICOBI info when we create the analyze object. So the structure graph will not have ICOBI and ICOOP as edge properties.

I think to keep it simple we can simply not have them in single structure graph object?

It was implemented like this as ICOOP and ICOBI extension was not implemented before. Now we can simply have different sg objects for based on different analysis objects.

Let me know what you think of this? I will then make changes there

Copy link
Owner

@JaGeo JaGeo Sep 13, 2023

Choose a reason for hiding this comment

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

Can't you add a kwarg or something to Analysis to pass the ICOBI, ICOOP to LobsterNeighbors stuff?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I can, but I think it can be quite confusing if we are already planning to extend the analysis to COBIs and COOPs.

If the user does analysis for COBICAR, then sg will not have COHP info added with our current implementation in pymatgen. I will need to first update LobsterNeighbors if we want to go this way.

Copy link
Owner

Choose a reason for hiding this comment

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

Ideally, we can determine bonds based on ICOHP, ICOBI and add ICOHP, ICOBI values to each structure graph. I guess we will keep the current implementation for now and then think about improvements later.

Copy link
Owner

Choose a reason for hiding this comment

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

Thanks for checking!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ideally, we can determine bonds based on ICOHP, ICOBI and add ICOHP, ICOBI values to each structure graph. I guess we will keep the current implementation for now and then think about improvements later.

Yes, I agree 😄

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for checking!

You are welcome

path_to_charge=self.path_to_charge,
path_to_cohpcar=self.path_to_cohpcar,
path_to_poscar=self.path_to_poscar,
path_to_icohplist=self.path_to_icohplist,
path_to_madelung=self.path_to_madelung,
whichbonds=self.which_bonds,
cutoff_icohp=self.cutoff_icohp,
)

# Store the summarized dictionary object containing bonding information
cba = analyze.condensed_bonding_analysis

Copy link
Owner

Choose a reason for hiding this comment

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

Mayybe add a comment to describe what you are doing in each step?

Copy link
Collaborator Author

@naik-aakash naik-aakash Nov 1, 2022

Choose a reason for hiding this comment

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

Added some additional comments as requested. Hope these do not cause linit errors , I just added via GUI on git

Copy link
Owner

Choose a reason for hiding this comment

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

I think we need to add precommit to the workflows at some point.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will do add it next time

# Iterate over sites in the dictionary
for k, v in cba["sites"].items():
for k2, v2 in lobster_env.graph.nodes.data():
# Check if ions are same and add its corresponding environment in node properties
if v["ion"] == v2["specie"]:
v2["properties"].update({"env": v["env"]})

for (
edge_prop
) in lobster_env.graph.edges.data(): # Iterate over structure graph edges
_ab, ab_p, _b, b_p = analyze._integrate_antbdstates_below_efermi(
cohp=analyze.chemenv.completecohp.get_cohp_by_label(
edge_prop[2]["bond_label"]
),
start=self.start,
) # Compute bonding- antibonding percentages for each bond in structure graph object
edge_prop[2][
"ICOHP_bonding_perc"
] = b_p # Store bonding percentage in edge of graph object
edge_prop[2][
"ICOHP_antibonding_perc"
] = ab_p # Store anti-bonding percentage in edge graph object

return lobster_env
Empty file.
Loading