237 lines
8.4 KiB
Python
Executable File
237 lines
8.4 KiB
Python
Executable File
"""
|
||
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})")
|
||
|