Exemple #1
0
    def setUp(self):
        with open(os.path.join(test_dir, "CaO_2605_bandstructure.json"),
                  "r",
                  encoding="utf-8") as f:
            d = json.loads(f.read())
            self.bs = BandStructureSymmLine.from_dict(d)
            self.plotter = BSPlotter(self.bs)

        self.assertEqual(len(self.plotter._bs), 1,
                         "wrong number of band objects")

        with open(os.path.join(test_dir, "N2_12103_bandstructure.json"),
                  "r",
                  encoding="utf-8") as f:
            d = json.loads(f.read())
            self.sbs_sc = BandStructureSymmLine.from_dict(d)

        with open(os.path.join(test_dir, "C_48_bandstructure.json"),
                  "r",
                  encoding="utf-8") as f:
            d = json.loads(f.read())
            self.sbs_met = BandStructureSymmLine.from_dict(d)

        self.plotter_multi = BSPlotter([self.sbs_sc, self.sbs_met])
        self.assertEqual(len(self.plotter_multi._bs), 2,
                         "wrong number of band objects")
        self.assertEqual(self.plotter_multi._nb_bands, [96, 96],
                         "wrong number of bands")
        warnings.simplefilter("ignore")
Exemple #2
0
    def setUp(self):
        with open(os.path.join(test_dir, "Cu2O_361_bandstructure.json"),
                  "r",
                  encoding='utf-8') as f:
            d = json.load(f)
            self.bs = BandStructureSymmLine.from_dict(d)
            self.assertListEqual(
                self.bs._projections[Spin.up][10][12][Orbital.s],
                [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], "wrong projections")
            self.assertListEqual(
                self.bs._projections[Spin.up][25][0][Orbital.dyz],
                [0.0, 0.0, 0.0011, 0.0219, 0.0219, 0.069], "wrong projections")
            self.assertAlmostEqual(
                self.bs.get_projection_on_elements()[Spin.up][25][10]['O'],
                0.0328)
            self.assertAlmostEqual(
                self.bs.get_projection_on_elements()[Spin.up][22][25]['Cu'],
                0.8327)
            self.assertAlmostEqual(
                self.bs.get_projections_on_elts_and_orbitals(
                    {'Cu': ['s', 'd']})[Spin.up][25][0]['Cu']['s'], 0.0027)
            self.assertAlmostEqual(
                self.bs.get_projections_on_elts_and_orbitals(
                    {'Cu': ['s', 'd']})[Spin.up][25][0]['Cu']['d'],
                0.8495999999999999)

        with open(os.path.join(test_dir, "CaO_2605_bandstructure.json"),
                  "r",
                  encoding='utf-8') as f:
            d = json.load(f)
            #print d.keys()
            self.bs = BandStructureSymmLine.from_dict(d)
            #print self.bs.as_dict().keys()
            #this doesn't really test as_dict() -> from_dict very well
            #self.assertEqual(self.bs.as_dict().keys(), d.keys())
            self.one_kpoint = self.bs.kpoints[31]
            self.assertEqual(self.bs._nb_bands, 16)
            self.assertAlmostEqual(self.bs._bands[Spin.up][5][10], 0.5608)
            self.assertAlmostEqual(self.bs._bands[Spin.up][5][10], 0.5608)
            self.assertEqual(self.bs._branches[5]['name'], "L-U")
            self.assertEqual(self.bs._branches[5]['start_index'], 80)
            self.assertEqual(self.bs._branches[5]['end_index'], 95)
            self.assertAlmostEqual(self.bs._distance[70], 4.2335127528765737)
        with open(os.path.join(test_dir, "NiO_19009_bandstructure.json"),
                  "r",
                  encoding='utf-8') as f:
            d = json.load(f)
            self.bs_spin = BandStructureSymmLine.from_dict(d)
            #this doesn't really test as_dict() -> from_dict very well
            #self.assertEqual(self.bs_spin.as_dict().keys(), d.keys())
            self.assertEqual(self.bs_spin._nb_bands, 27)
            self.assertAlmostEqual(self.bs_spin._bands[Spin.up][5][10], 0.262)
            self.assertAlmostEqual(self.bs_spin._bands[Spin.down][5][10],
                                   1.6156)
    def setUp(self):
        with open(os.path.join(test_dir, "Cu2O_361_bandstructure.json"), "r", encoding="utf-8") as f:
            d = json.load(f)
            self.bs = BandStructureSymmLine.from_dict(d)

        with open(os.path.join(test_dir, "CaO_2605_bandstructure.json"), "r", encoding="utf-8") as f:
            d = json.load(f)
            self.bs2 = BandStructureSymmLine.from_dict(d)

        with open(os.path.join(test_dir, "NiO_19009_bandstructure.json"), "r", encoding="utf-8") as f:
            d = json.load(f)
            self.bs_spin = BandStructureSymmLine.from_dict(d)
Exemple #4
0
 def setUp(self):
     with open(os.path.join(test_dir, "CaO_2605_bandstructure.json"),
               "r", encoding='utf-8') as f:
         d = json.loads(f.read())
         self.bs = BandStructureSymmLine.from_dict(d)
         self.plotter = BSPlotter(self.bs)
     warnings.simplefilter("ignore")
Exemple #5
0
    def get_band_structure(self):
        """Return a BandStructureSymmLine object interpolating bands along a
        High symmetry path calculated from the structure using HighSymmKpath function"""

        kpath = HighSymmKpath(self.data.structure)
        kpt_line = [
            Kpoint(k, self.data.structure.lattice)
            for k in kpath.get_kpoints(coords_are_cartesian=False)[0]
        ]
        kpoints = np.array([kp.frac_coords for kp in kpt_line])

        labels_dict = {
            l: k
            for k, l in zip(*kpath.get_kpoints(coords_are_cartesian=False))
            if l
        }

        lattvec = self.data.get_lattvec()
        egrid, vgrid = fite.getBands(kpoints, self.equivalences, lattvec,
                                     self.coeffs)

        bands_dict = {Spin.up: (egrid / units.eV)}

        sbs = BandStructureSymmLine(
            kpoints,
            bands_dict,
            self.data.structure.lattice.reciprocal_lattice,
            self.efermi / units.eV,
            labels_dict=labels_dict)
        return sbs
