初次提交

This commit is contained in:
lzy
2025-05-09 14:16:33 +08:00
commit 3a50afeec4
56 changed files with 9224 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
import os
import sys
sys.path.append('/home/ubuntu/sas0/lzy/multi_mcp_server')
from sci_mcp.material_mcp.mattergen_gen.mattergen_service import format_cif_content
cif_zip_path = '/home/ubuntu/sas0/lzy/multi_mcp_server/temp/material/20250508110506/generated_crystals_cif.zip'
if os.path.exists(cif_zip_path):
with open(cif_zip_path, 'rb') as f:
cif_content = f.read().decode('utf-8', errors='replace')
print(format_cif_content(cif_content))

View File

@@ -0,0 +1,166 @@
"""
Test script for mattergen_gen/material_gen_tools.py
This script tests the generate_material function from the material_gen_tools module.
"""
import sys
import asyncio
import unittest
import json
import re
from pathlib import Path
# 添加项目根目录到Python路径
sys.path.append(str(Path(__file__).resolve().parents[2]))
from sci_mcp.material_mcp.mattergen_gen.material_gen_tools import generate_material_MatterGen
class TestMatterGen(unittest.TestCase):
"""Test cases for MatterGen material generation tools."""
def test_unconditional_generation(self):
"""Test unconditional crystal structure generation."""
# 无条件生成(不指定属性)
result = generate_material_MatterGen(properties=None, batch_size=1, num_batches=1)
# 验证结果是否包含预期的关键信息
self.assertIsInstance(result, str)
# 检查结果是否包含一些常见的描述性文本
self.assertIn("Material", result)
self.assertIn("structures", result)
print("无条件生成结果示例:")
print(result[:500] + "...\n" if len(result) > 500 else result)
return result
# def test_single_property_generation(self):
# """Test crystal structure generation with a single property constraint."""
# # 单属性条件生成 - 使用化学系统属性
# properties = {"chemical_system": "Si-O"}
# result = generate_material(properties=properties, batch_size=1, num_batches=1)
# # 验证结果是否包含预期的关键信息
# self.assertIsInstance(result, str)
# # 检查结果是否包含相关的化学元素
# self.assertIn("Si-O", result)
# print("单属性条件生成结果示例:")
# print(result[:500] + "...\n" if len(result) > 500 else result)
# return result
# def test_multi_property_generation(self):
# """Test crystal structure generation with multiple property constraints."""
# # 多属性条件生成
# properties = {
# "chemical_system": "Fe-O",
# "space_group": 227 # 立方晶系空间群Fd-3m
# }
# result = generate_material(properties=properties, batch_size=1, num_batches=1)
# # 验证结果是否为字符串
# self.assertIsInstance(result, str)
# # 检查结果 - 可能是成功生成或错误信息
# if "Error" in result:
# # 如果是错误信息,验证它包含相关的属性信息
# self.assertIn("properties", result)
# print("多属性条件生成返回错误 (这是预期的,因为可能不支持多属性):")
# else:
# # 如果成功,验证包含相关元素
# self.assertIn("Fe", result)
# self.assertIn("O", result)
# print("多属性条件生成成功:")
# print(result[:500] + "...\n" if len(result) > 500 else result)
# return result
# def test_batch_generation(self):
# """Test generating multiple structures in batches."""
# # 测试批量生成
# result = generate_material(properties=None, batch_size=2, num_batches=2)
# # 验证结果是否包含预期的关键信息
# self.assertIsInstance(result, str)
# # 检查结果是否提到了批量生成
# self.assertIn("structures", result)
# print("批量生成结果示例:")
# print(result[:500] + "...\n" if len(result) > 500 else result)
# return result
# def test_guidance_factor(self):
# """Test the effect of diffusion guidance factor."""
# # 测试不同的diffusion_guidance_factor值
# properties = {"chemical_system": "Al-O"}
# # 使用较低的指导因子
# result_low = generate_material(
# properties=properties,
# batch_size=1,
# num_batches=1,
# diffusion_guidance_factor=1.0
# )
# # 使用较高的指导因子
# result_high = generate_material(
# properties=properties,
# batch_size=1,
# num_batches=1,
# diffusion_guidance_factor=3.0
# )
# # 验证两个结果都是有效的
# self.assertIsInstance(result_low, str)
# self.assertIsInstance(result_high, str)
# self.assertIn("Al-O", result_low)
# self.assertIn("Al-O", result_high)
# # 验证两个结果都提到了diffusion guidance factor
# self.assertIn("guidance factor", result_low)
# self.assertIn("guidance factor", result_high)
# print("不同指导因子的生成结果示例:")
# print("低指导因子 (1.0):")
# print(result_low[:300] + "...\n" if len(result_low) > 300 else result_low)
# print("高指导因子 (3.0):")
# print(result_high[:300] + "...\n" if len(result_high) > 300 else result_high)
# return result_low, result_high
# def test_invalid_properties(self):
# """Test handling of invalid properties."""
# # 测试无效属性
# invalid_properties = {"invalid_property": "value"}
# result = generate_material(properties=invalid_properties)
# # 验证结果是否为字符串
# self.assertIsInstance(result, str)
# # 检查结果 - 可能返回错误信息或尝试生成
# if "Error" in result:
# print("无效属性测试返回错误 (预期行为):")
# else:
# # 如果没有返回错误,至少应该包含我们请求的属性名称
# self.assertIn("invalid_property", result)
# print("无效属性测试尝试生成:")
# print(result)
# return result
def run_tests():
"""运行所有测试。"""
unittest.main()
if __name__ == "__main__":
run_tests()

