From 478bb68c02cb8ff8c6357ae5fc89a221afa89558 Mon Sep 17 00:00:00 2001 From: anaik Date: Mon, 21 Aug 2023 13:39:24 +0200 Subject: [PATCH 01/11] crude icohp vs bond length plotter --- .github/workflows/python-package.yml | 4 +- lobsterpy/plotting/__init__.py | 79 ++++++++++++++++++++++++ lobsterpy/plotting/test/test_plotting.py | 30 ++++++++- pyproject.toml | 7 +++ 4 files changed, 117 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 7bbdcdaa..6d09220f 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -42,7 +42,7 @@ jobs: # run this locally to update tests durations # pytest --cov=lobsterpy --cov-append --splits 1 --group 1 --durations-path ./lobsterpy/TestData/.pytest-split-durations --store-durations run: | - pytest --cov=lobsterpy --cov-append --splits 5 --group ${{ matrix.split }} --durations-path ./lobsterpy/TestData/.pytest-split-durations + pytest --cov=lobsterpy --cov-report term-missing --cov-append --splits 5 --group ${{ matrix.split }} --durations-path ./lobsterpy/TestData/.pytest-split-durations - name: Upload coverage uses: actions/upload-artifact@v3 with: @@ -68,4 +68,4 @@ jobs: continue-on-error: true run: | coverage combine coverage*/.coverage* - coverage report + coverage report --show-missing diff --git a/lobsterpy/plotting/__init__.py b/lobsterpy/plotting/__init__.py index 81b0cab3..9a942966 100644 --- a/lobsterpy/plotting/__init__.py +++ b/lobsterpy/plotting/__init__.py @@ -12,6 +12,7 @@ import numpy as np from matplotlib import pyplot as plt from pkg_resources import resource_filename +from pymatgen.io.lobster import Icohplist from pymatgen.electronic_structure.core import Spin from pymatgen.electronic_structure.cohp import Cohp from pymatgen.electronic_structure.plotter import CohpPlotter @@ -648,3 +649,81 @@ def _insert_number_of_bonds_in_label( bond label with number of bonds inserted """ return label.replace(character, f"{character} {number_of_bonds} x", 1) + + +class IcohpPlotter: + """ + Plotter to generate ICOHP or ICOBI or ICOOP vs bond lengths plots + """ + + def __init__(self, icohplist: Icohplist): + """ + Args: + icohplist: pymatgen icohplist list object + """ + self.icohplist = icohplist + + def get_plot( + self, + ax: "matplotlib.axes.Axes | None" = None, + style: "matplotlib.plot.style| None" = None, + marker_size: float = 50, + marker_style: str = "o", + xlim: "Tuple[float, float] | None" = None, + ylim: "Tuple[float, float] | None" = None, + ): + """ + Get a matplotlib plot showing the COHP or COBI or COOP with respect to bond lengths. + + Args: + ax: Existing Matplotlib Axes object to plot to. + style: matplotlib style string, if None, will + use lobsterpy style by default. + marker_size: sets the size of markers in scatter plots + marker_style: sets type of marker used in plot + xlim: Specifies the x-axis limits. Defaults to None for + automatic determination. + ylim: Specifies the y-axis limits. Defaults to None for + automatic determination. + Returns: + A matplotlib object. + """ + if self.icohplist.are_coops and not self.icohplist.are_cobis: + cohp_label = "ICOOP" + elif self.icohplist.are_cobis and not self.icohplist.are_coops: + cohp_label = "ICOBI" + elif self.icohplist.are_cobis and self.icohplist.are_coops: + raise ValueError( + "Plot data should not contain ICOBI and ICOOP data at same time" + ) + else: + cohp_label = "ICOHP (eV)" + + if style is None: + style = get_style_list()[0] + plt.style.use(style) + + if ax is None: + _, ax = plt.subplots() + + if xlim: + ax.set_xlim(xlim) + if ylim: + ax.set_ylim(ylim) + + ax.set_ylabel(cohp_label) + ax.set_xlabel("Bond lengths (\u00c5)") + + icohps = [] + bond_len = [] + orb_data = {} + for label, data in self.icohplist.icohplist.items(): + orb_data.update({label: {}}) + for k, v in data["orbitals"].items(): + orb_data[label].update({k: sum(v["icohp"].values())}) + icohps.append(sum(data["icohp"].values())) + bond_len.append(data["length"]) + + ax.scatter(bond_len, icohps, s=marker_size, marker=marker_style) + + return plt diff --git a/lobsterpy/plotting/test/test_plotting.py b/lobsterpy/plotting/test/test_plotting.py index e41eb811..1c594902 100644 --- a/lobsterpy/plotting/test/test_plotting.py +++ b/lobsterpy/plotting/test/test_plotting.py @@ -5,9 +5,10 @@ import json from pathlib import Path from plotly.io import read_json +from pymatgen.io.lobster import Icohplist from lobsterpy.cohp.analyze import Analysis from lobsterpy.cohp.describe import Description -from lobsterpy.plotting import PlainCohpPlotter, InteractiveCohpPlotter +from lobsterpy.plotting import PlainCohpPlotter, InteractiveCohpPlotter, IcohpPlotter CurrentDir = Path(__file__).absolute().parent TestDir = CurrentDir / "../../" @@ -260,6 +261,33 @@ def test_plot_labels(self): self.assertEqual(fig.layout.xaxis["title"]["text"], "−COHP") +class IcohpPlotterTest(unittest.TestCase): + + def setUp(self): + + self.icohplist_nacl = Icohplist(filename=TestDir / "TestData/NaCl/ICOHPLIST.lobster") + self.icohplist_nasi = Icohplist(filename=TestDir / "TestData/NaSi/ICOHPLIST.lobster", are_cobis=True) + self.icohplist_k3sb = Icohplist(filename=TestDir / "TestData/K3Sb/ICOHPLIST.lobster.gz", are_coops=True) + + def test_icohp_plotter_labels(self): + + self.icohp_plotter = IcohpPlotter(icohplist=self.icohplist_nacl) + fig = self.icohp_plotter.get_plot().gca() + + self.assertEqual(fig.get_ylabel(), "ICOHP (eV)") + + self.icohp_plotter = IcohpPlotter(icohplist=self.icohplist_nasi) + fig = self.icohp_plotter.get_plot().gca() + + self.assertEqual(fig.get_ylabel(), "ICOBI") + + self.icohp_plotter = IcohpPlotter(icohplist=self.icohplist_k3sb) + fig = self.icohp_plotter.get_plot().gca() + + self.assertEqual(fig.get_ylabel(), "ICOOP") + self.assertEqual(fig.get_xlabel(), "Bond lengths (Å)") + + class TestPlotterExceptions(unittest.TestCase): def test_plotter_exception(self): with self.assertRaises(Exception) as err: diff --git a/pyproject.toml b/pyproject.toml index 88f72d90..728b516e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -117,6 +117,13 @@ exclude_lines = [ "show_plot", ] +[tool.coverage.run] +omit = [ + # omit anything in test directory anywhere + "*/test/*", + "*/*/test/", +] + [tool.mypy] ignore_missing_imports = true namespace_packages = true From 5af11b1b50ff2dda4b63688027a14dff59229e1d Mon Sep 17 00:00:00 2001 From: anaik Date: Mon, 21 Aug 2023 13:45:52 +0200 Subject: [PATCH 02/11] temp mypy fix --- lobsterpy/plotting/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lobsterpy/plotting/__init__.py b/lobsterpy/plotting/__init__.py index 9a942966..39f01e99 100644 --- a/lobsterpy/plotting/__init__.py +++ b/lobsterpy/plotting/__init__.py @@ -716,7 +716,7 @@ def get_plot( icohps = [] bond_len = [] - orb_data = {} + orb_data = {} # type: ignore for label, data in self.icohplist.icohplist.items(): orb_data.update({label: {}}) for k, v in data["orbitals"].items(): From fcf7cb0e5d9fed3c563d960e91130a7831bc12a5 Mon Sep 17 00:00:00 2001 From: anaik Date: Mon, 21 Aug 2023 13:49:56 +0200 Subject: [PATCH 03/11] fix linting errors --- lobsterpy/plotting/__init__.py | 3 ++- lobsterpy/plotting/test/test_plotting.py | 15 +++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lobsterpy/plotting/__init__.py b/lobsterpy/plotting/__init__.py index 39f01e99..14dcbe43 100644 --- a/lobsterpy/plotting/__init__.py +++ b/lobsterpy/plotting/__init__.py @@ -685,6 +685,7 @@ def get_plot( automatic determination. ylim: Specifies the y-axis limits. Defaults to None for automatic determination. + Returns: A matplotlib object. """ @@ -716,7 +717,7 @@ def get_plot( icohps = [] bond_len = [] - orb_data = {} # type: ignore + orb_data = {} # type: ignore for label, data in self.icohplist.icohplist.items(): orb_data.update({label: {}}) for k, v in data["orbitals"].items(): diff --git a/lobsterpy/plotting/test/test_plotting.py b/lobsterpy/plotting/test/test_plotting.py index 1c594902..db54e992 100644 --- a/lobsterpy/plotting/test/test_plotting.py +++ b/lobsterpy/plotting/test/test_plotting.py @@ -262,15 +262,18 @@ def test_plot_labels(self): class IcohpPlotterTest(unittest.TestCase): - def setUp(self): - - self.icohplist_nacl = Icohplist(filename=TestDir / "TestData/NaCl/ICOHPLIST.lobster") - self.icohplist_nasi = Icohplist(filename=TestDir / "TestData/NaSi/ICOHPLIST.lobster", are_cobis=True) - self.icohplist_k3sb = Icohplist(filename=TestDir / "TestData/K3Sb/ICOHPLIST.lobster.gz", are_coops=True) + self.icohplist_nacl = Icohplist( + filename=TestDir / "TestData/NaCl/ICOHPLIST.lobster" + ) + self.icohplist_nasi = Icohplist( + filename=TestDir / "TestData/NaSi/ICOHPLIST.lobster", are_cobis=True + ) + self.icohplist_k3sb = Icohplist( + filename=TestDir / "TestData/K3Sb/ICOHPLIST.lobster.gz", are_coops=True + ) def test_icohp_plotter_labels(self): - self.icohp_plotter = IcohpPlotter(icohplist=self.icohplist_nacl) fig = self.icohp_plotter.get_plot().gca() From 5c1723eba2b760223f6cf81afd8484b704aac64e Mon Sep 17 00:00:00 2001 From: anaik Date: Thu, 31 Aug 2023 16:35:00 +0200 Subject: [PATCH 04/11] reorg cli args, icohp plot cli intergration, add tests --- lobsterpy/cli.py | 79 +++++++++++++++++++----- lobsterpy/plotting/__init__.py | 61 +++++++++++++----- lobsterpy/plotting/test/test_plotting.py | 17 +++-- lobsterpy/test/test_cli.py | 7 +++ 4 files changed, 126 insertions(+), 38 deletions(-) diff --git a/lobsterpy/cli.py b/lobsterpy/cli.py index a1009a05..9a9a914e 100644 --- a/lobsterpy/cli.py +++ b/lobsterpy/cli.py @@ -13,10 +13,10 @@ import matplotlib.style from pymatgen.electronic_structure.cohp import CompleteCohp - +from pymatgen.io.lobster import Icohplist from lobsterpy.cohp.analyze import Analysis from lobsterpy.cohp.describe import Description -from lobsterpy.plotting import PlainCohpPlotter, get_style_list, InteractiveCohpPlotter +from lobsterpy.plotting import PlainCohpPlotter, get_style_list, IcohpPlotter def main() -> None: @@ -75,6 +75,19 @@ def get_parser() -> argparse.ArgumentParser: type=Path, help=('path to POTCAR. Default is "POTCAR".'), ) + input_coops_cobis = input_file_group.add_mutually_exclusive_group() + input_coops_cobis.add_argument( + "--cobis", + "--cobi", + action="store_true", + help="Specifies input file contains COBIS", + ) + input_coops_cobis.add_argument( + "--coops", + "--coop", + action="store_true", + help="Specifies input file contains COOPS", + ) output_parent = argparse.ArgumentParser(add_help=False) output_file_group = output_parent.add_argument_group("Output files") @@ -271,6 +284,13 @@ def get_parser() -> argparse.ArgumentParser: ), ) + subparsers.add_parser( + "plot-icohps", + aliases=["ploticohps"], + parents=[input_parent, plotting_parent], + help=("Will plot icohps with respect to bond lengths"), + ) + # Mode for normal plotting (without automatic detection of relevant COHPs) plot_parser = subparsers.add_parser( "plot", @@ -284,19 +304,6 @@ def get_parser() -> argparse.ArgumentParser: type=int, help="List of bond numbers, determining COHPs/COBIs/COOPs to include in plot.", ) - plot_coops_cobis = plot_parser.add_mutually_exclusive_group() - plot_coops_cobis.add_argument( - "--cobis", - "--cobi", - action="store_true", - help="Plot COBIs", - ) - plot_coops_cobis.add_argument( - "--coops", - "--coop", - action="store_true", - help="Plot COOPs", - ) plot_grouping = plot_parser.add_mutually_exclusive_group() plot_grouping.add_argument( "--summed", @@ -435,6 +442,8 @@ def run(args): "automatic-plot-ia", "auto-plot-ia", "autoplotia", + "plot-icohps", + "ploticohps", ]: style_kwargs = {} style_kwargs.update(_user_figsize(args.width, args.height)) @@ -495,7 +504,9 @@ def run(args): filename = filename.with_name(filename.name + ".gz") options = {"are_cobis": False, "are_coops": True} else: - filename = args.cohpcar + filename = args.cohpcar.parent / "COHPCAR.lobster" + if not filename.exists(): + filename = filename.with_name(filename.name + ".gz") options = {"are_cobis": False, "are_coops": False} completecohp = CompleteCohp.from_file( @@ -673,6 +684,42 @@ def run(args): 'please use "--overwrite" if you would like to overwrite existing lobster inputs' ) + if args.action in ["plot-icohps", "ploticohps"]: + if args.cobis: + filename = args.icohplist.parent / "ICOBILIST.lobster" + if not filename.exists(): + filename = filename.with_name(filename.name + ".gz") + options = {"are_cobis": True, "are_coops": False} + elif args.coops: + filename = args.icohplist.parent / "ICOOPLIST.lobster" + if not filename.exists(): + filename = filename.with_name(filename.name + ".gz") + options = {"are_cobis": False, "are_coops": True} + else: + filename = args.icohplist.parent / "ICOHPLIST.lobster" + if not filename.exists(): + filename = filename.with_name(filename.name + ".gz") + options = {"are_cobis": False, "are_coops": False} + + icohplist = Icohplist(filename=filename, **options) + icohp_plotter = IcohpPlotter(**options) + + icohp_plotter.add_icohps(icohplist=icohplist, label="") + + plt = icohp_plotter.get_plot(xlim=args.xlim, ylim=args.ylim) + + ax = plt.gca() + ax.set_title(args.title) + + if not args.hideplot and not args.save_plot: + plt.show() + elif args.save_plot and not args.hideplot: + plt.show() + fig = plt.gcf() + fig.savefig(args.save_plot) + if args.save_plot and args.hideplot: + plt.savefig(args.save_plot) + if __name__ == "__main__": main() diff --git a/lobsterpy/plotting/__init__.py b/lobsterpy/plotting/__init__.py index 14dcbe43..8d2e450b 100644 --- a/lobsterpy/plotting/__init__.py +++ b/lobsterpy/plotting/__init__.py @@ -656,12 +656,41 @@ class IcohpPlotter: Plotter to generate ICOHP or ICOBI or ICOOP vs bond lengths plots """ - def __init__(self, icohplist: Icohplist): + def __init__(self, are_coops: bool = False, are_cobis: bool = False): """ Args: - icohplist: pymatgen icohplist list object + are_coops: Switch to indicate that these are ICOOPs, not ICOHPs. + Defaults to False for ICOHPs. + are_cobis: Switch to indicate that these are ICOBIs, not ICOHPs/COOPs. + Defaults to False for ICOHPs. """ - self.icohplist = icohplist + self.are_coops = are_coops + self.are_cobis = are_cobis + self._icohps = {} # type: ignore + + def add_icohps(self, label, icohplist: Icohplist): + """ + Adds a ICOHPs or ICOBIs or ICOOPS for plotting. + + Args: + label: Label for the ICOHPs. Must be unique. + icohplist: Icohplist object. + """ + icohps = [] + bond_len = [] + orb_data = {} # type: ignore + for bond_label, data in icohplist.icohplist.items(): + orb_data.update({bond_label: {}}) + for k, v in data["orbitals"].items(): + orb_data[bond_label].update({k: sum(v["icohp"].values())}) + icohps.append(sum(data["icohp"].values())) + bond_len.append(data["length"]) + + self._icohps[label] = { + "icohps": icohps, + "bond_lengths": bond_len, + "orb_data": orb_data, + } def get_plot( self, @@ -671,6 +700,7 @@ def get_plot( marker_style: str = "o", xlim: "Tuple[float, float] | None" = None, ylim: "Tuple[float, float] | None" = None, + plot_negative: bool = True, ): """ Get a matplotlib plot showing the COHP or COBI or COOP with respect to bond lengths. @@ -685,15 +715,16 @@ def get_plot( automatic determination. ylim: Specifies the y-axis limits. Defaults to None for automatic determination. + plot_negative: Will plot -1*ICOHPs. Works only for ICOHPs Returns: A matplotlib object. """ - if self.icohplist.are_coops and not self.icohplist.are_cobis: + if self.are_coops and not self.are_cobis: cohp_label = "ICOOP" - elif self.icohplist.are_cobis and not self.icohplist.are_coops: + elif self.are_cobis and not self.are_coops: cohp_label = "ICOBI" - elif self.icohplist.are_cobis and self.icohplist.are_coops: + elif self.are_cobis and self.are_coops: raise ValueError( "Plot data should not contain ICOBI and ICOOP data at same time" ) @@ -715,16 +746,14 @@ def get_plot( ax.set_ylabel(cohp_label) ax.set_xlabel("Bond lengths (\u00c5)") - icohps = [] - bond_len = [] - orb_data = {} # type: ignore - for label, data in self.icohplist.icohplist.items(): - orb_data.update({label: {}}) - for k, v in data["orbitals"].items(): - orb_data[label].update({k: sum(v["icohp"].values())}) - icohps.append(sum(data["icohp"].values())) - bond_len.append(data["length"]) + for label, data in self._icohps.items(): + x = data["bond_lengths"] + if plot_negative and cohp_label == "ICOHP (eV)": + ax.set_ylabel("$-$" + cohp_label) + y = [-1 * icohp for icohp in data["icohps"]] + else: + y = data["icohps"] - ax.scatter(bond_len, icohps, s=marker_size, marker=marker_style) + ax.scatter(x, y, s=marker_size, marker=marker_style, label=label) return plt diff --git a/lobsterpy/plotting/test/test_plotting.py b/lobsterpy/plotting/test/test_plotting.py index db54e992..7aa23c34 100644 --- a/lobsterpy/plotting/test/test_plotting.py +++ b/lobsterpy/plotting/test/test_plotting.py @@ -274,19 +274,24 @@ def setUp(self): ) def test_icohp_plotter_labels(self): - self.icohp_plotter = IcohpPlotter(icohplist=self.icohplist_nacl) + self.icohp_plotter = IcohpPlotter() + self.icohp_plotter.add_icohps(label="NaCl", icohplist=self.icohplist_nacl) fig = self.icohp_plotter.get_plot().gca() - self.assertEqual(fig.get_ylabel(), "ICOHP (eV)") - self.icohp_plotter = IcohpPlotter(icohplist=self.icohplist_nasi) - fig = self.icohp_plotter.get_plot().gca() + self.icohp_plotter = IcohpPlotter() + self.icohp_plotter.add_icohps(label="NaCl", icohplist=self.icohplist_nacl) + fig = self.icohp_plotter.get_plot(plot_negative=True).gca() + self.assertEqual(fig.get_ylabel(), "$-$" + "ICOHP (eV)") + self.icohp_plotter = IcohpPlotter(are_cobis=True) + self.icohp_plotter.add_icohps(label="NaSi", icohplist=self.icohplist_nasi) + fig = self.icohp_plotter.get_plot().gca() self.assertEqual(fig.get_ylabel(), "ICOBI") - self.icohp_plotter = IcohpPlotter(icohplist=self.icohplist_k3sb) + self.icohp_plotter = IcohpPlotter(are_coops=True) + self.icohp_plotter.add_icohps(label="K3Sb", icohplist=self.icohplist_k3sb) fig = self.icohp_plotter.get_plot().gca() - self.assertEqual(fig.get_ylabel(), "ICOOP") self.assertEqual(fig.get_xlabel(), "Bond lengths (Å)") diff --git a/lobsterpy/test/test_cli.py b/lobsterpy/test/test_cli.py index 618d76db..e31f3914 100644 --- a/lobsterpy/test/test_cli.py +++ b/lobsterpy/test/test_cli.py @@ -159,6 +159,13 @@ def test_iaplot_saved(self, tmp_path, inject_mocks, clean_plot): run(test) self.assert_is_finite_file(plot_path) + def test_icohpplot_saved(self, tmp_path, inject_mocks, clean_plot): + plot_path = tmp_path / "plot.png" + args = ["ploticohps", "--hideplot", "--saveplot", str(plot_path)] + test = get_parser().parse_args(args) + run(test) + self.assert_is_finite_file(plot_path) + def test_lobsterin_generation(self, tmp_path): os.chdir(TestDir / "TestData/Test_Input_Generation_Empty") lobsterinpath = tmp_path / "lobsterin.lobsterpy" From eab8354d94c392345cb1db37ceee796dac0d4f5f Mon Sep 17 00:00:00 2001 From: anaik Date: Thu, 31 Aug 2023 16:40:58 +0200 Subject: [PATCH 05/11] update test --- lobsterpy/plotting/test/test_plotting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lobsterpy/plotting/test/test_plotting.py b/lobsterpy/plotting/test/test_plotting.py index 7aa23c34..ceb68aca 100644 --- a/lobsterpy/plotting/test/test_plotting.py +++ b/lobsterpy/plotting/test/test_plotting.py @@ -277,7 +277,7 @@ def test_icohp_plotter_labels(self): self.icohp_plotter = IcohpPlotter() self.icohp_plotter.add_icohps(label="NaCl", icohplist=self.icohplist_nacl) fig = self.icohp_plotter.get_plot().gca() - self.assertEqual(fig.get_ylabel(), "ICOHP (eV)") + self.assertEqual(fig.get_ylabel(), "$-$" + "ICOHP (eV)") self.icohp_plotter = IcohpPlotter() self.icohp_plotter.add_icohps(label="NaCl", icohplist=self.icohplist_nacl) From 4dba132c31e7ae66e8211ef68d89ef718a4af87e Mon Sep 17 00:00:00 2001 From: anaik Date: Thu, 31 Aug 2023 16:58:51 +0200 Subject: [PATCH 06/11] fix cli bug --- lobsterpy/cli.py | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/lobsterpy/cli.py b/lobsterpy/cli.py index 9a9a914e..165eace5 100644 --- a/lobsterpy/cli.py +++ b/lobsterpy/cli.py @@ -442,8 +442,6 @@ def run(args): "automatic-plot-ia", "auto-plot-ia", "autoplotia", - "plot-icohps", - "ploticohps", ]: style_kwargs = {} style_kwargs.update(_user_figsize(args.width, args.height)) @@ -701,24 +699,24 @@ def run(args): filename = filename.with_name(filename.name + ".gz") options = {"are_cobis": False, "are_coops": False} - icohplist = Icohplist(filename=filename, **options) - icohp_plotter = IcohpPlotter(**options) + icohplist = Icohplist(filename=filename, **options) + icohp_plotter = IcohpPlotter(**options) - icohp_plotter.add_icohps(icohplist=icohplist, label="") + icohp_plotter.add_icohps(icohplist=icohplist, label="") - plt = icohp_plotter.get_plot(xlim=args.xlim, ylim=args.ylim) + plt = icohp_plotter.get_plot(xlim=args.xlim, ylim=args.ylim) - ax = plt.gca() - ax.set_title(args.title) + ax = plt.gca() + ax.set_title(args.title) - if not args.hideplot and not args.save_plot: - plt.show() - elif args.save_plot and not args.hideplot: - plt.show() - fig = plt.gcf() - fig.savefig(args.save_plot) - if args.save_plot and args.hideplot: - plt.savefig(args.save_plot) + if not args.hideplot and not args.save_plot: + plt.show() + elif args.save_plot and not args.hideplot: + plt.show() + fig = plt.gcf() + fig.savefig(args.save_plot) + if args.save_plot and args.hideplot: + plt.savefig(args.save_plot) if __name__ == "__main__": From 251f2c9daefe12e6a72c2002170cadcd92268811 Mon Sep 17 00:00:00 2001 From: anaik Date: Thu, 31 Aug 2023 17:01:25 +0200 Subject: [PATCH 07/11] fix cli --- lobsterpy/cli.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lobsterpy/cli.py b/lobsterpy/cli.py index 165eace5..bbb0329c 100644 --- a/lobsterpy/cli.py +++ b/lobsterpy/cli.py @@ -442,6 +442,8 @@ def run(args): "automatic-plot-ia", "auto-plot-ia", "autoplotia", + "plot-icohps", + "ploticohps" ]: style_kwargs = {} style_kwargs.update(_user_figsize(args.width, args.height)) From 94d92bb7e37a33b8d12946a122c87e9a25ea0a87 Mon Sep 17 00:00:00 2001 From: anaik Date: Thu, 31 Aug 2023 17:05:05 +0200 Subject: [PATCH 08/11] fix black --- lobsterpy/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lobsterpy/cli.py b/lobsterpy/cli.py index bbb0329c..0cb2ac32 100644 --- a/lobsterpy/cli.py +++ b/lobsterpy/cli.py @@ -443,7 +443,7 @@ def run(args): "auto-plot-ia", "autoplotia", "plot-icohps", - "ploticohps" + "ploticohps", ]: style_kwargs = {} style_kwargs.update(_user_figsize(args.width, args.height)) From 73b6cdf7827c73f669e110634a1f4ac43073a388 Mon Sep 17 00:00:00 2001 From: anaik Date: Fri, 1 Sep 2023 17:00:24 +0200 Subject: [PATCH 09/11] update tests and add test files --- .../NaCl_comp_range/ICOBILIST.lobster.gz | Bin 0 -> 8827 bytes .../NaCl_comp_range/ICOOPLIST.lobster.gz | Bin 0 -> 9350 bytes lobsterpy/cli.py | 4 +- lobsterpy/plotting/__init__.py | 24 +-- lobsterpy/plotting/test/test_plotting.py | 138 ++++++++++++++++-- 5 files changed, 144 insertions(+), 22 deletions(-) create mode 100644 lobsterpy/TestData/NaCl_comp_range/ICOBILIST.lobster.gz create mode 100644 lobsterpy/TestData/NaCl_comp_range/ICOOPLIST.lobster.gz diff --git a/lobsterpy/TestData/NaCl_comp_range/ICOBILIST.lobster.gz b/lobsterpy/TestData/NaCl_comp_range/ICOBILIST.lobster.gz new file mode 100644 index 0000000000000000000000000000000000000000..848b6d6c669406c570a27121e8be1759e15b8548 GIT binary patch literal 8827 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 z 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 literal 0 HcmV?d00001 diff --git a/lobsterpy/cli.py b/lobsterpy/cli.py index 0cb2ac32..b847ae7f 100644 --- a/lobsterpy/cli.py +++ b/lobsterpy/cli.py @@ -701,10 +701,10 @@ def run(args): filename = filename.with_name(filename.name + ".gz") options = {"are_cobis": False, "are_coops": False} - icohplist = Icohplist(filename=filename, **options) + icohpcollection = Icohplist(filename=filename, **options).icohpcollection icohp_plotter = IcohpPlotter(**options) - icohp_plotter.add_icohps(icohplist=icohplist, label="") + icohp_plotter.add_icohps(icohpcollection=icohpcollection, label="") plt = icohp_plotter.get_plot(xlim=args.xlim, ylim=args.ylim) diff --git a/lobsterpy/plotting/__init__.py b/lobsterpy/plotting/__init__.py index 8d2e450b..2468df18 100644 --- a/lobsterpy/plotting/__init__.py +++ b/lobsterpy/plotting/__init__.py @@ -14,7 +14,7 @@ from pkg_resources import resource_filename from pymatgen.io.lobster import Icohplist from pymatgen.electronic_structure.core import Spin -from pymatgen.electronic_structure.cohp import Cohp +from pymatgen.electronic_structure.cohp import Cohp, IcohpCollection from pymatgen.electronic_structure.plotter import CohpPlotter import plotly.graph_objs as go from lobsterpy.cohp.analyze import Analysis @@ -668,25 +668,31 @@ def __init__(self, are_coops: bool = False, are_cobis: bool = False): self.are_cobis = are_cobis self._icohps = {} # type: ignore - def add_icohps(self, label, icohplist: Icohplist): + def add_icohps(self, label, icohpcollection: IcohpCollection): """ Adds a ICOHPs or ICOBIs or ICOOPS for plotting. Args: label: Label for the ICOHPs. Must be unique. - icohplist: Icohplist object. + icohpcollection: IcohpCollection object. """ icohps = [] bond_len = [] + atom_pairs = [] orb_data = {} # type: ignore - for bond_label, data in icohplist.icohplist.items(): + for indx, bond_label in enumerate(icohpcollection._list_labels): orb_data.update({bond_label: {}}) - for k, v in data["orbitals"].items(): + for k, v in icohpcollection._list_orb_icohp[indx].items(): orb_data[bond_label].update({k: sum(v["icohp"].values())}) - icohps.append(sum(data["icohp"].values())) - bond_len.append(data["length"]) + icohps.append(sum(icohpcollection._list_icohp[indx].values())) + bond_len.append(icohpcollection._list_length[indx]) + atom1 = icohpcollection._list_atom1[indx] + atom2 = icohpcollection._list_atom2[indx] + atom_pairs.append(atom1 + "-" + atom2) self._icohps[label] = { + "atom_pairs": atom_pairs, + "bond_labels": icohpcollection._list_labels, "icohps": icohps, "bond_lengths": bond_len, "orb_data": orb_data, @@ -731,10 +737,6 @@ def get_plot( else: cohp_label = "ICOHP (eV)" - if style is None: - style = get_style_list()[0] - plt.style.use(style) - if ax is None: _, ax = plt.subplots() diff --git a/lobsterpy/plotting/test/test_plotting.py b/lobsterpy/plotting/test/test_plotting.py index ceb68aca..64c575f6 100644 --- a/lobsterpy/plotting/test/test_plotting.py +++ b/lobsterpy/plotting/test/test_plotting.py @@ -264,37 +264,157 @@ def test_plot_labels(self): class IcohpPlotterTest(unittest.TestCase): def setUp(self): self.icohplist_nacl = Icohplist( - filename=TestDir / "TestData/NaCl/ICOHPLIST.lobster" + filename=TestDir / "TestData/NaCl_comp_range/ICOHPLIST.lobster.gz" ) - self.icohplist_nasi = Icohplist( - filename=TestDir / "TestData/NaSi/ICOHPLIST.lobster", are_cobis=True + self.icobilist_nacl = Icohplist( + filename=TestDir / "TestData/NaCl_comp_range/ICOBILIST.lobster.gz", + are_cobis=True, ) - self.icohplist_k3sb = Icohplist( - filename=TestDir / "TestData/K3Sb/ICOHPLIST.lobster.gz", are_coops=True + self.icooplist_nacl = Icohplist( + filename=TestDir / "TestData/NaCl_comp_range/ICOOPLIST.lobster.gz", + are_coops=True, ) def test_icohp_plotter_labels(self): self.icohp_plotter = IcohpPlotter() - self.icohp_plotter.add_icohps(label="NaCl", icohplist=self.icohplist_nacl) + self.icohp_plotter.add_icohps( + label="NaCl", icohpcollection=self.icohplist_nacl.icohpcollection + ) fig = self.icohp_plotter.get_plot().gca() self.assertEqual(fig.get_ylabel(), "$-$" + "ICOHP (eV)") self.icohp_plotter = IcohpPlotter() - self.icohp_plotter.add_icohps(label="NaCl", icohplist=self.icohplist_nacl) + self.icohp_plotter.add_icohps( + label="NaCl_icohp", icohpcollection=self.icohplist_nacl.icohpcollection + ) fig = self.icohp_plotter.get_plot(plot_negative=True).gca() self.assertEqual(fig.get_ylabel(), "$-$" + "ICOHP (eV)") self.icohp_plotter = IcohpPlotter(are_cobis=True) - self.icohp_plotter.add_icohps(label="NaSi", icohplist=self.icohplist_nasi) + self.icohp_plotter.add_icohps( + label="NaCl_icobi", icohpcollection=self.icobilist_nacl.icohpcollection + ) fig = self.icohp_plotter.get_plot().gca() self.assertEqual(fig.get_ylabel(), "ICOBI") self.icohp_plotter = IcohpPlotter(are_coops=True) - self.icohp_plotter.add_icohps(label="K3Sb", icohplist=self.icohplist_k3sb) + self.icohp_plotter.add_icohps( + label="NaCl_icoop", icohpcollection=self.icooplist_nacl.icohpcollection + ) fig = self.icohp_plotter.get_plot().gca() self.assertEqual(fig.get_ylabel(), "ICOOP") self.assertEqual(fig.get_xlabel(), "Bond lengths (Å)") + def test_plot_data(self): + self.icohp_plotter = IcohpPlotter() + self.icohp_plotter.add_icohps( + label="NaCl", icohpcollection=self.icohplist_nacl.icohpcollection + ) + + ref_xdata = self.icohplist_nacl.icohpcollection._list_length + ref_ydata = [] + for ydata in self.icohplist_nacl.icohpcollection._list_icohp: + ref_ydata.append( + abs(sum(ydata.values())) + ) # get absolute icohp values as in plots + + fig_xydata = ( + self.icohp_plotter.get_plot() + .gcf() + .axes[0] + .get_children()[0] + .get_offsets() + .data + ) + + fig_xdata = [row[0] for row in fig_xydata] + fig_ydata = [row[1] for row in fig_xydata] + + self.assertListEqual(ref_xdata, fig_xdata) + self.assertListEqual(ref_ydata, fig_ydata) + + fig_xydata = self.icohp_plotter.get_plot(xlim=(0, 4), ylim=(0, 6)).gcf() + + fig_x_lims = list(fig_xydata.axes[0].get_children()[5].get_view_interval()) + fig_y_lims = list(fig_xydata.axes[0].get_children()[6].get_view_interval()) + + self.assertListEqual([0, 4], fig_x_lims) + self.assertListEqual([0, 6], fig_y_lims) + + # icobi + + self.icobi_plotter = IcohpPlotter(are_cobis=True) + self.icobi_plotter.add_icohps( + label="NaCl", icohpcollection=self.icobilist_nacl.icohpcollection + ) + + ref_xdata = self.icobilist_nacl.icohpcollection._list_length + ref_ydata = [] + for ydata in self.icobilist_nacl.icohpcollection._list_icohp: + ref_ydata.append( + sum(ydata.values()) + ) # get absolute icohp values as in plots + + fig_xydata = ( + self.icobi_plotter.get_plot() + .gcf() + .axes[0] + .get_children()[0] + .get_offsets() + .data + ) + + fig_xdata = [row[0] for row in fig_xydata] + fig_ydata = [row[1] for row in fig_xydata] + + self.assertListEqual(ref_xdata, fig_xdata) + self.assertListEqual(ref_ydata, fig_ydata) + + fig_xydata = self.icobi_plotter.get_plot(xlim=(0, 4), ylim=(0, 6)).gcf() + + fig_x_lims = list(fig_xydata.axes[0].get_children()[5].get_view_interval()) + fig_y_lims = list(fig_xydata.axes[0].get_children()[6].get_view_interval()) + + self.assertListEqual([0, 4], fig_x_lims) + self.assertListEqual([0, 6], fig_y_lims) + + # icoop + + self.icoop_plotter = IcohpPlotter(are_coops=True) + self.icoop_plotter.add_icohps( + label="NaCl", icohpcollection=self.icooplist_nacl.icohpcollection + ) + + ref_xdata = self.icooplist_nacl.icohpcollection._list_length + ref_ydata = [] + for ydata in self.icooplist_nacl.icohpcollection._list_icohp: + ref_ydata.append( + sum(ydata.values()) + ) # get absolute icohp values as in plots + + fig_xydata = ( + self.icoop_plotter.get_plot() + .gcf() + .axes[0] + .get_children()[0] + .get_offsets() + .data + ) + + fig_xdata = [row[0] for row in fig_xydata] + fig_ydata = [row[1] for row in fig_xydata] + + self.assertListEqual(ref_xdata, fig_xdata) + self.assertListEqual(ref_ydata, fig_ydata) + + fig_xydata = self.icoop_plotter.get_plot(xlim=(0, 4), ylim=(0, 6)).gcf() + + fig_x_lims = list(fig_xydata.axes[0].get_children()[5].get_view_interval()) + fig_y_lims = list(fig_xydata.axes[0].get_children()[6].get_view_interval()) + + self.assertListEqual([0, 4], fig_x_lims) + self.assertListEqual([0, 6], fig_y_lims) + class TestPlotterExceptions(unittest.TestCase): def test_plotter_exception(self): From 2e95104d33df2290fc7529c3be88b12794d0fea7 Mon Sep 17 00:00:00 2001 From: JaGeo Date: Wed, 6 Sep 2023 11:31:20 +0200 Subject: [PATCH 10/11] Fix names of classes and arguments --- lobsterpy/cli.py | 14 +++++++------- lobsterpy/plotting/__init__.py | 2 +- lobsterpy/plotting/test/test_plotting.py | 18 +++++++++--------- lobsterpy/test/test_cli.py | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lobsterpy/cli.py b/lobsterpy/cli.py index b847ae7f..bbc35180 100644 --- a/lobsterpy/cli.py +++ b/lobsterpy/cli.py @@ -16,7 +16,7 @@ from pymatgen.io.lobster import Icohplist from lobsterpy.cohp.analyze import Analysis from lobsterpy.cohp.describe import Description -from lobsterpy.plotting import PlainCohpPlotter, get_style_list, IcohpPlotter +from lobsterpy.plotting import PlainCohpPlotter, get_style_list, IcohpDistancePlotter def main() -> None: @@ -285,8 +285,8 @@ def get_parser() -> argparse.ArgumentParser: ) subparsers.add_parser( - "plot-icohps", - aliases=["ploticohps"], + "plot-icohps-distances", + aliases=["ploticohpsdistances"], parents=[input_parent, plotting_parent], help=("Will plot icohps with respect to bond lengths"), ) @@ -442,8 +442,8 @@ def run(args): "automatic-plot-ia", "auto-plot-ia", "autoplotia", - "plot-icohps", - "ploticohps", + "plot-icohps-distances", + "ploticohpsdistances", ]: style_kwargs = {} style_kwargs.update(_user_figsize(args.width, args.height)) @@ -684,7 +684,7 @@ def run(args): 'please use "--overwrite" if you would like to overwrite existing lobster inputs' ) - if args.action in ["plot-icohps", "ploticohps"]: + if args.action in ["plot-icohps-distances", "ploticohpsdistances"]: if args.cobis: filename = args.icohplist.parent / "ICOBILIST.lobster" if not filename.exists(): @@ -702,7 +702,7 @@ def run(args): options = {"are_cobis": False, "are_coops": False} icohpcollection = Icohplist(filename=filename, **options).icohpcollection - icohp_plotter = IcohpPlotter(**options) + icohp_plotter = IcohpDistancePlotter(**options) icohp_plotter.add_icohps(icohpcollection=icohpcollection, label="") diff --git a/lobsterpy/plotting/__init__.py b/lobsterpy/plotting/__init__.py index 2468df18..74752edc 100644 --- a/lobsterpy/plotting/__init__.py +++ b/lobsterpy/plotting/__init__.py @@ -651,7 +651,7 @@ def _insert_number_of_bonds_in_label( return label.replace(character, f"{character} {number_of_bonds} x", 1) -class IcohpPlotter: +class IcohpDistancePlotter: """ Plotter to generate ICOHP or ICOBI or ICOOP vs bond lengths plots """ diff --git a/lobsterpy/plotting/test/test_plotting.py b/lobsterpy/plotting/test/test_plotting.py index 64c575f6..d7dfb242 100644 --- a/lobsterpy/plotting/test/test_plotting.py +++ b/lobsterpy/plotting/test/test_plotting.py @@ -8,7 +8,7 @@ from pymatgen.io.lobster import Icohplist from lobsterpy.cohp.analyze import Analysis from lobsterpy.cohp.describe import Description -from lobsterpy.plotting import PlainCohpPlotter, InteractiveCohpPlotter, IcohpPlotter +from lobsterpy.plotting import PlainCohpPlotter, InteractiveCohpPlotter, IcohpDistancePlotter CurrentDir = Path(__file__).absolute().parent TestDir = CurrentDir / "../../" @@ -261,7 +261,7 @@ def test_plot_labels(self): self.assertEqual(fig.layout.xaxis["title"]["text"], "−COHP") -class IcohpPlotterTest(unittest.TestCase): +class IcohpDistancePlotterTest(unittest.TestCase): def setUp(self): self.icohplist_nacl = Icohplist( filename=TestDir / "TestData/NaCl_comp_range/ICOHPLIST.lobster.gz" @@ -276,28 +276,28 @@ def setUp(self): ) def test_icohp_plotter_labels(self): - self.icohp_plotter = IcohpPlotter() + self.icohp_plotter = IcohpDistancePlotter() self.icohp_plotter.add_icohps( label="NaCl", icohpcollection=self.icohplist_nacl.icohpcollection ) fig = self.icohp_plotter.get_plot().gca() self.assertEqual(fig.get_ylabel(), "$-$" + "ICOHP (eV)") - self.icohp_plotter = IcohpPlotter() + self.icohp_plotter = IcohpDistancePlotter() self.icohp_plotter.add_icohps( label="NaCl_icohp", icohpcollection=self.icohplist_nacl.icohpcollection ) fig = self.icohp_plotter.get_plot(plot_negative=True).gca() self.assertEqual(fig.get_ylabel(), "$-$" + "ICOHP (eV)") - self.icohp_plotter = IcohpPlotter(are_cobis=True) + self.icohp_plotter = IcohpDistancePlotter(are_cobis=True) self.icohp_plotter.add_icohps( label="NaCl_icobi", icohpcollection=self.icobilist_nacl.icohpcollection ) fig = self.icohp_plotter.get_plot().gca() self.assertEqual(fig.get_ylabel(), "ICOBI") - self.icohp_plotter = IcohpPlotter(are_coops=True) + self.icohp_plotter = IcohpDistancePlotter(are_coops=True) self.icohp_plotter.add_icohps( label="NaCl_icoop", icohpcollection=self.icooplist_nacl.icohpcollection ) @@ -306,7 +306,7 @@ def test_icohp_plotter_labels(self): self.assertEqual(fig.get_xlabel(), "Bond lengths (Å)") def test_plot_data(self): - self.icohp_plotter = IcohpPlotter() + self.icohp_plotter = IcohpDistancePlotter() self.icohp_plotter.add_icohps( label="NaCl", icohpcollection=self.icohplist_nacl.icohpcollection ) @@ -343,7 +343,7 @@ def test_plot_data(self): # icobi - self.icobi_plotter = IcohpPlotter(are_cobis=True) + self.icobi_plotter = IcohpDistancePlotter(are_cobis=True) self.icobi_plotter.add_icohps( label="NaCl", icohpcollection=self.icobilist_nacl.icohpcollection ) @@ -380,7 +380,7 @@ def test_plot_data(self): # icoop - self.icoop_plotter = IcohpPlotter(are_coops=True) + self.icoop_plotter = IcohpDistancePlotter(are_coops=True) self.icoop_plotter.add_icohps( label="NaCl", icohpcollection=self.icooplist_nacl.icohpcollection ) diff --git a/lobsterpy/test/test_cli.py b/lobsterpy/test/test_cli.py index e31f3914..e096e455 100644 --- a/lobsterpy/test/test_cli.py +++ b/lobsterpy/test/test_cli.py @@ -161,7 +161,7 @@ def test_iaplot_saved(self, tmp_path, inject_mocks, clean_plot): def test_icohpplot_saved(self, tmp_path, inject_mocks, clean_plot): plot_path = tmp_path / "plot.png" - args = ["ploticohps", "--hideplot", "--saveplot", str(plot_path)] + args = ["ploticohpsdistances", "--hideplot", "--saveplot", str(plot_path)] test = get_parser().parse_args(args) run(test) self.assert_is_finite_file(plot_path) From e6de9f355e386f90f5249c92868f635d66153823 Mon Sep 17 00:00:00 2001 From: JaGeo Date: Wed, 6 Sep 2023 11:46:21 +0200 Subject: [PATCH 11/11] fix linting --- lobsterpy/plotting/test/test_plotting.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lobsterpy/plotting/test/test_plotting.py b/lobsterpy/plotting/test/test_plotting.py index d7dfb242..4a3b5f85 100644 --- a/lobsterpy/plotting/test/test_plotting.py +++ b/lobsterpy/plotting/test/test_plotting.py @@ -8,7 +8,11 @@ from pymatgen.io.lobster import Icohplist from lobsterpy.cohp.analyze import Analysis from lobsterpy.cohp.describe import Description -from lobsterpy.plotting import PlainCohpPlotter, InteractiveCohpPlotter, IcohpDistancePlotter +from lobsterpy.plotting import ( + PlainCohpPlotter, + InteractiveCohpPlotter, + IcohpDistancePlotter, +) CurrentDir = Path(__file__).absolute().parent TestDir = CurrentDir / "../../"