|
import streamlit as st |
|
import requests |
|
import pandas as pd |
|
import matplotlib.pyplot as plt |
|
import seaborn as sns |
|
from rdkit import Chem |
|
from rdkit.Chem import Draw |
|
from fpdf import FPDF |
|
import tempfile |
|
import logging |
|
import os |
|
import plotly.graph_objects as go |
|
import networkx as nx |
|
from typing import Optional, Dict, List, Any |
|
from datetime import datetime |
|
|
|
|
|
|
|
|
|
st.set_page_config(page_title="Pharma Research Expert Platform", layout="wide") |
|
logging.basicConfig(level=logging.ERROR) |
|
|
|
|
|
|
|
|
|
API_ENDPOINTS = { |
|
"clinical_trials": "https://clinicaltrials.gov/api/v2/studies", |
|
"pubchem": "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/{}/JSON", |
|
"pubmed": "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi", |
|
"fda_drug_approval": "https://api.fda.gov/drug/label.json", |
|
"faers_adverse_events": "https://api.fda.gov/drug/event.json", |
|
|
|
"pharmgkb_gene_variants": "https://api.pharmgkb.org/v1/data/gene/{}/variants", |
|
|
|
"rxnorm_rxcui": "https://rxnav.nlm.nih.gov/REST/rxcui.json", |
|
"rxnorm_properties": "https://rxnav.nlm.nih.gov/REST/rxcui/{}/properties.json", |
|
|
|
"rxclass_by_drug": "https://rxnav.nlm.nih.gov/REST/class/byDrugName.json" |
|
} |
|
|
|
|
|
|
|
|
|
TRADE_TO_GENERIC = { |
|
"tylenol": "acetaminophen", |
|
"panadol": "acetaminophen", |
|
"advil": "ibuprofen", |
|
|
|
} |
|
|
|
|
|
|
|
|
|
OPENAI_API_KEY = st.secrets.get("OPENAI_API_KEY") |
|
OPENFDA_KEY = st.secrets.get("OPENFDA_KEY") |
|
PUB_EMAIL = st.secrets.get("PUB_EMAIL") |
|
|
|
if not PUB_EMAIL: |
|
st.error("PUB_EMAIL is not configured in secrets.") |
|
if not OPENFDA_KEY: |
|
st.error("OPENFDA_KEY is not configured in secrets.") |
|
if not OPENAI_API_KEY: |
|
st.error("OPENAI_API_KEY is not configured in secrets.") |
|
|
|
|
|
|
|
|
|
from openai import OpenAI |
|
openai_client = OpenAI(api_key=OPENAI_API_KEY) |
|
|
|
def generate_ai_content(prompt: str) -> str: |
|
"""Generate innovative insights using GPT‑4.""" |
|
try: |
|
response = openai_client.chat.completions.create( |
|
model="gpt-4", |
|
messages=[{"role": "user", "content": prompt}], |
|
max_tokens=300 |
|
) |
|
return response.choices[0].message.content.strip() |
|
except Exception as e: |
|
st.error(f"GPT‑4 generation error: {e}") |
|
logging.error(e) |
|
return "AI content generation failed." |
|
|
|
|
|
|
|
|
|
@st.cache_data(show_spinner=False) |
|
def query_api(endpoint: str, params: Optional[Dict] = None, headers: Optional[Dict] = None) -> Optional[Dict]: |
|
"""HTTP GET with error handling and caching.""" |
|
try: |
|
response = requests.get(endpoint, params=params, headers=headers, timeout=15) |
|
response.raise_for_status() |
|
return response.json() |
|
except Exception as e: |
|
st.error(f"API error for {endpoint}: {e}") |
|
logging.error(e) |
|
return None |
|
|
|
@st.cache_data(show_spinner=False) |
|
def get_pubchem_drug_details(drug_name: str) -> Optional[Dict[str, str]]: |
|
"""Retrieve drug details (including molecular formula, IUPAC name, and SMILES) from PubChem.""" |
|
url = API_ENDPOINTS["pubchem"].format(drug_name) |
|
data = query_api(url) |
|
details = {} |
|
if data and data.get("PC_Compounds"): |
|
compound = data["PC_Compounds"][0] |
|
for prop in compound.get("props", []): |
|
urn = prop.get("urn", {}) |
|
if urn.get("label") == "Molecular Formula": |
|
details["Molecular Formula"] = prop["value"]["sval"] |
|
if urn.get("name") == "Preferred": |
|
details["IUPAC Name"] = prop["value"]["sval"] |
|
if prop.get("name") == "Canonical SMILES": |
|
details["Canonical SMILES"] = prop["value"]["sval"] |
|
return details |
|
return None |
|
|
|
def save_pdf_report(report_content: str, filename: str) -> Optional[str]: |
|
"""Save a text report as a PDF file using FPDF.""" |
|
try: |
|
pdf = FPDF() |
|
pdf.add_page() |
|
pdf.set_font("Arial", size=12) |
|
pdf.multi_cell(0, 10, report_content) |
|
pdf.output(filename) |
|
return filename |
|
except Exception as e: |
|
st.error(f"Error saving PDF: {e}") |
|
logging.error(e) |
|
return None |
|
|
|
@st.cache_data(show_spinner=False) |
|
def get_clinical_trials(query: str) -> Optional[Dict]: |
|
"""Query ClinicalTrials.gov (NCT number or term search).""" |
|
if query.upper().startswith("NCT") and query[3:].isdigit(): |
|
params = {"id": query, "fmt": "json"} |
|
else: |
|
params = {"query.term": query, "retmax": 10, "retmode": "json"} |
|
return query_api(API_ENDPOINTS["clinical_trials"], params) |
|
|
|
@st.cache_data(show_spinner=False) |
|
def get_pubmed(query: str) -> Optional[Dict]: |
|
"""Query PubMed using the given search term.""" |
|
params = {"db": "pubmed", "term": query, "retmax": 10, "retmode": "json", "email": PUB_EMAIL} |
|
return query_api(API_ENDPOINTS["pubmed"], params) |
|
|
|
@st.cache_data(show_spinner=False) |
|
def get_fda_approval(drug_name: str) -> Optional[Dict]: |
|
"""Retrieve FDA drug approval data using openFDA.""" |
|
query = f'openfda.brand_name:"{drug_name}"' |
|
params = {"api_key": OPENFDA_KEY, "search": query, "limit": 1} |
|
data = query_api(API_ENDPOINTS["fda_drug_approval"], params) |
|
if data and data.get("results"): |
|
return data["results"][0] |
|
return None |
|
|
|
@st.cache_data(show_spinner=False) |
|
def analyze_adverse_events(drug_name: str, limit: int = 5) -> Optional[Dict]: |
|
"""Retrieve adverse event data from FAERS.""" |
|
query = f'patient.drug.medicinalproduct:"{drug_name}"' |
|
params = {"api_key": OPENFDA_KEY, "search": query, "limit": limit} |
|
return query_api(API_ENDPOINTS["faers_adverse_events"], params) |
|
|
|
@st.cache_data(show_spinner=False) |
|
def get_rxnorm_rxcui(drug_name: str) -> Optional[str]: |
|
"""Retrieve the RxCUI for a drug from RxNorm.""" |
|
url = f"{API_ENDPOINTS['rxnorm_rxcui']}?name={drug_name}" |
|
data = query_api(url) |
|
if data and "idGroup" in data and data["idGroup"].get("rxnormId"): |
|
return data["idGroup"]["rxnormId"][0] |
|
st.warning(f"No RxCUI found for {drug_name}.") |
|
return None |
|
|
|
@st.cache_data(show_spinner=False) |
|
def get_rxnorm_properties(rxcui: str) -> Optional[Dict]: |
|
"""Retrieve RxNorm properties for a given RxCUI.""" |
|
url = API_ENDPOINTS["rxnorm_properties"].format(rxcui) |
|
return query_api(url) |
|
|
|
@st.cache_data(show_spinner=False) |
|
def get_rxclass_by_drug_name(drug_name: str) -> Optional[Dict]: |
|
"""Query RxClass for drug classification info. (Fallback if no data is returned.)""" |
|
url = f"{API_ENDPOINTS['rxclass_by_drug']}?drugName={drug_name}" |
|
data = query_api(url) |
|
return data |
|
|
|
def create_variant_network(gene: str, variants: List[str], annotations: Dict[str, List[str]]) -> go.Figure: |
|
"""Generate a gene-variant-drug network graph using NetworkX and Plotly.""" |
|
G = nx.Graph() |
|
G.add_node(gene, color="lightblue") |
|
for variant in variants: |
|
G.add_node(variant, color="lightgreen") |
|
G.add_edge(gene, variant) |
|
for drug in annotations.get(variant, []): |
|
if drug and drug != "N/A": |
|
G.add_node(drug, color="lightcoral") |
|
G.add_edge(variant, drug) |
|
pos = nx.spring_layout(G) |
|
edge_x, edge_y = [], [] |
|
for edge in G.edges(): |
|
x0, y0 = pos[edge[0]] |
|
x1, y1 = pos[edge[1]] |
|
edge_x.extend([x0, x1, None]) |
|
edge_y.extend([y0, y1, None]) |
|
edge_trace = go.Scatter( |
|
x=edge_x, y=edge_y, line=dict(width=1, color="#888"), |
|
hoverinfo="none", mode="lines" |
|
) |
|
node_x, node_y, node_text, node_color = [], [], [], [] |
|
for node in G.nodes(): |
|
x, y = pos[node] |
|
node_x.append(x) |
|
node_y.append(y) |
|
node_text.append(node) |
|
node_color.append(G.nodes[node].get("color", "gray")) |
|
node_trace = go.Scatter( |
|
x=node_x, y=node_y, mode="markers+text", hoverinfo="text", |
|
text=node_text, textposition="bottom center", |
|
marker=dict(color=node_color, size=12, line_width=2) |
|
) |
|
fig = go.Figure(data=[edge_trace, node_trace], |
|
layout=go.Layout( |
|
title=dict(text="Gene-Variant-Drug Network", font=dict(size=16)), |
|
showlegend=False, |
|
hovermode="closest", |
|
margin=dict(b=20, l=5, r=5, t=40), |
|
xaxis=dict(showgrid=False, zeroline=False, showticklabels=False), |
|
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False) |
|
)) |
|
return fig |
|
|
|
|
|
|
|
|
|
def generate_drug_insights(drug_name: str) -> str: |
|
""" |
|
Gather data from FDA, PubChem, RxNorm, and RxClass (using generic fallback) and build a GPT‑4 prompt |
|
for an innovative, bullet‑point drug analysis. |
|
""" |
|
query_name = TRADE_TO_GENERIC.get(drug_name.lower(), drug_name) |
|
|
|
|
|
fda_info = get_fda_approval(query_name) |
|
fda_status = "Not Approved" |
|
if fda_info and fda_info.get("openfda", {}).get("brand_name"): |
|
fda_status = ", ".join(fda_info["openfda"]["brand_name"]) |
|
|
|
|
|
pubchem_details = get_pubchem_drug_details(query_name) |
|
if pubchem_details: |
|
formula = pubchem_details.get("Molecular Formula", "N/A") |
|
iupac = pubchem_details.get("IUPAC Name", "N/A") |
|
canon_smiles = pubchem_details.get("Canonical SMILES", "N/A") |
|
else: |
|
formula = iupac = canon_smiles = "Not Available" |
|
|
|
|
|
rxnorm_id = get_rxnorm_rxcui(query_name) |
|
if rxnorm_id: |
|
rx_props = get_rxnorm_properties(rxnorm_id) |
|
rxnorm_info = f"RxCUI: {rxnorm_id}\nProperties: {rx_props}" |
|
else: |
|
rxnorm_info = "No RxNorm data available." |
|
|
|
|
|
rxclass_data = get_rxclass_by_drug_name(query_name) |
|
rxclass_info = rxclass_data if rxclass_data else "No RxClass data available." |
|
|
|
|
|
prompt = ( |
|
f"Provide an innovative, advanced drug analysis for '{drug_name}' (generic: {query_name}).\n\n" |
|
f"**FDA Approval Status:** {fda_status}\n\n" |
|
f"**PubChem Details:**\n" |
|
f"- Molecular Formula: {formula}\n" |
|
f"- IUPAC Name: {iupac}\n" |
|
f"- Canonical SMILES: {canon_smiles}\n\n" |
|
f"**RxNorm Info:** {rxnorm_info}\n\n" |
|
f"**RxClass Info:** {rxclass_info}\n\n" |
|
f"Include in bullet points:\n" |
|
f"- Pharmacogenomic considerations (e.g. genetic variants impacting metabolism or toxicity)\n" |
|
f"- Potential repurposing opportunities and innovative therapeutic insights\n" |
|
f"- Regulatory challenges and suggestions for personalized medicine approaches\n" |
|
f"- Forward‑looking recommendations for future research and integration of diverse data sources\n" |
|
) |
|
return generate_ai_content(prompt) |
|
|
|
|
|
|
|
|
|
tabs = st.tabs([ |
|
"💊 Drug Development", |
|
"📊 Trial Analytics", |
|
"🧬 Molecular Profiling", |
|
"📜 Regulatory Intelligence", |
|
"📚 Literature Search", |
|
"📈 Dashboard", |
|
"🧪 Drug Data Integration", |
|
"🤖 AI Insights" |
|
]) |
|
|
|
|
|
with tabs[0]: |
|
st.header("AI‑Driven Drug Development Strategy") |
|
target = st.text_input("Target Disease/Pathway:", placeholder="Enter disease mechanism or target") |
|
target_gene = st.text_input("Target Gene (PharmGKB Accession):", placeholder="e.g., PA1234") |
|
strategy = st.selectbox("Development Strategy:", ["First-in-class", "Me-too", "Repurposing", "Biologic"]) |
|
|
|
if st.button("Generate Development Plan"): |
|
with st.spinner("Generating comprehensive development plan..."): |
|
plan_prompt = ( |
|
f"Develop a detailed drug development plan for treating {target} using a {strategy} strategy. " |
|
"Include sections on target validation, lead optimization, preclinical testing, clinical trial design, " |
|
"regulatory strategy, market analysis, competitive landscape, and pharmacogenomic considerations." |
|
) |
|
plan = generate_ai_content(plan_prompt) |
|
st.subheader("Comprehensive Development Plan") |
|
st.markdown(plan) |
|
|
|
st.subheader("FDA Regulatory Insights") |
|
if target: |
|
fda_data = get_fda_approval(target.split()[0]) |
|
if fda_data: |
|
st.json(fda_data) |
|
else: |
|
st.write("No FDA data found for the given target.") |
|
|
|
st.subheader("Pharmacogenomic Considerations") |
|
if target_gene: |
|
if not target_gene.startswith("PA"): |
|
st.warning("Enter a valid PharmGKB accession (e.g., PA1234).") |
|
else: |
|
variants = get_pharmgkb_variants_for_gene(target_gene) |
|
if variants: |
|
st.write("PharmGKB Variants:") |
|
st.write(variants) |
|
|
|
sample_annots = {} |
|
for vid in variants[:3]: |
|
|
|
|
|
sample_annots[vid] = ["DrugA", "DrugB"] |
|
try: |
|
net_fig = create_variant_network(target_gene, variants[:3], sample_annots) |
|
st.plotly_chart(net_fig, use_container_width=True) |
|
except Exception as e: |
|
st.error(f"Network graph error: {e}") |
|
else: |
|
st.write("No variants found for the specified PharmGKB gene accession.") |
|
else: |
|
st.write("Provide a PharmGKB gene accession to retrieve pharmacogenomic data.") |
|
|
|
|
|
with tabs[1]: |
|
st.header("Clinical Trial Landscape Analytics") |
|
trial_query = st.text_input("Search Clinical Trials:", placeholder="Enter condition, intervention, or NCT number") |
|
if st.button("Analyze Trial Landscape"): |
|
with st.spinner("Fetching trial data..."): |
|
trials = get_clinical_trials(trial_query) |
|
if trials and trials.get("studies"): |
|
trial_data = [] |
|
for study in trials["studies"][:5]: |
|
trial_data.append({ |
|
"Title": study.get("protocolSection", {}).get("identificationModule", {}).get("briefTitle", "N/A"), |
|
"Status": study.get("protocolSection", {}).get("statusModule", {}).get("overallStatus", "N/A"), |
|
"Phase": study.get("protocolSection", {}).get("designModule", {}).get("phases", ["Not Available"])[0], |
|
"Enrollment": study.get("protocolSection", {}).get("designModule", {}).get("enrollmentInfo", {}).get("count", "N/A") |
|
}) |
|
df_trials = pd.DataFrame(trial_data) |
|
st.dataframe(df_trials) |
|
else: |
|
st.warning("No clinical trials found for the query.") |
|
|
|
ae_data = analyze_adverse_events(trial_query) |
|
if ae_data and ae_data.get("results"): |
|
st.subheader("Adverse Event Profile (Top 5)") |
|
ae_results = ae_data["results"][:5] |
|
ae_df = pd.json_normalize(ae_results) |
|
st.dataframe(ae_df) |
|
if "patient.reaction.reactionmeddrapt" in ae_df.columns: |
|
try: |
|
reactions = ae_df["patient.reaction.reactionmeddrapt"].explode().dropna() |
|
top_reactions = reactions.value_counts().nlargest(10) |
|
fig, ax = plt.subplots(figsize=(10, 6)) |
|
sns.barplot(x=top_reactions.values, y=top_reactions.index, ax=ax) |
|
ax.set_title("Top Adverse Reactions") |
|
ax.set_xlabel("Frequency") |
|
ax.set_ylabel("Reaction") |
|
st.pyplot(fig) |
|
except Exception as e: |
|
st.error(f"Error visualizing adverse events: {e}") |
|
else: |
|
st.write("No adverse event data available.") |
|
|
|
|
|
with tabs[2]: |
|
st.header("Advanced Molecular Profiling") |
|
compound_input = st.text_input("Compound Identifier:", placeholder="Enter drug name, SMILES, or INN") |
|
if st.button("Analyze Compound"): |
|
with st.spinner("Querying PubChem for molecular structure and properties..."): |
|
|
|
query_compound = TRADE_TO_GENERIC.get(compound_input.lower(), compound_input) |
|
pubchem_info = get_pubchem_drug_details(query_compound) |
|
if pubchem_info: |
|
smiles = pubchem_info.get("Canonical SMILES") |
|
if smiles and smiles != "N/A": |
|
mol_image = draw_molecule(smiles) |
|
if mol_image: |
|
st.image(mol_image, caption="2D Molecular Structure") |
|
else: |
|
st.error("Canonical SMILES not found for this compound.") |
|
st.subheader("Physicochemical Properties") |
|
st.write(f"**Molecular Formula:** {pubchem_info.get('Molecular Formula', 'N/A')}") |
|
st.write(f"**IUPAC Name:** {pubchem_info.get('IUPAC Name', 'N/A')}") |
|
st.write(f"**Canonical SMILES:** {pubchem_info.get('Canonical SMILES', 'N/A')}") |
|
else: |
|
st.error("PubChem details not available for the given compound.") |
|
|
|
|
|
with tabs[3]: |
|
st.header("Global Regulatory Monitoring") |
|
st.markdown("**Note:** This section focuses on FDA data and PubChem drug details due to limitations with EMA/WHO/DailyMed APIs.") |
|
drug_prod = st.text_input("Drug Product:", placeholder="Enter generic or brand name") |
|
if st.button("Generate Regulatory Report"): |
|
with st.spinner("Compiling regulatory data..."): |
|
fda_data = get_fda_approval(drug_prod) |
|
fda_status = "Not Approved" |
|
if fda_data and fda_data.get("openfda", {}).get("brand_name"): |
|
fda_status = ", ".join(fda_data["openfda"]["brand_name"]) |
|
pubchem_details = get_pubchem_drug_details(drug_prod) |
|
if pubchem_details: |
|
formula = pubchem_details.get("Molecular Formula", "N/A") |
|
iupac = pubchem_details.get("IUPAC Name", "N/A") |
|
canon_smiles = pubchem_details.get("Canonical SMILES", "N/A") |
|
else: |
|
formula = iupac = canon_smiles = "Not Available" |
|
col1, col2 = st.columns(2) |
|
with col1: |
|
st.markdown("**FDA Status**") |
|
st.write(fda_status) |
|
with col2: |
|
st.markdown("**Drug Details (PubChem)**") |
|
st.write(f"**Molecular Formula:** {formula}") |
|
st.write(f"**IUPAC Name:** {iupac}") |
|
st.write(f"**Canonical SMILES:** {canon_smiles}") |
|
report_text = ( |
|
f"### Regulatory Report for {drug_prod}\n\n" |
|
f"**FDA Status:** {fda_status}\n\n" |
|
f"**Molecular Formula:** {formula}\n\n" |
|
f"**IUPAC Name:** {iupac}\n\n" |
|
f"**Canonical SMILES:** {canon_smiles}\n" |
|
) |
|
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp: |
|
pdf_file = save_pdf_report(report_text, tmp.name) |
|
if pdf_file: |
|
with open(pdf_file, "rb") as f: |
|
st.download_button("Download Regulatory Report (PDF)", data=f, file_name=f"{drug_prod}_report.pdf", mime="application/pdf") |
|
os.remove(pdf_file) |
|
|
|
|
|
with tabs[4]: |
|
st.header("Literature Search") |
|
lit_query = st.text_input("Enter search query for PubMed:", placeholder="e.g., Alzheimer's disease genetics") |
|
if st.button("Search PubMed"): |
|
with st.spinner("Searching PubMed..."): |
|
pubmed_results = get_pubmed(lit_query) |
|
if pubmed_results and pubmed_results.get("esearchresult", {}).get("idlist"): |
|
id_list = pubmed_results["esearchresult"]["idlist"] |
|
st.subheader(f"Found {len(id_list)} PubMed Results") |
|
for pmid in id_list: |
|
st.markdown(f"- [PMID: {pmid}](https://pubmed.ncbi.nlm.nih.gov/{pmid}/)") |
|
else: |
|
st.write("No PubMed results found.") |
|
|
|
|
|
|
|
with tabs[5]: |
|
st.header("Comprehensive Dashboard") |
|
|
|
kpi_fda = 5000 |
|
kpi_trials = 12000 |
|
kpi_pubs = 250000 |
|
col1, col2, col3 = st.columns(3) |
|
col1.metric("FDA Approved Drugs", kpi_fda) |
|
col2.metric("Ongoing Trials", kpi_trials) |
|
col3.metric("Publications", kpi_pubs) |
|
st.subheader("Trend Analysis") |
|
years = list(range(2000, 2026)) |
|
approvals = [kpi_fda // len(years)] * len(years) |
|
fig_trend, ax_trend = plt.subplots(figsize=(10, 6)) |
|
sns.lineplot(x=years, y=approvals, marker="o", ax=ax_trend) |
|
ax_trend.set_title("FDA Approvals Over Time") |
|
ax_trend.set_xlabel("Year") |
|
ax_trend.set_ylabel("Number of Approvals") |
|
st.pyplot(fig_trend) |
|
st.subheader("Gene-Variant-Drug Network (Sample)") |
|
|
|
sample_gene = "CYP2C19" |
|
sample_variants = ["rs4244285", "rs12248560"] |
|
sample_annots = {"rs4244285": ["Clopidogrel", "Omeprazole"], "rs12248560": ["Sertraline"]} |
|
try: |
|
net_fig = create_variant_network(sample_gene, sample_variants, sample_annots) |
|
st.plotly_chart(net_fig, use_container_width=True) |
|
except Exception as e: |
|
st.error(f"Network graph error: {e}") |
|
|
|
|
|
with tabs[6]: |
|
st.header("🧪 Drug Data Integration") |
|
drug_integration = st.text_input("Enter Drug Name for API Integration:", placeholder="e.g., aspirin") |
|
if st.button("Retrieve Drug Data"): |
|
with st.spinner("Fetching drug data from multiple sources..."): |
|
query_drug = TRADE_TO_GENERIC.get(drug_integration.lower(), drug_integration) |
|
rxnorm_id = get_rxnorm_rxcui(query_drug) |
|
rx_props = get_rxnorm_properties(rxnorm_id) if rxnorm_id else None |
|
rxclass_info = get_rxclass_by_drug_name(query_drug) |
|
st.subheader("RxNorm Data") |
|
if rxnorm_id: |
|
st.write(f"RxCUI for {drug_integration}: {rxnorm_id}") |
|
st.json(rx_props if rx_props else {"message": "No RxNorm properties found."}) |
|
else: |
|
st.write("No RxCUI found for the given drug name.") |
|
st.subheader("RxClass Information") |
|
if rxclass_info: |
|
st.json(rxclass_info) |
|
else: |
|
st.write("No RxClass data found for the given drug.") |
|
pubchem_info = get_pubchem_drug_details(query_drug) |
|
st.subheader("PubChem Drug Details") |
|
if pubchem_info: |
|
st.write(f"**Molecular Formula:** {pubchem_info.get('Molecular Formula', 'N/A')}") |
|
st.write(f"**IUPAC Name:** {pubchem_info.get('IUPAC Name', 'N/A')}") |
|
st.write(f"**Canonical SMILES:** {pubchem_info.get('Canonical SMILES', 'N/A')}") |
|
else: |
|
st.write("No PubChem details found.") |
|
|
|
|
|
with tabs[7]: |
|
st.header("🤖 AI Insights") |
|
ai_drug = st.text_input("Enter Drug Name for AI-Driven Analysis:", placeholder="e.g., tylenol") |
|
if st.button("Generate AI Insights"): |
|
with st.spinner("Generating AI-driven insights..."): |
|
query_ai_drug = TRADE_TO_GENERIC.get(ai_drug.lower(), ai_drug) |
|
insights_text = generate_drug_insights(query_ai_drug) |
|
st.subheader("AI‑Driven Drug Analysis") |
|
st.markdown(insights_text) |
|
|