add: inci search, multiple cas selection, added DAP, check if link exists before download

This commit is contained in:
adish-rmr 2026-01-03 11:29:38 +01:00
parent 28d7028095
commit 1e5b9adeac
4 changed files with 158 additions and 17 deletions

24
app.py
View file

@ -1,6 +1,6 @@
import streamlit as st
from functions_ui import search_cas_number
from functions_ui import search_cas_inci
# Configure page
st.set_page_config(
@ -48,11 +48,16 @@ def home():
# Inizializza session_state per il CAS number se non esiste
if 'selected_cas' not in st.session_state:
st.session_state.selected_cas = None
input = st.text_input("Enter CAS Number:", "")
# choose between cas or inci
type = st.radio("Search by:", ("CAS Number", "INCI Name"), index=0, key="search_mode")
input = st.text_input("Enter input:", "")
if input:
st.caption(f"Ricerca per {input}: trovati i seguenti ingredienti.")
results = search_cas_number(input)
if type == "CAS Number":
results = search_cas_inci(input, type='cas')
else:
results = search_cas_inci(input, type='inci')
if results:
# Crea le stringhe per la selectbox: "CAS - INCI"
@ -64,14 +69,20 @@ def home():
# Salva solo il CAS selezionato nel session_state (estrae la parte prima del " - ")
if selected_display and selected_display != "":
selected_cas = selected_display.split(" - ")[0]
if ";" in selected_cas:
selected_cas = st.selectbox(options=selected_cas.split(";"), label="Multiple CAS found, please select one:")
elif "/" in selected_cas:
selected_cas = st.selectbox(options=selected_cas.split("/"), label="Multiple CAS found, please select one:")
st.session_state.selected_cas = selected_cas
st.success(f"CAS Number selezionato: {selected_cas}")
else:
# Nessun risultato trovato: permetti di usare l'input manuale
st.warning("Nessun risultato trovato nel database.")
if st.button("Usa questo CAS Number"):
if st.button("Usa questo CAS Number") and type == "CAS Number":
st.session_state.selected_cas = input
st.success(f"CAS Number salvato: {input}")
else:
st.info("INCI non trovato, scegli per CAS o modifica l'input.")
# Mostra il CAS attualmente selezionato
if st.session_state.selected_cas:
@ -81,13 +92,14 @@ def home():
home_page = st.Page(home, title="Home", icon="🏠", default=True)
echa_page = st.Page("pages/echa.py", title="ECHA Database", icon="🧪")
cosing_page = st.Page("pages/cosing.py", title="CosIng", icon="💄")
dap_page = st.Page("pages/dap.py", title="DAP", icon="🧬")
#pubchem_page = st.Page("pages/pubchem.py", title="PubChem", icon="🧬")
#cir_page = st.Page("pages/cir.py", title="CIR", icon="📊")
pg = st.navigation({
"Ricerca": [home_page],
"Database": [echa_page, cosing_page]
"Database": [echa_page, cosing_page, dap_page]
})
pg.run()

View file

@ -29,14 +29,20 @@ def cosing_request(cas_num: str) -> Dict[str, Any]:
def generate_pdf_download(cas, origin, link):
url = 'https://api.cosmoguard.it/api/v1/common/generate-pdf'
name = f'{cas}_{origin}'
response = requests.post(
url,
json = {
'link': link,
'name': name
if link is not None:
response = requests.post(
url,
json = {
'link': link,
'name': name
}
)
data = response.json()
else:
data = {
'success': False,
'error': 'No dossier exists for this origin.'
}
)
data = response.json()
if data['success'] == True:
url = f'https://api.cosmoguard.it/api/v1/common/download-pdf/{name}'
response = requests.get(url)

View file

@ -14,11 +14,13 @@ def open_csv_file(file_path):
con.execute(query)
return con
def search_cas_number(cas_number, type = 'cas'):
def search_cas_inci(input, type = 'cas'):
"""Cerca un numero CAS nei dati forniti e restituisce CAS e INCI."""
con = open_csv_file('data.csv')
query = f"SELECT * FROM index WHERE casNo LIKE '%{cas_number}%'"
if type == 'cas':
query = f"SELECT * FROM index WHERE casNo LIKE '%{input}%'"
else:
query = f"SELECT * FROM index WHERE inciName ILIKE '%{input}%'"
results = con.execute(query).fetchdf()
# Restituisce una lista di tuple (casNo, inciName)
@ -45,5 +47,5 @@ def download_pdf(casNo, origin, link):
)
if __name__ == "__main__":
data = search_cas_number('102242-62-6')
data = search_cas_inci('102242-62-6')
print(data)

121
pages/dap.py Normal file
View file

@ -0,0 +1,121 @@
import streamlit as st
import requests
import json
st.title("PubChem Data Viewer")
if st.session_state.get('selected_cas', None) is None:
st.warning("Nessun CAS Number selezionato. Torna alla pagina principale per effettuare una ricerca.")
st.stop()
else:
cas_number = st.session_state.selected_cas
# Make API request
with st.spinner("Fetching data from PubChem..."):
try:
response = requests.post(
"https://api.cosmoguard.it/api/v1/common/pubchem",
json={"cas": cas_number}
)
response.raise_for_status()
result = response.json()
except requests.exceptions.RequestException as e:
st.error(f"Error fetching data: {e}")
st.stop()
# Check if request was successful
if not result.get("success", False):
st.error(f"API Error: {result.get('error', 'Unknown error')}")
st.stop()
data = result.get("data", {})
# Display substance header
st.subheader(f"{data.get('first_pubchem_name', 'Unknown').title()}")
# Basic info container
with st.container(border=True):
col1, col2, col3 = st.columns(3)
with col1:
st.caption("CAS Number")
st.write(data.get("CAS", ""))
with col2:
st.caption("PubChem CID")
st.write(data.get("CID", ""))
with col3:
if data.get("pubchem_link"):
st.link_button("View on PubChem", data.get("pubchem_link"))
st.divider()
# Physical/Chemical Properties
st.subheader("Physical & Chemical Properties")
with st.container(border=True):
prop_col1, prop_col2, prop_col3, prop_col4 = st.columns(4)
with prop_col1:
st.metric("Molecular Weight", f"{data.get('MolecularWeight', '')} g/mol" if data.get('MolecularWeight') else "")
with prop_col2:
st.metric("XLogP", data.get('XLogP', ''))
with prop_col3:
st.metric("Exact Mass", data.get('ExactMass', ''))
with prop_col4:
st.metric("TPSA", f"{data.get('TPSA', '')} Ų" if data.get('TPSA') else "")
st.divider()
# Melting Point
melting_points = data.get("Melting Point", [])
if melting_points:
st.subheader("Melting Point")
with st.expander(f"View {len(melting_points)} reference(s)", expanded=True):
for idx, mp in enumerate(melting_points):
with st.container(border=True):
st.markdown(f"**Reference {idx + 1}**")
if mp.get("Value"):
st.info(mp.get("Value"))
if mp.get("Reference"):
st.caption(f"📚 {mp.get('Reference')}")
if mp.get("Description"):
st.caption(f" {mp.get('Description')}")
if mp.get("ReferenceNumber"):
st.caption(f"Ref #: {mp.get('ReferenceNumber')}")
# Dissociation Constants
dissociation_constants = data.get("Dissociation Constants", [])
if dissociation_constants:
st.divider()
st.subheader("Dissociation Constants (pKa)")
with st.expander(f"View {len(dissociation_constants)} reference(s)", expanded=True):
for idx, dc in enumerate(dissociation_constants):
with st.container(border=True):
st.markdown(f"**Reference {idx + 1}**")
if dc.get("Value"):
# Check if it's a dictionary or string
value = dc.get("Value")
if isinstance(value, dict):
st.code(json.dumps(value, indent=2))
else:
st.info(value)
if dc.get("Reference"):
st.caption(f"📚 {dc.get('Reference')}")
if dc.get("ReferenceNumber"):
st.caption(f"Ref #: {dc.get('ReferenceNumber')}")
# Raw JSON viewer
st.divider()
with st.expander("View Raw JSON Response"):
st.json(result)