abinit / abipy

Open-source library for analyzing the results produced by ABINIT
http://abinit.github.io/abipy
Other
117 stars 96 forks source link

"NoneType object is not subscriptable" error when trying to plot a band structure #230

Open RemiLacroix-IDRIS opened 3 years ago

RemiLacroix-IDRIS commented 3 years ago

Hello,

One of our users is trying to plot a band structure using Abipy:

from abipy.abilab import abiopen
import abipy.data as abidata

filename="big_GSR.nc"

with abiopen(filename) as ncfile:
    ebands = ncfile.ebands

ebands.plot(with_gaps=True, title="Band structure", show=False, savefig="bands.png")

ebands.kpoints.plot(show=False, savefig="kpoints.png")

This works for most inputs but he is getting an error with the big_GSR.nc file attached:

~/.conda/envs/abipy/lib/python3.7/site-packages/pymatgen/symmetry/kpath.py:180: UserWarning: The input structure does not match the expected standard primitive! The path can be incorrect. Use at your own risk.
  "The input structure does not match the expected standard primitive! "
Traceback (most recent call last):
  File "plot_ebands_user.py", line 9, in <module>
    ebands.plot(with_gaps=True, title="Silicon band structure", show=False, savefig="bands.png")
  File "~/.conda/envs/abipy/lib/python3.7/site-packages/pymatgen/util/plotting.py", line 573, in wrapper
    fig = func(*args, **kwargs)
  File "~/.conda/envs/abipy/lib/python3.7/site-packages/abipy/electrons/ebands.py", line 1967, in plot
    self.decorate_ax(ax, klabels=klabels)
  File "~/.conda/envs/abipy/lib/python3.7/site-packages/abipy/electrons/ebands.py", line 2256, in decorate_ax
    ticks, labels = self._make_ticks_and_labels(klabels)
  File "~/.conda/envs/abipy/lib/python3.7/site-packages/abipy/electrons/ebands.py", line 2410, in _make_ticks_and_labels
    d = self._auto_klabels
  File "~/.conda/envs/abipy/lib/python3.7/site-packages/monty/functools.py", line 238, in __get__
    value = self.__func(inst)
  File "~/.conda/envs/abipy/lib/python3.7/site-packages/abipy/electrons/ebands.py", line 560, in _auto_klabels
    name = kpoint.name if kpoint.name is not None else self.structure.findname_in_hsym_stars(kpoint)
  File "~/.conda/envs/abipy/lib/python3.7/site-packages/abipy/core/structure.py", line 1185, in findname_in_hsym_stars
    for star in self.hsym_stars:
  File "~/.conda/envs/abipy/lib/python3.7/site-packages/monty/functools.py", line 238, in __get__
    value = self.__func(inst)
  File "~/.conda/envs/abipy/lib/python3.7/site-packages/abipy/core/structure.py", line 1152, in hsym_stars
    return [kpoint.compute_star(self.abi_spacegroup.fm_symmops) for kpoint in self.hsym_kpoints]
  File "~/.conda/envs/abipy/lib/python3.7/site-packages/monty/functools.py", line 238, in __get__
    value = self.__func(inst)
  File "~/.conda/envs/abipy/lib/python3.7/site-packages/abipy/core/structure.py", line 1105, in hsym_kpoints
    name2frac_coords = self.hsym_kpath.kpath["kpoints"]
TypeError: 'NoneType' object is not subscriptable

The warning at the beginning might be relevant but it also appears for other input files for which the plots are successfully generated.

Best regards, Rémi Lacroix

gmatteo commented 3 years ago

Hi,

A similar problem has been reported here although the patch I was suggesting is not enough to handle your case.

The problem is that kpath is initialized to None and there may be crystalline structures for which pymatgen cannot detect the "correct" value. The patch below fixes your problem by calling self.undetected if self._kpath is still None at the end of __init__:

diff --git a/pymatgen/symmetry/kpath.py b/pymatgen/symmetry/kpath.py
index b58810571..48f1f24bb 100644
--- a/pymatgen/symmetry/kpath.py
+++ b/pymatgen/symmetry/kpath.py
@@ -266,21 +266,29 @@ class KPathSetyawanCurtarolo(KPathBase):
                 warn("Unexpected value for spg_symbol: %s" % spg_symbol)

         elif lattice_type == "triclinic":
+            angles = self._rec_lattice.parameters[3:6]
             kalpha = self._rec_lattice.parameters[3]
             kbeta = self._rec_lattice.parameters[4]
             kgamma = self._rec_lattice.parameters[5]
             if kalpha > 90 and kbeta > 90 and kgamma > 90:
                 self._kpath = self.tria()
-            if kalpha < 90 and kbeta < 90 and kgamma < 90:
+            elif kalpha < 90 and kbeta < 90 and kgamma < 90:
                 self._kpath = self.trib()
-            if kalpha > 90 and kbeta > 90 and kgamma == 90:
+            elif kalpha > 90 and kbeta > 90 and kgamma == 90:
                 self._kpath = self.tria()
-            if kalpha < 90 and kbeta < 90 and kgamma == 90:
+            elif kalpha < 90 and kbeta < 90 and kgamma == 90:
                 self._kpath = self.trib()
+            elif np.allclose(angles, 90):
+                self._kpath = self.orc()
+            else:
+                warn(f"Unexpected angles: {angles} for spg_symbol: {spg_symbol}")

         else:
             warn("Unknown lattice type %s" % lattice_type)

+        if self._kpath is None:
+            self._kpath = self.undetected()
+
     @property
     def conventional(self):
         """
@@ -305,6 +313,20 @@ class KPathSetyawanCurtarolo(KPathBase):
         """
         return self._rec_lattice

+    def undetected(self):
+        """
+        UNDETECTED Path
+        """
+        self.name = "UNDETECTED"
+        kpoints = {
+            "\\Gamma": np.array([0.0, 0.0, 0.0]),
+            "b1/2": np.array([0.5, 0.0, 0.0]),
+            "b2/2": np.array([0.0, 0.5, 0.0]),
+            "b3/2": np.array([0.0, 0.0, 0.5]),
+        }
+        path = [["\\Gamma", "b1/2", "b2/2", "b3/2"]]
+        return {"kpoints": kpoints, "path": path}
+
     def cubic(self):
         """
         CUB Path
RemiLacroix-IDRIS commented 3 years ago

Hi,

Thanks for the feedback, will you report that to pymatgen so that the patch is integrated upstream?

gmatteo commented 3 years ago

will you report that to pymatgen so that the patch is integrated upstream?

Yes, I'm working on it.

RemiLacroix-IDRIS commented 2 years ago

@gmatteo : Any news about this?