View File

@@ -0,0 +1,73 @@
import asyncio
import sys
sys.path.append('/home/ubuntu/sas0/lzy/multi_mcp_server')
import matgl
from sci_mcp.material_mcp.matgl_tools import relax_crystal_structure_M3GNet,predict_formation_energy_M3GNet,run_molecular_dynamics_M3GNet,calculate_single_point_energy_M3GNet
print(matgl.get_available_pretrained_models())
cif_file_name = 'GdPbGdHGd.cif'
cif_content="""data_Ti4V
_symmetry_space_group_name_H-M Fmmm
_cell_length_a 3.18353600
_cell_length_b 4.52677200
_cell_length_c 22.74397000
_cell_angle_alpha 90.00000000
_cell_angle_beta 90.00000000
_cell_angle_gamma 90.00000000
_symmetry_Int_Tables_number 69
_chemical_formula_structural Ti4V
_chemical_formula_sum 'Ti16 V4'
_cell_volume 327.76657340
_cell_formula_units_Z 4
loop_
_symmetry_equiv_pos_site_id
_symmetry_equiv_pos_as_xyz
1 'x, y, z'
2 '-x, -y, -z'
3 '-x, -y, z'
4 'x, y, -z'
5 'x, -y, -z'
6 '-x, y, z'
7 '-x, y, -z'
8 'x, -y, z'
9 'x+1/2, y, z+1/2'
10 '-x+1/2, -y, -z+1/2'
11 '-x+1/2, -y, z+1/2'
12 'x+1/2, y, -z+1/2'
13 'x+1/2, -y, -z+1/2'
14 '-x+1/2, y, z+1/2'
15 '-x+1/2, y, -z+1/2'
16 'x+1/2, -y, z+1/2'
17 'x+1/2, y+1/2, z'
18 '-x+1/2, -y+1/2, -z'
19 '-x+1/2, -y+1/2, z'
20 'x+1/2, y+1/2, -z'
21 'x+1/2, -y+1/2, -z'
22 '-x+1/2, y+1/2, z'
23 '-x+1/2, y+1/2, -z'
24 'x+1/2, -y+1/2, z'
25 'x, y+1/2, z+1/2'
26 '-x, -y+1/2, -z+1/2'
27 '-x, -y+1/2, z+1/2'
28 'x, y+1/2, -z+1/2'
29 'x, -y+1/2, -z+1/2'
30 '-x, y+1/2, z+1/2'
31 '-x, y+1/2, -z+1/2'
32 'x, -y+1/2, z+1/2'
loop_
_atom_site_type_symbol
_atom_site_label
_atom_site_symmetry_multiplicity
_atom_site_fract_x
_atom_site_fract_y
_atom_site_fract_z
_atom_site_occupancy
Ti Ti0 8 0.00000000 0.00000000 0.19939400 1.0
Ti Ti1 8 0.00000000 0.00000000 0.40878900 1.0
V V2 4 0.00000000 0.00000000 0.00000000 1.0
"""
#print(asyncio.run(relax_crystal_structure(cif_file_name)))
print(asyncio.run(predict_formation_energy_M3GNet(cif_content)))
#print(asyncio.run(calculate_single_point_energy(cif_file_name)))
#print(asyncio.run(run_molecular_dynamics(cif_file_name)))

View File

