Esempio n. 1
0
        def _get_soap_graph(feature, label):

            spectrum = {
                "data": [{
                    "coloraxis": "coloraxis",
                    #'hovertemplate': 'x: %{x}<br>y: %{y}<br>color: %{z}<extra></extra>',
                    "type": "heatmap",
                    "z": feature.tolist(),
                }]
            }

            spectrum["layout"] = {
                "xaxis": {
                    "visible": False
                },
                "yaxis": {
                    "visible": False
                },
                "paper_bgcolor": "rgba(0,0,0,0)",
                "plot_bgcolor": "rgba(0,0,0,0)",
                "coloraxis": {
                    "colorscale": [
                        [0.0, "#0d0887"],
                        [0.1111111111111111, "#46039f"],
                        [0.2222222222222222, "#7201a8"],
                        [0.3333333333333333, "#9c179e"],
                        [0.4444444444444444, "#bd3786"],
                        [0.5555555555555556, "#d8576b"],
                        [0.6666666666666666, "#ed7953"],
                        [0.7777777777777778, "#fb9f3a"],
                        [0.8888888888888888, "#fdca26"],
                        [1.0, "#f0f921"],
                    ],
                    "showscale":
                    False,
                },
                "margin": {
                    "l": 0,
                    "b": 0,
                    "t": 0,
                    "r": 0,
                    "pad": 0
                },
                # "height": 20*feature.shape[0],  # for fixed size plots
                # "width": 20*feature.shape[1]
            }

            return Columns([
                Column(Label(label), size="1"),
                Column(
                    dcc.Graph(
                        figure=spectrum,
                        config={"displayModeBar": False},
                        responsive=True,
                        style={"height": "60px"},
                    )),
            ])
Esempio n. 2
0
    def update_contents(self, new_store_contents):

        struct = self.from_data(new_store_contents)

        msa = CollinearMagneticStructureAnalyzer(struct, round_magmoms=1)
        if not msa.is_magnetic:
            # TODO: detect magnetic elements (?)
            return html.Div(
                "This structure is not magnetic or does not have "
                "magnetic information associated with it."
            )

        mag_species_and_magmoms = msa.magnetic_species_and_magmoms
        for k, v in mag_species_and_magmoms.items():
            if not isinstance(v, list):
                mag_species_and_magmoms[k] = [v]
        magnetic_atoms = "\n".join(
            [
                f"{sp} ({', '.join([f'{magmom} µB' for magmom in magmoms])})"
                for sp, magmoms in mag_species_and_magmoms.items()
            ]
        )

        magnetization_per_formula_unit = (
            msa.total_magmoms
            / msa.structure.composition.get_reduced_composition_and_factor()[1]
        )

        rows = []
        rows.append(
            (
                html.B("Total magnetization per formula unit"),
                html.Br(),
                f"{magnetization_per_formula_unit:.1f} µB",
            )
        )
        rows.append((html.B("Atoms with local magnetic moments"), html.Br(),
                     magnetic_atoms))

        data_block = html.Div([html.P([html.Span(cell) for cell in row]) for row in rows])

        viewer = StructureMoleculeComponent(
            struct,
            id=self.id("structure"), color_scheme="magmom",
            static=True
        )

        return Columns([
            Column(html.Div([viewer.struct_layout], style={"height": "60vmin"})),
            Column(data_block)
        ])
Esempio n. 3
0
    def layout(self):
        if self.dim in [2, 3]:
            return Columns([
                Column([
                    html.Div(self._sub_layouts["energy"]),
                    self._sub_layouts["allow_shallow"]
                ]),
                Column([self._sub_layouts["cpd"], self.vertex_list])
            ])

        else:
            return Columns([
                Column([
                    self.vertex_list, self._sub_layouts["allow_shallow"],
                    self._sub_layouts["cpd_label"]
                ]),
                Column(html.Div(self._sub_layouts["energy"]))
            ])
Esempio n. 4
0
    def update_contents(self, new_store_contents):

        #JSONViewComponent(id=self.id("json-editor"),
        #                  src=loads(new_store_contents))

        return Columns(
            [  #Column(self.editor_layout), Column(self.json_layout),
                Column()
            ])
