使用python与streamlit构建的空间微生物分析

发布于:2025-08-07 ⋅ 阅读:(12) ⋅ 点赞:(0)

我们尝试使用python与streamlit实现了一个交互式的空间微生物消杀效果分析的web应用示例,用于分析微生物在不同环境下的行为,并评估各种消毒方法的效果。

环境与微生物行为分析,用户可以选择地球或太空环境,并输入温度、湿度等参数,系统会模拟微生物(如大肠杆菌、霉菌等)的生长速率,预测其在无消毒处理时的峰值浓度。

消毒方法评估,提供多种消毒方法(如气体等离子体、臭氧、湿巾等),计算每种方法在不同环境下的效率(百分比),并生成图表对比。

安全评估与推荐,根据用户输入的环境条件和选择的消毒方法,显示峰值浓度是否超出安全标准(如空间站的1000 CFU/m³),并推荐适合该环境的消毒方案。

import streamlit as st
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib as mpl
from matplotlib.font_manager import FontProperties
import sys
import plotly.graph_objects as go
import plotly.express as px
from plotly.subplots import make_subplots

# ===== 初始化设置 =====
st.set_page_config(
    page_title="微生物消杀模拟系统",
    page_icon="🦠",
    layout="wide",
    initial_sidebar_state="expanded"
)

# ===== 设置字体支持 =====
try:
    font_path = 'C:/Windows/Fonts/arialuni.ttf'  # 优先选择支持特殊字符的字体
    if sys.platform == "darwin":  # macOS
        font_path = '/System/Library/Fonts/PingFang.ttc'
    elif sys.platform == "linux":  # Linux
        font_path = '/usr/share/fonts/truetype/wqy/wqy-microhei.ttc'
    
    font = FontProperties(fname=font_path)
    plt.rcParams['font.family'] = font.get_name()
    plt.rcParams['axes.unicode_minus'] = False
except Exception as e:
    st.warning(f"字体设置异常: {str(e)},使用默认字体")

# ===== 环境类型设置 =====
ENVIRONMENT_TYPES = {
    "地球环境": {
        "gravity": 1.0,
        "humidity_range": (30, 90),
        "temperature_range": (10, 40),
        "pressure": 1.0,
        "radiation": "低"
    },
    "太空环境": {
        "gravity": 0.01,
        "humidity_range": (10, 50),  # 太空湿度范围较窄
        "temperature_range": (15, 35),  # 太空温度范围较窄
        "pressure": 0.7,
        "radiation": "高"
    }
}

# ===== 微生物种类数据库 =====
MICROBE_SPECIES = {
    # 细菌
    "大肠杆菌": {"type": "细菌", "growth_rate": 0.25, "resistance": 0.2, "radiation_resist": 0.1},
    "金黄色葡萄球菌": {"type": "细菌", "growth_rate": 0.22, "resistance": 0.3, "radiation_resist": 0.15},
    "沙门氏菌": {"type": "细菌", "growth_rate": 0.24, "resistance": 0.25, "radiation_resist": 0.12},
    
    # 真菌
    "霉菌": {"type": "真菌", "growth_rate": 0.18, "resistance": 0.4, "radiation_resist": 0.25},
    "酵母菌": {"type": "真菌", "growth_rate": 0.16, "resistance": 0.35, "radiation_resist": 0.2},
    "黑曲霉": {"type": "真菌", "growth_rate": 0.17, "resistance": 0.45, "radiation_resist": 0.3},
    
    # 孢子
    "枯草芽孢杆菌": {"type": "孢子", "growth_rate": 0.12, "resistance": 0.65, "radiation_resist": 0.6},
    "艰难梭菌": {"type": "孢子", "growth_rate": 0.1, "resistance": 0.7, "radiation_resist": 0.65},
    "炭疽杆菌": {"type": "孢子", "growth_rate": 0.11, "resistance": 0.75, "radiation_resist": 0.7}
}