@@ -0,0 +1,15 @@
import sys
sys.path.append('/home/ubuntu/sas0/lzy/multi_mcp_server/')
from sci_mcp_server.material_mcp.mp_query.mp_query_tools import search_material_property_from_material_project,search_crystal_structures_from_materials_project
import asyncio
from sci_mcp_server.core.llm_tools import set_llm_context, clear_llm_context
set_llm_context(True)
print(asyncio.run(search_material_property_from_material_project("CsPbBr3")))
clear_llm_context()
print(asyncio.run(search_material_property_from_material_project("CsPbBr3")))
set_llm_context(True)
print(asyncio.run(search_crystal_structures_from_materials_project("CsPbBr3")))
clear_llm_context()
print(asyncio.run(search_crystal_structures_from_materials_project("CsPbBr3")))

View File

@@ -0,0 +1,143 @@
"""
Test script for property_pred_tools.py
This script tests the predict_properties function from the property_pred_tools module.
"""
import os
import sys
import asyncio
import unittest
from pathlib import Path
# 添加项目根目录到Python路径
sys.path.append(str(Path(__file__).resolve().parents[2]))
from sci_mcp.material_mcp.mattersim_pred.property_pred_tools import predict_properties_MatterSim
class TestPropertyPrediction(unittest.TestCase):
"""Test cases for property prediction tools."""
def setUp(self):
"""Set up test fixtures."""
# 简单的CIF字符串示例 - 硅晶体结构
self.simple_cif = """
data_Si
_cell_length_a 5.43
_cell_length_b 5.43
_cell_length_c 5.43
_cell_angle_alpha 90
_cell_angle_beta 90
_cell_angle_gamma 90
_symmetry_space_group_name_H-M 'P 1'
_symmetry_Int_Tables_number 1
loop_
_atom_site_label
_atom_site_fract_x
_atom_site_fract_y
_atom_site_fract_z
Si 0.0 0.0 0.0
Si 0.5 0.5 0.0
Si 0.5 0.0 0.5
Si 0.0 0.5 0.5
Si 0.25 0.25 0.25
Si 0.75 0.75 0.25
Si 0.75 0.25 0.75
Si 0.25 0.75 0.75
"""
def test_predict_properties_async(self):
"""Test predict_properties function with a simple CIF string (异步版本)."""
async def _async_test():
result = await predict_properties(self.simple_cif)
# 验证结果是否包含预期的关键信息
self.assertIsInstance(result, str)
self.assertIn("Crystal Structure Property Prediction Results", result)
self.assertIn("Total Energy (eV):", result)
self.assertIn("Energy per Atom (eV/atom):", result)
self.assertIn("Forces (eV/Angstrom):", result)
self.assertIn("Stress (GPa):", result)
self.assertIn("Stress (eV/A^3):", result)
print("预测结果示例:")
print(result)
return result
loop = asyncio.get_event_loop()
return loop.run_until_complete(_async_test())
def test_predict_properties_sync(self):
"""同步方式测试predict_properties函数。"""
self.test_predict_properties_async()
class TestPropertyPredictionWithFile(unittest.TestCase):
"""使用文件测试属性预测工具。"""
def setUp(self):
"""设置测试夹具创建临时CIF文件。"""
self.temp_cif_path = "temp_test_structure.cif"
# 简单的CIF内容 - 氧化铝结构
cif_content = """
data_Al2O3
_cell_length_a 4.76
_cell_length_b 4.76
_cell_length_c 12.99
_cell_angle_alpha 90
_cell_angle_beta 90
_cell_angle_gamma 120
_symmetry_space_group_name_H-M 'R -3 c'
_symmetry_Int_Tables_number 167
loop_
_atom_site_label
_atom_site_fract_x
_atom_site_fract_y
_atom_site_fract_z
Al 0.0 0.0 0.35
Al 0.0 0.0 0.85
O 0.31 0.0 0.25
"""
# 创建临时文件
with open(self.temp_cif_path, "w") as f:
f.write(cif_content)
def tearDown(self):
"""清理测试夹具,删除临时文件。"""
if os.path.exists(self.temp_cif_path):
os.remove(self.temp_cif_path)
def test_predict_properties_from_file_async(self):
"""测试从文件预测属性(异步版本)。"""
async def _async_test():
result = await predict_properties(self.temp_cif_path)
# 验证结果
self.assertIsInstance(result, str)
self.assertIn("Crystal Structure Property Prediction Results", result)
self.assertIn("Total Energy (eV):", result)
print("从文件预测结果示例:")
print(result)
return result
loop = asyncio.get_event_loop()
return loop.run_until_complete(_async_test())
def test_predict_properties_from_file_sync(self):
"""同步方式测试从文件预测属性。"""
self.test_predict_properties_from_file_async()
def run_tests():
"""运行所有测试。"""
unittest.main()
if __name__ == "__main__":
run_tests()

View File