Exemple #6
0
def get_bands_symkpath(efermi=0., mode="tb"):
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()
    if rank == 0:
        gmodel = get_gmodel()
        kpath = get_symkpath()
        nk = (len(kpath.kpath["kpoints"])-1)*12
        k_vec, k_dist, k_node = gmodel.k_path(kpath.kpath["kpoints"]. \
                values(), nk)
    else:
        gmodel = kpath = k_vec = k_dist = k_node = None
    gmodel = comm.bcast(gmodel, root=0)
    kpath = comm.bcast(kpath, root=0)
    k_vec = comm.bcast(k_vec, root=0)
    k_dist = comm.bcast(k_dist, root=0)
    k_node = comm.bcast(k_node, root=0)
    bnd_es, bnd_vs = mpiget_bndev(k_vec, gmodel=gmodel, mode=mode)
    # prepare the args for pymatgen bs class.
    if rank == 0:
        eigenvals = {}
        eigenvals[Spin.up] = bnd_es[0].T
        if len(bnd_es) == 2:
            eigenvals[Spin.down] = bnd_es[1].T
        bs = BandStructureSymmLine(k_vec, eigenvals, \
                kpath._structure.lattice.reciprocal_lattice, \
                efermi, kpath.kpath["kpoints"])
    else:
        bs = None
    return bs
Exemple #7
0
def band_structure(bands_file, cell_file=None):
    """Convert band structure data from CASTEP to Pymatgen/Sumo format

    Args:
        bands_file (:obj:`str`): Path to CASTEP prefix.bands output file. The
            lattice parameters, k-point positions and eigenvalues are read from
            this file.
        cell_file (:obj:`str`, optional): Path to CASTEP prefix.cell input
            file. If found, the positions of high-symmetry points are read from
            the ``[bs|spectral]_kpoint(s)_[path|list]`` block in this file.

    Returns:
        :obj:`pymatgen.electronic_structure.bandstructure.BandStructureSymmLine`

    """

    header = _read_bands_header_verbose(bands_file)

    lattice = Lattice(header['lattice_vectors'])
    lattice = Lattice(lattice.matrix * _bohr_to_angstrom)

    logging.info("Reading band structure eigenvalues...")
    kpoints, _, eigenvalues = read_bands_eigenvalues(bands_file, header)

    if cell_file is None:
        labels = {}
    else:
        labels = labels_from_cell(cell_file)

    return BandStructureSymmLine(kpoints,
                                 eigenvalues,
                                 lattice.reciprocal_lattice_crystallographic,
                                 header['e_fermi'][0] * _ry_to_ev * 2,
                                 labels,
                                 coords_are_cartesian=False)
Exemple #8
0
 def setUp(self):
     with open(os.path.join(test_dir, "CaO_2605_bandstructure.json"),
               "r",
               encoding='utf-8') as f:
         d = json.loads(f.read())
         self.bs = BandStructureSymmLine.from_dict(d)
         self.plotter = BSPlotter(self.bs)
Exemple #9
0
def extract_bs(mat):

    bs = None

    # Process the bandstructure for information
    if "bs" in mat["bandstructure"]:
        bs_dict = mat["bandstructure"]["bs"]
        # Add in structure if not already there
        if "structure" not in bs_dict:
            bs_dict["structure"] = mat["structure"]

        # Add in High Symm K Path if not already there
        if len(bs_dict.get("labels_dict", {})) == 0:
            labels = get(mat, "inputs.nscf_line.kpoints.labels", None)
            kpts = get(mat, "inputs.nscf_line.kpoints.kpoints", None)
            if labels and kpts:
                labels_dict = dict(zip(labels, kpts))
                labels_dict.pop(None, None)
            else:
                struc = Structure.from_dict(mat["structure"])
                labels_dict = HighSymmKpath(struc)._kpath["kpoints"]

            bs_dict["labels_dict"] = labels_dict

        bs = BandStructureSymmLine.from_dict(
            BandStructure.from_dict(bs_dict).as_dict())

    return bs
Exemple #10
0
 def test_old_format_load(self):
     with open(os.path.join(test_dir, "bs_ZnS_old.json"),
               "r", encoding='utf-8') as f:
         d = json.load(f)
         bs_old = BandStructureSymmLine.from_dict(d)
         self.assertEqual(bs_old.get_projection_on_elements()[
                              Spin.up][0][0]['Zn'], 0.0971)
Exemple #11
0
    def setUp(self):
        with open(os.path.join(test_dir, 'si_structure.json'), 'r') as sth:
            si_str = Structure.from_dict(json.load(sth))

        with open(os.path.join(test_dir, 'si_bandstructure_line.json'),
                  'r') as bsh:
            si_bs_line = BandStructureSymmLine.from_dict(json.load(bsh))
        si_bs_line.structure = si_str

        with open(os.path.join(test_dir, 'si_bandstructure_uniform.json'),
                  'r') as bsh:
            si_bs_uniform = BandStructure.from_dict(json.load(bsh))
        si_bs_uniform.structure = si_str
        self.si_kpts = list(HighSymmKpath(si_str).kpath['kpoints'].values())
        self.df = pd.DataFrame({
            'bs_line': [si_bs_line],
            'bs_uniform': [si_bs_uniform]
        })

        with open(os.path.join(test_dir, 'VBr2_971787_bandstructure.json'),
                  'r') as bsh:
            vbr2_uniform = BandStructure.from_dict(json.load(bsh))

        self.vbr2kpts = [
            k.frac_coords for k in vbr2_uniform.labels_dict.values()
        ]
        self.vbr2kpts = [
            [0.0, 0.0, 0.0],  # \\Gamma
            [0.2, 0.0, 0.0],  # between \\Gamma and M
            [0.5, 0.0, 0.0],  # M
            [0.5, 0.0, 0.5]
        ]  # L

        self.df2 = pd.DataFrame({'bs_line': [vbr2_uniform]})
Exemple #12
0
 def setUp(self):
     with open(os.path.join(test_dir, "Cu2O_361_bandstructure.json"),
               "r", encoding='utf-8') as f:
         d = json.load(f)
         self.bs = BandStructureSymmLine.from_dict(d)
         self.plotter = BSPlotterProjected(self.bs)
     warnings.simplefilter("ignore")