# ===== 消杀方法数据库 =====
DISINFECTION_METHODS = {
    "紫外线照射(254nm)": {
        "efficiency": {"地球": 0.02, "太空": 0.015},
        "limitations": "无法穿透物体阴影",
        "cost": "中",
        "safety": "安全"
    },
    "过氧化氢蒸汽": {
        "efficiency": {"地球": 0.03, "太空": 0.025},
        "limitations": "高湿度需求,可能腐蚀设备",
        "cost": "高",
        "safety": "中等"
    },
    "气体等离子体": {
        "efficiency": {"地球": 0.025, "太空": 0.022},
        "limitations": "可能产生有害副产物",
        "cost": "高",
        "safety": "中等"
    },
    "光催化氧化(TiO₂)": {
        "efficiency": {"地球": 0.015, "太空": 0.01},
        "limitations": "需要持续光照",
        "cost": "中",
        "safety": "安全"
    },
    "超临界CO₂": {
        "efficiency": {"地球": 0.035, "太空": 0.03},
        "limitations": "需要高压设备",
        "cost": "很高",
        "safety": "安全"
    },
    "臭氧(O₃)": {
        "efficiency": {"地球": 0.027, "太空": 0.02},
        "limitations": "高浓度对人体有害",
        "cost": "中",
        "safety": "低"
    },
    "环氧乙烷(EtO)": {
        "efficiency": {"地球": 0.032, "太空": 0.025},
        "limitations": "易燃易爆,有残留毒性",
        "cost": "高",
        "safety": "低"
    },
    "季铵盐湿巾": {
        "efficiency": {"地球": 0.012, "太空": 0.005},
        "limitations": "难以覆盖所有表面",
        "cost": "低",
        "safety": "安全"
    }
}

# ===== 侧边栏参数设置 =====
st.sidebar.header("环境设置")
environment = st.sidebar.selectbox("环境类型", list(ENVIRONMENT_TYPES.keys()))
env_params = ENVIRONMENT_TYPES[environment]

st.sidebar.subheader(f"{environment}参数")
temp = st.sidebar.slider(
    "温度(℃)", 
    min_value=env_params["temperature_range"][0],
    max_value=env_params["temperature_range"][1],
    value=25
)
humidity = st.sidebar.slider(
    "湿度(%)", 
    min_value=env_params["humidity_range"][0],
    max_value=env_params["humidity_range"][1],
    value=45 if environment == "太空环境" else 60
)
volume = st.sidebar.selectbox("空间体积(m³)", [10, 50, 100, 200, 500], index=2)

st.sidebar.header("微生物参数")
microbe_species = st.sidebar.selectbox(
    "微生物种类", 
    options=list(MICROBE_SPECIES.keys()),
    index=0
)

# 获取微生物参数
microbe_params = MICROBE_SPECIES[microbe_species]
st.sidebar.markdown(f"**类型**: {microbe_params['type']}")
st.sidebar.markdown(f"**生长速率**: {microbe_params['growth_rate']:.2f}/h")
st.sidebar.markdown(f"**抗性**: {microbe_params['resistance']*100:.0f}%")
st.sidebar.markdown(f"**辐射抵抗**: {microbe_params['radiation_resist']*100:.0f}%")

init_concentration = st.sidebar.number_input(
    "初始浓度(CFU/m³)", 
    min_value=100, 
    max_value=10000, 
    value=1000
)

st.sidebar.header("消杀方案")
selected_methods = st.sidebar.multiselect(
    "选择消杀方法(可多选)", 
    options=list(DISINFECTION_METHODS.keys()),
    default=["气体等离子体", "超临界CO₂"]
)

exposure_time = st.sidebar.slider("作用时间(分钟)", 1, 120, 30)

# ===== 核心算法 =====
def growth_rate(temp, humidity, microbe_params, env_params):
    """
    微生物生长速率模型 - 基于文档2.1-2.11节
    """
    base_rate = microbe_params["growth_rate"]
    
    # 温度影响系数 - 25℃为最适温度
    temp_factor = np.exp(-0.5 * ((temp - 25) / 10)**2)
    
    # 湿度影响系数
    if environment == "太空环境":
        # 太空环境下湿度影响减小
        humid_factor = 0.7 + 0.3 * ((humidity - 10) / 40)  # 适应太空的窄湿度范围
    else:
        humid_factor = 0.5 + 0.5 * (humidity / 100)
    
    # 重力影响系数
    gravity_factor = 1.2 - 0.2 * env_params["gravity"]  # 微重力环境下生长更快
    
    # 辐射影响系数(针对太空环境)
    radiation_factor = 1.0 if environment == "地球环境" else 0.9 + microbe_params["radiation_resist"] * 0.2
    
    return base_rate * temp_factor * humid_factor * gravity_factor * radiation_factor