@@ -0,0 +1,208 @@
"""
Test script for pymatgen_cal_tools.py
This script tests the functions from the pymatgen_cal_tools module.
"""
import os
import sys
import asyncio
import unittest
from pathlib import Path
# 添加项目根目录到Python路径
sys.path.append(str(Path(__file__).resolve().parents[2]))
from sci_mcp.material_mcp.pymatgen_cal.pymatgen_cal_tools import (
calculate_density,
get_element_composition,
calculate_symmetry
)
class TestPymatgenCalculations(unittest.TestCase):
"""Test cases for pymatgen calculation tools."""
def setUp(self):
"""Set up test fixtures."""
# 简单的CIF字符串示例 - 硅晶体结构
self.simple_cif = """
data_Si
_cell_length_a 5.43
_cell_length_b 5.43
_cell_length_c 5.43
_cell_angle_alpha 90
_cell_angle_beta 90
_cell_angle_gamma 90
_symmetry_space_group_name_H-M 'P 1'
_symmetry_Int_Tables_number 1
loop_
_atom_site_label
_atom_site_fract_x
_atom_site_fract_y
_atom_site_fract_z
Si 0.0 0.0 0.0
Si 0.5 0.5 0.0
Si 0.5 0.0 0.5
Si 0.0 0.5 0.5
Si 0.25 0.25 0.25
Si 0.75 0.75 0.25
Si 0.75 0.25 0.75
Si 0.25 0.75 0.75
"""
def test_calculate_density_async(self):
"""Test calculate_density function with a simple CIF string (异步版本)."""
async def _async_test():
result = await calculate_density(self.simple_cif)
# 验证结果是否包含预期的关键信息
self.assertIsInstance(result, str)
self.assertIn("Density Calculation", result)
self.assertIn("Density", result)
self.assertIn("g/cm³", result)
print("密度计算结果示例:")
print(result)
return result
loop = asyncio.get_event_loop()
return loop.run_until_complete(_async_test())
def test_get_element_composition_async(self):
"""Test get_element_composition function with a simple CIF string (异步版本)."""
async def _async_test():
result = await get_element_composition(self.simple_cif)
# 验证结果是否包含预期的关键信息
self.assertIsInstance(result, str)
self.assertIn("Element Composition", result)
self.assertIn("Composition", result)
self.assertIn("Si", result)
print("元素组成计算结果示例:")
print(result)
return result
loop = asyncio.get_event_loop()
return loop.run_until_complete(_async_test())
def test_calculate_symmetry_async(self):
"""Test calculate_symmetry function with a simple CIF string (异步版本)."""
async def _async_test():
result = await calculate_symmetry(self.simple_cif)
# 验证结果是否包含预期的关键信息
self.assertIsInstance(result, str)
self.assertIn("Symmetry Information", result)
self.assertIn("Space Group", result)
self.assertIn("Number", result)
print("对称性计算结果示例:")
print(result)
return result
loop = asyncio.get_event_loop()
return loop.run_until_complete(_async_test())
class TestPymatgenCalculationsWithFile(unittest.TestCase):
"""使用文件测试pymatgen计算工具。"""
def setUp(self):
"""设置测试夹具创建临时CIF文件。"""
self.temp_cif_path = "temp_test_structure.cif"
# 简单的CIF内容 - 氧化铝结构
cif_content = """
data_Al2O3
_cell_length_a 4.76
_cell_length_b 4.76
_cell_length_c 12.99
_cell_angle_alpha 90
_cell_angle_beta 90
_cell_angle_gamma 120
_symmetry_space_group_name_H-M 'R -3 c'
_symmetry_Int_Tables_number 167
_symmetry_equiv_pos_as_xyz 'x, y, z'
_symmetry_equiv_pos_as_xyz '-x, -y, -z'
loop_
_atom_site_label
_atom_site_type_symbol
_atom_site_fract_x
_atom_site_fract_y
_atom_site_fract_z
_atom_site_occupancy
Al1 Al 0.0 0.0 0.35 1.0
Al2 Al 0.0 0.0 0.85 1.0
O1 O 0.31 0.0 0.25 1.0
"""
# 创建临时文件
with open(self.temp_cif_path, "w") as f:
f.write(cif_content)
def tearDown(self):
"""清理测试夹具,删除临时文件。"""
if os.path.exists(self.temp_cif_path):
os.remove(self.temp_cif_path)
def test_calculate_density_from_file_async(self):
"""测试从文件计算密度(异步版本)。"""
async def _async_test():
result = await calculate_density(self.temp_cif_path)
# 验证结果
self.assertIsInstance(result, str)
self.assertIn("Density Calculation", result)
self.assertIn("Density", result)
print("从文件计算密度结果示例:")
print(result)
return result
loop = asyncio.get_event_loop()
return loop.run_until_complete(_async_test())
def test_get_element_composition_from_file_async(self):
"""测试从文件获取元素组成(异步版本)。"""
async def _async_test():
result = await get_element_composition(self.temp_cif_path)
# 验证结果
self.assertIsInstance(result, str)
self.assertIn("Element Composition", result)
self.assertIn("Composition", result)
print("从文件获取元素组成结果示例:")
print(result)
return result
loop = asyncio.get_event_loop()
return loop.run_until_complete(_async_test())
def test_calculate_symmetry_from_file_async(self):
"""测试从文件计算对称性(异步版本)。"""
async def _async_test():
result = await calculate_symmetry(self.temp_cif_path)
# 验证结果
self.assertIsInstance(result, str)
self.assertIn("Symmetry Information", result)
self.assertIn("Space Group", result)
print("从文件计算对称性结果示例:")
print(result)
return result
loop = asyncio.get_event_loop()
return loop.run_until_complete(_async_test())
def run_tests():
"""运行所有测试。"""
unittest.main()
if __name__ == "__main__":
run_tests()

