import streamlit as st import pandas as pd from PIL import Image import re import base64 with open("images/Materials_bg_InDeS.png", "rb") as f: encoded = base64.b64encode(f.read()).decode() image_url = f"data:image/png;base64,{encoded}" st.set_page_config(initial_sidebar_state="expanded") def extract_matrix_fiber_from_abbr(abbr: str): if not isinstance(abbr, str): return None, None text = abbr.lower() matrix_map = { "epoxy": "Epoxy", "cyanate ester": "Cyanate Ester", "cynate ester": "Cyanate Ester", "polypropylene": "Polypropylene", "pp": "Polypropylene", "peek": "PEEK", "pei": "PEI", "nylon": "Nylon", "pa6": "PA6", "polyester": "Polyester", "vinyl ester": "Vinyl Ester", "phenolic": "Phenolic" } matrix = None for key, val in matrix_map.items(): if key in text: matrix = val break fiber_map = { "carbon": "Carbon Fiber", "glass": "Glass Fiber", "e-glass": "E-Glass Fiber", "s-glass": "S-Glass Fiber", "aramid": "Aramid Fiber", "kevlar": "Kevlar Fiber", "basalt": "Basalt Fiber", "natural": "Natural Fiber" } fiber = None for key, val in fiber_map.items(): if key in text: fiber = val break return matrix, fiber def main(): st.markdown(f"""

Categorized Material Search

Explore the AIM materials database by browsing polymers, fibers, and composites in a structured, category-driven view.
Use the filters to narrow down materials by class, composition, and property type, then inspect detailed property data and associated experimental plots where available.

""", unsafe_allow_html=True ) mat_section = st.sidebar.expander("Materials", expanded=False) with mat_section: thermo = mat_section.button("Composites") polymers = mat_section.button("Polymers") Fibers = mat_section.button("Fibers") if "material_type" not in st.session_state: st.session_state.material_type = "Composites" if thermo: st.session_state.material_type = "Composites" elif polymers: st.session_state.material_type = "Polymers" elif Fibers: st.session_state.material_type = "Fibers" @st.cache_data def load_data(material_type): file_map = { "Composites": "data/Composites_material_data.csv", "Polymers": "data/polymers_material_data.csv", "Fibers": "data/Fibers_material_data.csv", } return pd.read_csv(file_map[material_type]) csv_data = load_data(st.session_state.material_type) CLASS_MAP = { "Polymers": "Polymer", "Fibers": "Fiber", "Composites": "Composite", } current_class = CLASS_MAP[st.session_state.material_type] if "user_uploaded_data" in st.session_state: user_df = st.session_state["user_uploaded_data"] filtered_user_df = user_df[ user_df["material_class"] == current_class ] df = pd.concat([csv_data, filtered_user_df], ignore_index=True) else: df = csv_data st.session_state["base_data"] = df st.title("Materials DataSet") materials_df = ( df[["material_abbreviation", "material_name"]] .fillna("") .drop_duplicates() .reset_index(drop=True) ) materials_df[["Matrix", "Fiber"]] = materials_df["material_abbreviation"].apply( lambda x: pd.Series(extract_matrix_fiber_from_abbr(x)) ) if "search_term" in st.session_state: term = st.session_state.pop("search_term") try: pattern = re.compile(term, re.IGNORECASE) except re.error: pattern = re.compile(re.escape(term), re.IGNORECASE) mask = ( materials_df["material_abbreviation"].astype(str).str.contains(pattern) | materials_df["material_name"].astype(str).str.contains(pattern) ) filtered_materials_df = materials_df[mask].reset_index(drop=True) else: filtered_materials_df = materials_df.copy() def get_selected_value(df, key, column_name): if key in st.session_state: sel = st.session_state[key]["selection"]["cells"] if sel: row_idx = sel[0][0] return df.iloc[row_idx][column_name] return None mat = get_selected_value(filtered_materials_df, "material_table", "material_abbreviation") properties_df = pd.DataFrame(columns=["property_name", "section"]) prop_col, _ = st.columns([4, 6]) with st.container(border=True): with prop_col: with st.expander("Select Property", expanded=bool(mat)): if mat: filtered_df = df[ (df["material_abbreviation"] == mat) & (df["value"].notna()) & (df["property_name"].notna()) ] else: filtered_df = df[df["value"].notna() & df["property_name"].notna()] available_sections = list(filtered_df["section"].drop_duplicates()) if "selected_section" in st.session_state: incoming = st.session_state.pop("selected_section") matched = incoming if incoming in available_sections else None if not matched: incoming_lower = incoming.lower() for s in available_sections: if s.lower() == incoming_lower: matched = s break if matched: if "property_selectbox" in st.session_state: del st.session_state["property_selectbox"] st.session_state["property_selectbox"] = matched property_sel = st.selectbox( "Type of Property", available_sections, key="property_selectbox" ) properties_df = ( filtered_df[filtered_df["section"] == property_sel][["property_name", "section"]] .drop_duplicates() .reset_index(drop=True) ) st.dataframe( properties_df.style.set_properties(**{ 'background-color': 'white', 'color': "#c8c0c0", 'border': '1px solid #e0e0e0', 'font-family': 'monospace', 'font-size': '12px' }).set_table_styles([ { 'selector': 'thead tr th', 'props': [ ('background-color', '#f5f5f5'), ('color', "#C8C4C4"), ('font-weight', '600'), ('border-bottom', '2px solid #d0d0d0'), ('font-family', 'monospace'), ] }, { 'selector': 'tbody tr:hover', 'props': [('background-color', '#f9f9f9')] } ]), key="property_table", selection_mode="single-cell", on_select="rerun", use_container_width=True, height=300 ) selected_matrix = "All" selected_fiber = "All" if st.session_state.material_type == "Composites": matrix_options = sorted(filtered_materials_df["Matrix"].dropna().unique()) fiber_options = sorted(filtered_materials_df["Fiber"].dropna().unique()) fcol1, fcol2, _ = st.columns([2, 2, 6]) with fcol1: selected_matrix = st.selectbox("Matrix Material", ["All"] + matrix_options) with fcol2: selected_fiber = st.selectbox("Fiber Material", ["All"] + fiber_options) if st.session_state.material_type == "Composites": if selected_matrix != "All": filtered_materials_df = filtered_materials_df[ filtered_materials_df["Matrix"] == selected_matrix ] if selected_fiber != "All": filtered_materials_df = filtered_materials_df[ filtered_materials_df["Fiber"] == selected_fiber ] st.dataframe( filtered_materials_df.style.set_properties(**{ 'background-color': 'white', 'color': "#d3cccc", 'border': '1px solid #e0e0e0', 'font-family': 'monospace', 'font-size': '12px' }).set_table_styles([ { 'selector': 'thead tr th', 'props': [ ('background-color', '#f5f5f5'), ('color', "#D3C9C9"), ('font-weight', '600'), ('border-bottom', '2px solid #d0d0d0'), ('font-family', 'monospace'), ] }, { 'selector': 'tbody tr:hover', 'props': [('background-color', '#f9f9f9')] } ]), key="material_table", selection_mode="single-cell", on_select="rerun", use_container_width=True, height=500 ) prop = get_selected_value(properties_df, "property_table", "property_name") st.write("") if st.button("Search", disabled=not (mat and prop)): st.write(f"**Material:** {mat}") st.write(f"**Property:** {prop}") result = df[ (df["material_abbreviation"] == mat) & (df["property_name"] == prop) & (df["value"].notna()) ] if not result.empty: st.subheader("Property Data") st.dataframe(result.T, use_container_width=True) st.subheader("Property Graph") img_path = f"images/{mat}_{prop}.png" try: img = Image.open(img_path) st.image(img, use_container_width=True, caption="Stress strain curve") except FileNotFoundError: st.write("") else: st.warning("No data found for this material-property combination")