Exemple #13
0
    def read_band_structure(self):
        raise NotImplementedError("")
        structure = self.read_structure()
        from pprint import pprint

        kpoints = self.read_value("reduced_coordinates_of_kpoints")
        efermi = Ha2eV(self.read_value("fermie"))
        np_eigvals = Ha2eV(self.read_value("eigenvalues"))
        # TODO
        #assert np_eigvals.units == "atomic units"
        nsppol = np_eigvals.shape[0]

        # FIXME: Here I need the labels
        labels_dict = {}
        for (i, kpoint) in enumerate(kpoints):
            labels_dict[str(i)] = kpoint

        eigenvals = {}
        for isp in range(nsppol):
            spin = Spin.up
            if isp == 1: spin = Spin.down
            eigenvals[spin] = np_eigvals[isp,:,:].transpose()
            print(eigenvals[spin].shape)
            #tmp = np_eigvals[isp,:,:].transpose()

        #bands = BandStructure(kpoints, eigenvals, structure.lattice, efermi,
        # labels_dict=None, structure=structure)

        bands = BandStructureSymmLine(kpoints, eigenvals, structure.lattice,
                                      efermi, labels_dict, structure=structure)
        return bands
Exemple #14
0
 def test_old_format_load(self):
     with open(os.path.join(PymatgenTest.TEST_FILES_DIR, "bs_ZnS_old.json"),
               encoding="utf-8") as f:
         d = json.load(f)
         bs_old = BandStructureSymmLine.from_dict(d)
         self.assertEqual(
             bs_old.get_projection_on_elements()[Spin.up][0][0]["Zn"],
             0.0971)
Exemple #15
0
 def setUp(self):
     with open(os.path.join(PymatgenTest.TEST_FILES_DIR,
                            "Cu2O_361_bandstructure.json"),
               encoding="utf-8") as f:
         d = json.load(f)
         self.bs = BandStructureSymmLine.from_dict(d)
         self.plotter = BSPlotterProjected(self.bs)
     warnings.simplefilter("ignore")
Exemple #16
0
    def setUp(self):
        with open(os.path.join(test_dir, "Cu2O_361_bandstructure.json"),
                  "r",
                  encoding='utf-8') as f:
            d = json.load(f)
            self.bs = BandStructureSymmLine.from_dict(d)

        with open(os.path.join(test_dir, "CaO_2605_bandstructure.json"),
                  "r",
                  encoding='utf-8') as f:
            d = json.load(f)
            self.bs2 = BandStructureSymmLine.from_dict(d)

        with open(os.path.join(test_dir, "NiO_19009_bandstructure.json"),
                  "r",
                  encoding='utf-8') as f:
            d = json.load(f)
            self.bs_spin = BandStructureSymmLine.from_dict(d)
def get_bs(db_file):
    """ return bandstructure object from the database """
    d1, d2, d3, d4 = get_collections(db_file)
    db = get_db(db_file)
    fs = gridfs.GridFS(db, 'bandstructure_fs')
    bs_fs_id = d3["calcs_reversed"][0]["bandstructure_fs_id"]
    bs_json = zlib.decompress(fs.get(bs_fs_id).read())
    bs_dict = json.loads(bs_json.decode())
    return BandStructureSymmLine.from_dict(bs_dict)
Exemple #18
0
    def get_line_mode_band_structure(
        self,
        line_density: int = 50,
        energy_cutoff: Optional[float] = None,
        scissor: Optional[float] = None,
        bandgap: Optional[float] = None,
        symprec: float = 0.01,
    ) -> BandStructureSymmLine:
        """Gets the interpolated band structure along high symmetry directions.

        Args:
            line_density: The maximum number of k-points between each two
                consecutive high-symmetry k-points
            energy_cutoff: The energy cut-off to determine which bands are
                included in the interpolation. If the energy of a band falls
                within the cut-off at any k-point it will be included. For
                metals the range is defined as the Fermi level ± energy_cutoff.
                For gapped materials, the energy range is from the VBM -
                energy_cutoff to the CBM + energy_cutoff.
            scissor: The amount by which the band gap is scissored. Cannot
                be used in conjunction with the ``bandgap`` option. Has no
                effect for metallic systems.
            bandgap: Automatically adjust the band gap to this value. Cannot
                be used in conjunction with the ``scissor`` option. Has no
                effect for metallic systems.
            symprec: The symmetry tolerance used to determine the space group
                and high-symmetry path.

        Returns:
            The line mode band structure.
        """

        hsk = HighSymmKpath(self._band_structure.structure, symprec=symprec)
        kpoints, labels = hsk.get_kpoints(line_density=line_density,
                                          coords_are_cartesian=True)
        labels_dict = {
            label: kpoint
            for kpoint, label in zip(kpoints, labels) if label != ""
        }

        energies = self.get_energies(
            kpoints,
            scissor=scissor,
            bandgap=bandgap,
            atomic_units=False,
            energy_cutoff=energy_cutoff,
            coords_are_cartesian=True,
        )

        return BandStructureSymmLine(
            kpoints,
            energies,
            self._band_structure.structure.lattice,
            self._band_structure.efermi,
            labels_dict,
            coords_are_cartesian=True,
        )
Exemple #19
0
    def get_band_structure(self,
                           kpaths=None,
                           kpoints_lbls_dict=None,
                           density=20):
        """
        Return a BandStructureSymmLine object interpolating bands along a
        High symmetry path calculated from the structure using HighSymmKpath
        function. If kpaths and kpoints_lbls_dict are provided, a custom
        path is interpolated.
        kpaths: List of lists of following kpoints labels defining
                the segments of the path. E.g. [['L','M'],['L','X']]
        kpoints_lbls_dict: Dict where keys are the kpoint labels used in kpaths
                and values are their fractional coordinates.
                E.g. {'L':np.array(0.5,0.5,0.5)},
                      'M':np.array(0.5,0.,0.5),
                      'X':np.array(0.5,0.5,0.)}
        density: Number of points in each segment.
        """

        if isinstance(kpaths, list) and isinstance(kpoints_lbls_dict, dict):
            kpoints = []
            for kpath in kpaths:
                for i, k in enumerate(kpath[:-1]):
                    sta = kpoints_lbls_dict[kpath[i]]
                    end = kpoints_lbls_dict[kpath[i + 1]]
                    kpoints.append(np.linspace(sta, end, density))
            kpoints = np.concatenate(kpoints)
        else:
            kpath = HighSymmKpath(self.data.structure)
            kpoints = np.vstack(
                kpath.get_kpoints(density, coords_are_cartesian=False)[0])
            kpoints_lbls_dict = kpath.kpath["kpoints"]

        lattvec = self.data.get_lattvec()
        egrid, vgrid = fite.getBands(kpoints, self.equivalences, lattvec,
                                     self.coeffs)
        # print(egrid.shape)
        if self.data.is_spin_polarized:
            h = sum(np.array_split(self.accepted, 2)[0])
            egrid = np.array_split(egrid, [h], axis=0)
            bands_dict = {
                Spin.up: (egrid[0] / units.eV),
                Spin.down: (egrid[1] / units.eV),
            }
        else:
            bands_dict = {Spin.up: (egrid / units.eV)}

        sbs = BandStructureSymmLine(
            kpoints,
            bands_dict,
            self.data.structure.lattice.reciprocal_lattice,
            self.efermi / units.eV,
            labels_dict=kpoints_lbls_dict,
        )
        return sbs
 def get_band_structure(self, task_id, line_mode=False):
     m_task = self.collection.find_one({"task_id": task_id},
                                       {"calcs_reversed": 1})
     fs_id = m_task['calcs_reversed'][0]['bandstructure_fs_id']
     fs = gridfs.GridFS(self.db, 'bandstructure_fs')
     bs_json = zlib.decompress(fs.get(fs_id).read())
     bs_dict = json.loads(bs_json)
     if line_mode:
         return BandStructureSymmLine.from_dict(bs_dict)
     else:
         return BandStructure.from_dict(bs_dict)