Esempio n. 5
0
        def _get_soap_graph(feature, label):

            spectrum = px.imshow(feature,
                                 aspect="equal",
                                 color_continuous_scale="plasma")

            coloraxis = spectrum.layout.coloraxis
            coloraxis["showscale"] = False

            layout = {
                "xaxis": {
                    "visible": False
                },
                "yaxis": {
                    "visible": False
                },
                "paper_bgcolor": "rgba(0,0,0,0)",
                "plot_bgcolor": "rgba(0,0,0,0)",
                "coloraxis": coloraxis,
                "margin": {
                    "l": 0,
                    "b": 0,
                    "t": 0,
                    "r": 0,
                    "pad": 0
                },
                # "height": 20*feature.shape[0],  # for fixed size plots
                # "width": 20*feature.shape[1]
            }

            spectrum.layout = layout

            return Columns([
                Column(Label(label), size="1"),
                Column(
                    dcc.Graph(
                        figure=spectrum,
                        config={"displayModeBar": False},
                        responsive=True,
                        style={"height": "60px"},
                    )),
            ])
Esempio n. 6
0
    def initial_contents(self):
        # TODO: this is so dumb, PanelComponent needs a rethink
        # (this comment is definition of technical debt)

        editor = dcc.Textarea(
            id=self.id("editor"),
            rows=16,
            className="textarea",
            style={
                "max-width": "88%",
                "max-height": "800px",
                "height": "100%"
            },
        )
        json = Box(
            dcc.SyntaxHighlighter(id=self.id("highlighted"),
                                  customStyle={
                                      "height": "100%",
                                      "max-height": "800px"
                                  }))

        return Columns([Column(editor), Column(json)])
Esempio n. 7
0
    def update_contents(self, new_store_contents):

        editor = dcc.Textarea(
            id=self.id("editor"),
            rows=16,
            className="textarea",
            style={
                "max-width": "88%",
                "max-height": "800px",
                "height": "100%"
            },
            value=new_store_contents,
        )
        json = Box(
            dcc.SyntaxHighlighter(id=self.id("highlighted"),
                                  customStyle={
                                      "height": "100%",
                                      "max-height": "800px"
                                  },
                                  children=new_store_contents))

        return Columns([Column(editor), Column(json)])
Esempio n. 8
0
    def container_layout(self, state=None, structure=None) -> html.Div:
        """
        :return: Layout defining transformation and its options.
        """

        container = MessageContainer(
            [
                MessageHeader(
                    html.Div([
                        self._sub_layouts["enable"],
                        html.Span(
                            self.title,
                            style={
                                "vertical-align": "middle",
                                "margin-left": "1rem",
                            },
                        ),
                    ])),
                MessageBody([
                    Columns([
                        Column([
                            self._sub_layouts["description"],
                            html.Br(),
                            html.Div(
                                self.options_layouts(state=state,
                                                     structure=structure)),
                            html.Br(),
                            self._sub_layouts["message"],
                        ])
                    ])
                ]),
            ],
            kind="dark",
            id=self.id("container"),
        )

        return container