def disinfection_efficiency(method, time, microbe_params, env_params):
    """
    消杀效率模型 - 基于文档3.1-3.8节
    """
    method_params = DISINFECTION_METHODS[method]
    
    # 基础效率
    base_efficiency = method_params["efficiency"]["太空" if environment == "太空环境" else "地球"]
    efficiency = base_efficiency * time
    
    # 微生物抗性影响
    efficiency *= (1 - microbe_params["resistance"])
    
    # 环境因素影响
    if environment == "太空环境":
        # 太空环境下某些方法效率降低
        if method in ["季铵盐湿巾", "臭氧(O₃)"]:
            efficiency *= 0.8  # 太空环境下湿巾效果变差
        elif method in ["光催化氧化(TiO₂)"]:
            efficiency *= 0.9  # 光催化在太空环境下略有降低
    
    # 效率上限
    return min(0.95, efficiency)  # 最大效率95%

# ===== 动态模拟 =====
# 生成时间序列
hours = np.linspace(0, 48, 200)  # 扩展到48小时
growth_rate_val = growth_rate(temp, humidity, microbe_params, env_params)
growth_curve = init_concentration * np.exp(growth_rate_val * hours)

# 计算消杀时间点
disinfection_idx = min(int(exposure_time / (24*60) * len(hours)), len(hours)-1)

# ===== 主界面布局 =====
st.title(f"密闭空间微生物消杀效果模拟 - {environment}")
st.caption("基于《密闭空间微生物消杀方法研究进展》戴荣继等(北京理工大学)")

# 创建选项卡
tab1, tab2, tab3 = st.tabs(["生长与消杀曲线", "环境对比分析", "方法对比矩阵"])

with tab1:
    # === 图1:微生物生长与消杀曲线 ===
    st.subheader(f"{microbe_species}在不同消杀方案下的浓度变化")
    
    fig1 = go.Figure()
    fig1.add_trace(go.Scatter(
        x=hours, 
        y=growth_curve, 
        mode='lines',
        name='自然生长',
        line=dict(color='blue', width=2)
    ))
    
    # 添加各种消杀方案的曲线
    colors = px.colors.qualitative.Plotly
    for i, method in enumerate(selected_methods):
        disinfection_eff = disinfection_efficiency(method, exposure_time, microbe_params, env_params)
        
        # 消杀后曲线
        post_disinfection = growth_curve.copy()
        post_disinfection[disinfection_idx:] = (
            growth_curve[disinfection_idx] * (1 - disinfection_eff) * 
            np.exp(growth_rate_val * (hours[disinfection_idx:] - hours[disinfection_idx]))
        )
        
        fig1.add_trace(go.Scatter(
            x=hours, 
            y=post_disinfection, 
            mode='lines',
            name=f"{method} (效率: {disinfection_eff*100:.1f}%)",
            line=dict(color=colors[i % len(colors)], width=2, dash='dash')
        ))
    
    # 添加消杀时间线
    fig1.add_vline(
        x=hours[disinfection_idx], 
        line_dash="dash", 
        line_color="green",
        annotation_text=f"消杀开始 ({exposure_time}分钟)",
        annotation_position="top right"
    )
    
    # 设置安全标准线
    fig1.add_hline(
        y=1000, 
        line_dash="dot", 
        line_color="red",
        annotation_text="安全浓度上限 (1000 CFU/m³)", 
        annotation_position="bottom right"
    )
    
    fig1.update_layout(
        title=f"微生物生长与消杀模拟曲线",
        xaxis_title="时间 (小时)",
        yaxis_title="微生物浓度 (CFU/m³)",
        legend_title="消杀方法",
        hovermode="x unified",
        height=500
    )
    
    st.plotly_chart(fig1, use_container_width=True)
    
    # === 效果对比表格 ===
    st.subheader("消杀效果评估")
    
    eff_data = []
    for method in DISINFECTION_METHODS:
        eff = disinfection_efficiency(method, exposure_time, microbe_params, env_params)
        eff_data.append({
            "消杀方法": method,
            f"{exposure_time}分钟效率": f"{eff*100:.1f}%",
            "适用场景": DISINFECTION_METHODS[method]["limitations"],
            "安全性": DISINFECTION_METHODS[method]["safety"],
            "成本": DISINFECTION_METHODS[method]["cost"]
        })
    
    df_eff = pd.DataFrame(eff_data)
    df_eff = df_eff.sort_values(f"{exposure_time}分钟效率", ascending=False)
    
    # 高亮显示所选方法
    def highlight_selected(row):
        if row["消杀方法"] in selected_methods:
            return ['background-color: #e6f7ff'] * len(row)
        return [''] * len(row)
    
    st.dataframe(
        df_eff.style.apply(highlight_selected, axis=1),
        use_container_width=True
    )