Exemple #21
0
 def get_BandStructureSymmLine(self):
     eigenvalues = self.eigenvalues
     eigendict = {Spin.up: eigenvalues}
     highsymmkpath = HighSymmKpath(
         self.get_Structure().get_primitive_structure()).kpath
     return BandStructureSymmLine(efermi=self.fermi_energy,
                                  eigenvals=eigendict,
                                  kpoints=self.k_points,
                                  structure=self.get_Structure(),
                                  labels_dict=highsymmkpath['kpoints'],
                                  lattice=self.get_reciprocal_Lattice())
Exemple #22
0
 def get_band_structure(self, task_id, line_mode=False):
     m_task = self.collection.find_one({"task_id": task_id},
                                       {"calcs_reversed": 1})
     fs_id = m_task['calcs_reversed'][0]['bandstructure_fs_id']
     fs = gridfs.GridFS(self.db, 'bandstructure_fs')
     bs_json = zlib.decompress(fs.get(fs_id).read())
     bs_dict = json.loads(bs_json)
     if line_mode:
         return BandStructureSymmLine.from_dict(bs_dict)
     else:
         return BandStructure.from_dict(bs_dict)
def update_dosbandsfig(n_clicks, dos, bs, projlist):
    ## figure updates when the inputs change or the button is clicked
    ## figure does NOT update when elements or orbitals are selected
    ## de-serialize dos and bs from json format to pymatgen objects
    if dos:
        dos = CompleteDos.from_dict(json.loads(dos))
    if bs:
        bs = BandStructureSymmLine.from_dict(json.loads(bs))
    ## update the band structure and dos figure
    dosbandfig = BandsFig().generate_fig(dos, bs, projlist)
    return dosbandfig
Exemple #24
0
 def get_band_structure(self, task_id):
     m_task = self.collection.find_one({"task_id": task_id}, {"calcs_reversed": 1})
     fs_id = m_task['calcs_reversed'][0]['bandstructure_fs_id']
     fs = gridfs.GridFS(self.db, 'bandstructure_fs')
     bs_json = zlib.decompress(fs.get(fs_id).read())
     bs_dict = json.loads(bs_json.decode())
     if bs_dict["@class"] == "BandStructure":
         return BandStructure.from_dict(bs_dict)
     elif bs_dict["@class"] == "BandStructureSymmLine":
         return BandStructureSymmLine.from_dict(bs_dict)
     else:
         raise ValueError("Unknown class for band structure! {}".format(bs_dict["@class"]))
Exemple #25
0
 def get_band_structure(self, task_id):
     m_task = self.collection.find_one({"task_id": task_id}, {"calcs_reversed": 1})
     fs_id = m_task['calcs_reversed'][0]['bandstructure_fs_id']
     fs = gridfs.GridFS(self.db, 'bandstructure_fs')
     bs_json = zlib.decompress(fs.get(fs_id).read())
     bs_dict = json.loads(bs_json.decode())
     if bs_dict["@class"] == "BandStructure":
         return BandStructure.from_dict(bs_dict)
     elif bs_dict["@class"] == "BandStructureSymmLine":
         return BandStructureSymmLine.from_dict(bs_dict)
     else:
         raise ValueError("Unknown class for band structure! {}".format(bs_dict["@class"]))
Exemple #26
0
    def setUp(self):
        with open(os.path.join(test_dir, "Cu2O_361_bandstructure.json"),
                  "r", encoding='utf-8') as f:
            d = json.load(f)
            self.bs = BandStructureSymmLine.from_dict(d)
            self.assertListEqual(self.bs._projections[Spin.up][10][12][Orbital.s], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], "wrong projections")
            self.assertListEqual(self.bs._projections[Spin.up][25][0][Orbital.dyz], [0.0, 0.0, 0.0011, 0.0219, 0.0219, 0.069], "wrong projections")
            self.assertAlmostEqual(self.bs.get_projection_on_elements()[Spin.up][25][10]['O'], 0.0328)
            self.assertAlmostEqual(self.bs.get_projection_on_elements()[Spin.up][22][25]['Cu'], 0.8327)
            self.assertAlmostEqual(self.bs.get_projections_on_elts_and_orbitals({'Cu':['s','d']})[Spin.up][25][0]['Cu']['s'], 0.0027)
            self.assertAlmostEqual(self.bs.get_projections_on_elts_and_orbitals({'Cu':['s','d']})[Spin.up][25][0]['Cu']['d'], 0.8495999999999999)

        with open(os.path.join(test_dir, "CaO_2605_bandstructure.json"), "r",
                  encoding='utf-8') as f:
            d = json.load(f)
            #print d.keys()
            self.bs = BandStructureSymmLine.from_dict(d)
            #print self.bs.as_dict().keys()
            #this doesn't really test as_dict() -> from_dict very well
            #self.assertEqual(self.bs.as_dict().keys(), d.keys())
            self.one_kpoint = self.bs.kpoints[31]
            self.assertEqual(self.bs._nb_bands, 16)
            self.assertAlmostEqual(self.bs._bands[Spin.up][5][10], 0.5608)
            self.assertAlmostEqual(self.bs._bands[Spin.up][5][10], 0.5608)
            self.assertEqual(self.bs._branches[5]['name'], "L-U")
            self.assertEqual(self.bs._branches[5]['start_index'], 80)
            self.assertEqual(self.bs._branches[5]['end_index'], 95)
            self.assertAlmostEqual(self.bs._distance[70], 4.2335127528765737)
        with open(os.path.join(test_dir, "NiO_19009_bandstructure.json"),
                  "r", encoding='utf-8') as f:
            d = json.load(f)
            self.bs_spin = BandStructureSymmLine.from_dict(d)
            #this doesn't really test as_dict() -> from_dict very well
            #self.assertEqual(self.bs_spin.as_dict().keys(), d.keys())
            self.assertEqual(self.bs_spin._nb_bands, 27)
            self.assertAlmostEqual(self.bs_spin._bands[Spin.up][5][10], 0.262)
            self.assertAlmostEqual(self.bs_spin._bands[Spin.down][5][10],
                                   1.6156)
