update
This commit is contained in:
@ -60,31 +60,6 @@ def calculate_molecular_weight_from_smiles(smiles):
|
|||||||
st.error(f"SMILES分子量计算错误: {str(e)}")
|
st.error(f"SMILES分子量计算错误: {str(e)}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def generate_molecule_image(inchi=None, smiles=None):
|
|
||||||
"""从SMILES生成分子结构图"""
|
|
||||||
return None
|
|
||||||
try:
|
|
||||||
if inchi:
|
|
||||||
mol = Chem.MolFromInchi(inchi)
|
|
||||||
elif smiles:
|
|
||||||
mol = Chem.MolFromSmiles(smiles)
|
|
||||||
else:
|
|
||||||
st.error("必须提供InChI或SMILES字符串")
|
|
||||||
return None
|
|
||||||
if mol:
|
|
||||||
# 生成分子图像
|
|
||||||
img = Draw.MolToImage(mol, size=(300, 300))
|
|
||||||
# 将图像转换为字节流
|
|
||||||
img_buffer = BytesIO()
|
|
||||||
img.save("a.png")
|
|
||||||
img.save(img_buffer, format='PNG')
|
|
||||||
img_buffer.seek(0)
|
|
||||||
return img_buffer
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
except Exception as e:
|
|
||||||
st.error(f"分子结构图生成错误: {str(e)}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_pubchem_properties(compound):
|
def get_pubchem_properties(compound):
|
||||||
"""从PubChem获取密度、熔点、沸点信息"""
|
"""从PubChem获取密度、熔点、沸点信息"""
|
||||||
@ -144,16 +119,6 @@ def get_pubchem_properties(compound):
|
|||||||
'boiling_point': None
|
'boiling_point': None
|
||||||
}
|
}
|
||||||
|
|
||||||
def is_liquid_at_room_temp(melting_point):
|
|
||||||
"""判断常温下是否为液体(假设常温为25°C)"""
|
|
||||||
if melting_point is None:
|
|
||||||
return False
|
|
||||||
try:
|
|
||||||
mp = float(melting_point)
|
|
||||||
return mp < 25 # 熔点低于25°C认为是液体
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def sync_calculations(compound_data, mmol=None, mass=None, volume=None, changed_field=None):
|
def sync_calculations(compound_data, mmol=None, mass=None, volume=None, changed_field=None):
|
||||||
"""同步计算mmol、质量、体积"""
|
"""同步计算mmol、质量、体积"""
|
||||||
if not compound_data:
|
if not compound_data:
|
||||||
@ -315,17 +280,6 @@ with col2:
|
|||||||
st.markdown("### 其他数据")
|
st.markdown("### 其他数据")
|
||||||
st.page_link(f"https://pubchem.ncbi.nlm.nih.gov/compound/{data['cid']}",label="**访问PubChem**")
|
st.page_link(f"https://pubchem.ncbi.nlm.nih.gov/compound/{data['cid']}",label="**访问PubChem**")
|
||||||
st.image(f"https://pubchem.ncbi.nlm.nih.gov/image/imgsrv.fcgi?cid={data['cid']}&t=s","结构式")
|
st.image(f"https://pubchem.ncbi.nlm.nih.gov/image/imgsrv.fcgi?cid={data['cid']}&t=s","结构式")
|
||||||
# st.button("访问PubChem",on_click=lambda :st.dire)
|
|
||||||
# if data['melting_point']:
|
|
||||||
# st.metric("熔点 (°C)", data['melting_point'])
|
|
||||||
# # 显示分子结构图
|
|
||||||
# if data.get('inchi') or data.get('smiles'):
|
|
||||||
# st.markdown("分子结构图")
|
|
||||||
# mol_img = generate_molecule_image(inchi=data['inchi'], smiles=data['smiles'])
|
|
||||||
# if mol_img:
|
|
||||||
# st.image(mol_img, caption="分子键线式结构图", width=150)
|
|
||||||
# else:
|
|
||||||
# st.info("无法生成分子结构图")
|
|
||||||
|
|
||||||
# 添加熔沸点信息的展开区域
|
# 添加熔沸点信息的展开区域
|
||||||
if data.get('melting_point_src') or data.get('boiling_point_src'):
|
if data.get('melting_point_src') or data.get('boiling_point_src'):
|
||||||
@ -357,9 +311,6 @@ with col2:
|
|||||||
melting_point = re.search(r'\d*\.\d+', melting_data[0])
|
melting_point = re.search(r'\d*\.\d+', melting_data[0])
|
||||||
if melting_point:
|
if melting_point:
|
||||||
melting_point = float(melting_point.group())
|
melting_point = float(melting_point.group())
|
||||||
is_liquid = is_liquid_at_room_temp(melting_point)
|
|
||||||
else:
|
|
||||||
is_liquid = False
|
|
||||||
|
|
||||||
# 检测值变化并执行计算
|
# 检测值变化并执行计算
|
||||||
def handle_change(field_name, new_value, current_value):
|
def handle_change(field_name, new_value, current_value):
|
||||||
@ -427,10 +378,7 @@ with col2:
|
|||||||
# 密度显示选项
|
# 密度显示选项
|
||||||
show_density = False
|
show_density = False
|
||||||
if data['density_src']:
|
if data['density_src']:
|
||||||
if is_liquid:
|
show_density = st.checkbox("显示密度信息", value=False)
|
||||||
show_density = st.checkbox("显示密度信息", value=True)
|
|
||||||
else:
|
|
||||||
show_density = st.checkbox("显示密度信息", value=False)
|
|
||||||
|
|
||||||
if show_density:
|
if show_density:
|
||||||
import re
|
import re
|
@ -203,7 +203,38 @@ def calculate_properties(molecular_weight: float, amount_mmol: Optional[float] =
|
|||||||
|
|
||||||
def reaction_table_page():
|
def reaction_table_page():
|
||||||
"""反应表格页面"""
|
"""反应表格页面"""
|
||||||
st.header("⚗️ 反应表格")
|
st.header("反应表格")
|
||||||
|
|
||||||
|
with st.expander("**使用说明**", expanded=False):
|
||||||
|
st.markdown('''在下方的表格中,您可以输入反应数据,程序会尝试计算其余各项。当量为0时,该物质不参与当量计算。
|
||||||
|
### 立即计算
|
||||||
|
|
||||||
|
选中`立即计算`选项后,输入后立即尝试计算修改部分,您可以实时查看计算结果。但请注意,请勿同时修改多项内容。如果输入某项后计算未正确进行,这是潜在的缺陷,请反馈。
|
||||||
|
|
||||||
|
不保证在您主动修改计算结果后程序能正确处理(例如,程序算出质量后您主动修改),通常这会伴随着警告,但也有可能遗漏某些情况。
|
||||||
|
|
||||||
|
### 延迟计算
|
||||||
|
|
||||||
|
不选中`立即计算`后,在完成输入后,您可以点击“计算”按钮,程序会尝试计算所有可用的结果。
|
||||||
|
|
||||||
|
程序在计算时会检查是否有冗余数据,例如同时给定分子量、用量、质量,并拒绝在这种情况下计算。您可以选中`不使用检查`选项来禁用检查,但请保证数据自洽(即使得所有已知量之间的关系成立),否则会发生未定义行为。
|
||||||
|
|
||||||
|
如果计算后您想要修改或补充内容再次计算,请选中`不使用检查`选项。
|
||||||
|
''')
|
||||||
|
with st.expander("关于未定义行为"):
|
||||||
|
st.markdown('''程序内部计算顺序为
|
||||||
|
1. n -> mass
|
||||||
|
2. mass -> n
|
||||||
|
3. mass -> volumn
|
||||||
|
4. volumn -> mass
|
||||||
|
5. mass -> n
|
||||||
|
6. eqiv -> n
|
||||||
|
7. n -> mass
|
||||||
|
8. mass -> volumn
|
||||||
|
|
||||||
|
如果存在不自洽的数据,您可以通过上述内容预测程序行为。但这不应该在实际使用中依赖,因为在不同版本下实现可能发生变化。
|
||||||
|
|
||||||
|
''')
|
||||||
|
|
||||||
# 初始化数据
|
# 初始化数据
|
||||||
if 'reaction_data' not in st.session_state:
|
if 'reaction_data' not in st.session_state:
|
||||||
@ -222,12 +253,11 @@ def reaction_table_page():
|
|||||||
st.session_state.reaction_data = df
|
st.session_state.reaction_data = df
|
||||||
|
|
||||||
|
|
||||||
st.write("### 反应物质表格")
|
st.info(f"💡 当量为0时,该物质不参与当量计算。")
|
||||||
use_on_change = st.checkbox("是否立即计算", value=True)
|
use_on_change = st.checkbox("立即计算", value=True)
|
||||||
st.info(f"💡 当量为0时,该物质不参与当量计算。"+("如果保证表格已有内容自洽,可选中不使用检查。" if not use_on_change else ""))
|
|
||||||
if not use_on_change:
|
if not use_on_change:
|
||||||
st.button("计算",on_click=calc_reaction_data)
|
|
||||||
st.checkbox("不使用检查", value=False,key="no_check",)
|
st.checkbox("不使用检查", value=False,key="no_check",)
|
||||||
|
st.button("计算",on_click=calc_reaction_data,type="primary")
|
||||||
|
|
||||||
# 使用data_editor创建可编辑表格
|
# 使用data_editor创建可编辑表格
|
||||||
edited_data = st.data_editor(
|
edited_data = st.data_editor(
|
||||||
@ -359,7 +389,17 @@ def calc_reaction_data():
|
|||||||
fil = df["rho"].notna() & df["mass"].notna() & eqfil
|
fil = df["rho"].notna() & df["mass"].notna() & eqfil
|
||||||
df.loc[fil, "vol"] = df[fil]["mass"] / df[fil]["rho"] # g -> mL,再除以 g/mL
|
df.loc[fil, "vol"] = df[fil]["mass"] / df[fil]["rho"] # g -> mL,再除以 g/mL
|
||||||
|
|
||||||
df.columns = [
|
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# if "df" in locals():
|
||||||
|
# st.session_state.reaction_data = df
|
||||||
|
st.error("计算过程中出错,表格可能有误")
|
||||||
|
print("calc_reaction_data error:", traceback.format_exc())
|
||||||
|
return
|
||||||
|
finally:
|
||||||
|
if "df" in locals():
|
||||||
|
df.columns = [
|
||||||
"物质",
|
"物质",
|
||||||
"分子量",
|
"分子量",
|
||||||
"当量",
|
"当量",
|
||||||
@ -368,15 +408,8 @@ def calc_reaction_data():
|
|||||||
"密度(g/mL)",
|
"密度(g/mL)",
|
||||||
"体积(mL)",
|
"体积(mL)",
|
||||||
"备注"
|
"备注"
|
||||||
]
|
]
|
||||||
st.session_state.reaction_data = df
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
if "df" in locals():
|
|
||||||
st.session_state.reaction_data = df
|
st.session_state.reaction_data = df
|
||||||
st.error("计算过程中出错,表格可能有误")
|
|
||||||
print("calc_reaction_data error:", traceback.format_exc())
|
|
||||||
return
|
|
||||||
|
|
||||||
def recalculate_reaction_data():
|
def recalculate_reaction_data():
|
||||||
"""根据最近一次编辑的行及当量,推算其他未编辑行的用量,并更新质量/体积。"""
|
"""根据最近一次编辑的行及当量,推算其他未编辑行的用量,并更新质量/体积。"""
|
||||||
@ -579,8 +612,31 @@ def add_compound_to_reaction(compound:PubChemCompound):
|
|||||||
def compound_search_page():
|
def compound_search_page():
|
||||||
"""化合物搜索页面"""
|
"""化合物搜索页面"""
|
||||||
# 输入区域
|
# 输入区域
|
||||||
st.header("📝 输入查询条件")
|
|
||||||
|
|
||||||
|
|
||||||
|
with st.expander("**使用说明**"):
|
||||||
|
st.markdown("""
|
||||||
|
1. **选择搜索类型**:
|
||||||
|
- 名称: 输入化合物的常用名称或IUPAC名称
|
||||||
|
- 化学式: 输入分子式 (如 C2H6O)
|
||||||
|
- SMILES: 输入SMILES字符串 (如 CCO)
|
||||||
|
|
||||||
|
2. **输入查询条件**: 在输入框中输入相应的查询词
|
||||||
|
|
||||||
|
3. **点击搜索**: 系统将从PubChem数据库中查询匹配的化合物
|
||||||
|
|
||||||
|
4. **查看结果**:
|
||||||
|
- 基本信息包括名称、化学式、分子量和2D结构图
|
||||||
|
- 密度和熔沸点信息可在展开区域查看
|
||||||
|
- 计算器可帮助您计算用量、质量和体积的关系
|
||||||
|
|
||||||
|
### 示例查询
|
||||||
|
- **名称**: ethanol, water, glucose
|
||||||
|
- **化学式**: C2H6O, H2O, C6H12O6
|
||||||
|
- **SMILES**: CCO, O, C(C1C(C(C(C(O1)O)O)O)O)O
|
||||||
|
""")
|
||||||
|
|
||||||
|
st.header("查询条件")
|
||||||
col1, col2 = st.columns([1, 2])
|
col1, col2 = st.columns([1, 2])
|
||||||
|
|
||||||
with col1:
|
with col1:
|
||||||
@ -803,44 +859,18 @@ def compound_search_page():
|
|||||||
else:
|
else:
|
||||||
st.warning("无分子量数据,无法进行计算")
|
st.warning("无分子量数据,无法进行计算")
|
||||||
|
|
||||||
else:
|
|
||||||
# 显示使用说明
|
|
||||||
st.info("👈 请在左侧输入化合物信息开始查询")
|
|
||||||
|
|
||||||
st.markdown("""
|
|
||||||
### 🔍 使用说明
|
|
||||||
|
|
||||||
1. **选择搜索类型**:
|
|
||||||
- 名称: 输入化合物的常用名称或IUPAC名称
|
|
||||||
- 化学式: 输入分子式 (如 C2H6O)
|
|
||||||
- SMILES: 输入SMILES字符串 (如 CCO)
|
|
||||||
|
|
||||||
2. **输入查询条件**: 在输入框中输入相应的查询词
|
|
||||||
|
|
||||||
3. **点击搜索**: 系统将从PubChem数据库中查询匹配的化合物
|
|
||||||
|
|
||||||
4. **查看结果**:
|
|
||||||
- 基本信息包括名称、化学式、分子量和2D结构图
|
|
||||||
- 密度和熔沸点信息可在展开区域查看
|
|
||||||
- 计算器可帮助您计算用量、质量和体积的关系
|
|
||||||
|
|
||||||
### 📝 示例查询
|
|
||||||
- **名称**: ethanol, water, glucose
|
|
||||||
- **化学式**: C2H6O, H2O, C6H12O6
|
|
||||||
- **SMILES**: CCO, O, C(C1C(C(C(C(O1)O)O)O)O)O
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
st.set_page_config(
|
st.set_page_config(
|
||||||
page_title="PubChem化合物查询工具",
|
page_title="有机合成用量计算工具",
|
||||||
page_icon="🧪",
|
page_icon="🧪",
|
||||||
layout="wide"
|
layout="wide"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 侧边栏导航
|
# 侧边栏导航
|
||||||
with st.sidebar:
|
with st.sidebar:
|
||||||
st.title("🧪 化学工具")
|
|
||||||
page = st.radio(
|
page = st.radio(
|
||||||
"选择功能页面",
|
"选择功能页面",
|
||||||
["化合物查询", "反应表格"],
|
["化合物查询", "反应表格"],
|
||||||
|
Reference in New Issue
Block a user