Esempio n. 9
0
        def get_chemenv_analysis(struct, distance_cutoff, angle_cutoff):

            if not struct:
                raise PreventUpdate

            struct = self.from_data(struct)
            kwargs = self.reconstruct_kwargs_from_state(
                callback_context.inputs)
            distance_cutoff = kwargs["distance_cutoff"]
            angle_cutoff = kwargs["angle_cutoff"]

            # TODO: remove these brittle guard statements, figure out more robust way to handle multiple input types
            if isinstance(struct, StructureGraph):
                struct = struct.structure

            def get_valences(struct):
                valences = [
                    getattr(site.specie, "oxi_state", None) for site in struct
                ]
                valences = [v for v in valences if v is not None]
                if len(valences) == len(struct):
                    return valences
                else:
                    return "undefined"

            # decide which indices to present to user
            sga = SpacegroupAnalyzer(struct)
            symm_struct = sga.get_symmetrized_structure()
            inequivalent_indices = [
                indices[0] for indices in symm_struct.equivalent_indices
            ]
            wyckoffs = symm_struct.wyckoff_symbols

            lgf = LocalGeometryFinder()
            lgf.setup_structure(structure=struct)

            se = lgf.compute_structure_environments(
                maximum_distance_factor=distance_cutoff + 0.01,
                only_indices=inequivalent_indices,
                valences=get_valences(struct),
            )
            strategy = SimplestChemenvStrategy(distance_cutoff=distance_cutoff,
                                               angle_cutoff=angle_cutoff)
            lse = LightStructureEnvironments.from_structure_environments(
                strategy=strategy, structure_environments=se)
            all_ce = AllCoordinationGeometries()

            envs = []
            unknown_sites = []

            for index, wyckoff in zip(inequivalent_indices, wyckoffs):

                datalist = {
                    "Site": unicodeify_species(struct[index].species_string),
                    "Wyckoff Label": wyckoff,
                }

                if not lse.neighbors_sets[index]:
                    unknown_sites.append(
                        f"{struct[index].species_string} ({wyckoff})")
                    continue

                # represent the local environment as a molecule
                mol = Molecule.from_sites(
                    [struct[index]] +
                    lse.neighbors_sets[index][0].neighb_sites)
                mol = mol.get_centered_molecule()
                mg = MoleculeGraph.with_empty_graph(molecule=mol)
                for i in range(1, len(mol)):
                    mg.add_edge(0, i)

                view = html.Div(
                    [
                        StructureMoleculeComponent(
                            struct_or_mol=mg,
                            disable_callbacks=True,
                            id=
                            f"{struct.composition.reduced_formula}_site_{index}",
                            scene_settings={
                                "enableZoom": False,
                                "defaultZoom": 0.6
                            },
                        )._sub_layouts["struct"]
                    ],
                    style={
                        "width": "300px",
                        "height": "300px"
                    },
                )

                env = lse.coordination_environments[index]
                co = all_ce.get_geometry_from_mp_symbol(env[0]["ce_symbol"])
                name = co.name
                if co.alternative_names:
                    name += f" (also known as {', '.join(co.alternative_names)})"

                datalist.update({
                    "Environment":
                    name,
                    "IUPAC Symbol":
                    co.IUPAC_symbol_str,
                    get_tooltip(
                        "CSM",
                        "The continuous symmetry measure (CSM) describes the similarity to an "
                        "ideal coordination environment. It can be understood as a 'distance' to "
                        "a shape and ranges from 0 to 100 in which 0 corresponds to a "
                        "coordination environment that is exactly identical to the ideal one. A "
                        "CSM larger than 5.0 already indicates a relatively strong distortion of "
                        "the investigated coordination environment.",
                    ):
                    f"{env[0]['csm']:.2f}",
                    "Interactive View":
                    view,
                })

                envs.append(get_data_list(datalist))

            # TODO: switch to tiles?
            envs_grouped = [envs[i:i + 2] for i in range(0, len(envs), 2)]
            analysis_contents = []
            for env_group in envs_grouped:
                analysis_contents.append(
                    Columns([Column(e, size=6) for e in env_group]))

            if unknown_sites:
                unknown_sites = html.Strong(
                    f"The following sites were not identified: {', '.join(unknown_sites)}. "
                    f"Please try changing the distance or angle cut-offs to identify these sites, "
                    f"or try an alternative algorithm such as LocalEnv.")
            else:
                unknown_sites = html.Span()

            return html.Div(
                [html.Div(analysis_contents),
                 html.Br(), unknown_sites])
Esempio n. 10
0
    def update_contents(self, new_store_contents):

        return Columns([Column(self.editor_layout), Column(self.json_layout)])
Esempio n. 11
0
 def layout(self):
     return html.Div([Columns(Column(self._sub_layouts["graph"]))])