Exemple #27
0
    def get_band_structure(self, task_id):
        """
        Read the BS data into a PMG BandStructure or BandStructureSymmLine object

        Args:
            task_id(int or str): the task_id containing the data
        Returns:
            BandStructure or BandStructureSymmLine
        """
        obj_dict = self.get_data_from_maggma_or_gridfs(task_id,
                                                       key="bandstructure")
        if obj_dict["@class"] == "BandStructure":
            return BandStructure.from_dict(obj_dict)
        elif obj_dict["@class"] == "BandStructureSymmLine":
            return BandStructureSymmLine.from_dict(obj_dict)
        else:
            raise ValueError("Unknown class for band structure! {}".format(
                obj_dict["@class"]))
Exemple #28
0
    def setUp(self):
        with open(os.path.join(test_dir, 'si_structure.json'), 'r') as sth:
            si_str = Structure.from_dict(json.load(sth))

        with open(os.path.join(test_dir, 'si_bandstructure_line.json'),
                  'r') as bsh:
            si_bs_line = BandStructureSymmLine.from_dict(json.load(bsh))
        si_bs_line.structure = si_str

        with open(os.path.join(test_dir, 'si_bandstructure_uniform.json'),
                  'r') as bsh:
            si_bs_uniform = BandStructure.from_dict(json.load(bsh))
        si_bs_uniform.structure = si_str
        self.si_kpts = list(HighSymmKpath(si_str).kpath['kpoints'].values())
        self.df = pd.DataFrame({
            'bs_line': [si_bs_line],
            'bs_uniform': [si_bs_uniform]
        })
Exemple #29
0
    def _get_bs_dos(data):

        data = data or {}

        # this component can be loaded either from mpid or
        # directly from BandStructureSymmLine or CompleteDos objects
        # if mpid is supplied, this is preferred

        mpid = data.get("mpid")
        bandstructure_symm_line = data.get("bandstructure_symm_line")
        density_of_states = data.get("density_of_states")

        if not mpid and (bandstructure_symm_line is None
                         or density_of_states is None):
            return None, None

        if mpid:

            with MPRester() as mpr:

                try:
                    bandstructure_symm_line = mpr.get_bandstructure_by_material_id(
                        mpid)
                except Exception as exc:
                    print(exc)
                    bandstructure_symm_line = None

                try:
                    density_of_states = mpr.get_dos_by_material_id(mpid)
                except Exception as exc:
                    print(exc)
                    density_of_states = None

        else:

            if bandstructure_symm_line and isinstance(bandstructure_symm_line,
                                                      dict):
                bandstructure_symm_line = BandStructureSymmLine.from_dict(
                    bandstructure_symm_line)

            if density_of_states and isinstance(density_of_states, dict):
                density_of_states = CompleteDos.from_dict(density_of_states)

        return bandstructure_symm_line, density_of_states
Exemple #30
0
def build_bs(bs_dict, mat):

    bs_dict["structure"] = mat["structure"]

    # Add in High Symm K Path if not already there
    if len(bs_dict.get("labels_dict", {})) == 0:
        labels = get(mat, "inputs.nscf_line.kpoints.labels", None)
        kpts = get(mat, "inputs.nscf_line.kpoints.kpoints", None)
        if labels and kpts:
            labels_dict = dict(zip(labels, kpts))
            labels_dict.pop(None, None)
        else:
            struc = Structure.from_dict(bs_dict["structure"])
            labels_dict = HighSymmKpath(struc)._kpath["kpoints"]

        bs_dict["labels_dict"] = labels_dict

    # This is somethign to do with BandStructureSymmLine's from dict being problematic
    bs = BandStructureSymmLine.from_dict(bs_dict)

    return bs
    def setUp(self):
        with open(os.path.join(test_dir, 'si_structure.json'),'r') as sth:
            si_str = Structure.from_dict(json.load(sth))

        with open(os.path.join(test_dir, 'si_bandstructure_line.json'),'r') as bsh:
            si_bs_line = BandStructureSymmLine.from_dict(json.load(bsh))
        si_bs_line.structure = si_str

        with open(os.path.join(test_dir, 'si_bandstructure_uniform.json'),'r') as bsh:
            si_bs_uniform = BandStructure.from_dict(json.load(bsh))
        si_bs_uniform.structure = si_str
        self.si_kpts = list(HighSymmKpath(si_str).kpath['kpoints'].values())
        self.df = pd.DataFrame({'bs_line': [si_bs_line], 'bs_uniform': [si_bs_uniform]})

        with open(os.path.join(test_dir, 'VBr2_971787_bandstructure.json'), 'r') as bsh:
            vbr2_uniform = BandStructure.from_dict(json.load(bsh))

        self.vbr2kpts = [k.frac_coords for k in vbr2_uniform.labels_dict.values()]
        self.vbr2kpts = [[0.0, 0.0, 0.0], # \\Gamma
                         [0.2, 0.0, 0.0], # between \\Gamma and M
                         [0.5, 0.0, 0.0], # M
                         [0.5, 0.0, 0.5]] # L

        self.df2 = pd.DataFrame({'bs_line': [vbr2_uniform]})
