Spaces:
Running
Running
File size: 5,980 Bytes
d638802 8f98f3c d638802 8f98f3c d638802 8f98f3c d638802 8f98f3c d638802 8f98f3c d638802 8f98f3c d638802 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
import gradio as gr
from slices.core import SLICES
from pymatgen.core.structure import Structure
from pymatgen.io.cif import CifWriter
from pymatgen.io.ase import AseAtomsAdaptor
from ase.io import write as ase_write
import tempfile
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
import os
# Initialize SLICES backend
backend = SLICES(relax_model="chgnet", fmax=0.4, steps=25)
def wrap_structure(structure):
"""Wrap all atoms back into the unit cell."""
for i, site in enumerate(structure):
frac_coords = site.frac_coords % 1.0
structure.replace(i, species=site.species, coords=frac_coords, coords_are_cartesian=False)
return structure
def get_primitive_structure(structure):
"""Convert the structure to its primitive cell."""
analyzer = SpacegroupAnalyzer(structure)
return analyzer.get_primitive_standard_structure()
def visualize_structure(structure):
"""Generate an image of the structure."""
atoms = AseAtomsAdaptor.get_atoms(structure)
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as temp_file:
ase_write(temp_file.name, atoms, format='png', rotation='10x,10y,10z')
return temp_file.name
def process_structure(structure):
"""Wrap and convert to primitive cell."""
structure = wrap_structure(structure)
return get_primitive_structure(structure)
def cif_to_slices(cif_file):
try:
structure = Structure.from_file(cif_file.name)
structure = process_structure(structure)
slices_string = backend.structure2SLICES(structure)
image_file = visualize_structure(structure)
return slices_string, image_file, None, slices_string, slices_string # Added another slices_string for aug_slices_input
except Exception as e:
return str(e), None, None, "", ""
def slices_to_cif(slices_string):
try:
structure, energy = backend.SLICES2structure(slices_string)
structure = process_structure(structure)
with tempfile.NamedTemporaryFile(mode='w', suffix='.cif', delete=False) as temp_file:
CifWriter(structure).write_file(temp_file.name)
image_file = visualize_structure(structure)
return temp_file.name, image_file, f"Conversion successful. Energy: {energy:.4f} eV/atom"
except Exception as e:
return None, None, f"Conversion failed. Error: {str(e)}"
def augment_and_canonicalize_slices(slices_string, num_augmentations):
try:
augmented_slices = backend.SLICES2SLICESAug_atom_order(slices_string,num=num_augmentations)
unique_augmented_slices = list(set(augmented_slices))
canonical_slices = list(set([backend.get_canonical_SLICES(s) for s in unique_augmented_slices]))
return augmented_slices, canonical_slices
except Exception as e:
return [], [], str(e)
# Gradio interface
with gr.Blocks() as iface:
gr.Markdown("# Crystal Structure and SLICES Converter", elem_classes=["center"])
with gr.Row(elem_classes=["center"]):
gr.Image("1.png", label="SLICES Representation", show_label=False, width=600, height=250)
gr.Markdown("SLICES provides a text-based encoding of crystal structures, allowing for efficient manipulation and generation of new materials.", elem_classes=["center"])
with gr.Tab("CIF-SLICES Conversion"):
with gr.Row():
with gr.Column():
file_choice = gr.Radio(
["Use example CIF (NdSiRu.cif)", "Upload custom CIF"],
label="Choose CIF source",
value="Use example CIF (NdSiRu.cif)"
)
example_file = gr.File(value="NdSiRu.cif", visible=False, interactive=False)
custom_file = gr.File(label="Upload CIF file", file_types=[".cif"], visible=False)
convert_cif_button = gr.Button("Convert CIF to SLICES")
slices_input = gr.Textbox(label="Enter SLICES String")
convert_slices_button = gr.Button("Convert SLICES to CIF")
with gr.Column():
slices_output = gr.Textbox(label="SLICES String")
cif_output = gr.File(label="Download CIF", file_types=[".cif"])
conversion_status = gr.Textbox(label="Conversion Status")
with gr.Row():
cif_image = gr.Image(label="Original Structure")
slices_image = gr.Image(label="Converted Structure")
with gr.Tab("SLICES Augmentation and Canonicalization"):
aug_slices_input = gr.Textbox(label="Enter SLICES String")
num_augmentations = gr.Slider(minimum=1, maximum=50, step=1, value=10, label="Number of Augmentations")
augment_button = gr.Button("Augment and Canonicalize")
aug_slices_output = gr.Textbox(label="Augmented SLICES Strings")
canon_slices_output = gr.Textbox(label="Canonical SLICES Strings")
# Event handlers
def update_file_visibility(choice):
return gr.update(visible=choice == "Use example CIF (NdSiRu.cif)"), gr.update(visible=choice == "Upload custom CIF")
file_choice.change(
update_file_visibility,
inputs=[file_choice],
outputs=[example_file, custom_file]
)
def get_active_file(choice, example, custom):
return example if choice == "Use example CIF (NdSiRu.cif)" else custom
convert_cif_button.click(
lambda choice, example, custom: cif_to_slices(get_active_file(choice, example, custom)),
inputs=[file_choice, example_file, custom_file],
outputs=[slices_output, cif_image, conversion_status, slices_input, aug_slices_input]
)
convert_slices_button.click(
slices_to_cif,
inputs=[slices_input],
outputs=[cif_output, slices_image, conversion_status]
)
augment_button.click(
augment_and_canonicalize_slices,
inputs=[aug_slices_input, num_augmentations],
outputs=[aug_slices_output, canon_slices_output]
)
iface.launch(share=True) |