Esempio n. 12
0
 def layout(self):
     return Columns([
         Column([self.vertex_list, self._sub_layouts["cpd_label"]]),
         Column(html.Div(self._sub_layouts["energy"]))
     ])
Esempio n. 13
0
        def retrieve_grain_boundaries(mpid):

            if not mpid or "mpid" not in mpid:
                raise PreventUpdate

            data = None

            with MPRester() as mpr:

                data = mpr.get_gb_data(mpid["mpid"])

            if not data:

                return (
                    "No grain boundary information computed for this crystal structure. "
                    "Grain boundary information has only been computed for elemental ground state "
                    "crystal structures at present.")

            table_data = [{
                "Sigma":
                d["sigma"],
                "Rotation Axis":
                f"{d['rotation_axis']}",
                "Rotation Angle / º":
                f"{d['rotation_angle']:.2f}",
                "Grain Boundary Plane":
                f"({' '.join(map(str, d['gb_plane']))})",
                "Grain Boundary Energy / Jm⁻²":
                f"{d['gb_energy']:.2f}",
            } for d in data]
            df = pd.DataFrame(table_data)

            table = dt.DataTable(
                id=self.id("table"),
                columns=[{
                    "name": i,
                    "id": i
                } for i in df.columns],
                data=df.to_dict("records"),
                style_cell={
                    "minWidth": "0px",
                    "maxWidth": "200px",
                    "whiteSpace": "normal",
                },
                css=[{
                    "selector":
                    ".dash-cell div.dash-cell-value",
                    "rule":
                    "display: inline; white-space: inherit; overflow: inherit; text-overflow: inherit;",
                }],
                sort_action="native",
                sort_mode="multi",
            )

            view = html.Div(
                [
                    StructureMoleculeComponent(
                        data[2]["initial_structure"],
                        id=self.id("struct"),
                        static=True,
                        color_scheme="grain_label",
                    ).struct_layout
                ],
                style={
                    "width": "400px",
                    "height": "400px"
                },
            )

            return Columns([Column(table), Column(view)])
Esempio n. 14
0
        def update_contents(data, symprec, angle_tolerance):

            if not data:
                return html.Div()

            struct = self.from_data(data)

            if not isinstance(struct, Structure):
                return html.Div(
                    "Can only analyze symmetry of crystal structures at present."
                )

            kwargs = self.reconstruct_kwargs_from_state(
                callback_context.inputs)
            symprec = kwargs["symprec"]
            angle_tolerance = kwargs["angle_tolerance"]

            if symprec <= 0:
                return html.Span(
                    f"Please use a positive symmetry-finding tolerance (currently {symprec})."
                )

            sga = SpacegroupAnalyzer(struct,
                                     symprec=symprec,
                                     angle_tolerance=angle_tolerance)

            try:
                data = dict()
                data["Crystal System"] = sga.get_crystal_system().title()
                data["Lattice System"] = sga.get_lattice_type().title()
                data["Hall Number"] = sga.get_hall()
                data["International Number"] = sga.get_space_group_number()
                data["Symbol"] = unicodeify_spacegroup(
                    sga.get_space_group_symbol())
                data["Point Group"] = unicodeify_spacegroup(
                    sga.get_point_group_symbol())

                sym_struct = sga.get_symmetrized_structure()
            except Exception:
                return html.Span(
                    f"Failed to calculate symmetry with this combination of "
                    f"symmetry-finding ({symprec}) and angle tolerances ({angle_tolerance})."
                )

            datalist = get_data_list(data)

            wyckoff_contents = []

            wyckoff_data = sorted(
                zip(sym_struct.wyckoff_symbols, sym_struct.equivalent_sites),
                key=lambda x: "".join(filter(lambda w: w.isalpha(), x[0])),
            )

            for symbol, equiv_sites in wyckoff_data:
                wyckoff_contents.append(
                    html.Label(
                        f"{symbol}, {unicodeify_species(equiv_sites[0].species_string)}",
                        className="mpc-label",
                    ))
                site_data = [(
                    self.pretty_frac_format(site.frac_coords[0]),
                    self.pretty_frac_format(site.frac_coords[1]),
                    self.pretty_frac_format(site.frac_coords[2]),
                ) for site in equiv_sites]
                wyckoff_contents.append(get_table(site_data))

            return Columns([
                Column([H5("Overview"), datalist]),
                Column([H5("Wyckoff Positions"),
                        html.Div(wyckoff_contents)]),
            ])