Exemple #32
0
    def get_line_mode_band_structure(
        self,
        line_density: int = 50,
        kpath: Optional[Kpath] = None,
        symprec: Optional[float] = defaults["symprec"],
        return_other_properties: bool = False,
    ) -> Union[
        BandStructureSymmLine,
        Tuple[BandStructureSymmLine, Dict[Spin, Dict[str, np.ndarray]]],
    ]:
        """Gets the interpolated band structure along high symmetry directions.

        Args:
            line_density: The maximum number of k-points between each two
                consecutive high-symmetry k-points
            symprec: The symmetry tolerance used to determine the space group
                and high-symmetry path.
            return_other_properties: Whether to include the interpolated
                other_properties data for each k-point along the band structure path.

        Returns:
            The line mode band structure.
        """
        if not kpath:
            kpath = PymatgenKpath(self.structure, symprec=symprec)

        kpoints, labels = kpath.get_kpoints(line_density=line_density, cart_coords=True)
        labels_dict = {
            label: kpoint for kpoint, label in zip(kpoints, labels) if label != ""
        }

        rlat = self.structure.lattice.reciprocal_lattice
        frac_kpoints = rlat.get_fractional_coords(kpoints)

        energies = {}
        other_properties = defaultdict(dict)
        for spin in self.spins:
            energies[spin] = self._interpolate_spin(
                spin, frac_kpoints, self.bs_interpolator
            )

            if return_other_properties:
                for prop, property_interpolator in self.property_interpolators.items():
                    other_properties[spin][prop] = self._interpolate_spin(
                        spin, frac_kpoints, property_interpolator
                    )

        bs = BandStructureSymmLine(
            kpoints,
            energies,
            rlat,
            self.efermi,
            labels_dict,
            coords_are_cartesian=True,
            structure=self.structure,
        )

        if return_other_properties:
            return bs, other_properties
        else:
            return bs
Exemple #33
0
    def get_continuous_path(bandstructure):
        """
        Obtain a continous version of an inputted path using graph theory.
        This routine will attempt to add connections between nodes of
        odd-degree to ensure a Eulerian path can be formed. Initial
        k-path must be able to be converted to a connected graph. See
        npj Comput Mater 6, 112 (2020). 10.1038/s41524-020-00383-7
        for more details.

        Args:
        bandstructure (BandstructureSymmLine): BandstructureSymmLine object.

        Returns:
        bandstructure (BandstructureSymmLine): New BandstructureSymmLine object with continous path.
        """

        G = nx.Graph()

        labels = []
        for point in bandstructure.kpoints:
            if point.label is not None:
                labels.append(point.label)

        plot_axis = []
        for i in range(int(len(labels) / 2)):
            G.add_edges_from([(labels[2 * i], labels[(2 * i) + 1])])
            plot_axis.append((labels[2 * i], labels[(2 * i) + 1]))

        G_euler = nx.algorithms.euler.eulerize(G)

        G_euler_circuit = nx.algorithms.euler.eulerian_circuit(G_euler)

        distances_map = []
        kpath_euler = []

        for edge_euler in G_euler_circuit:
            kpath_euler.append(edge_euler)
            for edge_reg in plot_axis:
                if edge_euler == edge_reg:
                    distances_map.append((plot_axis.index(edge_reg), False))
                elif edge_euler[::-1] == edge_reg:
                    distances_map.append((plot_axis.index(edge_reg), True))

        if bandstructure.is_spin_polarized:
            spins = [Spin.up, Spin.down]
        else:
            spins = [Spin.up]

        new_kpoints = []
        new_bands = {
            spin: [np.array([]) for _ in range(bandstructure.nb_bands)]
            for spin in spins
        }
        new_projections = {
            spin: [[] for _ in range(bandstructure.nb_bands)]
            for spin in spins
        }

        for entry in distances_map:
            if not entry[1]:
                branch = bandstructure.branches[entry[0]]
                start = branch["start_index"]
                stop = branch["end_index"] + 1
                step = 1

            else:
                branch = bandstructure.branches[entry[0]]
                start = branch["end_index"]
                stop = branch["start_index"] - 1
                step = -1

            # kpoints
            new_kpoints += [
                point.frac_coords
                for point in bandstructure.kpoints[start:stop:step]
            ]

            # eigenvals
            for spin in spins:
                for n, band in enumerate(bandstructure.bands[spin]):

                    new_bands[spin][n] = np.concatenate(
                        (new_bands[spin][n], band[start:stop:step]))

            # projections
            for spin in spins:
                for n, band in enumerate(bandstructure.projections[spin]):

                    new_projections[spin][n] += band[start:stop:step].tolist()

        for spin in spins:
            new_projections[spin] = np.array(new_projections[spin])

        new_labels_dict = {
            label: point.frac_coords
            for label, point in bandstructure.labels_dict.items()
        }

        new_bandstructure = BandStructureSymmLine(
            kpoints=new_kpoints,
            eigenvals=new_bands,
            lattice=bandstructure.lattice_rec,
            efermi=bandstructure.efermi,
            labels_dict=new_labels_dict,
            structure=bandstructure.structure,
            projections=new_projections,
        )

        return new_bandstructure
