Compare commits

..

No commits in common. "75e1dcb0ebd8a2a4d7be28b32747051231203f5f" and "93a6f8654d5d70984d9ff0da66fe3f5b4a7f9975" have entirely different histories.

16 changed files with 5 additions and 2776 deletions

View File

@ -68,11 +68,6 @@ clean_data: requirements
data: requirements
$(PYTHON_INTERPRETER) scripts/process_data.py
## Process dataset for final training (interim -> processed/final, train:val=9:1, no test)
.PHONY: data_final
data_final: requirements
$(PYTHON_INTERPRETER) scripts/process_data_final.py
## Process external data for pretrain (external -> processed)
.PHONY: data_pretrain
data_pretrain: requirements
@ -133,16 +128,6 @@ train: requirements
finetune: requirements
$(PYTHON_INTERPRETER) -m lnp_ml.modeling.train --init-from-pretrain models/pretrain_delivery.pt $(FREEZE_FLAG) $(MPNN_FLAG) $(DEVICE_FLAG)
## Final training using all data (train:val=9:1, no test set), with pretrained weights
.PHONY: train_final
train_final: requirements
$(PYTHON_INTERPRETER) -m lnp_ml.modeling.train \
--train-path data/processed/final/train.parquet \
--val-path data/processed/final/val.parquet \
--output-dir models/final \
--init-from-pretrain models/pretrain_delivery.pt \
$(FREEZE_FLAG) $(MPNN_FLAG) $(DEVICE_FLAG)
## Finetune with cross-validation on internal data (5-fold, amine-based split) with pretrained weights
.PHONY: finetune_cv
finetune_cv: requirements
@ -174,31 +159,6 @@ predict: requirements
test: requirements
$(PYTHON_INTERPRETER) -m lnp_ml.modeling.predict test $(DEVICE_FLAG)
## Formulation optimization: find optimal LNP formulation for target organ
## Usage: make optimize SMILES="CC(C)..." ORGAN=liver
.PHONY: optimize
optimize: requirements
$(PYTHON_INTERPRETER) -m app.optimize --smiles "$(SMILES)" --organ $(ORGAN) $(DEVICE_FLAG)
## Start FastAPI backend server (port 8000)
.PHONY: api
api: requirements
uvicorn app.api:app --host 0.0.0.0 --port 8000 --reload
## Start Streamlit frontend app (port 8501)
.PHONY: webapp
webapp: requirements
streamlit run app/app.py --server.port 8501
## Start both API and webapp (run in separate terminals)
.PHONY: serve
serve:
@echo "请在两个终端分别运行:"
@echo " 终端 1: make api"
@echo " 终端 2: make webapp"
@echo ""
@echo "然后访问: http://localhost:8501"
#################################################################################
# Self Documenting Commands #

View File