Esempio n. 15
0
          CalcResults(structure=defect_structure, energy=0.5, **common)]

de_common = dict(name="Va_O1",
                structure=defect_structure, site_symmetry="1",
                perturbed_structure=defect_structure, defect_center=[[0]*3])

defect_entries = [DefectEntry(charge=0, **de_common),
                 DefectEntry(charge=1, **de_common)]

corrections = [ManualCorrection(correction_energy=1.0),
              ManualCorrection(correction_energy=1.0)]

cpd_e_component = CpdEnergyComponent(cpd_plot_info,
                                     perfect,
                                     defects,
                                     defect_entries,
                                     corrections,
                                     unitcell_vbm=0.0,
                                     unitcell_cbm=1.0)

my_layout = html.Div([Column(cpd_e_component.layout)])
ctc.register_crystal_toolkit(app=app, layout=my_layout, cache=None)


# In[5]:


app.run_server(port=8099)
#app.run_server(mode='inline', port=8096)

Esempio n. 16
0
        def get_chemenv_analysis(struct, distance_cutoff, angle_cutoff):

            if not struct:
                raise PreventUpdate

            struct = self.from_data(struct)
            distance_cutoff = float(distance_cutoff)
            angle_cutoff = float(angle_cutoff)

            # decide which indices to present to user
            sga = SpacegroupAnalyzer(struct)
            symm_struct = sga.get_symmetrized_structure()
            inequivalent_indices = [
                indices[0] for indices in symm_struct.equivalent_indices
            ]
            wyckoffs = symm_struct.wyckoff_symbols

            lgf = LocalGeometryFinder()
            lgf.setup_structure(structure=struct)

            se = lgf.compute_structure_environments(
                maximum_distance_factor=distance_cutoff + 0.01,
                only_indices=inequivalent_indices,
            )
            strategy = SimplestChemenvStrategy(distance_cutoff=distance_cutoff,
                                               angle_cutoff=angle_cutoff)
            lse = LightStructureEnvironments.from_structure_environments(
                strategy=strategy, structure_environments=se)
            all_ce = AllCoordinationGeometries()

            envs = []
            unknown_sites = []

            for index, wyckoff in zip(inequivalent_indices, wyckoffs):

                datalist = {
                    "Site": struct[index].species_string,
                    "Wyckoff Label": wyckoff,
                }

                if not lse.neighbors_sets[index]:
                    unknown_sites.append(
                        f"{struct[index].species_string} ({wyckoff})")
                    continue

                # represent the local environment as a molecule
                mol = Molecule.from_sites(
                    [struct[index]] +
                    lse.neighbors_sets[index][0].neighb_sites)
                mol = mol.get_centered_molecule()
                mg = MoleculeGraph.with_empty_graph(molecule=mol)
                for i in range(1, len(mol)):
                    mg.add_edge(0, i)

                view = html.Div(
                    [
                        StructureMoleculeComponent(
                            struct_or_mol=mg,
                            static=True,
                            id=
                            f"{struct.composition.reduced_formula}_site_{index}",
                            scene_settings={
                                "enableZoom": False,
                                "defaultZoom": 0.6
                            },
                        ).all_layouts["struct"]
                    ],
                    style={
                        "width": "300px",
                        "height": "300px"
                    },
                )

                env = lse.coordination_environments[index]
                co = all_ce.get_geometry_from_mp_symbol(env[0]["ce_symbol"])
                name = co.name
                if co.alternative_names:
                    name += f" (also known as {', '.join(co.alternative_names)})"

                datalist.update({
                    "Environment":
                    name,
                    "IUPAC Symbol":
                    co.IUPAC_symbol_str,
                    get_tooltip(
                        "CSM",
                        '"Continuous Symmetry Measure," a measure of how symmetrical a '
                        "local environment is from most symmetrical at 0% to least "
                        "symmetrical at 100%",
                    ):
                    f"{env[0]['csm']:.2f}%",
                    "Interactive View":
                    view,
                })

                envs.append(get_data_list(datalist))

            # TODO: switch to tiles?
            envs_grouped = [envs[i:i + 2] for i in range(0, len(envs), 2)]
            analysis_contents = []
            for env_group in envs_grouped:
                analysis_contents.append(
                    Columns([Column(e, size=6) for e in env_group]))

            if unknown_sites:
                unknown_sites = html.Strong(
                    f"The following sites were not identified: {', '.join(unknown_sites)}. "
                    f"Please try changing the distance or angle cut-offs to identify these sites."
                )
            else:
                unknown_sites = html.Span()

            return html.Div(
                [html.Div(analysis_contents),
                 html.Br(), unknown_sites])