Exemple #34
0
    def get_line_mode_band_structure(
        self,
        line_density: int = 50,
        kpath: Optional[Kpath] = None,
        energy_cutoff: Optional[float] = None,
        scissor: Optional[float] = None,
        bandgap: Optional[float] = None,
        symprec: float = defaults["symprec"],
        return_other_properties: bool = False,
    ) -> Union[BandStructureSymmLine, Tuple[BandStructureSymmLine, Dict[
            Spin, Dict[str, np.ndarray]]], ]:
        """Gets the interpolated band structure along high symmetry directions.

        Args:
            line_density: The maximum number of k-points between each two
                consecutive high-symmetry k-points
            energy_cutoff: The energy cut-off to determine which bands are
                included in the interpolation. If the energy of a band falls
                within the cut-off at any k-point it will be included. For
                metals the range is defined as the Fermi level ± energy_cutoff.
                For gapped materials, the energy range is from the VBM -
                energy_cutoff to the CBM + energy_cutoff.
            scissor: The amount by which the band gap is scissored. Cannot
                be used in conjunction with the ``bandgap`` option. Has no
                effect for metallic systems.
            bandgap: Automatically adjust the band gap to this value. Cannot
                be used in conjunction with the ``scissor`` option. Has no
                effect for metallic systems.
            symprec: The symmetry tolerance used to determine the space group
                and high-symmetry path.
            return_other_properties: Whether to include the interpolated
                other_properties data for each k-point along the band structure path.

        Returns:
            The line mode band structure.
        """
        if not kpath:
            kpath = PymatgenKpath(self._band_structure.structure,
                                  symprec=symprec)

        kpoints, labels = kpath.get_kpoints(line_density=line_density,
                                            cart_coords=True)
        labels_dict = {
            label: kpoint
            for kpoint, label in zip(kpoints, labels) if label != ""
        }

        energies = self.get_energies(
            kpoints,
            scissor=scissor,
            bandgap=bandgap,
            atomic_units=False,
            energy_cutoff=energy_cutoff,
            coords_are_cartesian=True,
            return_other_properties=return_other_properties,
            symprec=symprec,
        )

        if return_other_properties:
            energies, other_properties = energies

        bs = BandStructureSymmLine(
            kpoints,
            energies,
            self._band_structure.structure.lattice,
            self._band_structure.efermi,
            labels_dict,
            coords_are_cartesian=True,
        )

        if return_other_properties:
            return bs, other_properties
        else:
            return bs
    def process_item(self, mat):
        """
        Process the tasks and materials into just a list of materials

        Args:
            mat (dict): material document

        Returns:
            (dict): electronic_structure document
        """

        self.logger.info("Processing: {}".format(mat[self.materials.key]))

        d = {self.electronic_structure.key: mat[
            self.materials.key], "bandstructure": {}}
        bs = None
        dos = None
        interpolated_dos = None

        # Process the bandstructure for information
        if "bs" in mat["bandstructure"]:
            if "structure" not in mat["bandstructure"]["bs"]:
                mat["bandstructure"]["bs"]["structure"] = mat["structure"]
            if len(mat["bandstructure"]["bs"].get("labels_dict", {})) == 0:
                struc = Structure.from_dict(mat["structure"])
                kpath = HighSymmKpath(struc)._kpath["kpoints"]
                mat["bandstructure"]["bs"]["labels_dict"] = kpath
            # Somethign is wrong with the as_dict / from_dict encoding in the two band structure objects so have to use this hodge podge serialization
            # TODO: Fix bandstructure objects in pymatgen
            bs = BandStructureSymmLine.from_dict(
                BandStructure.from_dict(mat["bandstructure"]["bs"]).as_dict())
            d["bandstructure"]["band_gap"] = {"band_gap": bs.get_band_gap()["energy"],
                                              "direct_gap": bs.get_direct_band_gap(),
                                              "is_direct": bs.get_band_gap()["direct"],
                                              "transition": bs.get_band_gap()["transition"]}

            if self.small_plot:
                d["bandstructure"]["plot_small"] = get_small_plot(bs)

        if "dos" in mat["bandstructure"]:
            dos = CompleteDos.from_dict(mat["bandstructure"]["dos"])

        if self.interpolate_dos and "uniform_bs" in mat["bandstructure"]:
            try:
                interpolated_dos = self.get_interpolated_dos(mat)
            except Exception:
                self.logger.warning("Boltztrap interpolation failed for {}. Continuing with regular DOS".format(mat[self.materials.key]))

        # Generate static images
        if self.static_images:
            try:
                ylim = None
                if bs:
                    plotter = WebBSPlotter(bs)
                    fig = plotter.get_plot()
                    ylim = fig.ylim()  # Used by DOS plot
                    fig.close()

                    d["bandstructure"]["bs_plot"] = image_from_plotter(plotter)

                if dos:
                    plotter = WebDosVertPlotter()
                    plotter.add_dos_dict(dos.get_element_dos())

                    if interpolated_dos:
                        plotter.add_dos("Total DOS", interpolated_dos)
                        d["bandstructure"]["dos_plot"] = image_from_plotter(plotter, ylim=ylim)

                    d["bandstructure"]["dos_plot"] = image_from_plotter(plotter, ylim=ylim)

            except Exception:
                self.logger.warning(
                    "Caught error in electronic structure plotting for {}: {}".format(mat[self.materials.key], traceback.format_exc()))
                return None

        return d
Exemple #36
0
        def bs_dos_traces(bandStructureSymmLine, densityOfStates):

            if bandStructureSymmLine == "error" or densityOfStates == "error":
                return "error"

            if bandStructureSymmLine == None or densityOfStates == None:
                raise PreventUpdate

            # - BS Data
            bstraces = []

            bs_reg_plot = BSPlotter(BSML.from_dict(bandStructureSymmLine))

            bs_data = bs_reg_plot.bs_plot_data()

            # -- Strip latex math wrapping
            str_replace = {
                "$": "",
                "\\mid": "|",
                "\\Gamma": "Γ",
                "\\Sigma": "Σ",
                "_1": "₁",
                "_2": "₂",
                "_3": "₃",
                "_4": "₄",
            }

            for entry_num in range(len(bs_data["ticks"]["label"])):
                for key in str_replace.keys():
                    if key in bs_data["ticks"]["label"][entry_num]:
                        bs_data["ticks"]["label"][entry_num] = bs_data[
                            "ticks"]["label"][entry_num].replace(
                                key, str_replace[key])

            for d in range(len(bs_data["distances"])):
                for i in range(bs_reg_plot._nb_bands):
                    bstraces.append(
                        go.Scatter(
                            x=bs_data["distances"][d],
                            y=[
                                bs_data["energy"][d][str(Spin.up)][i][j]
                                for j in range(len(bs_data["distances"][d]))
                            ],
                            mode="lines",
                            line=dict(color=("#666666"), width=2),
                            hoverinfo="skip",
                            showlegend=False,
                        ))

                    if bs_reg_plot._bs.is_spin_polarized:
                        bstraces.append(
                            go.Scatter(
                                x=bs_data["distances"][d],
                                y=[
                                    bs_data["energy"][d][str(Spin.down)][i][j]
                                    for j in range(len(bs_data["distances"]
                                                       [d]))
                                ],
                                mode="lines",
                                line=dict(color=("#666666"),
                                          width=2,
                                          dash="dash"),
                                hoverinfo="skip",
                                showlegend=False,
                            ))

            # -- DOS Data
            dostraces = []

            dos = CompleteDos.from_dict(densityOfStates)

            if Spin.down in dos.densities:
                # Add second spin data if available
                trace_tdos = go.Scatter(
                    x=dos.densities[Spin.down],
                    y=dos.energies - dos.efermi,
                    mode="lines",
                    name="Total DOS (spin ↓)",
                    line=go.scatter.Line(color="#444444", dash="dash"),
                    fill="tozeroy",
                )

                dostraces.append(trace_tdos)

                tdos_label = "Total DOS (spin ↑)"
            else:
                tdos_label = "Total DOS"

            # Total DOS
            trace_tdos = go.Scatter(
                x=dos.densities[Spin.up],
                y=dos.energies - dos.efermi,
                mode="lines",
                name=tdos_label,
                line=go.scatter.Line(color="#444444"),
                fill="tozeroy",
                legendgroup="spinup",
            )

            dostraces.append(trace_tdos)

            p_ele_dos = dos.get_element_dos()

            # Projected DOS
            count = 0
            colors = [
                "#1f77b4",  # muted blue
                "#ff7f0e",  # safety orange
                "#2ca02c",  # cooked asparagus green
                "#d62728",  # brick red
                "#9467bd",  # muted purple
                "#8c564b",  # chestnut brown
                "#e377c2",  # raspberry yogurt pink
                "#bcbd22",  # curry yellow-green
                "#17becf",  # blue-teal
            ]

            for ele in p_ele_dos.keys():

                if bs_reg_plot._bs.is_spin_polarized:
                    trace = go.Scatter(
                        x=p_ele_dos[ele].densities[Spin.down],
                        y=dos.energies - dos.efermi,
                        mode="lines",
                        name=ele.symbol + " (spin ↓)",
                        line=dict(width=3, color=colors[count], dash="dash"),
                    )

                    dostraces.append(trace)
                    spin_up_label = ele.symbol + " (spin ↑)"

                else:
                    spin_up_label = ele.symbol

                trace = go.Scatter(
                    x=p_ele_dos[ele].densities[Spin.up],
                    y=dos.energies - dos.efermi,
                    mode="lines",
                    name=spin_up_label,
                    line=dict(width=3, color=colors[count]),
                )

                dostraces.append(trace)

                count += 1

            traces = [bstraces, dostraces, bs_data]

            return traces
