Spaces:
Running
Running
| import os | |
| import gradio as gr | |
| from pymatgen.ext.matproj import MPRester | |
| from crystal_toolkit.components.structure import StructureMoleculeComponent | |
| import json | |
| from crystal_toolkit.core.scene import Scene | |
| # Get the API key from environment variable | |
| MATERIALS_PROJECT_API_KEY = os.getenv('MATERIALS_PROJECT_API_KEY') | |
| def search_materials(query): | |
| with MPRester(MATERIALS_PROJECT_API_KEY) as mpr: | |
| results = mpr.summary.search( | |
| chemsys=query, | |
| fields=["material_id", "formula_pretty"] | |
| ) | |
| options = {res.material_id: f"{res.formula_pretty} ({res.material_id})" for res in results} | |
| if not options: | |
| return gr.update(choices=[], label="Select Material", value=None) | |
| return gr.update(choices=list(options.keys()), label="Select Material", value=list(options.keys())[0]) | |
| def get_material_data(material_id): | |
| with MPRester(MATERIALS_PROJECT_API_KEY) as mpr: | |
| material = mpr.get_structure_by_material_id(material_id) | |
| summary = mpr.summary.get_data_by_id(material_id) | |
| return material, summary | |
| def generate_structure_html(scene_json_str): | |
| import uuid | |
| div_id = 'structure_' + str(uuid.uuid4()) | |
| html = f''' | |
| <div id="{div_id}" style="width: 500px; height: 500px;"></div> | |
| <script src="https://unpkg.com/crystaltoolkit@latest/crystaltoolkit.min.js"></script> | |
| <script type="application/json" id="{div_id}_data"> | |
| {scene_json_str} | |
| </script> | |
| <script> | |
| const sceneData = JSON.parse(document.getElementById("{div_id}_data").textContent); | |
| const viewer = new crystalToolkit.ThreeJSViewer("{div_id}", sceneData); | |
| viewer.render(); | |
| </script> | |
| ''' | |
| return html | |
| def display_material(material_id): | |
| if not material_id: | |
| return "", "Please select a material." | |
| material, summary = get_material_data(material_id) | |
| # Create StructureMoleculeComponent | |
| structure_component = StructureMoleculeComponent(material, id="my_structure") | |
| # Access the scene json from the component | |
| scene_json = structure_component._initial_data["scene"] | |
| # What to do here??? | |
| structure_html = "<p></p>" | |
| # Extract key properties | |
| properties = { | |
| "Material ID": material_id, | |
| "Formula": summary.formula_pretty, | |
| "Energy Above Hull (eV/atom)": summary.energy_above_hull, | |
| "Space Group": summary.symmetry.symbol, | |
| "Band Gap (eV)": summary.band_gap, | |
| "Formation Energy (eV/atom)": summary.formation_energy_per_atom, | |
| "Magnetic Ordering": summary.ordering, | |
| "Total Magnetization (μB/f.u.)": summary.total_magnetization, | |
| "Experimentally Observed": summary.is_stable, | |
| "Crystal System": summary.symmetry.crystal_system, | |
| "Density (g/cm³)": summary.density, | |
| } | |
| # Format properties as HTML | |
| properties_html = "<table>" | |
| for key, value in properties.items(): | |
| properties_html += f"<tr><td><strong>{key}</strong></td><td>{value}</td></tr>" | |
| properties_html += "</table>" | |
| return structure_html, properties_html | |
| with gr.Blocks() as demo: | |
| gr.Markdown("## Interactive Crystal Viewer") | |
| with gr.Row(): | |
| query_input = gr.Textbox(label="Search by Chemical System (e.g., 'Ac-Cd-Ge')", value="Ac-Cd-Ge") | |
| search_button = gr.Button("Search") | |
| material_dropdown = gr.Dropdown(label="Select Material", choices=[]) | |
| display_button = gr.Button("Display Material") | |
| with gr.Row(): | |
| structure_viewer = gr.HTML() | |
| properties_output = gr.HTML() | |
| search_button.click( | |
| fn=search_materials, | |
| inputs=query_input, | |
| outputs=material_dropdown | |
| ) | |
| display_button.click( | |
| fn=display_material, | |
| inputs=material_dropdown, | |
| outputs=[structure_viewer, properties_output] | |
| ) | |
| demo.launch() | |