View File

@@ -0,0 +1,118 @@
"""
测试晶体结构优化工具函数
此脚本测试改进后的optimize_crystal_structure函数
该函数接受单一的file_name_or_content_string参数可以是文件路径或直接的结构内容。
"""
import sys
import asyncio
import os
import tempfile
sys.path.append("/home/ubuntu/sas0/lzy/multi_mcp_server")
from sci_mcp.material_mcp.fairchem_structure_opt.structure_opt_tools import optimize_crystal_structure
from sci_mcp.core.config import material_config
# 简单的CIF结构示例
SAMPLE_CIF = """
data_SrTiO3
_cell_length_a 3.905
_cell_length_b 3.905
_cell_length_c 3.905
_cell_angle_alpha 90
_cell_angle_beta 90
_cell_angle_gamma 90
_symmetry_space_group_name_H-M 'P m -3 m'
_symmetry_Int_Tables_number 221
loop_
_atom_site_label
_atom_site_type_symbol
_atom_site_fract_x
_atom_site_fract_y
_atom_site_fract_z
Sr1 Sr 0.0 0.0 0.0
Ti1 Ti 0.5 0.5 0.5
O1 O 0.5 0.5 0.0
O2 O 0.5 0.0 0.5
O3 O 0.0 0.5 0.5
"""
async def test_with_content():
"""测试使用直接结构内容"""
print("\n=== 测试使用直接结构内容 ===")
result = await optimize_crystal_structure(
file_name_or_content_string=SAMPLE_CIF,
format_type="cif",
optimization_level="quick"
)
print(result)
async def test_with_file():
"""测试使用文件路径(如果文件存在)"""
print("\n=== 测试使用文件路径 ===")
# 创建临时CIF文件
with tempfile.NamedTemporaryFile(suffix=".cif", mode="w", delete=False) as tmp_file:
tmp_file.write(SAMPLE_CIF)
tmp_path = tmp_file.name
try:
result = await optimize_crystal_structure(
file_name_or_content_string=tmp_path,
format_type="auto",
optimization_level="quick"
)
print(result)
finally:
# 清理临时文件
if os.path.exists(tmp_path):
os.unlink(tmp_path)
async def test_with_temp_file():
"""测试使用临时目录中的文件名"""
print("\n=== 测试使用临时目录中的文件名 ===")
# 确保临时目录存在
os.makedirs(material_config.TEMP_ROOT, exist_ok=True)
# 在临时目录中创建文件
temp_filename = "test_structure.cif"
temp_filepath = os.path.join(material_config.TEMP_ROOT, temp_filename)
with open(temp_filepath, 'w', encoding='utf-8') as f:
f.write(SAMPLE_CIF)
try:
# 只传递文件名,而不是完整路径
result = await optimize_crystal_structure(
file_name_or_content_string=temp_filename,
format_type="auto",
optimization_level="quick"
)
print(result)
finally:
# 清理临时文件
if os.path.exists(temp_filepath):
os.unlink(temp_filepath)
async def test_auto_format():
"""测试自动格式检测"""
print("\n=== 测试自动格式检测 ===")
result = await optimize_crystal_structure(
file_name_or_content_string=SAMPLE_CIF,
format_type="auto"
)
print(result)
async def main():
"""运行所有测试"""
print("测试改进后的optimize_crystal_structure函数")
await test_with_content()
await test_with_file()
await test_with_temp_file()
await test_auto_format()
if __name__ == "__main__":
asyncio.run(main())