@ -156,12 +156,5 @@ python -m lnp_ml.modeling.train \
└── plots.py <- Code to create visualizations
```
### 配方筛选
```
make optimize SMILES="CC(C)NCCNC(C)C" ORGAN=liver
```
--------

View File

@ -1,62 +0,0 @@
## Possible Values
# comp token([B, 5], the sum of the latter four ratio is always 1)
Cationic_Lipid_to_mRNA_weight_ratio(float, Min: 0.05, Max: 0.3, Step Size: 0.01)
Cationic_Lipid_Mol_Ratio(float, Min: 0.05, Max: 0.8, Step Size: 0.01)
Phospholipid_Mol_Ratio(float, Min: 0, Max: 0.8, Step Size: 0.01)
Cholesterol_Mol_Ratio(float, Min: 0, Max: 0.8, Step Size: 0.01)
PEG_Lipid_Mol_Ratio(float, Min: 0, Max: 0.05, Step Size: 0.01)
# phys token([B, 12])
Purity_Pure(one-hot for Purity, always Pure)
Purity_Crude(one-hot for Purity, always Pure)
Mix_type_Microfluidic(one-hot for Mix_type, always Microfluidic)
Mix_type_Microfluidic(one-hot for Mix_type, always Microfluidic)
Cargo_type_mRNA(one-hot for Cargo_type, always mRNA)
Cargo_type_pDNA(one-hot for Cargo_type, always mRNA)
Cargo_type_siRNA(one-hot for Cargo_type, always mRNA)
Target_or_delivered_gene_FFL(one-hot for Target_or_delivered_gene, always FFL)
Target_or_delivered_gene_Peptide_barcode(one-hot for Target_or_delivered_gene, always FFL)
Target_or_delivered_gene_hEPO(one-hot for Target_or_delivered_gene, always FFL)
Target_or_delivered_gene_FVII(one-hot for Target_or_delivered_gene, always FFL)
Target_or_delivered_gene_GFP(one-hot for Target_or_delivered_gene, always FFL)
# help token([B, 4])
Helper_lipid_ID_DOPE(one-hot for Helper_lipid_ID, one of {DOPE, DSPC, DOTAP})
Helper_lipid_ID_DOTAP(one-hot for Helper_lipid_ID, one of {DOPE, DSPC, DOTAP})
Helper_lipid_ID_DSPC(one-hot for Helper_lipid_ID, one of {DOPE, DSPC, DOTAP})
Helper_lipid_ID_MDOA(one-hot for Helper_lipid_ID, one of {DOPE, DSPC, DOTAP})
# exp token([B, 32])
Model_type_A549(one-hot for Model_type, always Mouse)
Model_type_BDMC(one-hot for Model_type, always Mouse)
Model_type_BMDM(one-hot for Model_type, always Mouse)
Model_type_HBEC_ALI(one-hot for Model_type, always Mouse)
Model_type_HEK293T(one-hot for Model_type, always Mouse)
Model_type_HeLa(one-hot for Model_type, always Mouse)
Model_type_IGROV1(one-hot for Model_type, always Mouse)
Model_type_Mouse(one-hot for Model_type, always Mouse)
Model_type_RAW264p7(one-hot for Model_type, always Mouse)
Delivery_target_dendritic_cell(one-hot for Delivery_target, always body)
Delivery_target_generic_cell(one-hot for Delivery_target, always body)
Delivery_target_liver(one-hot for Delivery_target, always body)
Delivery_target_lung(one-hot for Delivery_target, always body)
Delivery_target_lung_epithelium(one-hot for Delivery_target, always body)
Delivery_target_macrophage(one-hot for Delivery_target, always body)
Delivery_target_muscle(one-hot for Delivery_target, always body)
Delivery_target_spleen(one-hot for Delivery_target, always body)
Delivery_target_body(one-hot for Delivery_target, always body)
Route_of_administration_in_vitro(one-hot for Route_of_administration, one of {Intravenous, Intramuscular})
Route_of_administration_intravenous(one-hot for Route_of_administration, one of {Intravenous, Intramuscular})
Route_of_administration_intramuscular(one-hot for Route_of_administration, one of {Intravenous, Intramuscular})
Route_of_administration_intratracheal(one-hot for Route_of_administration, one of {Intravenous, Intramuscular})
Sample_organization_type_individual(one-hot for Sample_organization_type, always Individual)
Sample_organization_type_barcoded(one-hot for Sample_organization_type, always Individual)
Value_name_log_luminescence(one-hot for Value_name, always luminescence)
Value_name_luminescence(one-hot for Value_name, always luminescence)
Value_name_FFL_silencing(one-hot for Value_name, always luminescence)
Value_name_Peptide_abundance(one-hot for Value_name, always luminescence)
Value_name_hEPO(one-hot for Value_name, always luminescence)
Value_name_FVII_silencing(one-hot for Value_name, always luminescence)
Value_name_GFP_delivery(one-hot for Value_name, always luminescence)
Value_name_Discretized_luminescence(one-hot for Value_name, always luminescence)

View File

@ -1,2 +0,0 @@
"""LNP 配方优化应用"""

View File

@ -1,244 +0,0 @@
"""
FastAPI 配方优化 API
启动服务:
uvicorn app.api:app --host 0.0.0.0 --port 8000 --reload
"""
import os
from pathlib import Path
from typing import List, Dict, Optional
from contextlib import asynccontextmanager
import torch
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
from loguru import logger
from lnp_ml.config import MODELS_DIR
from lnp_ml.modeling.predict import load_model
from app.optimize import (
optimize,
format_results,
AVAILABLE_ORGANS,
TARGET_BIODIST,
)
# ============ Pydantic Models ============
class OptimizeRequest(BaseModel):
"""优化请求"""
smiles: str = Field(..., description="Cationic lipid SMILES string")
organ: str = Field(..., description="Target organ for optimization")
top_k: int = Field(default=20, ge=1, le=100, description="Number of top formulations")
class Config:
json_schema_extra = {
"example": {
"smiles": "CC(C)NCCNC(C)C",
"organ": "liver",
"top_k": 20
}
}
class FormulationResult(BaseModel):
"""单个配方结果"""
rank: int
target_biodist: float
cationic_lipid_to_mrna_ratio: float
cationic_lipid_mol_ratio: float
phospholipid_mol_ratio: float
cholesterol_mol_ratio: float
peg_lipid_mol_ratio: float
helper_lipid: str
route: str
all_biodist: Dict[str, float]
class OptimizeResponse(BaseModel):
"""优化响应"""
smiles: str
target_organ: str
formulations: List[FormulationResult]
message: str
class HealthResponse(BaseModel):
"""健康检查响应"""
status: str
model_loaded: bool
device: str
available_organs: List[str]
# ============ Global State ============
class ModelState:
"""模型状态管理"""
model = None
device = None
model_path = None
state = ModelState()
# ============ Lifespan ============
@asynccontextmanager
async def lifespan(app: FastAPI):
"""应用生命周期管理:启动时加载模型"""
# Startup
logger.info("Starting API server...")
# 确定设备
if torch.cuda.is_available():
device_str = "cuda"
elif hasattr(torch.backends, "mps") and torch.backends.mps.is_available():
device_str = "mps"
else:
device_str = "cpu"
# 可通过环境变量覆盖
device_str = os.environ.get("DEVICE", device_str)
state.device = torch.device(device_str)
logger.info(f"Using device: {state.device}")
# 加载模型
model_path = Path(os.environ.get("MODEL_PATH", MODELS_DIR / "final" / "model.pt"))
state.model_path = model_path
logger.info(f"Loading model from {model_path}...")
try:
state.model = load_model(model_path, state.device)
logger.success("Model loaded successfully!")
except Exception as e:
logger.error(f"Failed to load model: {e}")
raise
yield
# Shutdown
logger.info("Shutting down API server...")
state.model = None
torch.cuda.empty_cache() if torch.cuda.is_available() else None
# ============ FastAPI App ============
app = FastAPI(
title="LNP 配方优化 API",
description="基于深度学习的 LNP 纳米颗粒配方优化服务",
version="1.0.0",
lifespan=lifespan,
)
# CORS 配置
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# ============ Endpoints ============
@app.get("/", response_model=HealthResponse)
async def health_check():
"""健康检查"""
return HealthResponse(
status="healthy" if state.model is not None else "model_not_loaded",
model_loaded=state.model is not None,
device=str(state.device),
available_organs=AVAILABLE_ORGANS,
)
@app.get("/organs", response_model=List[str])
async def get_available_organs():
"""获取可用的目标器官列表"""
return AVAILABLE_ORGANS
@app.post("/optimize", response_model=OptimizeResponse)
async def optimize_formulation(request: OptimizeRequest):
"""
执行配方优化
通过迭代式 Grid Search 寻找最大化目标器官 Biodistribution 的最优配方
"""
# 验证模型状态
if state.model is None:
raise HTTPException(status_code=503, detail="Model not loaded")
# 验证器官
if request.organ not in AVAILABLE_ORGANS:
raise HTTPException(
status_code=400,
detail=f"Invalid organ: {request.organ}. Available: {AVAILABLE_ORGANS}"
)
# 验证 SMILES
if not request.smiles or len(request.smiles.strip()) == 0:
raise HTTPException(status_code=400, detail="SMILES string cannot be empty")
logger.info(f"Optimization request: organ={request.organ}, smiles={request.smiles[:50]}...")
try:
# 执行优化
results = optimize(
smiles=request.smiles,
organ=request.organ,
model=state.model,
device=state.device,
top_k=request.top_k,
batch_size=256,
)
# 转换结果
formulations = []
for i, f in enumerate(results):
formulations.append(FormulationResult(
rank=i + 1,
target_biodist=f.get_biodist(request.organ),
cationic_lipid_to_mrna_ratio=f.cationic_lipid_to_mrna_ratio,
cationic_lipid_mol_ratio=f.cationic_lipid_mol_ratio,
phospholipid_mol_ratio=f.phospholipid_mol_ratio,
cholesterol_mol_ratio=f.cholesterol_mol_ratio,
peg_lipid_mol_ratio=f.peg_lipid_mol_ratio,
helper_lipid=f.helper_lipid,
route=f.route,
all_biodist={
col.replace("Biodistribution_", ""): f.biodist_predictions.get(col, 0.0)
for col in TARGET_BIODIST
},
))
logger.success(f"Optimization completed: {len(formulations)} formulations")
return OptimizeResponse(
smiles=request.smiles,
target_organ=request.organ,
formulations=formulations,
message=f"Successfully found top {len(formulations)} formulations for {request.organ}",
)
except Exception as e:
logger.error(f"Optimization failed: {e}")
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"app.api:app",
host="0.0.0.0",
port=8000,
reload=True,
)

View File

@ -1,395 +0,0 @@
"""
Streamlit 配方优化交互界面
启动应用:
streamlit run app/app.py
"""
import io
from datetime import datetime
import httpx
import pandas as pd
import streamlit as st
# ============ 配置 ============
API_URL = "http://localhost:8000"
AVAILABLE_ORGANS = [
"liver",
"spleen",
"lung",
"heart",
"kidney",
"muscle",
"lymph_nodes",
]
ORGAN_LABELS = {
"liver": "🫀 肝脏 (Liver)",
"spleen": "🟣 脾脏 (Spleen)",
"lung": "🫁 肺 (Lung)",
"heart": "❤️ 心脏 (Heart)",
"kidney": "🫘 肾脏 (Kidney)",
"muscle": "💪 肌肉 (Muscle)",
"lymph_nodes": "🔵 淋巴结 (Lymph Nodes)",
}
# ============ 页面配置 ============
st.set_page_config(
page_title="LNP 配方优化",
page_icon="🧬",
layout="wide",
initial_sidebar_state="expanded",
)
# ============ 自定义样式 ============
st.markdown("""
<style>
/* 主标题样式 */
.main-title {
font-size: 2.5rem;
font-weight: 700;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-align: center;
margin-bottom: 0.5rem;
}
/* 副标题样式 */
.sub-title {
font-size: 1.1rem;
color: #6c757d;
text-align: center;
margin-bottom: 2rem;
}
/* 结果卡片 */
.result-card {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1rem;
}
/* 指标高亮 */
.metric-highlight {
font-size: 2rem;
font-weight: 700;
color: #667eea;
}
/* 侧边栏样式 */
.sidebar-section {
background: #f8f9fa;
border-radius: 8px;
padding: 1rem;
margin-bottom: 1rem;
}
/* 状态指示器 */
.status-online {
color: #28a745;
font-weight: 600;
}
.status-offline {
color: #dc3545;
font-weight: 600;
}
/* 表格样式优化 */
.dataframe {
font-size: 0.85rem;
}
</style>
""", unsafe_allow_html=True)
# ============ 辅助函数 ============
def check_api_status() -> bool:
"""检查 API 状态"""
try:
with httpx.Client(timeout=5) as client:
response = client.get(f"{API_URL}/")
return response.status_code == 200
except:
return False
def call_optimize_api(smiles: str, organ: str, top_k: int = 20) -> dict:
"""调用优化 API"""
with httpx.Client(timeout=300) as client: # 5 分钟超时
response = client.post(
f"{API_URL}/optimize",
json={
"smiles": smiles,
"organ": organ,
"top_k": top_k,
},
)
response.raise_for_status()
return response.json()
def format_results_dataframe(results: dict) -> pd.DataFrame:
"""将 API 结果转换为 DataFrame"""
formulations = results["formulations"]
target_organ = results["target_organ"]
rows = []
for f in formulations:
row = {
"排名": f["rank"],
f"Biodist_{target_organ}": f"{f['target_biodist']:.4f}",
"阳离子脂质/mRNA": f["cationic_lipid_to_mrna_ratio"],
"阳离子脂质(mol)": f["cationic_lipid_mol_ratio"],
"磷脂(mol)": f["phospholipid_mol_ratio"],
"胆固醇(mol)": f["cholesterol_mol_ratio"],
"PEG脂质(mol)": f["peg_lipid_mol_ratio"],
"辅助脂质": f["helper_lipid"],
"给药途径": f["route"],
}
# 添加其他器官的 biodist
for organ, value in f["all_biodist"].items():
if organ != target_organ:
row[f"Biodist_{organ}"] = f"{value:.4f}"
rows.append(row)
return pd.DataFrame(rows)
def create_export_csv(df: pd.DataFrame, smiles: str, organ: str) -> str:
"""创建导出用的 CSV 内容"""
# 添加元信息
meta_info = f"# LNP 配方优化结果\n# SMILES: {smiles}\n# 目标器官: {organ}\n# 导出时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
csv_content = df.to_csv(index=False)
return meta_info + csv_content
# ============ 主界面 ============
def main():
# 标题
st.markdown('<h1 class="main-title">🧬 LNP 配方优化系统</h1>', unsafe_allow_html=True)
st.markdown('<p class="sub-title">基于深度学习的脂质纳米颗粒配方智能优选</p>', unsafe_allow_html=True)
# 检查 API 状态
api_online = check_api_status()
# ========== 侧边栏 ==========
with st.sidebar:
st.header("⚙️ 参数设置")
# API 状态
if api_online:
st.success("🟢 API 服务在线")
else:
st.error("🔴 API 服务离线")
st.info("请先启动 API 服务:\n```\nuvicorn app.api:app --port 8000\n```")
st.divider()
# SMILES 输入
st.subheader("🔬 分子结构")
smiles_input = st.text_area(
"输入阳离子脂质 SMILES",
value="",
height=100,
placeholder="例如: CC(C)NCCNC(C)C",
help="输入阳离子脂质的 SMILES 字符串",
)
# 示例 SMILES
with st.expander("📋 示例 SMILES"):
example_smiles = {
"DLin-MC3-DMA": "CC(C)=CCCC(C)=CCCC(C)=CCN(C)CCCCCCCCOC(=O)CCCCCCC/C=C\\CCCCCCCC",
"简单胺": "CC(C)NCCNC(C)C",
"长链胺": "CCCCCCCCCCCCNCCNCCCCCCCCCCCC",
}
for name, smi in example_smiles.items():
if st.button(f"使用 {name}", key=f"example_{name}"):
st.session_state["smiles_input"] = smi
st.rerun()
st.divider()
# 目标器官选择
st.subheader("🎯 目标器官")
selected_organ = st.selectbox(
"选择优化目标器官",
options=AVAILABLE_ORGANS,
format_func=lambda x: ORGAN_LABELS.get(x, x),
index=0,
)
st.divider()
# 高级选项
with st.expander("🔧 高级选项"):
top_k = st.slider(
"返回配方数量",
min_value=5,
max_value=50,
value=20,
step=5,
)
st.divider()
# 优化按钮
optimize_button = st.button(
"🚀 开始配方优选",
type="primary",
use_container_width=True,
disabled=not api_online or not smiles_input.strip(),
)
# ========== 主内容区 ==========
# 使用 session state 存储结果
if "results" not in st.session_state:
st.session_state["results"] = None
if "results_df" not in st.session_state:
st.session_state["results_df"] = None
# 执行优化
if optimize_button and smiles_input.strip():
with st.spinner("🔄 正在优化配方,请稍候..."):
try:
results = call_optimize_api(
smiles=smiles_input.strip(),
organ=selected_organ,
top_k=top_k,
)
st.session_state["results"] = results
st.session_state["results_df"] = format_results_dataframe(results)
st.session_state["smiles_used"] = smiles_input.strip()
st.session_state["organ_used"] = selected_organ
st.success("✅ 优化完成!")
except httpx.RequestError as e:
st.error(f"❌ API 请求失败: {e}")
except Exception as e:
st.error(f"❌ 发生错误: {e}")
# 显示结果
if st.session_state["results"] is not None:
results = st.session_state["results"]
df = st.session_state["results_df"]
# 结果概览
col1, col2, col3 = st.columns(3)
with col1:
st.metric(
"目标器官",
ORGAN_LABELS.get(results["target_organ"], results["target_organ"]).split(" ")[0],
)
with col2:
best_score = results["formulations"][0]["target_biodist"]
st.metric(
"最优 Biodistribution",
f"{best_score:.4f}",
)
with col3:
st.metric(
"优选配方数",
len(results["formulations"]),
)
st.divider()
# 结果表格
st.subheader("📊 优选配方列表")
# 导出按钮行
col_export, col_spacer = st.columns([1, 4])
with col_export:
csv_content = create_export_csv(
df,
st.session_state.get("smiles_used", ""),
st.session_state.get("organ_used", ""),
)
st.download_button(
label="📥 导出 CSV",
data=csv_content,
file_name=f"lnp_optimization_{results['target_organ']}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
mime="text/csv",
)
# 显示表格
st.dataframe(
df,
use_container_width=True,
hide_index=True,
height=600,
)
# 详细信息
with st.expander("🔍 查看最优配方详情"):
best = results["formulations"][0]
col1, col2 = st.columns(2)
with col1:
st.markdown("**配方参数**")
st.json({
"阳离子脂质/mRNA 比例": best["cationic_lipid_to_mrna_ratio"],
"阳离子脂质 (mol%)": best["cationic_lipid_mol_ratio"],
"磷脂 (mol%)": best["phospholipid_mol_ratio"],
"胆固醇 (mol%)": best["cholesterol_mol_ratio"],
"PEG 脂质 (mol%)": best["peg_lipid_mol_ratio"],
"辅助脂质": best["helper_lipid"],
"给药途径": best["route"],
})
with col2:
st.markdown("**各器官 Biodistribution 预测**")
biodist_df = pd.DataFrame([
{"器官": ORGAN_LABELS.get(k, k), "Biodistribution": f"{v:.4f}"}
for k, v in best["all_biodist"].items()
])
st.dataframe(biodist_df, hide_index=True, use_container_width=True)
else:
# 欢迎信息
st.info("👈 请在左侧输入 SMILES 并选择目标器官,然后点击「开始配方优选」")
# 使用说明
with st.expander("📖 使用说明"):
st.markdown("""
### 如何使用
1. **输入 SMILES**: 在左侧输入框中输入阳离子脂质的 SMILES 字符串
2. **选择目标器官**: 选择您希望优化的器官靶向
3. **点击优选**: 系统将自动搜索最优配方组合
4. **查看结果**: 右侧将显示 Top-20 优选配方
5. **导出数据**: 点击导出按钮将结果保存为 CSV 文件
### 优化参数
系统会优化以下配方参数:
- **阳离子脂质/mRNA 比例**: 0.05 - 0.30
- **阳离子脂质 mol 比例**: 0.05 - 0.80
- **磷脂 mol 比例**: 0.00 - 0.80
- **胆固醇 mol 比例**: 0.00 - 0.80
- **PEG 脂质 mol 比例**: 0.00 - 0.05
- **辅助脂质**: DOPE / DSPC / DOTAP
- **给药途径**: 静脉注射 / 肌肉注射
### 约束条件
mol 比例之和 = 1 (阳离子脂质 + 磷脂 + 胆固醇 + PEG 脂质)
""")
if __name__ == "__main__":
main()

View File

@ -1,532 +0,0 @@
"""
配方优化模拟程序
通过迭代式 Grid Search 寻找最优 LNP 配方最大化目标器官的 Biodistribution
使用方法:
python -m app.optimize --smiles "CC(C)..." --organ liver
"""
import itertools
from pathlib import Path
from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass, field
import numpy as np
import pandas as pd
import torch
from torch.utils.data import DataLoader
from loguru import logger
from tqdm import tqdm
import typer
from lnp_ml.config import MODELS_DIR
from lnp_ml.dataset import (
LNPDataset,
LNPDatasetConfig,
collate_fn,
SMILES_COL,
COMP_COLS,
HELP_COLS,
TARGET_BIODIST,
get_phys_cols,
get_exp_cols,
)
from lnp_ml.modeling.predict import load_model
app = typer.Typer()
# ============ 参数配置 ============
# 可用的目标器官
AVAILABLE_ORGANS = ["lymph_nodes", "heart", "liver", "spleen", "lung", "kidney", "muscle"]
# comp token 参数范围
COMP_PARAM_RANGES = {
"Cationic_Lipid_to_mRNA_weight_ratio": (0.05, 0.30),
"Cationic_Lipid_Mol_Ratio": (0.05, 0.80),
"Phospholipid_Mol_Ratio": (0.00, 0.80),
"Cholesterol_Mol_Ratio": (0.00, 0.80),
"PEG_Lipid_Mol_Ratio": (0.00, 0.05),
}
# 最小 step size
MIN_STEP_SIZE = 0.01
# 迭代策略:每个迭代的 step_size
ITERATION_STEP_SIZES = [0.10, 0.02, 0.01]
# Helper lipid 选项
HELPER_LIPID_OPTIONS = ["DOPE", "DSPC", "DOTAP"]
# Route of administration 选项
ROUTE_OPTIONS = ["intravenous", "intramuscular"]
@dataclass
class Formulation:
"""配方数据结构"""
# comp token
cationic_lipid_to_mrna_ratio: float
cationic_lipid_mol_ratio: float
phospholipid_mol_ratio: float
cholesterol_mol_ratio: float
peg_lipid_mol_ratio: float
# 离散选项
helper_lipid: str = "DOPE"
route: str = "intravenous"
# 预测结果(填充后)
biodist_predictions: Dict[str, float] = field(default_factory=dict)
def to_dict(self) -> Dict:
"""转换为字典"""
return {
"Cationic_Lipid_to_mRNA_weight_ratio": self.cationic_lipid_to_mrna_ratio,
"Cationic_Lipid_Mol_Ratio": self.cationic_lipid_mol_ratio,
"Phospholipid_Mol_Ratio": self.phospholipid_mol_ratio,
"Cholesterol_Mol_Ratio": self.cholesterol_mol_ratio,
"PEG_Lipid_Mol_Ratio": self.peg_lipid_mol_ratio,
"helper_lipid": self.helper_lipid,
"route": self.route,
}
def get_biodist(self, organ: str) -> float:
"""获取指定器官的 biodistribution 预测值"""
col = f"Biodistribution_{organ}"
return self.biodist_predictions.get(col, 0.0)
def generate_grid_values(
center: float,
step_size: float,
min_val: float,
max_val: float,
radius: int = 2,
) -> List[float]:
"""
围绕中心点生成网格值
Args:
center: 中心值
step_size: 步长
min_val: 最小值
max_val: 最大值
radius: 扩展半径生成 2*radius+1 个点
Returns:
网格值列表
"""
values = []
for i in range(-radius, radius + 1):
val = center + i * step_size
if min_val <= val <= max_val:
values.append(round(val, 4))
return sorted(set(values))
def generate_initial_grid(step_size: float) -> List[Tuple[float, float, float, float, float]]:
"""
生成初始搜索网格满足 mol ratio 和为 1 的约束
Returns:
List of (cationic_ratio, cationic_mol, phospholipid_mol, cholesterol_mol, peg_mol)
"""
grid = []
# Cationic_Lipid_to_mRNA_weight_ratio
weight_ratios = np.arange(0.05, 0.31, step_size)
# PEG: 单独处理,范围很小
peg_values = np.arange(0.00, 0.06, MIN_STEP_SIZE) # PEG 始终用 0.01 步长
# 其他三个 mol ratio 需要满足和为 1 - PEG
mol_step = step_size
for weight_ratio in weight_ratios:
for peg in peg_values:
remaining = 1.0 - peg
# 生成满足约束的组合
for cationic_mol in np.arange(0.05, min(0.81, remaining + 0.001), mol_step):
for phospholipid_mol in np.arange(0.00, min(0.81, remaining - cationic_mol + 0.001), mol_step):
cholesterol_mol = remaining - cationic_mol - phospholipid_mol
# 检查约束
if 0.00 <= cholesterol_mol <= 0.80:
grid.append((
round(weight_ratio, 4),
round(cationic_mol, 4),
round(phospholipid_mol, 4),
round(cholesterol_mol, 4),
round(peg, 4),
))
return grid
def generate_refined_grid(
seeds: List[Formulation],
step_size: float,
radius: int = 2,
) -> List[Tuple[float, float, float, float, float]]:
"""
围绕种子点生成精细化网格
Args:
seeds: 种子配方列表
step_size: 步长
radius: 扩展半径
Returns:
新的网格点列表
"""
grid_set = set()
for seed in seeds:
# Weight ratio
weight_ratios = generate_grid_values(
seed.cationic_lipid_to_mrna_ratio, step_size, 0.05, 0.30, radius
)
# PEG (始终用最小步长)
peg_values = generate_grid_values(
seed.peg_lipid_mol_ratio, MIN_STEP_SIZE, 0.00, 0.05, radius
)
# Mol ratios
cationic_mols = generate_grid_values(
seed.cationic_lipid_mol_ratio, step_size, 0.05, 0.80, radius
)
phospholipid_mols = generate_grid_values(
seed.phospholipid_mol_ratio, step_size, 0.00, 0.80, radius
)
for weight_ratio in weight_ratios:
for peg in peg_values:
remaining = 1.0 - peg
for cationic_mol in cationic_mols:
for phospholipid_mol in phospholipid_mols:
cholesterol_mol = remaining - cationic_mol - phospholipid_mol
# 检查约束
if (0.05 <= cationic_mol <= 0.80 and
0.00 <= phospholipid_mol <= 0.80 and
0.00 <= cholesterol_mol <= 0.80 and
0.00 <= peg <= 0.05):
grid_set.add((
round(weight_ratio, 4),
round(cationic_mol, 4),
round(phospholipid_mol, 4),
round(cholesterol_mol, 4),
round(peg, 4),
))
return list(grid_set)
def create_dataframe_from_formulations(
smiles: str,
grid: List[Tuple[float, float, float, float, float]],
helper_lipids: List[str],
routes: List[str],
) -> pd.DataFrame:
"""
从配方网格创建 DataFrame
使用固定的 phys tokenPure, Microfluidic, mRNA, FFL exp tokenMouse, body, luminescence
"""
rows = []
for comp_values in grid:
for helper in helper_lipids:
for route in routes:
row = {
SMILES_COL: smiles,
# comp token
"Cationic_Lipid_to_mRNA_weight_ratio": comp_values[0],
"Cationic_Lipid_Mol_Ratio": comp_values[1],
"Phospholipid_Mol_Ratio": comp_values[2],
"Cholesterol_Mol_Ratio": comp_values[3],
"PEG_Lipid_Mol_Ratio": comp_values[4],
# phys token (固定值)
"Purity_Pure": 1.0,
"Purity_Crude": 0.0,
"Mix_type_Microfluidic": 1.0,
"Mix_type_Pipetting": 0.0,
"Cargo_type_mRNA": 1.0,
"Cargo_type_pDNA": 0.0,
"Cargo_type_siRNA": 0.0,
"Target_or_delivered_gene_FFL": 1.0,
"Target_or_delivered_gene_Peptide_barcode": 0.0,
"Target_or_delivered_gene_hEPO": 0.0,
"Target_or_delivered_gene_FVII": 0.0,
"Target_or_delivered_gene_GFP": 0.0,
# help token
"Helper_lipid_ID_DOPE": 1.0 if helper == "DOPE" else 0.0,
"Helper_lipid_ID_DOTAP": 1.0 if helper == "DOTAP" else 0.0,
"Helper_lipid_ID_DSPC": 1.0 if helper == "DSPC" else 0.0,
"Helper_lipid_ID_MDOA": 0.0, # 不使用
# exp token (固定值)
"Model_type_Mouse": 1.0,
"Delivery_target_body": 1.0,
f"Route_of_administration_{route}": 1.0,
"Batch_or_individual_or_barcoded_Individual": 1.0,
"Value_name_luminescence": 1.0,
# 存储配方元信息
"_helper_lipid": helper,
"_route": route,
}
# 其他 exp token 默认为 0
for col in get_exp_cols():
if col not in row:
row[col] = 0.0
rows.append(row)
return pd.DataFrame(rows)
def predict_biodist(
model: torch.nn.Module,
df: pd.DataFrame,
device: torch.device,
batch_size: int = 256,
) -> pd.DataFrame:
"""
使用模型预测 biodistribution
Returns:
添加了预测列的 DataFrame
"""
dataset = LNPDataset(df)
dataloader = DataLoader(
dataset, batch_size=batch_size, shuffle=False, collate_fn=collate_fn
)
all_biodist_preds = []
with torch.no_grad():
for batch in dataloader:
smiles = batch["smiles"]
tabular = {k: v.to(device) for k, v in batch["tabular"].items()}
outputs = model(smiles, tabular)
# biodist 输出是 softmax 后的概率分布 [B, 7]
biodist_pred = outputs["biodist"].cpu().numpy()
all_biodist_preds.append(biodist_pred)
biodist_preds = np.concatenate(all_biodist_preds, axis=0)
# 添加到 DataFrame
for i, col in enumerate(TARGET_BIODIST):
df[f"pred_{col}"] = biodist_preds[:, i]
return df
def select_top_k(
df: pd.DataFrame,
organ: str,
k: int = 20,
) -> List[Formulation]:
"""
选择 top-k 配方
Args:
df: 包含预测结果的 DataFrame
organ: 目标器官
k: 选择数量
Returns:
Top-k 配方列表
"""
pred_col = f"pred_Biodistribution_{organ}"
if pred_col not in df.columns:
raise ValueError(f"Prediction column {pred_col} not found")
# 排序并去重
df_sorted = df.sort_values(pred_col, ascending=False)
# 创建配方对象
formulations = []
seen = set()
for _, row in df_sorted.iterrows():
key = (
row["Cationic_Lipid_to_mRNA_weight_ratio"],
row["Cationic_Lipid_Mol_Ratio"],
row["Phospholipid_Mol_Ratio"],
row["Cholesterol_Mol_Ratio"],
row["PEG_Lipid_Mol_Ratio"],
row["_helper_lipid"],
row["_route"],
)
if key not in seen:
seen.add(key)
formulation = Formulation(
cationic_lipid_to_mrna_ratio=row["Cationic_Lipid_to_mRNA_weight_ratio"],
cationic_lipid_mol_ratio=row["Cationic_Lipid_Mol_Ratio"],
phospholipid_mol_ratio=row["Phospholipid_Mol_Ratio"],
cholesterol_mol_ratio=row["Cholesterol_Mol_Ratio"],
peg_lipid_mol_ratio=row["PEG_Lipid_Mol_Ratio"],
helper_lipid=row["_helper_lipid"],
route=row["_route"],
biodist_predictions={
col: row[f"pred_{col}"] for col in TARGET_BIODIST
},
)
formulations.append(formulation)
if len(formulations) >= k:
break
return formulations
def optimize(
smiles: str,
organ: str,
model: torch.nn.Module,
device: torch.device,
top_k: int = 20,
batch_size: int = 256,
) -> List[Formulation]:
"""
执行配方优化
Args:
smiles: SMILES 字符串
organ: 目标器官
model: 训练好的模型
device: 计算设备
top_k: 每轮保留的最优配方数
batch_size: 预测批次大小
Returns:
最终 top-k 配方列表
"""
logger.info(f"Starting optimization for organ: {organ}")
logger.info(f"SMILES: {smiles}")
seeds = None
for iteration, step_size in enumerate(ITERATION_STEP_SIZES):
logger.info(f"\n{'='*60}")
logger.info(f"Iteration {iteration + 1}/{len(ITERATION_STEP_SIZES)}, step_size={step_size}")
logger.info(f"{'='*60}")
# 生成网格
if seeds is None:
# 第一次迭代:生成完整初始网格
logger.info("Generating initial grid...")
grid = generate_initial_grid(step_size)
else:
# 后续迭代:围绕种子点精细化
logger.info(f"Generating refined grid around {len(seeds)} seeds...")
grid = generate_refined_grid(seeds, step_size, radius=2)
logger.info(f"Grid size: {len(grid)} comp combinations")
# 扩展到所有 helper lipid 和 route 组合
total_combinations = len(grid) * len(HELPER_LIPID_OPTIONS) * len(ROUTE_OPTIONS)
logger.info(f"Total combinations: {total_combinations}")
# 创建 DataFrame
df = create_dataframe_from_formulations(
smiles, grid, HELPER_LIPID_OPTIONS, ROUTE_OPTIONS
)
# 预测
logger.info("Running predictions...")
df = predict_biodist(model, df, device, batch_size)
# 选择 top-k
seeds = select_top_k(df, organ, top_k)
# 显示当前最优
best = seeds[0]
logger.info(f"Current best Biodistribution_{organ}: {best.get_biodist(organ):.4f}")
logger.info(f"Best formulation: {best.to_dict()}")
return seeds
def format_results(formulations: List[Formulation], organ: str) -> pd.DataFrame:
"""格式化结果为 DataFrame"""
rows = []
for i, f in enumerate(formulations):
row = {
"rank": i + 1,
f"Biodistribution_{organ}": f.get_biodist(organ),
**f.to_dict(),
}
# 添加其他器官的预测
for col in TARGET_BIODIST:
if col != f"Biodistribution_{organ}":
row[col] = f.biodist_predictions.get(col, 0.0)
rows.append(row)
return pd.DataFrame(rows)
@app.command()
def main(
smiles: str = typer.Option(..., "--smiles", "-s", help="Cationic lipid SMILES string"),
organ: str = typer.Option(..., "--organ", "-o", help=f"Target organ: {AVAILABLE_ORGANS}"),
model_path: Path = typer.Option(
MODELS_DIR / "final" / "model.pt",
"--model", "-m",
help="Path to trained model checkpoint"
),
output_path: Optional[Path] = typer.Option(
None, "--output", "-O",
help="Output CSV path (optional)"
),
top_k: int = typer.Option(20, "--top-k", "-k", help="Number of top formulations to return"),
batch_size: int = typer.Option(256, "--batch-size", "-b", help="Prediction batch size"),
device: str = typer.Option("cuda" if torch.cuda.is_available() else "cpu", "--device", "-d", help="Device"),
):
"""
配方优化程序寻找最大化目标器官 Biodistribution 的最优 LNP 配方
示例:
python -m app.optimize --smiles "CC(C)..." --organ liver
python -m app.optimize -s "CC(C)..." -o spleen -k 10
"""
# 验证器官
if organ not in AVAILABLE_ORGANS:
logger.error(f"Invalid organ: {organ}. Available: {AVAILABLE_ORGANS}")
raise typer.Exit(1)
# 加载模型
logger.info(f"Loading model from {model_path}")
device = torch.device(device)
model = load_model(model_path, device)
# 执行优化
results = optimize(
smiles=smiles,
organ=organ,
model=model,
device=device,
top_k=top_k,
batch_size=batch_size,
)
# 格式化并显示结果
df_results = format_results(results, organ)
logger.info(f"\n{'='*60}")
logger.info(f"TOP {top_k} FORMULATIONS FOR {organ.upper()}")
logger.info(f"{'='*60}")
print(df_results.to_string(index=False))
# 保存结果
if output_path:
df_results.to_csv(output_path, index=False)
logger.success(f"Results saved to {output_path}")
return df_results
if __name__ == "__main__":
app()

View File

@ -1,89 +0,0 @@
# Feature columns configuration (final training)
# SMILES
smiles
# comp token [5]
Cationic_Lipid_to_mRNA_weight_ratio
Cationic_Lipid_Mol_Ratio
Phospholipid_Mol_Ratio
Cholesterol_Mol_Ratio
PEG_Lipid_Mol_Ratio
# phys token [12]
Purity_Pure
Purity_Crude
Mix_type_Microfluidic
Mix_type_Pipetting
Cargo_type_mRNA
Cargo_type_pDNA
Cargo_type_siRNA
Target_or_delivered_gene_FFL
Target_or_delivered_gene_Peptide_barcode
Target_or_delivered_gene_hEPO
Target_or_delivered_gene_FVII
Target_or_delivered_gene_GFP
# help token [4]
Helper_lipid_ID_DOPE
Helper_lipid_ID_DOTAP
Helper_lipid_ID_DSPC
Helper_lipid_ID_MDOA
# exp token [32]
Model_type_A549
Model_type_BDMC
Model_type_BMDM
Model_type_HBEC_ALI
Model_type_HEK293T
Model_type_HeLa
Model_type_IGROV1
Model_type_Mouse
Model_type_RAW264p7
Delivery_target_body
Delivery_target_dendritic_cell
Delivery_target_generic_cell
Delivery_target_liver
Delivery_target_lung
Delivery_target_lung_epithelium
Delivery_target_macrophage
Delivery_target_muscle
Delivery_target_spleen
Route_of_administration_in_vitro
Route_of_administration_intramuscular
Route_of_administration_intratracheal
Route_of_administration_intravenous
Batch_or_individual_or_barcoded_Barcoded
Batch_or_individual_or_barcoded_Individual
Value_name_log_luminescence
Value_name_luminescence
Value_name_FFL_silencing
Value_name_Peptide_abundance
Value_name_hEPO
Value_name_FVII_silencing
Value_name_GFP_delivery
Value_name_Discretized_luminescence
# Targets
## Regression
size
quantified_delivery
## PDI classification
PDI_0_0to0_2
PDI_0_2to0_3
PDI_0_3to0_4
PDI_0_4to0_5
## EE classification
Encapsulation_Efficiency_EE<50
Encapsulation_Efficiency_50<=EE<80
Encapsulation_Efficiency_80<EE<=100
## Toxic
toxic
## Biodistribution
Biodistribution_lymph_nodes
Biodistribution_heart
Biodistribution_liver
Biodistribution_spleen
Biodistribution_lung
Biodistribution_kidney
Biodistribution_muscle

Binary file not shown.

Binary file not shown.

View File

@ -1,720 +0,0 @@
{
"train": [
{
"loss": 16.125412720900314,
"loss_size": 10.958004199541532,
"loss_pdi": 1.2954746576455922,
"loss_ee": 1.032385032910567,
"loss_delivery": 0.9622580982171572,
"loss_biodist": 1.3037926875627959,
"loss_toxic": 0.5734981435995835
},
{
"loss": 5.045667318197397,
"loss_size": 0.9689683621892562,
"loss_pdi": 0.9294195175170898,
"loss_ee": 0.9251096065227802,
"loss_delivery": 0.8660176992416382,
"loss_biodist": 1.0843104399167574,
"loss_toxic": 0.27184163607083833
},
{
"loss": 3.8401913826282206,
"loss_size": 0.2623294328267758,
"loss_pdi": 0.6934819909242483,
"loss_ee": 0.8734692564377418,
"loss_delivery": 0.9325725705577776,
"loss_biodist": 0.8828928974958566,
"loss_toxic": 0.1954453088916265
},
{
"loss": 3.3800897414867697,
"loss_size": 0.25510963281759846,
"loss_pdi": 0.6420884224084707,
"loss_ee": 0.8549692860016456,
"loss_delivery": 0.8087867188912171,
"loss_biodist": 0.6538480222225189,
"loss_toxic": 0.1652876244714627
},
{
"loss": 3.126784379665668,
"loss_size": 0.24261613419422737,
"loss_pdi": 0.6058944624203902,
"loss_ee": 0.8256107156093304,
"loss_delivery": 0.7888596923305438,
"loss_biodist": 0.531504328434284,
"loss_toxic": 0.13229898621256536
},
{
"loss": 2.8701502359830418,
"loss_size": 0.2547111769135182,
"loss_pdi": 0.5767100866024311,
"loss_ee": 0.7695629459161025,
"loss_delivery": 0.7461442443040701,
"loss_biodist": 0.42365796520159793,
"loss_toxic": 0.0993638989300682
},
{
"loss": 2.640800641133235,
"loss_size": 0.23404385321415389,
"loss_pdi": 0.569634735584259,
"loss_ee": 0.7578622423685514,
"loss_delivery": 0.6383189450089748,
"loss_biodist": 0.3649272185105544,
"loss_toxic": 0.0760135928598734
},
{
"loss": 2.5832578127200785,
"loss_size": 0.23187803878233984,
"loss_pdi": 0.5650712022414575,
"loss_ee": 0.7505346032289358,
"loss_delivery": 0.6600469161684697,
"loss_biodist": 0.31232603925925034,
"loss_toxic": 0.06340097868815064
},
{
"loss": 2.4268490993059597,
"loss_size": 0.2535917151432771,
"loss_pdi": 0.49883827567100525,
"loss_ee": 0.6963567412816561,
"loss_delivery": 0.6287171774758742,
"loss_biodist": 0.2783840080866447,
"loss_toxic": 0.07096117032835117
},
{
"loss": 2.260506345675542,
"loss_size": 0.2080249826495464,
"loss_pdi": 0.5252504096581385,
"loss_ee": 0.6650349016372974,
"loss_delivery": 0.5313630184301963,
"loss_biodist": 0.26103301919423616,
"loss_toxic": 0.06980002821924594
},
{
"loss": 2.2684748631257277,
"loss_size": 0.23266072456653303,
"loss_pdi": 0.5147650150152353,
"loss_ee": 0.6746502197705783,
"loss_delivery": 0.5654611770923321,
"loss_biodist": 0.2386850737608396,
"loss_toxic": 0.04225267691967579
},
{
"loss": 2.085041247881376,
"loss_size": 0.21298694839844337,
"loss_pdi": 0.478065183529487,
"loss_ee": 0.624563992023468,
"loss_delivery": 0.4895915320286384,
"loss_biodist": 0.24257883085654333,
"loss_toxic": 0.03725476738495322
},
{
"loss": 2.034342252291166,
"loss_size": 0.20522931390083754,
"loss_pdi": 0.49255690895594084,
"loss_ee": 0.6087538760442001,
"loss_delivery": 0.480256066012841,
"loss_biodist": 0.2110953021507997,
"loss_toxic": 0.03645075023031005
},
{
"loss": 1.9308108733250544,
"loss_size": 0.17175877896639016,
"loss_pdi": 0.45260854638539827,
"loss_ee": 0.6115030990197108,
"loss_delivery": 0.46177717126332796,
"loss_biodist": 0.17210170110830894,
"loss_toxic": 0.06106155129292837
},
{
"loss": 1.8926622317387507,
"loss_size": 0.18219156162096903,
"loss_pdi": 0.45498812886384815,
"loss_ee": 0.6137785132114704,
"loss_delivery": 0.442503636273054,
"loss_biodist": 0.1760710489291411,
"loss_toxic": 0.023129337216512516
},
{
"loss": 1.973634958267212,
"loss_size": 0.1851495263668207,
"loss_pdi": 0.44218484254983753,
"loss_ee": 0.5531376554415777,
"loss_delivery": 0.5962466007241836,
"loss_biodist": 0.1732567583139126,
"loss_toxic": 0.023659600159869745
},
{
"loss": 1.834187232531034,
"loss_size": 0.1886328814121393,
"loss_pdi": 0.417209030343936,
"loss_ee": 0.6130589017501245,
"loss_delivery": 0.41392402522839034,
"loss_biodist": 0.17852016595693734,
"loss_toxic": 0.022842258698521897
},
{
"loss": 1.6386324167251587,
"loss_size": 0.1619069530413701,
"loss_pdi": 0.40920511002723986,
"loss_ee": 0.543202471274596,
"loss_delivery": 0.3477886743270434,
"loss_biodist": 0.15435600338073877,
"loss_toxic": 0.02217323684061949
},
{
"loss": 1.6642086597589345,
"loss_size": 0.1822590002646813,
"loss_pdi": 0.38968331194840944,
"loss_ee": 0.5327657415316656,
"loss_delivery": 0.38456671570356077,
"loss_biodist": 0.15715198791944063,
"loss_toxic": 0.01778192028331642
},
{
"loss": 1.561285321529095,
"loss_size": 0.1437432708648535,
"loss_pdi": 0.38639354361937595,
"loss_ee": 0.5043096313109765,
"loss_delivery": 0.35284727811813354,
"loss_biodist": 0.15738230026685274,
"loss_toxic": 0.016609296166839507
},
{
"loss": 1.5598738010113056,
"loss_size": 0.14988142280624464,
"loss_pdi": 0.41852312133862424,
"loss_ee": 0.5153307456236619,
"loss_delivery": 0.30808181086411845,
"loss_biodist": 0.1537162667283645,
"loss_toxic": 0.014340438235264558
},
{
"loss": 1.586504679459792,
"loss_size": 0.1579624334206948,
"loss_pdi": 0.4118466583582071,
"loss_ee": 0.5027729616715357,
"loss_delivery": 0.33311148560964143,
"loss_biodist": 0.16044681118084833,
"loss_toxic": 0.020364307870085422
},
{
"loss": 1.5559651026358972,
"loss_size": 0.15422992723492476,
"loss_pdi": 0.40416549490048337,
"loss_ee": 0.5043272055112399,
"loss_delivery": 0.34229428607683915,
"loss_biodist": 0.13546629192737433,
"loss_toxic": 0.015481884215170374
},
{
"loss": 1.474733068392827,
"loss_size": 0.1376458337673774,
"loss_pdi": 0.3663271631185825,
"loss_ee": 0.5019905475469736,
"loss_delivery": 0.3069626304965753,
"loss_biodist": 0.1442684789116566,
"loss_toxic": 0.01753841727398909
},
{
"loss": 1.4861183900099535,
"loss_size": 0.15266291739848944,
"loss_pdi": 0.3844867234046643,
"loss_ee": 0.49344547666036165,
"loss_delivery": 0.292184143112256,
"loss_biodist": 0.14641749343046775,
"loss_toxic": 0.016921617932474382
},
{
"loss": 1.512233894604903,
"loss_size": 0.14189060032367706,
"loss_pdi": 0.4098552969785837,
"loss_ee": 0.4653961268755106,
"loss_delivery": 0.29666711619267094,
"loss_biodist": 0.13669535231131774,
"loss_toxic": 0.061729387344362646
},
{
"loss": 1.4599237900513868,
"loss_size": 0.14220070122526243,
"loss_pdi": 0.4150706483767583,
"loss_ee": 0.46269946602674633,
"loss_delivery": 0.2918037512841133,
"loss_biodist": 0.13078988859286675,
"loss_toxic": 0.017359334491909698
},
{
"loss": 1.576150316458482,
"loss_size": 0.1595412979905422,
"loss_pdi": 0.3765770483475465,
"loss_ee": 0.5104989432371579,
"loss_delivery": 0.3169563438456792,
"loss_biodist": 0.16685812347210371,
"loss_toxic": 0.04571856157137798
},
{
"loss": 1.4343401743815496,
"loss_size": 0.13940962203420126,
"loss_pdi": 0.3983347278374892,
"loss_ee": 0.4601492996399219,
"loss_delivery": 0.27466822358278126,
"loss_biodist": 0.1437123933663735,
"loss_toxic": 0.018065906255147778
},
{
"loss": 1.3912398769305303,
"loss_size": 0.12413510250357482,
"loss_pdi": 0.37387907390411085,
"loss_ee": 0.4670978830410884,
"loss_delivery": 0.2875180955116565,
"loss_biodist": 0.1249157666013791,
"loss_toxic": 0.01369395311205433
},
{
"loss": 1.424091059427995,
"loss_size": 0.15850819360751373,
"loss_pdi": 0.3705967183296497,
"loss_ee": 0.4417672294836778,
"loss_delivery": 0.30434694112493443,
"loss_biodist": 0.13330914022830817,
"loss_toxic": 0.015562845026859297
},
{
"loss": 1.40188762316337,
"loss_size": 0.13292228774382517,
"loss_pdi": 0.3610769865604547,
"loss_ee": 0.5077145374738253,
"loss_delivery": 0.2582832815555426,
"loss_biodist": 0.12532487941476014,
"loss_toxic": 0.0165656553223156
},
{
"loss": 1.3533825324131892,
"loss_size": 0.13495178577991632,
"loss_pdi": 0.3524953780265955,
"loss_ee": 0.4514327874550453,
"loss_delivery": 0.25540869382138437,
"loss_biodist": 0.13806180197459,
"loss_toxic": 0.021032094086806934
},
{
"loss": 1.3358305784372182,
"loss_size": 0.14862898737192154,
"loss_pdi": 0.3689935069817763,
"loss_ee": 0.4314877482560965,
"loss_delivery": 0.24364815193873185,
"loss_biodist": 0.13041460055571336,
"loss_toxic": 0.01265757203173752
}
],
"val": [
{
"loss": 9.567692279815674,
"loss_size": 4.553072690963745,
"loss_pdi": 1.0625805258750916,
"loss_ee": 0.9942680895328522,
"loss_delivery": 1.47209894657135,
"loss_biodist": 1.1432022452354431,
"loss_toxic": 0.3424694389104843,
"acc_pdi": 0.75,
"acc_ee": 0.5909090909090909,
"acc_toxic": 1.0
},
{
"loss": 4.354300379753113,
"loss_size": 0.20095597207546234,
"loss_pdi": 0.7770168483257294,
"loss_ee": 0.9953322410583496,
"loss_delivery": 1.3067785501480103,
"loss_biodist": 0.9856867492198944,
"loss_toxic": 0.08853016048669815,
"acc_pdi": 0.75,
"acc_ee": 0.5909090909090909,
"acc_toxic": 1.0
},
{
"loss": 4.091485023498535,
"loss_size": 0.1840391382575035,
"loss_pdi": 0.6579808592796326,
"loss_ee": 0.9572223722934723,
"loss_delivery": 1.386644184589386,
"loss_biodist": 0.8630380034446716,
"loss_toxic": 0.04256031848490238,
"acc_pdi": 0.75,
"acc_ee": 0.5909090909090909,
"acc_toxic": 1.0
},
{
"loss": 3.5865455865859985,
"loss_size": 0.16276441887021065,
"loss_pdi": 0.6156152784824371,
"loss_ee": 0.8769127726554871,
"loss_delivery": 1.185390830039978,
"loss_biodist": 0.693861186504364,
"loss_toxic": 0.05200100876390934,
"acc_pdi": 0.75,
"acc_ee": 0.5909090909090909,
"acc_toxic": 1.0
},
{
"loss": 3.216905355453491,
"loss_size": 0.20165041834115982,
"loss_pdi": 0.6010490655899048,
"loss_ee": 0.8362293839454651,
"loss_delivery": 1.0108550190925598,
"loss_biodist": 0.4944496750831604,
"loss_toxic": 0.0726719107478857,
"acc_pdi": 0.75,
"acc_ee": 0.6363636363636364,
"acc_toxic": 1.0
},
{
"loss": 3.0632435083389282,
"loss_size": 0.24732542037963867,
"loss_pdi": 0.5763635039329529,
"loss_ee": 0.8021132349967957,
"loss_delivery": 0.8960984945297241,
"loss_biodist": 0.4863189309835434,
"loss_toxic": 0.05502396076917648,
"acc_pdi": 0.75,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.8909536600112915,
"loss_size": 0.19840088486671448,
"loss_pdi": 0.5675790905952454,
"loss_ee": 0.789268285036087,
"loss_delivery": 0.8245587646961212,
"loss_biodist": 0.45656538009643555,
"loss_toxic": 0.054581284523010254,
"acc_pdi": 0.7272727272727273,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.771771550178528,
"loss_size": 0.1412012092769146,
"loss_pdi": 0.5785803645849228,
"loss_ee": 0.7794539630413055,
"loss_delivery": 0.7300527393817902,
"loss_biodist": 0.4118006229400635,
"loss_toxic": 0.130682535469532,
"acc_pdi": 0.7272727272727273,
"acc_ee": 0.6363636363636364,
"acc_toxic": 0.9090909090909091
},
{
"loss": 2.692520260810852,
"loss_size": 0.1475178860127926,
"loss_pdi": 0.5785025954246521,
"loss_ee": 0.7986349761486053,
"loss_delivery": 0.6745082139968872,
"loss_biodist": 0.3999589830636978,
"loss_toxic": 0.09339761920273304,
"acc_pdi": 0.7272727272727273,
"acc_ee": 0.5454545454545454,
"acc_toxic": 1.0
},
{
"loss": 2.8346426486968994,
"loss_size": 0.1516040787100792,
"loss_pdi": 0.5753654837608337,
"loss_ee": 0.8160740733146667,
"loss_delivery": 0.7168894708156586,
"loss_biodist": 0.47982172667980194,
"loss_toxic": 0.09488803520798683,
"acc_pdi": 0.75,
"acc_ee": 0.6818181818181818,
"acc_toxic": 1.0
},
{
"loss": 2.7991228103637695,
"loss_size": 0.13234595209360123,
"loss_pdi": 0.5597751885652542,
"loss_ee": 0.8118472993373871,
"loss_delivery": 0.8289965093135834,
"loss_biodist": 0.3804939240217209,
"loss_toxic": 0.0856639239937067,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6136363636363636,
"acc_toxic": 1.0
},
{
"loss": 2.5899158716201782,
"loss_size": 0.10683015361428261,
"loss_pdi": 0.5460522472858429,
"loss_ee": 0.8205565512180328,
"loss_delivery": 0.5881542563438416,
"loss_biodist": 0.47443418204784393,
"loss_toxic": 0.053888481110334396,
"acc_pdi": 0.7954545454545454,
"acc_ee": 0.6818181818181818,
"acc_toxic": 1.0
},
{
"loss": 2.725231647491455,
"loss_size": 0.11643071845173836,
"loss_pdi": 0.5444842875003815,
"loss_ee": 0.8331143856048584,
"loss_delivery": 0.7808746695518494,
"loss_biodist": 0.3872501105070114,
"loss_toxic": 0.06307746656239033,
"acc_pdi": 0.8181818181818182,
"acc_ee": 0.6818181818181818,
"acc_toxic": 1.0
},
{
"loss": 2.6474616527557373,
"loss_size": 0.10570626705884933,
"loss_pdi": 0.5306982547044754,
"loss_ee": 0.8475350737571716,
"loss_delivery": 0.6773415505886078,
"loss_biodist": 0.45252545177936554,
"loss_toxic": 0.033654999919235706,
"acc_pdi": 0.7954545454545454,
"acc_ee": 0.7045454545454546,
"acc_toxic": 1.0
},
{
"loss": 2.7429730892181396,
"loss_size": 0.13143501430749893,
"loss_pdi": 0.5128554701805115,
"loss_ee": 0.8301066756248474,
"loss_delivery": 0.7826772928237915,
"loss_biodist": 0.4481300711631775,
"loss_toxic": 0.03776852134615183,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.7127978801727295,
"loss_size": 0.19175250455737114,
"loss_pdi": 0.516972616314888,
"loss_ee": 0.8794091939926147,
"loss_delivery": 0.6612942218780518,
"loss_biodist": 0.4495534151792526,
"loss_toxic": 0.01381598599255085,
"acc_pdi": 0.7954545454545454,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.605361819267273,
"loss_size": 0.0976286269724369,
"loss_pdi": 0.5153753459453583,
"loss_ee": 0.8854215145111084,
"loss_delivery": 0.6795051693916321,
"loss_biodist": 0.3929741233587265,
"loss_toxic": 0.0344569431617856,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6136363636363636,
"acc_toxic": 1.0
},
{
"loss": 2.6061036586761475,
"loss_size": 0.13404572382569313,
"loss_pdi": 0.5658221244812012,
"loss_ee": 0.8649452030658722,
"loss_delivery": 0.5898179858922958,
"loss_biodist": 0.4181220978498459,
"loss_toxic": 0.03335061576217413,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6363636363636364,
"acc_toxic": 1.0
},
{
"loss": 2.566210627555847,
"loss_size": 0.09801355004310608,
"loss_pdi": 0.5331112891435623,
"loss_ee": 0.8543781340122223,
"loss_delivery": 0.663883626461029,
"loss_biodist": 0.40053851902484894,
"loss_toxic": 0.01628561830148101,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6363636363636364,
"acc_toxic": 1.0
},
{
"loss": 2.5774325132369995,
"loss_size": 0.10316971689462662,
"loss_pdi": 0.5015804171562195,
"loss_ee": 0.8556492626667023,
"loss_delivery": 0.6874183714389801,
"loss_biodist": 0.40917880833148956,
"loss_toxic": 0.02043590322136879,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6818181818181818,
"acc_toxic": 1.0
},
{
"loss": 2.605422019958496,
"loss_size": 0.09912058711051941,
"loss_pdi": 0.5235853344202042,
"loss_ee": 0.873578816652298,
"loss_delivery": 0.6754274368286133,
"loss_biodist": 0.41106243431568146,
"loss_toxic": 0.022647667676210403,
"acc_pdi": 0.75,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.6543829441070557,
"loss_size": 0.09768814221024513,
"loss_pdi": 0.49928364157676697,
"loss_ee": 0.887874037027359,
"loss_delivery": 0.7190346419811249,
"loss_biodist": 0.3921310156583786,
"loss_toxic": 0.0583715345710516,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6818181818181818,
"acc_toxic": 0.9696969696969697
},
{
"loss": 2.567589282989502,
"loss_size": 0.09272187761962414,
"loss_pdi": 0.51718769967556,
"loss_ee": 0.9185941517353058,
"loss_delivery": 0.6525538563728333,
"loss_biodist": 0.37214455008506775,
"loss_toxic": 0.014387213159352541,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.5968352556228638,
"loss_size": 0.08045755326747894,
"loss_pdi": 0.5356858968734741,
"loss_ee": 0.9407581686973572,
"loss_delivery": 0.634858101606369,
"loss_biodist": 0.3985549360513687,
"loss_toxic": 0.006520765833556652,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.6400684118270874,
"loss_size": 0.10199694335460663,
"loss_pdi": 0.517327144742012,
"loss_ee": 0.9348995685577393,
"loss_delivery": 0.6469141840934753,
"loss_biodist": 0.4060143977403641,
"loss_toxic": 0.032916306518018246,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6818181818181818,
"acc_toxic": 1.0
},
{
"loss": 2.684706211090088,
"loss_size": 0.08828861452639103,
"loss_pdi": 0.5358051210641861,
"loss_ee": 0.9240424036979675,
"loss_delivery": 0.7182384729385376,
"loss_biodist": 0.4059095233678818,
"loss_toxic": 0.012422125786542892,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.665715456008911,
"loss_size": 0.09193641319870949,
"loss_pdi": 0.5586960315704346,
"loss_ee": 0.9341873526573181,
"loss_delivery": 0.6672921180725098,
"loss_biodist": 0.39184093475341797,
"loss_toxic": 0.021762709133327007,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.596559524536133,
"loss_size": 0.09265327453613281,
"loss_pdi": 0.528680682182312,
"loss_ee": 0.919374018907547,
"loss_delivery": 0.6490764021873474,
"loss_biodist": 0.3949074149131775,
"loss_toxic": 0.011867486871778965,
"acc_pdi": 0.75,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.585421562194824,
"loss_size": 0.0936437975615263,
"loss_pdi": 0.5345576107501984,
"loss_ee": 0.9352433085441589,
"loss_delivery": 0.6098059117794037,
"loss_biodist": 0.3938410133123398,
"loss_toxic": 0.018329923041164875,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.655733346939087,
"loss_size": 0.10606781952083111,
"loss_pdi": 0.5337405353784561,
"loss_ee": 0.9154745638370514,
"loss_delivery": 0.7101629674434662,
"loss_biodist": 0.38175711035728455,
"loss_toxic": 0.00853043282404542,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.6239495277404785,
"loss_size": 0.0914073996245861,
"loss_pdi": 0.5375382900238037,
"loss_ee": 0.9078292548656464,
"loss_delivery": 0.693512886762619,
"loss_biodist": 0.3826553374528885,
"loss_toxic": 0.011006365530192852,
"acc_pdi": 0.8181818181818182,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.6274508237838745,
"loss_size": 0.0975069236010313,
"loss_pdi": 0.5298525840044022,
"loss_ee": 0.9227176904678345,
"loss_delivery": 0.6834201812744141,
"loss_biodist": 0.3833360821008682,
"loss_toxic": 0.010617360007017851,
"acc_pdi": 0.7954545454545454,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.6211040019989014,
"loss_size": 0.108822550624609,
"loss_pdi": 0.5202214568853378,
"loss_ee": 0.9265661537647247,
"loss_delivery": 0.6657091081142426,
"loss_biodist": 0.39240916073322296,
"loss_toxic": 0.007375639397650957,
"acc_pdi": 0.75,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
},
{
"loss": 2.6309741735458374,
"loss_size": 0.10216855630278587,
"loss_pdi": 0.5254682153463364,
"loss_ee": 0.9219010472297668,
"loss_delivery": 0.6798527538776398,
"loss_biodist": 0.3923489600419998,
"loss_toxic": 0.009234576486051083,
"acc_pdi": 0.7727272727272727,
"acc_ee": 0.6590909090909091,
"acc_toxic": 1.0
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 KiB

Binary file not shown.

533
pixi.lock
View File

@ -53,14 +53,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/linux-64/xz-tools-5.8.1-hb9d3cd8_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_6.conda
- pypi: https://files.pythonhosted.org/packages/64/88/c7083fc61120ab661c5d0b82cb77079fc1429d3f913a456c1c82cf4658f7/alabaster-0.7.13-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9b/52/4a86a4fa1cc2aae79137cc9510b7080c3e5aede2310d14fae5486feec7f7/altair-5.4.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1b/b4/f7e396030e3b11394436358ca258a81d6010106582422f23443c16ca1873/anyio-4.5.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/2a/10164ed1f31196a2f7f3799368a821765c62851ead0e630ab52b8e14b4d0/blinker-1.8.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/72/76/20fa66124dbe6be5cafeb312ece67de6b61dd91a0247d1ea13db4ebb33c2/cachetools-5.5.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bf/fa/cf5bb2409a385f78750e78c8d2e24780964976acdaaed65dbd6083ae5b40/charset_normalizer-3.4.4-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/a0/ad/72361203906e2dbe9baa776c64e9246d555b516808dd0cce385f07f4cf71/chemprop-1.7.0-py3-none-any.whl
@ -72,19 +65,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/55/e2/2537ebcff11c1ee1ff17d8d0b6f4db75873e3b0fb32c2d4a2ee31ecb310a/docstring_parser-0.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/26/87/f238c0670b94533ac0353a4e2a1a771a0cc73277b88bff23d3ae35a256c1/docutils-0.20.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3e/57/aa70121b5008f44031be645a61a7c4abc24e0e888ad3fc8fda916f4d188e/fastapi-0.124.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a7/31/673a677c137d8b2429813f56be77986f44bcb43f5c113336a4c8347e0eb0/fastparquet-2024.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/af/6a/00d144ac1626fbb44c4ff36519712e258128985a5d0ae43344778ae5cbb9/Flask-2.1.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a5/0e/b6314a09a4d561aaa7e09de43fa700917be91e701f07df6178865962666c/fonttools-4.57.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/56/53/eb690efa8513166adef3e0669afd31e95ffde69fb3c52ec2ac7223ed6018/fsspec-2025.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/da/71/ae30dadffc90b9006d77af76b393cb9dfbfc9629f339fc1574a1c52e6806/future-1.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b6/cd/5b3334d39276067f54618ce0d0b48ed69d91352fbf137468c7095170d0e5/hyperopt-0.2.7-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl
@ -93,14 +79,11 @@ environments:
- pypi: https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/29/df4b9b42f2be0b623cbd5e2140cafcaa2bef0759a00b7b70104dcfe2fb51/joblib-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/69/4a/4f9dbeb84e8850557c02365a0eee0649abe5eb1d84af92a25731c6c0f922/jsonschema-4.23.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/76/36/ae40d7a3171e06f55ac77fe5536079e7be1d8be2a8210e08975c7f9b4d54/kiwisolver-1.4.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/c7/bd/50319665ce81bb10e90d1cf76f9e1aa269ea6f7fa30ab4521f14d122a3df/MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/30/33/cc27211d2ffeee4fd7402dca137b6e8a83f6dcae3d4be8d0ad5068555561/matplotlib-3.7.5-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/79/3f/8d450588206b437dd239a6d44230c63095e71135bd95d5a74347d07adbd5/narwhals-1.42.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a8/05/9d4f9b78ead6b2661d6e8ea772e111fc4a9fbd866ad0c81906c11206b55e/networkx-3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/98/5d/5738903efe0ecb73e51eb44feafba32bdba2081263d40c5043568ff60faf/numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/37/6d/121efd7382d5b0284239f4ab1fc1590d86d34ed4a4a2fdb13b30ca8e5740/nvidia_cublas_cu12-12.1.3.1-py3-none-manylinux1_x86_64.whl
@ -116,30 +99,22 @@ environments:
- pypi: https://files.pythonhosted.org/packages/46/0c/c75bbfb967457a0b7670b8ad267bfc4fffdf341c074e0a80db06c24ccfd4/nvidia_nvjitlink_cu12-12.9.86-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/da/d3/8057f0587683ed2fcd4dbfbdfdfa807b9160b809976099d36b8f60d08f03/nvidia_nvtx_cu12-12.1.105-py3-none-manylinux1_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/c0/da/977ded879c29cbd04de313843e76868e6e13408a94ed6b987245dc7c8506/openpyxl-3.1.5-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f8/7f/5b047effafbdd34e52c9e2d7e44f729a0655efafb22198c45cf692cdc157/pandas-2.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/5d/e6/71ed4d95676098159b533c4a4c424cf453fec9614edaff1a0633fe228eef/pandas_flavor-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/fb/ad/435fe29865f98a8fbdc64add8875a6e4f8c97749a93577a8919ec6f32c64/pillow-10.4.0-cp38-cp38-manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/c9/5c/3d4882ba113fd55bdba9326c1e4c62a15e674a2501de4869e6bd6301f87e/pkgutil_resolve_name-1.3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/85/e4/07c80521879c2d15f321465ac24c70efe2381378c00bf5e56a0f4fbac8cd/protobuf-5.29.5-cp38-abi3-manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/bd/db/ea0203e495be491c85af87b66e37acfd3bf756fd985f87e46fc5e3bf022c/py4j-0.10.9.9-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/c1/4c6bcdf7a820034aa91a8b4d25fef38809be79b42ca7aaa16d4680b0bbac/pyarrow-17.0.0-cp38-cp38-manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f7/a3/5f19bc495793546825ab160e530330c2afcee2281c02b5ffafd0b32ac05e/pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/ab/4c/b888e6cf58bd9db9c93f40d1c6be8283ff49d88919231afe93a6bcf61626/pydeck-0.9.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e5/0c/0e3c05b1c87bb6a1c76d281b0f35e78d2d80ac91b5f8f524cebf77f51049/pyparsing-3.1.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3d/84/63b2e66f5c7cb97ce994769afbbef85a1ac364fedbcb7d4a3c0f15d318a5/rdkit-2024.3.5-cp38-cp38-manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b7/59/2056f61236782a2c86b33906c025d4f4a0b17be0161b63b70fd9e8775d36/referencing-0.35.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/ce/af016c81fda833bf125b20d1677d816f230cad2ab189f46bcbfea3c7a375/rpds_py-0.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/3f/48/6fdd99f5717045f9984616b5c2ec683d6286d30c0ac234563062132b83ab/scikit_learn-1.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/69/f0/fb07a9548e48b687b8bf2fa81d71aba9cfc548d365046ca1c791e24db99d/scipy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/48/17/325cf6a257d84751a48ae90752b3d8fe0be8f9535b6253add61c49d0d9bc/sphinx-7.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/87/c7/b5c8015d823bfda1a346adb2c634a2101d50bb75d421eb6dcb31acd25ebc/sphinx_rtd_theme-3.1.0-py2.py3-none-any.whl
@ -150,22 +125,15 @@ environments:
- pypi: https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/14/05f9206cf4e9cfca1afb5fd224c7cd434dcc3a433d6d9e4e0264d29c6cdb/sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c6/77/5464ec50dd0f1c1037e3c93249b040c8fc8078fdda97530eeb02424b6eea/sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b6/c5/7ae467eeddb57260c8ce17a3a09f9f5edba35820fc022d7c55b7decd5d3a/starlette-0.44.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/14/857d0734989f3d26f2f965b2e3f67568ea7a6e8a60cb9c1ed7f774b6d606/streamlit-1.40.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/ff/c87e0622b1dadea79d2fb0b25ade9ed98954c9033722eb707053d310d4f3/sympy-1.13.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b6/cb/b86984bed139586d01532a587464b5805f12e397594f19f931c4c2fbfa61/tenacity-9.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/44/71/f3e7c9b2ab67e28c572ab4e9d5fa3499e0d252650f96d8a3a03e26677f53/tensorboardX-2.6.2.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/2c/ffbf7a134b9ab11a67b0cf0726453cedd9c5043a4fe7a35d1cefa9a1bcfb/threadpoolctl-3.5.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a9/71/45aac46b75742e08d2d6f9fc2b612223b5e36115b8b2ed673b23c21b5387/torch-2.4.1-cp38-cp38-manylinux1_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/22/55/b78a464de78051a30599ceb6983b01d8f732e6f69bf37b4ed07f642ac0fc/tornado-6.4.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/4d/b4/c37e2776a1390bab7e78a6d52bd525441cb3cad7260a6a00b11b0b702e7c/triton-3.0.0-1-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/ea/07/0055bb513de2b7cf23b2bfc7eeeb6a6ae6ff7b287e2a62ab80cf403d61e9/typed_argument_parser-1.10.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/98/79/2e2620337ef1e4ef7a058b351603b765f59ac28e6e3ac7c5e7cdee9ea1ab/uvicorn-0.33.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/01/d2/c8931ff840a7e5bd5dcb93f2bb2a1fd18faf8312e9f7f53ff1cf76ecc8ed/watchdog-4.0.2-py3-none-manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/fd/21/0a674dfe66e9df9072c46269c882e9f901d36d987d8ea50ead033a9c1e01/werkzeug-2.3.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b4/a7/897f484225bd8e179a4f39f8e9a4ca26c14e9f7055b495384b1d56e1382d/xarray-2023.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/8b/5ba542fa83c90e09eac972fc9baca7a88e7e7ca4b221a89251954019308b/zipp-3.20.2-py3-none-any.whl
@ -206,14 +174,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-gpl-tools-5.8.1-h9a6d368_2.conda
- conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-tools-5.8.1-h39f12f2_2.conda
- pypi: https://files.pythonhosted.org/packages/64/88/c7083fc61120ab661c5d0b82cb77079fc1429d3f913a456c1c82cf4658f7/alabaster-0.7.13-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9b/52/4a86a4fa1cc2aae79137cc9510b7080c3e5aede2310d14fae5486feec7f7/altair-5.4.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/1b/b4/f7e396030e3b11394436358ca258a81d6010106582422f23443c16ca1873/anyio-4.5.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bb/2a/10164ed1f31196a2f7f3799368a821765c62851ead0e630ab52b8e14b4d0/blinker-1.8.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/72/76/20fa66124dbe6be5cafeb312ece67de6b61dd91a0247d1ea13db4ebb33c2/cachetools-5.5.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0a/4e/3926a1c11f0433791985727965263f788af00db3482d89a7545ca5ecc921/charset_normalizer-3.4.4-cp38-cp38-macosx_10_9_universal2.whl
- pypi: https://files.pythonhosted.org/packages/a0/ad/72361203906e2dbe9baa776c64e9246d555b516808dd0cce385f07f4cf71/chemprop-1.7.0-py3-none-any.whl
@ -225,19 +186,12 @@ environments:
- pypi: https://files.pythonhosted.org/packages/55/e2/2537ebcff11c1ee1ff17d8d0b6f4db75873e3b0fb32c2d4a2ee31ecb310a/docstring_parser-0.17.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/26/87/f238c0670b94533ac0353a4e2a1a771a0cc73277b88bff23d3ae35a256c1/docutils-0.20.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/3e/57/aa70121b5008f44031be645a61a7c4abc24e0e888ad3fc8fda916f4d188e/fastapi-0.124.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/27/8e/ce64bc647728ee26bfffa9987fb375e7c99bba54b632404bc0d61b6e9fc2/fastparquet-2024.2.0-cp38-cp38-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/af/6a/00d144ac1626fbb44c4ff36519712e258128985a5d0ae43344778ae5cbb9/Flask-2.1.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8a/3f/c16dbbec7221783f37dcc2022d5a55f0d704ffc9feef67930f6eb517e8ce/fonttools-4.57.0-cp38-cp38-macosx_10_9_universal2.whl
- pypi: https://files.pythonhosted.org/packages/56/53/eb690efa8513166adef3e0669afd31e95ffde69fb3c52ec2ac7223ed6018/fsspec-2025.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/da/71/ae30dadffc90b9006d77af76b393cb9dfbfc9629f339fc1574a1c52e6806/future-1.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b6/cd/5b3334d39276067f54618ce0d0b48ed69d91352fbf137468c7095170d0e5/hyperopt-0.2.7-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl
@ -246,41 +200,30 @@ environments:
- pypi: https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/91/29/df4b9b42f2be0b623cbd5e2140cafcaa2bef0759a00b7b70104dcfe2fb51/joblib-1.4.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/69/4a/4f9dbeb84e8850557c02365a0eee0649abe5eb1d84af92a25731c6c0f922/jsonschema-4.23.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/14/a7/bb8ab10e12cc8764f4da0245d72dee4731cc720bdec0f085d5e9c6005b98/kiwisolver-1.4.7-cp38-cp38-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f8/ff/2c942a82c35a49df5de3a630ce0a8456ac2969691b230e530ac12314364c/MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl
- pypi: https://files.pythonhosted.org/packages/aa/59/4d13e5b6298b1ca5525eea8c68d3806ae93ab6d0bb17ca9846aa3156b92b/matplotlib-3.7.5-cp38-cp38-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/79/3f/8d450588206b437dd239a6d44230c63095e71135bd95d5a74347d07adbd5/narwhals-1.42.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a8/05/9d4f9b78ead6b2661d6e8ea772e111fc4a9fbd866ad0c81906c11206b55e/networkx-3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/a7/ae/f53b7b265fdc701e663fbb322a8e9d4b14d9cb7b2385f45ddfabfc4327e4/numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/c0/da/977ded879c29cbd04de313843e76868e6e13408a94ed6b987245dc7c8506/openpyxl-3.1.5-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/53/c3/f8e87361f7fdf42012def602bfa2a593423c729f5cb7c97aed7f51be66ac/pandas-2.0.3-cp38-cp38-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/5d/e6/71ed4d95676098159b533c4a4c424cf453fec9614edaff1a0633fe228eef/pandas_flavor-0.7.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/10/43/105823d233c5e5d31cea13428f4474ded9d961652307800979a59d6a4276/pillow-10.4.0-cp38-cp38-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/c9/5c/3d4882ba113fd55bdba9326c1e4c62a15e674a2501de4869e6bd6301f87e/pkgutil_resolve_name-1.3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/dd/73/10e1661c21f139f2c6ad9b23040ff36fee624310dc28fba20d33fdae124c/protobuf-5.29.5-cp38-abi3-macosx_10_9_universal2.whl
- pypi: https://files.pythonhosted.org/packages/bd/db/ea0203e495be491c85af87b66e37acfd3bf756fd985f87e46fc5e3bf022c/py4j-0.10.9.9-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/64/d9/51e35550f2f18b8815a2ab25948f735434db32000c0e91eba3a32634782a/pyarrow-17.0.0-cp38-cp38-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f4/20/26c549249769ed84877f862f7bb93f89a6ee08b4bee1ed8781616b7fbb5e/pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/ab/4c/b888e6cf58bd9db9c93f40d1c6be8283ff49d88919231afe93a6bcf61626/pydeck-0.9.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e5/0c/0e3c05b1c87bb6a1c76d281b0f35e78d2d80ac91b5f8f524cebf77f51049/pyparsing-3.1.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/bf/cb/c709b60f4815e18c00e1e8639204bdba04cb158e6278791d82f94f51a988/rdkit-2024.3.5-cp38-cp38-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/b7/59/2056f61236782a2c86b33906c025d4f4a0b17be0161b63b70fd9e8775d36/referencing-0.35.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/54/63/47d34dc4ddb3da73e78e10c9009dcf8edc42d355a221351c05c822c2a50b/rpds_py-0.20.1-cp38-cp38-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/a4/62/92e9cec3deca8b45abf62dd8f6469d688b3f28b9c170809fcc46f110b523/scikit_learn-1.3.2-cp38-cp38-macosx_12_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/93/4a/50c436de1353cce8b66b26e49a687f10b91fe7465bf34e4565d810153003/scipy-1.10.1-cp38-cp38-macosx_12_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/48/17/325cf6a257d84751a48ae90752b3d8fe0be8f9535b6253add61c49d0d9bc/sphinx-7.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/87/c7/b5c8015d823bfda1a346adb2c634a2101d50bb75d421eb6dcb31acd25ebc/sphinx_rtd_theme-3.1.0-py2.py3-none-any.whl
@ -291,20 +234,14 @@ environments:
- pypi: https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/14/05f9206cf4e9cfca1afb5fd224c7cd434dcc3a433d6d9e4e0264d29c6cdb/sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c6/77/5464ec50dd0f1c1037e3c93249b040c8fc8078fdda97530eeb02424b6eea/sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b6/c5/7ae467eeddb57260c8ce17a3a09f9f5edba35820fc022d7c55b7decd5d3a/starlette-0.44.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/14/857d0734989f3d26f2f965b2e3f67568ea7a6e8a60cb9c1ed7f774b6d606/streamlit-1.40.1-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/99/ff/c87e0622b1dadea79d2fb0b25ade9ed98954c9033722eb707053d310d4f3/sympy-1.13.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b6/cb/b86984bed139586d01532a587464b5805f12e397594f19f931c4c2fbfa61/tenacity-9.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/44/71/f3e7c9b2ab67e28c572ab4e9d5fa3499e0d252650f96d8a3a03e26677f53/tensorboardX-2.6.2.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/4b/2c/ffbf7a134b9ab11a67b0cf0726453cedd9c5043a4fe7a35d1cefa9a1bcfb/threadpoolctl-3.5.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c4/88/4d9f66de5fe732462a2713c9931cab614d3fd6a9b5d9ee1f04768ad64daa/torch-2.4.1-cp38-none-macosx_11_0_arm64.whl
- pypi: https://files.pythonhosted.org/packages/26/7e/71f604d8cea1b58f82ba3590290b66da1e72d840aeb37e0d5f7291bd30db/tornado-6.4.2-cp38-abi3-macosx_10_9_universal2.whl
- pypi: https://files.pythonhosted.org/packages/ea/07/0055bb513de2b7cf23b2bfc7eeeb6a6ae6ff7b287e2a62ab80cf403d61e9/typed_argument_parser-1.10.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/98/79/2e2620337ef1e4ef7a058b351603b765f59ac28e6e3ac7c5e7cdee9ea1ab/uvicorn-0.33.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/fd/21/0a674dfe66e9df9072c46269c882e9f901d36d987d8ea50ead033a9c1e01/werkzeug-2.3.8-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/b4/a7/897f484225bd8e179a4f39f8e9a4ca26c14e9f7055b495384b1d56e1382d/xarray-2023.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/62/8b/5ba542fa83c90e09eac972fc9baca7a88e7e7ca4b221a89251954019308b/zipp-3.20.2-py3-none-any.whl
@ -336,134 +273,6 @@ packages:
version: 0.7.13
sha256: 1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3
requires_python: '>=3.6'
- pypi: https://files.pythonhosted.org/packages/9b/52/4a86a4fa1cc2aae79137cc9510b7080c3e5aede2310d14fae5486feec7f7/altair-5.4.1-py3-none-any.whl
name: altair
version: 5.4.1
sha256: 0fb130b8297a569d08991fb6fe763582e7569f8a04643bbd9212436e3be04aef
requires_dist:
- jinja2
- jsonschema>=3.0
- narwhals>=1.5.2
- packaging
- typing-extensions>=4.10.0 ; python_full_version < '3.13'
- altair-tiles>=0.3.0 ; extra == 'all'
- anywidget>=0.9.0 ; extra == 'all'
- numpy ; extra == 'all'
- pandas>=0.25.3 ; extra == 'all'
- pyarrow>=11 ; extra == 'all'
- vega-datasets>=0.9.0 ; extra == 'all'
- vegafusion[embed]>=1.6.6 ; extra == 'all'
- vl-convert-python>=1.6.0 ; extra == 'all'
- geopandas ; extra == 'dev'
- hatch ; extra == 'dev'
- ibis-framework[polars] ; extra == 'dev'
- ipython[kernel] ; extra == 'dev'
- mistune ; extra == 'dev'
- mypy ; extra == 'dev'
- pandas-stubs ; extra == 'dev'
- pandas>=0.25.3 ; extra == 'dev'
- polars>=0.20.3 ; extra == 'dev'
- pytest ; extra == 'dev'
- pytest-cov ; extra == 'dev'
- pytest-xdist[psutil]~=3.5 ; extra == 'dev'
- ruff>=0.6.0 ; extra == 'dev'
- types-jsonschema ; extra == 'dev'
- types-setuptools ; extra == 'dev'
- docutils ; extra == 'doc'
- jinja2 ; extra == 'doc'
- myst-parser ; extra == 'doc'
- numpydoc ; extra == 'doc'
- pillow>=9,<10 ; extra == 'doc'
- pydata-sphinx-theme>=0.14.1 ; extra == 'doc'
- scipy ; extra == 'doc'
- sphinx ; extra == 'doc'
- sphinx-copybutton ; extra == 'doc'
- sphinx-design ; extra == 'doc'
- sphinxext-altair ; extra == 'doc'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl
name: annotated-doc
version: 0.0.4
sha256: 571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl
name: annotated-types
version: 0.7.0
sha256: 1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53
requires_dist:
- typing-extensions>=4.0.0 ; python_full_version < '3.9'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/1b/b4/f7e396030e3b11394436358ca258a81d6010106582422f23443c16ca1873/anyio-4.5.2-py3-none-any.whl
name: anyio
version: 4.5.2
sha256: c011ee36bc1e8ba40e5a81cb9df91925c218fe9b778554e0b56a21e1b5d4716f
requires_dist:
- idna>=2.8
- sniffio>=1.1
- exceptiongroup>=1.0.2 ; python_full_version < '3.11'
- typing-extensions>=4.1 ; python_full_version < '3.11'
- packaging ; extra == 'doc'
- sphinx~=7.4 ; extra == 'doc'
- sphinx-rtd-theme ; extra == 'doc'
- sphinx-autodoc-typehints>=1.2.0 ; extra == 'doc'
- anyio[trio] ; extra == 'test'
- coverage[toml]>=7 ; extra == 'test'
- exceptiongroup>=1.2.0 ; extra == 'test'
- hypothesis>=4.0 ; extra == 'test'
- psutil>=5.9 ; extra == 'test'
- pytest>=7.0 ; extra == 'test'
- pytest-mock>=3.6.1 ; extra == 'test'
- trustme ; extra == 'test'
- uvloop>=0.21.0b1 ; platform_python_implementation == 'CPython' and sys_platform != 'win32' and extra == 'test'
- truststore>=0.9.1 ; python_full_version >= '3.10' and extra == 'test'
- trio>=0.26.1 ; extra == 'trio'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl
name: attrs
version: 25.3.0
sha256: 427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3
requires_dist:
- cloudpickle ; platform_python_implementation == 'CPython' and extra == 'benchmark'
- hypothesis ; extra == 'benchmark'
- mypy>=1.11.1 ; python_full_version >= '3.10' and platform_python_implementation == 'CPython' and extra == 'benchmark'
- pympler ; extra == 'benchmark'
- pytest-codspeed ; extra == 'benchmark'
- pytest-mypy-plugins ; python_full_version >= '3.10' and platform_python_implementation == 'CPython' and extra == 'benchmark'
- pytest-xdist[psutil] ; extra == 'benchmark'
- pytest>=4.3.0 ; extra == 'benchmark'
- cloudpickle ; platform_python_implementation == 'CPython' and extra == 'cov'
- coverage[toml]>=5.3 ; extra == 'cov'
- hypothesis ; extra == 'cov'
- mypy>=1.11.1 ; python_full_version >= '3.10' and platform_python_implementation == 'CPython' and extra == 'cov'
- pympler ; extra == 'cov'
- pytest-mypy-plugins ; python_full_version >= '3.10' and platform_python_implementation == 'CPython' and extra == 'cov'
- pytest-xdist[psutil] ; extra == 'cov'
- pytest>=4.3.0 ; extra == 'cov'
- cloudpickle ; platform_python_implementation == 'CPython' and extra == 'dev'
- hypothesis ; extra == 'dev'
- mypy>=1.11.1 ; python_full_version >= '3.10' and platform_python_implementation == 'CPython' and extra == 'dev'
- pre-commit-uv ; extra == 'dev'
- pympler ; extra == 'dev'
- pytest-mypy-plugins ; python_full_version >= '3.10' and platform_python_implementation == 'CPython' and extra == 'dev'
- pytest-xdist[psutil] ; extra == 'dev'
- pytest>=4.3.0 ; extra == 'dev'
- cogapp ; extra == 'docs'
- furo ; extra == 'docs'
- myst-parser ; extra == 'docs'
- sphinx ; extra == 'docs'
- sphinx-notfound-page ; extra == 'docs'
- sphinxcontrib-towncrier ; extra == 'docs'
- towncrier ; extra == 'docs'
- cloudpickle ; platform_python_implementation == 'CPython' and extra == 'tests'
- hypothesis ; extra == 'tests'
- mypy>=1.11.1 ; python_full_version >= '3.10' and platform_python_implementation == 'CPython' and extra == 'tests'
- pympler ; extra == 'tests'
- pytest-mypy-plugins ; python_full_version >= '3.10' and platform_python_implementation == 'CPython' and extra == 'tests'
- pytest-xdist[psutil] ; extra == 'tests'
- pytest>=4.3.0 ; extra == 'tests'
- mypy>=1.11.1 ; python_full_version >= '3.10' and platform_python_implementation == 'CPython' and extra == 'tests-mypy'
- pytest-mypy-plugins ; python_full_version >= '3.10' and platform_python_implementation == 'CPython' and extra == 'tests-mypy'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl
name: babel
version: 2.17.0
@ -479,11 +288,6 @@ packages:
- pytz ; extra == 'dev'
- setuptools ; extra == 'dev'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/bb/2a/10164ed1f31196a2f7f3799368a821765c62851ead0e630ab52b8e14b4d0/blinker-1.8.2-py3-none-any.whl
name: blinker
version: 1.8.2
sha256: 1779309f71bf239144b9399d06ae925637cf6634cf6bd131104184531bf67c01
requires_python: '>=3.8'
- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_8.conda
sha256: c30daba32ddebbb7ded490f0e371eae90f51e72db620554089103b4a6934b0d5
md5: 51a19bba1b8ebfb60df25cde030b7ebc
@ -514,11 +318,6 @@ packages:
purls: []
size: 146519
timestamp: 1767500828366
- pypi: https://files.pythonhosted.org/packages/72/76/20fa66124dbe6be5cafeb312ece67de6b61dd91a0247d1ea13db4ebb33c2/cachetools-5.5.2-py3-none-any.whl
name: cachetools
version: 5.5.2
sha256: d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a
requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl
name: certifi
version: 2026.1.4
@ -702,48 +501,6 @@ packages:
version: 2.0.0
sha256: 7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl
name: exceptiongroup
version: 1.3.1
sha256: a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598
requires_dist:
- typing-extensions>=4.6.0 ; python_full_version < '3.13'
- pytest>=6 ; extra == 'test'
requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/3e/57/aa70121b5008f44031be645a61a7c4abc24e0e888ad3fc8fda916f4d188e/fastapi-0.124.4-py3-none-any.whl
name: fastapi
version: 0.124.4
sha256: 6d1e703698443ccb89e50abe4893f3c84d9d6689c0cf1ca4fad6d3c15cf69f15
requires_dist:
- starlette>=0.40.0,<0.51.0
- pydantic>=1.7.4,!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0
- typing-extensions>=4.8.0
- annotated-doc>=0.0.2
- fastapi-cli[standard]>=0.0.8 ; extra == 'standard'
- httpx>=0.23.0,<1.0.0 ; extra == 'standard'
- jinja2>=3.1.5 ; extra == 'standard'
- python-multipart>=0.0.18 ; extra == 'standard'
- email-validator>=2.0.0 ; extra == 'standard'
- uvicorn[standard]>=0.12.0 ; extra == 'standard'
- fastapi-cli[standard-no-fastapi-cloud-cli]>=0.0.8 ; extra == 'standard-no-fastapi-cloud-cli'
- httpx>=0.23.0,<1.0.0 ; extra == 'standard-no-fastapi-cloud-cli'
- jinja2>=3.1.5 ; extra == 'standard-no-fastapi-cloud-cli'
- python-multipart>=0.0.18 ; extra == 'standard-no-fastapi-cloud-cli'
- email-validator>=2.0.0 ; extra == 'standard-no-fastapi-cloud-cli'
- uvicorn[standard]>=0.12.0 ; extra == 'standard-no-fastapi-cloud-cli'
- fastapi-cli[standard]>=0.0.8 ; extra == 'all'
- httpx>=0.23.0,<1.0.0 ; extra == 'all'
- jinja2>=3.1.5 ; extra == 'all'
- python-multipart>=0.0.18 ; extra == 'all'
- itsdangerous>=1.1.0 ; extra == 'all'
- pyyaml>=5.3.1 ; extra == 'all'
- ujson>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0 ; extra == 'all'
- orjson>=3.2.1 ; extra == 'all'
- email-validator>=2.0.0 ; extra == 'all'
- uvicorn[standard]>=0.12.0 ; extra == 'all'
- pydantic-settings>=2.0.0 ; extra == 'all'
- pydantic-extra-types>=2.0.0 ; extra == 'all'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/27/8e/ce64bc647728ee26bfffa9987fb375e7c99bba54b632404bc0d61b6e9fc2/fastparquet-2024.2.0-cp38-cp38-macosx_11_0_arm64.whl
name: fastparquet
version: 2024.2.0
@ -984,70 +741,6 @@ packages:
version: 1.0.0
sha256: 929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216
requires_python: '>=2.6,!=3.0.*,!=3.1.*,!=3.2.*'
- pypi: https://files.pythonhosted.org/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl
name: gitdb
version: 4.0.12
sha256: 67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf
requires_dist:
- smmap>=3.0.1,<6
requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/6a/09/e21df6aef1e1ffc0c816f0522ddc3f6dcded766c3261813131c78a704470/gitpython-3.1.46-py3-none-any.whl
name: gitpython
version: 3.1.46
sha256: 79812ed143d9d25b6d176a10bb511de0f9c67b1fa641d82097b0ab90398a2058
requires_dist:
- gitdb>=4.0.1,<5
- typing-extensions>=3.10.0.2 ; python_full_version < '3.10'
- coverage[toml] ; extra == 'test'
- ddt>=1.1.1,!=1.4.3 ; extra == 'test'
- mock ; python_full_version < '3.8' and extra == 'test'
- mypy==1.18.2 ; python_full_version >= '3.9' and extra == 'test'
- pre-commit ; extra == 'test'
- pytest>=7.3.1 ; extra == 'test'
- pytest-cov ; extra == 'test'
- pytest-instafail ; extra == 'test'
- pytest-mock ; extra == 'test'
- pytest-sugar ; extra == 'test'
- typing-extensions ; python_full_version < '3.11' and extra == 'test'
- sphinx>=7.1.2,<7.2 ; extra == 'doc'
- sphinx-rtd-theme ; extra == 'doc'
- sphinx-autodoc-typehints ; extra == 'doc'
requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl
name: h11
version: 0.16.0
sha256: 63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl
name: httpcore
version: 1.0.9
sha256: 2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55
requires_dist:
- certifi
- h11>=0.16
- anyio>=4.0,<5.0 ; extra == 'asyncio'
- h2>=3,<5 ; extra == 'http2'
- socksio==1.* ; extra == 'socks'
- trio>=0.22.0,<1.0 ; extra == 'trio'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl
name: httpx
version: 0.28.1
sha256: d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad
requires_dist:
- anyio
- certifi
- httpcore==1.*
- idna
- brotli ; platform_python_implementation == 'CPython' and extra == 'brotli'
- brotlicffi ; platform_python_implementation != 'CPython' and extra == 'brotli'
- click==8.* ; extra == 'cli'
- pygments==2.* ; extra == 'cli'
- rich>=10,<14 ; extra == 'cli'
- h2>=3,<5 ; extra == 'http2'
- socksio==1.* ; extra == 'socks'
- zstandard>=0.18.0 ; extra == 'zstd'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/b6/cd/5b3334d39276067f54618ce0d0b48ed69d91352fbf137468c7095170d0e5/hyperopt-0.2.7-py2.py3-none-any.whl
name: hyperopt
version: 0.2.7
@ -1172,42 +865,6 @@ packages:
version: 1.4.2
sha256: 06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/69/4a/4f9dbeb84e8850557c02365a0eee0649abe5eb1d84af92a25731c6c0f922/jsonschema-4.23.0-py3-none-any.whl
name: jsonschema
version: 4.23.0
sha256: fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566
requires_dist:
- attrs>=22.2.0
- importlib-resources>=1.4.0 ; python_full_version < '3.9'
- jsonschema-specifications>=2023.3.6
- pkgutil-resolve-name>=1.3.10 ; python_full_version < '3.9'
- referencing>=0.28.4
- rpds-py>=0.7.1
- fqdn ; extra == 'format'
- idna ; extra == 'format'
- isoduration ; extra == 'format'
- jsonpointer>1.13 ; extra == 'format'
- rfc3339-validator ; extra == 'format'
- rfc3987 ; extra == 'format'
- uri-template ; extra == 'format'
- webcolors>=1.11 ; extra == 'format'
- fqdn ; extra == 'format-nongpl'
- idna ; extra == 'format-nongpl'
- isoduration ; extra == 'format-nongpl'
- jsonpointer>1.13 ; extra == 'format-nongpl'
- rfc3339-validator ; extra == 'format-nongpl'
- rfc3986-validator>0.1.0 ; extra == 'format-nongpl'
- uri-template ; extra == 'format-nongpl'
- webcolors>=24.6.0 ; extra == 'format-nongpl'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl
name: jsonschema-specifications
version: 2023.12.1
sha256: 87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c
requires_dist:
- importlib-resources>=1.4.0 ; python_full_version < '3.9'
- referencing>=0.31.0
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/14/a7/bb8ab10e12cc8764f4da0245d72dee4731cc720bdec0f085d5e9c6005b98/kiwisolver-1.4.7-cp38-cp38-macosx_11_0_arm64.whl
name: kiwisolver
version: 1.4.7
@ -1536,26 +1193,6 @@ packages:
version: 1.1.0
sha256: 1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/79/3f/8d450588206b437dd239a6d44230c63095e71135bd95d5a74347d07adbd5/narwhals-1.42.1-py3-none-any.whl
name: narwhals
version: 1.42.1
sha256: 7a270d44b94ccdb277a799ae890c42e8504c537c1849f195eb14717c6184977a
requires_dist:
- cudf>=24.10.0 ; extra == 'cudf'
- dask[dataframe]>=2024.8 ; extra == 'dask'
- duckdb>=1.0 ; extra == 'duckdb'
- ibis-framework>=6.0.0 ; extra == 'ibis'
- packaging ; extra == 'ibis'
- pyarrow-hotfix ; extra == 'ibis'
- rich ; extra == 'ibis'
- modin ; extra == 'modin'
- pandas>=0.25.3 ; extra == 'pandas'
- polars>=0.20.3 ; extra == 'polars'
- pyarrow>=11.0.0 ; extra == 'pyarrow'
- pyspark>=3.5.0 ; extra == 'pyspark'
- pyspark[connect]>=3.5.0 ; extra == 'pyspark-connect'
- sqlframe>=3.22.0 ; extra == 'sqlframe'
requires_python: '>=3.8'
- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda
sha256: 3fde293232fa3fca98635e1167de6b7c7fda83caf24b9d6c91ec9eefb4f4d586
md5: 47e340acb35de30501a76c7c799c41d7
@ -1709,10 +1346,10 @@ packages:
purls: []
size: 3108371
timestamp: 1762839712322
- pypi: https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl
name: packaging
version: '24.2'
sha256: 09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759
version: '25.0'
sha256: 29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/53/c3/f8e87361f7fdf42012def602bfa2a593423c729f5cb7c97aed7f51be66ac/pandas-2.0.3-cp38-cp38-macosx_11_0_arm64.whl
name: pandas
@ -1960,11 +1597,6 @@ packages:
- pkg:pypi/pip?source=hash-mapping
size: 1243168
timestamp: 1730203795600
- pypi: https://files.pythonhosted.org/packages/c9/5c/3d4882ba113fd55bdba9326c1e4c62a15e674a2501de4869e6bd6301f87e/pkgutil_resolve_name-1.3.10-py3-none-any.whl
name: pkgutil-resolve-name
version: 1.3.10
sha256: ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e
requires_python: '>=3.6'
- pypi: https://files.pythonhosted.org/packages/85/e4/07c80521879c2d15f321465ac24c70efe2381378c00bf5e56a0f4fbac8cd/protobuf-5.29.5-cp38-abi3-manylinux2014_x86_64.whl
name: protobuf
version: 5.29.5
@ -2003,44 +1635,6 @@ packages:
- pytz ; extra == 'test'
- pandas ; extra == 'test'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl
name: pydantic
version: 2.10.6
sha256: 427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584
requires_dist:
- annotated-types>=0.6.0
- pydantic-core==2.27.2
- typing-extensions>=4.12.2
- email-validator>=2.0.0 ; extra == 'email'
- tzdata ; python_full_version >= '3.9' and sys_platform == 'win32' and extra == 'timezone'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/f4/20/26c549249769ed84877f862f7bb93f89a6ee08b4bee1ed8781616b7fbb5e/pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl
name: pydantic-core
version: 2.27.2
sha256: 521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320
requires_dist:
- typing-extensions>=4.6.0,!=4.7.0
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/f7/a3/5f19bc495793546825ab160e530330c2afcee2281c02b5ffafd0b32ac05e/pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
name: pydantic-core
version: 2.27.2
sha256: 9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5
requires_dist:
- typing-extensions>=4.6.0,!=4.7.0
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/ab/4c/b888e6cf58bd9db9c93f40d1c6be8283ff49d88919231afe93a6bcf61626/pydeck-0.9.1-py2.py3-none-any.whl
name: pydeck
version: 0.9.1
sha256: b3f75ba0d273fc917094fa61224f3f6076ca8752b93d46faf3bcfd9f9d59b038
requires_dist:
- jinja2>=2.10.1
- numpy>=1.16.4
- pydeck-carto ; extra == 'carto'
- ipywidgets>=7,<8 ; extra == 'jupyter'
- traitlets>=4.3.2 ; extra == 'jupyter'
- ipython>=5.8.0 ; python_full_version < '3.4' and extra == 'jupyter'
- ipykernel>=5.1.2 ; python_full_version >= '3.4' and extra == 'jupyter'
requires_python: '>=3.8'
- conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.18.0-pyhd8ed1ab_0.conda
sha256: 78267adf4e76d0d64ea2ffab008c501156c108bb08fecb703816fb63e279780b
md5: b7f5c092b8f9800150d998a71b76d5a1
@ -2173,14 +1767,6 @@ packages:
purls: []
size: 313930
timestamp: 1765813902568
- pypi: https://files.pythonhosted.org/packages/b7/59/2056f61236782a2c86b33906c025d4f4a0b17be0161b63b70fd9e8775d36/referencing-0.35.1-py3-none-any.whl
name: referencing
version: 0.35.1
sha256: eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de
requires_dist:
- attrs>=22.2.0
- rpds-py>=0.7.0
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl
name: requests
version: 2.32.4
@ -2207,16 +1793,6 @@ packages:
- pkg:pypi/rich?source=hash-mapping
size: 185481
timestamp: 1730592349978
- pypi: https://files.pythonhosted.org/packages/54/63/47d34dc4ddb3da73e78e10c9009dcf8edc42d355a221351c05c822c2a50b/rpds_py-0.20.1-cp38-cp38-macosx_11_0_arm64.whl
name: rpds-py
version: 0.20.1
sha256: 3e310838a5801795207c66c73ea903deda321e6146d6f282e85fa7e3e4854804
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/c4/ce/af016c81fda833bf125b20d1677d816f230cad2ab189f46bcbfea3c7a375/rpds_py-0.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
name: rpds-py
version: 0.20.1
sha256: 02a0629ec053fc013808a85178524e3cb63a61dbc35b22499870194a63578fb9
requires_python: '>=3.8'
- conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.14.12-h4196e79_0.conda
noarch: python
sha256: 26c9f201a249cf54acacfa5055e96ad6e8e272cac3a25ac7caee8fe048e66b5a
@ -2423,16 +1999,6 @@ packages:
version: 1.17.0
sha256: 4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274
requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*'
- pypi: https://files.pythonhosted.org/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl
name: smmap
version: 5.0.2
sha256: b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e
requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl
name: sniffio
version: 1.3.1
sha256: 2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2
requires_python: '>=3.7'
- pypi: https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl
name: snowballstemmer
version: 3.0.1
@ -2554,46 +2120,6 @@ packages:
- docutils-stubs ; extra == 'lint'
- pytest ; extra == 'test'
requires_python: '>=3.5'
- pypi: https://files.pythonhosted.org/packages/b6/c5/7ae467eeddb57260c8ce17a3a09f9f5edba35820fc022d7c55b7decd5d3a/starlette-0.44.0-py3-none-any.whl
name: starlette
version: 0.44.0
sha256: 19edeb75844c16dcd4f9dd72f22f9108c1539f3fc9c4c88885654fef64f85aea
requires_dist:
- anyio>=3.4.0,<5
- typing-extensions>=3.10.0 ; python_full_version < '3.10'
- httpx>=0.27.0,<0.29.0 ; extra == 'full'
- itsdangerous ; extra == 'full'
- jinja2 ; extra == 'full'
- python-multipart>=0.0.18 ; extra == 'full'
- pyyaml ; extra == 'full'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/9a/14/857d0734989f3d26f2f965b2e3f67568ea7a6e8a60cb9c1ed7f774b6d606/streamlit-1.40.1-py2.py3-none-any.whl
name: streamlit
version: 1.40.1
sha256: b9d7a317a0cc88edd7857c7e07dde9cf95647d3ae51cbfa8a3db82fbb8a2990d
requires_dist:
- altair>=4.0,<6
- blinker>=1.0.0,<2
- cachetools>=4.0,<6
- click>=7.0,<9
- numpy>=1.20,<3
- packaging>=20,<25
- pandas>=1.4.0,<3
- pillow>=7.1.0,<12
- protobuf>=3.20,<6
- pyarrow>=7.0
- requests>=2.27,<3
- rich>=10.14.0,<14
- tenacity>=8.1.0,<10
- toml>=0.10.1,<2
- typing-extensions>=4.3.0,<5
- gitpython>=3.0.7,!=3.1.19,<4
- pydeck>=0.8.0b4,<1
- tornado>=6.0.3,<7
- watchdog>=2.1.5,<7 ; sys_platform != 'darwin'
- snowflake-snowpark-python[modin]>=1.17.0 ; python_full_version < '3.12' and extra == 'snowflake'
- snowflake-connector-python>=2.8.0 ; python_full_version < '3.12' and extra == 'snowflake'
requires_python: '>=3.8,!=3.9.7'
- pypi: https://files.pythonhosted.org/packages/99/ff/c87e0622b1dadea79d2fb0b25ade9ed98954c9033722eb707053d310d4f3/sympy-1.13.3-py3-none-any.whl
name: sympy
version: 1.13.3
@ -2603,17 +2129,6 @@ packages:
- pytest>=7.1.0 ; extra == 'dev'
- hypothesis>=6.70.0 ; extra == 'dev'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/b6/cb/b86984bed139586d01532a587464b5805f12e397594f19f931c4c2fbfa61/tenacity-9.0.0-py3-none-any.whl
name: tenacity
version: 9.0.0
sha256: 93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539
requires_dist:
- reno ; extra == 'doc'
- sphinx ; extra == 'doc'
- pytest ; extra == 'test'
- tornado>=4.5 ; extra == 'test'
- typeguard ; extra == 'test'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/44/71/f3e7c9b2ab67e28c572ab4e9d5fa3499e0d252650f96d8a3a03e26677f53/tensorboardX-2.6.2.2-py2.py3-none-any.whl
name: tensorboardx
version: 2.6.2.2
@ -2652,11 +2167,6 @@ packages:
purls: []
size: 3125484
timestamp: 1763055028377
- pypi: https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl
name: toml
version: 0.10.2
sha256: 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b
requires_python: '>=2.6,!=3.0.*,!=3.1.*,!=3.2.*'
- pypi: https://files.pythonhosted.org/packages/a9/71/45aac46b75742e08d2d6f9fc2b612223b5e36115b8b2ed673b23c21b5387/torch-2.4.1-cp38-cp38-manylinux1_x86_64.whl
name: torch
version: 2.4.1
@ -2709,16 +2219,6 @@ packages:
- opt-einsum>=3.3 ; extra == 'opt-einsum'
- optree>=0.11.0 ; extra == 'optree'
requires_python: '>=3.8.0'
- pypi: https://files.pythonhosted.org/packages/22/55/b78a464de78051a30599ceb6983b01d8f732e6f69bf37b4ed07f642ac0fc/tornado-6.4.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
name: tornado
version: 6.4.2
sha256: bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/26/7e/71f604d8cea1b58f82ba3590290b66da1e72d840aeb37e0d5f7291bd30db/tornado-6.4.2-cp38-abi3-macosx_10_9_universal2.whl
name: tornado
version: 6.4.2
sha256: e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1
requires_python: '>=3.8'
- conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.1-pyhd8ed1ab_0.conda
sha256: 5673b7104350a6998cb86cccf1d0058217d86950e8d6c927d8530606028edb1d
md5: 4085c9db273a148e149c03627350e22c
@ -2838,29 +2338,6 @@ packages:
- pysocks>=1.5.6,!=1.5.7,<2.0 ; extra == 'socks'
- zstandard>=0.18.0 ; extra == 'zstd'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/98/79/2e2620337ef1e4ef7a058b351603b765f59ac28e6e3ac7c5e7cdee9ea1ab/uvicorn-0.33.0-py3-none-any.whl
name: uvicorn
version: 0.33.0
sha256: 2c30de4aeea83661a520abab179b24084a0019c0c1bbe137e5409f741cbde5f8
requires_dist:
- click>=7.0
- h11>=0.8
- typing-extensions>=4.0 ; python_full_version < '3.11'
- colorama>=0.4 ; sys_platform == 'win32' and extra == 'standard'
- httptools>=0.6.3 ; extra == 'standard'
- python-dotenv>=0.13 ; extra == 'standard'
- pyyaml>=5.1 ; extra == 'standard'
- uvloop>=0.14.0,!=0.15.0,!=0.15.1 ; platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32' and extra == 'standard'
- watchfiles>=0.13 ; extra == 'standard'
- websockets>=10.4 ; extra == 'standard'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/01/d2/c8931ff840a7e5bd5dcb93f2bb2a1fd18faf8312e9f7f53ff1cf76ecc8ed/watchdog-4.0.2-py3-none-manylinux2014_x86_64.whl
name: watchdog
version: 4.0.2
sha256: c0b14488bd336c5b1845cee83d3e631a1f8b4e9c5091ec539406e4a324f882d8
requires_dist:
- pyyaml>=3.10 ; extra == 'watchmedo'
requires_python: '>=3.8'
- pypi: https://files.pythonhosted.org/packages/fd/21/0a674dfe66e9df9072c46269c882e9f901d36d987d8ea50ead033a9c1e01/werkzeug-2.3.8-py3-none-any.whl
name: werkzeug
version: 2.3.8

View File

@ -24,7 +24,3 @@ openpyxl = ">=3.1.5, <4"
python-dotenv = ">=1.0.1, <2"
pyarrow = ">=17.0.0, <18"
fastparquet = ">=2024.2.0, <2025"
fastapi = ">=0.124.4, <0.125"
streamlit = ">=1.40.1, <2"
httpx = ">=0.28.1, <0.29"
uvicorn = ">=0.33.0, <0.34"

View File

@ -1,153 +0,0 @@
"""最终训练数据处理脚本train:val = 9:1无测试集"""
from pathlib import Path
import pandas as pd
import typer
from loguru import logger
from lnp_ml.config import INTERIM_DATA_DIR, PROCESSED_DATA_DIR
from lnp_ml.dataset import (
process_dataframe,
SMILES_COL,
COMP_COLS,
HELP_COLS,
TARGET_REGRESSION,
TARGET_CLASSIFICATION_PDI,
TARGET_CLASSIFICATION_EE,
TARGET_TOXIC,
TARGET_BIODIST,
get_phys_cols,
get_exp_cols,
)
app = typer.Typer()
@app.command()
def main(
input_path: Path = INTERIM_DATA_DIR / "internal_corrected.csv",
output_dir: Path = PROCESSED_DATA_DIR / "final",
train_ratio: float = 0.9,
seed: int = 42,
):
"""
处理原始数据并划分训练/验证集无测试集
用于最终训练使用所有数据
输出文件:
- final/train.parquet: 训练集 (90%)
- final/val.parquet: 验证集 (10%)
- final/feature_columns.txt: 特征列名配置
"""
logger.info(f"Loading data from {input_path}")
df = pd.read_csv(input_path)
logger.info(f"Loaded {len(df)} samples")
# 处理数据
logger.info("Processing dataframe...")
df = process_dataframe(df)
# 定义要保留的列
phys_cols = get_phys_cols()
exp_cols = get_exp_cols()
keep_cols = (
[SMILES_COL]
+ COMP_COLS
+ phys_cols
+ HELP_COLS
+ exp_cols
+ TARGET_REGRESSION
+ TARGET_CLASSIFICATION_PDI
+ TARGET_CLASSIFICATION_EE
+ [TARGET_TOXIC]
+ TARGET_BIODIST
)
# 只保留存在的列
keep_cols = [c for c in keep_cols if c in df.columns]
df = df[keep_cols]
# 随机打乱并划分
logger.info(f"Splitting dataset (train:val = {train_ratio}:{1-train_ratio:.1f})...")
df = df.sample(frac=1, random_state=seed).reset_index(drop=True)
n = len(df)
n_train = int(n * train_ratio)
train_df = df.iloc[:n_train]
val_df = df.iloc[n_train:]
logger.info(f"Train: {len(train_df)}, Val: {len(val_df)}")
# 保存
output_dir.mkdir(parents=True, exist_ok=True)
train_path = output_dir / "train.parquet"
val_path = output_dir / "val.parquet"
train_df.to_parquet(train_path, index=False)
val_df.to_parquet(val_path, index=False)
logger.success(f"Saved train to {train_path}")
logger.success(f"Saved val to {val_path}")
# 保存列名配置
config_path = output_dir / "feature_columns.txt"
with open(config_path, "w") as f:
f.write("# Feature columns configuration (final training)\n\n")
f.write(f"# SMILES\n{SMILES_COL}\n\n")
f.write(f"# comp token [{len(COMP_COLS)}]\n")
f.write("\n".join(COMP_COLS) + "\n\n")
f.write(f"# phys token [{len(phys_cols)}]\n")
f.write("\n".join(phys_cols) + "\n\n")
f.write(f"# help token [{len(HELP_COLS)}]\n")
f.write("\n".join(HELP_COLS) + "\n\n")
f.write(f"# exp token [{len(exp_cols)}]\n")
f.write("\n".join(exp_cols) + "\n\n")
f.write("# Targets\n")
f.write("## Regression\n")
f.write("\n".join(TARGET_REGRESSION) + "\n")
f.write("## PDI classification\n")
f.write("\n".join(TARGET_CLASSIFICATION_PDI) + "\n")
f.write("## EE classification\n")
f.write("\n".join(TARGET_CLASSIFICATION_EE) + "\n")
f.write("## Toxic\n")
f.write(f"{TARGET_TOXIC}\n")
f.write("## Biodistribution\n")
f.write("\n".join(TARGET_BIODIST) + "\n")
logger.success(f"Saved feature config to {config_path}")
# 打印统计信息
logger.info("\n=== Dataset Statistics ===")
logger.info(f"Total samples: {n}")
logger.info(f"SMILES unique: {df[SMILES_COL].nunique()}")
# 缺失值统计
logger.info("\nMissing values in targets:")
for col in TARGET_REGRESSION + [TARGET_TOXIC]:
if col in df.columns:
missing = df[col].isna().sum()
logger.info(f" {col}: {missing} ({100*missing/n:.1f}%)")
# PDI 分布
if all(c in df.columns for c in TARGET_CLASSIFICATION_PDI):
pdi_sum = df[TARGET_CLASSIFICATION_PDI].sum()
logger.info(f"\nPDI distribution:")
for col, count in pdi_sum.items():
logger.info(f" {col}: {int(count)}")
# EE 分布
if all(c in df.columns for c in TARGET_CLASSIFICATION_EE):
ee_sum = df[TARGET_CLASSIFICATION_EE].sum()
logger.info(f"\nEE distribution:")
for col, count in ee_sum.items():
logger.info(f" {col}: {int(count)}")
if __name__ == "__main__":
app()