with tab2:
    # === 图2:环境对比分析 ===
    st.subheader("地球与太空环境微生物行为对比")
    
    # 创建子图
    fig2 = make_subplots(
        rows=2, 
        cols=2,
        subplot_titles=(
            "不同温度下生长速率对比",
            "不同湿度下生长速率对比",
            "不同环境消毒效率对比",
            "微生物类别抗性分析"
        ),
        vertical_spacing=0.15
    )
    
    # 面板1:不同温度下生长速率对比
    temps = np.linspace(10, 40, 20)
    earth_growth = [growth_rate(t, 60, MICROBE_SPECIES["大肠杆菌"], ENVIRONMENT_TYPES["地球环境"]) for t in temps]
    space_growth = [growth_rate(t, 30, MICROBE_SPECIES["大肠杆菌"], ENVIRONMENT_TYPES["太空环境"]) for t in temps]
    
    fig2.add_trace(go.Scatter(
        x=temps, y=earth_growth, name="地球环境-大肠杆菌",
        line=dict(color='blue', width=2)), row=1, col=1)
    
    fig2.add_trace(go.Scatter(
        x=temps, y=space_growth, name="太空环境-大肠杆菌",
        line=dict(color='red', width=2, dash='dash')), row=1, col=1)
    
    # 面板2:不同湿度下生长速率对比
    humidities = np.linspace(10, 90, 20)
    earth_growth_h = [growth_rate(25, h, MICROBE_SPECIES["大肠杆菌"], ENVIRONMENT_TYPES["地球环境"]) for h in humidities]
    space_growth_h = [growth_rate(25, h, MICROBE_SPECIES["大肠杆菌"], ENVIRONMENT_TYPES["太空环境"]) for h in humidities]
    
    fig2.add_trace(go.Scatter(
        x=humidities, y=earth_growth_h, name="地球环境-大肠杆菌",
        line=dict(color='blue', width=2), showlegend=False), row=1, col=2)
    
    fig2.add_trace(go.Scatter(
        x=humidities, y=space_growth_h, name="太空环境-大肠杆菌",
        line=dict(color='red', width=2, dash='dash'), showlegend=False), row=1, col=2)
    
    # 面板3:不同环境下消杀效率对比
    methods_list = list(DISINFECTION_METHODS.keys())
    earth_eff = [disinfection_efficiency(m, 30, MICROBE_SPECIES["大肠杆菌"], ENVIRONMENT_TYPES["地球环境"])*100 for m in methods_list]
    space_eff = [disinfection_efficiency(m, 30, MICROBE_SPECIES["大肠杆菌"], ENVIRONMENT_TYPES["太空环境"])*100 for m in methods_list]
    
    fig2.add_trace(go.Bar(
        x=methods_list, y=earth_eff, name="地球环境效率",
        marker_color='blue'), row=2, col=1)
    
    fig2.add_trace(go.Bar(
        x=methods_list, y=space_eff, name="太空环境效率",
        marker_color='red'), row=2, col=1)
    
    # 面板4:微生物抗性分析
    microbes = list(MICROBE_SPECIES.keys())
    growth_rates = [MICROBE_SPECIES[m]["growth_rate"] for m in microbes]
    resistances = [MICROBE_SPECIES[m]["resistance"] for m in microbes]
    
    fig2.add_trace(go.Bar(
        x=microbes, y=growth_rates, name="生长速率",
        marker_color='green'), row=2, col=2)
    
    fig2.add_trace(go.Bar(
        x=microbes, y=resistances, name="抗性",
        marker_color='purple'), row=2, col=2)
    
    fig2.update_layout(
        height=800,
        title_text="环境与微生物特性综合分析",
        showlegend=True
    )
    
    st.plotly_chart(fig2, use_container_width=True)