Exemple #37
0
 def setUp(self):
     with open(os.path.join(test_dir, "Cu2O_361_bandstructure.json"),
               "r", encoding='utf-8') as f:
         d = json.load(f)
         self.bs = BandStructureSymmLine.from_dict(d)
         self.plotter = BSPlotterProjected(self.bs)
Exemple #38
0
def get_reconstructed_band_structure(list_bs, efermi=None):
    """Combine a list of band structures into a single band structure.

    This is typically very useful when you split non self consistent
    band structure runs in several independent jobs and want to merge back
    the results.

    This method will also ensure that any BandStructure objects will contain
    branches.

    Args:
        list_bs (:obj:`list` of \
        :obj:`~pymatgen.electronic_structure.bandstructure.BandStructure` \
        or :obj:`~pymatgen.electronic_structure.bandstructure.BandStructureSymmLine`):
            The band structures.
        efermi (:obj:`float`, optional): The Fermi energy of the reconstructed
            band structure. If `None`, an average of all the Fermi energies
            across all band structures is used.

    Returns:
        :obj:`pymatgen.electronic_structure.bandstructure.BandStructure` or \
        :obj:`pymatgen.electronic_structure.bandstructureBandStructureSymmLine`:
        A band structure object. The type depends on the type of the band
        structures in ``list_bs``.
    """
    if efermi is None:
        efermi = sum([b.efermi for b in list_bs]) / len(list_bs)

    kpoints = []
    labels_dict = {}
    rec_lattice = list_bs[0].lattice_rec
    nb_bands = min([list_bs[i].nb_bands for i in range(len(list_bs))])

    kpoints = np.concatenate([[k.frac_coords for k in bs.kpoints]
                              for bs in list_bs])

    dicts = [bs.labels_dict for bs in list_bs]
    labels_dict = {k: v.frac_coords for d in dicts for k, v in d.items()}

    # pymatgen band structure objects support branches. These are formed when
    # two kpoints with the same label are next to each other. This bit of code
    # will ensure that the band structure will contain branches, if it doesn't
    # already.
    dup_ids = []
    for i, k in enumerate(kpoints):
        dup_ids.append(i)
        if (tuple(k) in tuple(map(tuple, labels_dict.values())) and i != 0
                and i != len(kpoints) - 1
                and (not np.array_equal(kpoints[i + 1], k)
                     or not np.array_equal(kpoints[i - 1], k))):
            dup_ids.append(i)

    kpoints = kpoints[dup_ids]

    eigenvals = {}
    eigenvals[Spin.up] = np.concatenate(
        [bs.bands[Spin.up][:nb_bands] for bs in list_bs], axis=1)
    eigenvals[Spin.up] = eigenvals[Spin.up][:, dup_ids]

    if list_bs[0].is_spin_polarized:
        eigenvals[Spin.down] = np.concatenate(
            [bs.bands[Spin.down][:nb_bands] for bs in list_bs], axis=1)
        eigenvals[Spin.down] = eigenvals[Spin.up][:, dup_ids]

    projections = {}
    if len(list_bs[0].projections) != 0:
        projs = [bs.projections[Spin.up][:nb_bands][dup_ids] for bs in list_bs]
        projections[Spin.up] = np.concatenate(projs, axis=1)[:, dup_ids]

        if list_bs[0].is_spin_polarized:
            projs = [
                bs.projections[Spin.down][:nb_bands][dup_ids] for bs in list_bs
            ]
            projections[Spin.down] = np.concatenate(projs, axis=1)[:, dup_ids]

    if isinstance(list_bs[0], BandStructureSymmLine):
        return BandStructureSymmLine(kpoints,
                                     eigenvals,
                                     rec_lattice,
                                     efermi,
                                     labels_dict,
                                     structure=list_bs[0].structure,
                                     projections=projections)
    else:
        return BandStructure(kpoints,
                             eigenvals,
                             rec_lattice,
                             efermi,
                             labels_dict,
                             structure=list_bs[0].structure,
                             projections=projections)
Exemple #39
0
 def setUp(self):
     with open(os.path.join(test_dir, "CaO_2605_bandstructure.json"),
               "rb") as f:
         d = json.loads(f.read())
         self.bs = BandStructureSymmLine.from_dict(d)
         self.plotter = BSPlotter(self.bs)