Esempio n. 17
0
def make_defect_formation_energy(args):
    formula = args.perfect_calc_results.structure.composition.reduced_formula
    chem_pot_diag = ChemPotDiag.from_yaml(args.cpd_yaml)
    pcr = args.perfect_calc_results

    defects, defect_entries, corrections, edge_states = [], [], [], []
    for d in args.dirs:
        if args.skip_shallow:
            edge_states = BandEdgeStates.from_yaml(d / "band_edge_states.yaml")
            if edge_states.is_shallow:
                continue
        defects.append(loadfn(d / "calc_results.json"))
        defect_entries.append(loadfn(d / "defect_entry.json"))
        corrections.append(loadfn(d / "correction.json"))

    if args.web_gui:
        from crystal_toolkit.settings import SETTINGS
        import dash_html_components as html
        from crystal_toolkit.helpers.layouts import Column
        import crystal_toolkit.components as ctc
        import dash

        edge_states = []
        for d in args.dirs:
            edge_states.append(
                BandEdgeStates.from_yaml(d / "band_edge_states.yaml"))

        app = dash.Dash(__name__,
                        suppress_callback_exceptions=True,
                        assets_folder=SETTINGS.ASSETS_PATH,
                        external_stylesheets=[
                            'https://codepen.io/chriddyp/pen/bWLwgP.css'
                        ])

        cpd_plot_info = CpdPlotInfo(chem_pot_diag)
        cpd_e_component = CpdEnergyComponent(cpd_plot_info, pcr, defects,
                                             defect_entries, corrections,
                                             args.unitcell.vbm,
                                             args.unitcell.cbm, edge_states)
        my_layout = html.Div([Column(cpd_e_component.layout)])
        ctc.register_crystal_toolkit(app=app, layout=my_layout, cache=None)
        app.run_server(port=args.port)
        return

    abs_chem_pot = chem_pot_diag.abs_chem_pot_dict(args.label)
    title = " ".join([latexify(formula), "point", args.label])
    defect_energies = make_energies(pcr, defects, defect_entries, corrections,
                                    abs_chem_pot)

    if args.print:
        defect_energies = slide_energy(defect_energies, args.unitcell.vbm)
        print("         charge          E_f   correction    ")
        for e in defect_energies:
            print(e)
            print("")

        print("-- cross points -- ")
        for e in defect_energies:
            print(e.name)
            print(
                e.cross_points(ef_min=args.unitcell.vbm,
                               ef_max=args.unitcell.cbm,
                               base_ef=args.unitcell.vbm))
            print("")
        return

    plotter = DefectEnergyMplPlotter(title=title,
                                     defect_energies=defect_energies,
                                     vbm=args.unitcell.vbm,
                                     cbm=args.unitcell.cbm,
                                     supercell_vbm=pcr.vbm,
                                     supercell_cbm=pcr.cbm,
                                     y_range=args.y_range,
                                     supercell_edge=args.supercell_edge,
                                     label_line=args.label_line,
                                     add_charges=args.add_charges)

    plotter.construct_plot()
    plotter.plt.savefig(f"energy_{args.label}.pdf")