with tab3:
    # === 图3:消杀方法对比矩阵 ===
    st.subheader("消杀方法综合能力评估")
    
    # 准备雷达图数据
    categories = ['效率', '安全性', '成本效益', '环境适应性', '抗性覆盖']
    
    radar_data = []
    for method in DISINFECTION_METHODS:
        params = DISINFECTION_METHODS[method]
        
        # 评估维度(0-1)
        efficiency = params["efficiency"]["地球"] * 1.2  # 效率权重较高
        safety = 0.9 if params["safety"] == "安全" else 0.5
        cost_effect = 0.8 if params["cost"] == "低" else 0.5
        env_adapt = 0.85 if environment == "地球环境" else 0.7
        resist_cover = 0.9 - min(params["efficiency"]["地球"], 0.3)  # 效率越低,抗性覆盖越差
        
        values = [efficiency, safety, cost_effect, env_adapt, resist_cover]
        
        radar_data.append(go.Scatterpolar(
            r=values,
            theta=categories,
            fill='toself',
            name=method
        ))
    
    fig3 = go.Figure(data=radar_data)
    fig3.update_layout(
        polar=dict(
            radialaxis=dict(
                visible=True,
                range=[0, 1.2]
            )),
        showlegend=True,
        title="消杀方法能力雷达图",
        height=600
    )
    
    st.plotly_chart(fig3, use_container_width=True)
    
    # 添加方法详情卡片
    cols = st.columns(2)
    for i, method in enumerate(selected_methods):
        with cols[i % 2]:
            params = DISINFECTION_METHODS[method]
            eff_earth = params["efficiency"]["地球"] * 100
            eff_space = params["efficiency"]["太空"] * 100
            
            st.markdown(f"### {method}")
            st.metric("地球环境效率", f"{eff_earth:.1f}%")
            st.metric("太空环境效率", f"{eff_space:.1f}%")
            st.markdown(f"**限制**: {params['limitations']}")
            st.markdown(f"**安全性**: {params['safety']}")
            st.markdown(f"**成本**: {params['cost']}")

# ===== 安全评估 =====
st.divider()
st.header("环境安全评估")
space_std = 1000  # 空间站安全标准 (CFU/m³)

# 当前选择的消杀方案评估
cols = st.columns(len(selected_methods)+1)

with cols[0]:
    st.metric("无消杀峰值浓度", f"{max(growth_curve):.0f} CFU/m³", 
              delta=f"超出安全线{(max(growth_curve)/space_std-1)*100:.0f}%" if max(growth_curve) > space_std else "安全范围内",
              delta_color="inverse")

for i, method in enumerate(selected_methods):
    disinfection_eff = disinfection_efficiency(method, exposure_time, microbe_params, env_params)
    post_disinfection = growth_curve.copy()
    post_disinfection[disinfection_idx:] = (
        growth_curve[disinfection_idx] * (1 - disinfection_eff) * 
        np.exp(growth_rate_val * (hours[disinfection_idx:] - hours[disinfection_idx]))
    )
    peak_concentration = max(post_disinfection)
    
    with cols[i+1]:
        st.metric(
            f"{method}峰值", 
            f"{peak_concentration:.0f} CFU/m³", 
            delta=f"效率: {disinfection_eff*100:.1f}%",
            delta_color="normal"
        )
        st.progress(disinfection_eff, text=f"消杀效率")

# === 方法推荐系统 ===
st.subheader("环境优化方案推荐")
if environment == "太空环境":
    st.warning("太空环境注意事项:")
    st.markdown("""
    - 优先考虑气态消杀方法(等离子体、臭氧)
    - 避免使用液体消毒剂(湿巾)
    - 考虑辐射增强消杀效果
    - 注意微重力对液体分布的影响
    """)
    recommended_methods = ["气体等离子体", "臭氧(O₃)", "超临界CO₂"]
else:
    st.success("地球环境建议:")
    st.markdown("""
    - 可使用液体消毒剂(湿巾、过氧化氢溶液)
    - 组合使用物理和化学方法
    - 考虑经济性和安全性平衡
    """)
    recommended_methods = ["过氧化氢蒸汽", "紫外线照射(254nm)", "季铵盐湿巾"]

st.markdown(f"**推荐消杀方法**: {', '.join(recommended_methods)}")


网站公告

今日签到

点亮在社区的每一天
去签到