Files
2026-08-03 18:42:47 +08:00

237 lines
8.4 KiB
Python
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
PlantCARE API 客户端
PlantCARE 是一个植物顺式作用调控元件数据库
URL: http://bioinformatics.psb.ugent.be/webtools/plantcare/html/
"""
import requests
import time
from typing import Dict, List, Optional, Any
from dataclasses import dataclass
from pathlib import Path
@dataclass
class CisElement:
"""顺式作用元件"""
name: str
sequence: str
function: str
position: Optional[int] = None
strand: Optional[str] = None
class PlantCAREClient:
"""
PlantCARE 数据库客户端
用于查询启动子区域的顺式作用调控元件
"""
BASE_URL = "http://bioinformatics.psb.ugent.be/webtools/plantcare/html/"
def __init__(self, rate_limit: float = 1.0):
"""
初始化客户端
Args:
rate_limit: 请求间隔(秒),避免过载服务器
"""
self.rate_limit = rate_limit
self.last_request_time = 0
self.session = requests.Session()
self.session.headers.update({
'User-Agent': 'bbav20311/1.0 (Research Tool)'
})
def _rate_limited_request(self, method: str, url: str, **kwargs) -> requests.Response:
"""带速率限制的请求"""
elapsed = time.time() - self.last_request_time
if elapsed < self.rate_limit:
time.sleep(self.rate_limit - elapsed)
response = self.session.request(method, url, **kwargs)
self.last_request_time = time.time()
return response
def search_elements(self, sequence: str, element_type: Optional[str] = None) -> List[CisElement]:
"""
搜索顺式作用元件
Args:
sequence: DNA 序列(启动子区域)
element_type: 元件类型过滤(如 "light", "hormone", "stress")
Returns:
顺式作用元件列表
"""
# PlantCARE 网页版没有公开 REST API
# 这里实现基于本地数据库的查询或网页解析
# 实际使用时可能需要本地部署 PlantCARE 数据库
# 模拟返回(实际应替换为真实查询)
elements = self._parse_sequence_for_elements(sequence)
if element_type:
elements = [e for e in elements if element_type.lower() in e.function.lower()]
return elements
def _parse_sequence_for_elements(self, sequence: str) -> List[CisElement]:
"""
解析序列中的顺式作用元件
基于 PlantCARE 已知元件模式进行匹配
"""
# PlantCARE 常见元件数据库(简化版)
element_patterns = {
'CAAT-box': {'pattern': 'CCAAT', 'function': 'core promoter element'},
'TATA-box': {'pattern': 'TATA', 'function': 'core promoter element'},
'G-box': {'pattern': 'CACGTG', 'function': 'light responsive'},
'ABRE': {'pattern': 'ACGTGG', 'function': 'abscisic acid responsive'},
'W-box': {'pattern': 'TTGAC', 'function': 'WRKY binding site'},
'WUN-motif': {'pattern': 'AAATTTCCT', 'function': 'wound responsive'},
'MYB-binding': {'pattern': 'CNGTT', 'function': 'MYB transcription factor binding'},
'MYC-binding': {'pattern': 'CACATG', 'function': 'MYC transcription factor binding'},
'GT-1 motif': {'pattern': 'GGTTAA', 'function': 'light responsive'},
'I-box': {'pattern': 'GATAA', 'function': 'light responsive'},
}
elements = []
sequence_upper = sequence.upper()
for name, info in element_patterns.items():
pattern = info['pattern']
# 支持简并碱基
import re
pattern_regex = pattern.replace('N', '[ATCG]')
for match in re.finditer(pattern_regex, sequence_upper):
elements.append(CisElement(
name=name,
sequence=sequence[match.start():match.end()],
function=info['function'],
position=match.start(),
strand='+'
))
return elements
def get_element_details(self, element_name: str) -> Optional[Dict[str, Any]]:
"""
获取元件详细信息
Args:
element_name: 元件名称(如 "G-box")
Returns:
元件详细信息字典
"""
# 本地元件数据库
element_db = {
'CAAT-box': {
'name': 'CAAT-box',
'consensus': 'CCAAT',
'function': 'Core promoter element, enhances transcription efficiency',
'factors': ['CTF/NF1', 'CCAAT-binding factors'],
'references': ['Mantovani, 1999'],
},
'TATA-box': {
'name': 'TATA-box',
'consensus': 'TATA(A/T)A(A/T)',
'function': 'Core promoter element, transcription start site selection',
'factors': ['TBP (TATA-binding protein)'],
'references': ['Smale & Kadonaga, 2003'],
},
'G-box': {
'name': 'G-box',
'consensus': 'CACGTG',
'function': 'Light-responsive element, also involved in ABA signaling',
'factors': ['bZIP transcription factors', 'HY5'],
'references': ['Menkens et al., 1995'],
},
'ABRE': {
'name': 'ABRE',
'consensus': 'ACGTGG/TC',
'function': 'Abscisic acid responsive element',
'factors': ['bZIP/ABF transcription factors'],
'references': ['Nakashima & Yamaguchi-Shinozaki, 2013'],
},
'W-box': {
'name': 'W-box',
'consensus': 'TTGAC(C/T)',
'function': 'WRKY transcription factor binding site, defense response',
'factors': ['WRKY transcription factors'],
'references': ['Eulgem et al., 2000'],
},
}
return element_db.get(element_name)
def analyze_promoter(self, promoter_sequence: str, upstream_length: int = 1500) -> Dict[str, Any]:
"""
全面分析启动子区域
Args:
promoter_sequence: 启动子序列
upstream_length: 上游长度(默认1500bp)
Returns:
分析结果字典
"""
elements = self.search_elements(promoter_sequence)
# 分类统计
categories = {}
for elem in elements:
category = self._categorize_element(elem)
if category not in categories:
categories[category] = []
categories[category].append(elem)
return {
'total_elements': len(elements),
'categories': {k: len(v) for k, v in categories.items()},
'elements_by_category': categories,
'core_promoter_elements': [e for e in elements if 'core promoter' in e.function],
'regulatory_elements': [e for e in elements if 'responsive' in e.function or 'binding' in e.function],
'sequence_length': len(promoter_sequence),
}
def _categorize_element(self, element: CisElement) -> str:
"""对元件进行分类"""
function_lower = element.function.lower()
if 'core promoter' in function_lower:
return 'core_promoter'
elif 'light' in function_lower:
return 'light_responsive'
elif 'hormone' in function_lower or 'acid' in function_lower:
return 'hormone_responsive'
elif 'stress' in function_lower or 'wound' in function_lower:
return 'stress_responsive'
elif 'binding' in function_lower:
return 'tf_binding'
else:
return 'other'
# 使用示例
if __name__ == "__main__":
client = PlantCAREClient()
# 测试序列
# 测试序列
test_seq = "ATGCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCGATCG"
# 搜索元件
elements = client.search_elements(test_seq)
print(f"Found {len(elements)} cis-elements")
for elem in elements:
print(f" - {elem.name}: {elem.sequence} ({elem.function})")