وبلاگ
پروژه: ساخت یک ابزار جستجوی ژن در NCBI با Biopython
فهرست مطالب
“تسلط به برنامهنویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT”
"تسلط به برنامهنویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT"
"با شرکت در این دوره جامع و کاربردی، به راحتی مهارتهای برنامهنویسی پایتون را از سطح مبتدی تا پیشرفته با کمک هوش مصنوعی ChatGPT بیاموزید. این دوره، با بیش از 6 ساعت محتوای آموزشی، شما را قادر میسازد تا به سرعت الگوریتمهای پیچیده را درک کرده و اپلیکیشنهای هوشمند ایجاد کنید. مناسب برای تمامی سطوح با زیرنویس فارسی حرفهای و امکان دانلود و تماشای آنلاین."
ویژگیهای کلیدی:
بدون نیاز به تجربه قبلی برنامهنویسی
زیرنویس فارسی با ترجمه حرفهای
۳۰ ٪ تخفیف ویژه برای دانشجویان و دانش آموزان
0 تا 100 عطرسازی + (30 فرمولاسیون اختصاصی حامی صنعت)
دوره آموزش Flutter و برنامه نویسی Dart [پروژه محور]
دوره جامع آموزش برنامهنویسی پایتون + هک اخلاقی [با همکاری شاهک]
دوره جامع آموزش فرمولاسیون لوازم آرایشی
دوره جامع علم داده، یادگیری ماشین، یادگیری عمیق و NLP
دوره فوق فشرده مکالمه زبان انگلیسی (ویژه بزرگسالان)
شمع سازی و عودسازی با محوریت رایحه درمانی
صابون سازی (دستساز و صنعتی)
صفر تا صد طراحی دارو
متخصص طب سنتی و گیاهان دارویی
متخصص کنترل کیفی شرکت دارویی
دنیای زیستشناسی مدرن در حال غرق شدن در سیل عظیمی از دادههاست. با پیشرفت تکنیکهای توالییابی نسل جدید (NGS) و سایر روشهای omics، پایگاههای داده عمومی مانند NCBI (National Center for Biotechnology Information) به مخازنی بیبدیل از اطلاعات بیولوژیکی تبدیل شدهاند. این پایگاهها حاوی میلیاردها رکورد از توالیهای ژنی و پروتئینی، مقالات علمی، ساختارهای سه بعدی و اطلاعات مربوط به بیماریها هستند. اما با این حجم عظیم از داده، چالش اصلی در دسترسی، سازماندهی و استخراج اطلاعات مرتبط نهفته است. محققان و متخصصان بیوانفورماتیک غالباً نیاز دارند تا به سرعت و به طور موثر ژنهای خاصی را بر اساس معیارهای مختلف جستجو کنند، جزئیات آنها را بازیابی نمایند، و حتی ارتباط آنها را با سایر موجودیتها بررسی کنند.
رابط وب NCBI (وبسایت مرسوم) برای جستجوهای دستی و اکتشافی بسیار قدرتمند و کاربرپسند است. اما تصور کنید که نیاز دارید هزاران ژن را برای یک پروژه بزرگ تحقیقاتی جستجو کرده، اطلاعات مربوط به آنها را استخراج کرده و سپس آنها را با دادههای آزمایشگاهی خود ترکیب کنید. انجام این کار به صورت دستی از طریق رابط وب نه تنها بسیار زمانبر و خستهکننده است، بلکه مستعد خطا نیز میباشد. در چنین سناریوهایی، نیاز به ابزارهای برنامهنویسی و خودکارسازی بیش از پیش برجسته میشود. اینجا جایی است که Biopython به میدان میآید.
Biopython مجموعهای قدرتمند از ابزارها و کتابخانههای پایتون برای محاسبات بیولوژیکی است. این کتابخانه به طور خاص برای سادهسازی تعامل با فرمتهای رایج فایلهای بیولوژیکی، دسترسی به پایگاههای داده آنلاین مانند NCBI و EBI، و اجرای تحلیلهای بیوانفورماتیکی پیچیده طراحی شده است. یکی از مهمترین ماژولهای Biopython، Bio.Entrez است که رابطی برنامهنویسی برای سیستم Entrez NCBI فراهم میکند. Entrez در واقع سیستم جامع جستجو و بازیابی دادههای NCBI است که دسترسی به پایگاههای داده مختلف از جمله PubMed، GenBank، Protein، Nucleotide، Gene و بسیاری دیگر را امکانپذیر میسازد.
هدف از این پروژه، گام به گام ساخت یک ابزار جستجوی ژن سفارشی با استفاده از Biopython و ماژول Bio.Entrez است. ما به شما نشان خواهیم داد که چگونه میتوانید با استفاده از پایتون، جستجوهای خودکار و هدفمندی را در پایگاه داده Gene در NCBI انجام دهید، اطلاعات تفصیلی ژنها را بازیابی کنید، و خروجیها را برای تحلیلهای بعدی پردازش نمایید. این ابزار به شما این امکان را میدهد که از محدودیتهای رابط وب فراتر رفته و گردش کار خود را به طور قابل توجهی تسریع و بهینه سازید. این مقاله برای متخصصان بیوانفورماتیک، زیستشناسان محاسباتی، و هر کسی که به دنبال خودکارسازی وظایف جستجوی دادههای ژنی است، طراحی شده است و فرض بر این است که خواننده آشنایی اولیه با زبان برنامهنویسی پایتون دارد.
آشنایی با Biopython و API های Entrez در NCBI
پیش از غواصی در کدنویسی، لازم است درک عمیقی از ابزارهایی که قرار است استفاده کنیم، داشته باشیم. Biopython به عنوان ستون فقرات برنامهنویسی ما و سیستم Entrez در NCBI به عنوان منبع دادههایمان عمل خواهد کرد.
Biopython: کتابخانه مرجع برای زیستشناسان محاسباتی
Biopython یک پروژه جامعهمحور است که هدف آن ارائه یک مجموعه جامع از ابزارهای پایتون برای بیوانفورماتیک است. این کتابخانه مجموعهای از ماژولها را برای کار با موارد زیر ارائه میدهد:
- توالیها (Sequences): شیء
Seqبرای کار با توالیهای DNA، RNA و پروتئین، همراه با ابزارهایی برای دستکاری، ترجمه و رونویسی آنها. - فایلها (File Formats): خواندن و نوشتن فرمتهای رایج بیولوژیکی مانند FASTA، GenBank، PDB و Clustal.
- رابط با پایگاههای داده (Database Interfaces): ماژولهایی مانند
Bio.Entrezبرای NCBI،Bio.ExPASyبرای ExPASy وBio.PDBبرای بانک داده پروتئین. - الگوریتمهای بیوانفورماتیک (Bioinformatics Algorithms): ابزارهایی برای همترازی توالیها (Sequence Alignment)، فیلوژنتیک (Phylogenetics)، مدلسازی ساختاری (Structural Modeling) و غیره.
در این پروژه، تمرکز اصلی ما بر روی ماژول Bio.Entrez خواهد بود.
سیستم Entrez و API های NCBI
Entrez یک سیستم بازیابی اطلاعات متقاطع است که توسط NCBI برای دسترسی به پایگاههای دادههای زیستپزشکی توسعه یافته است. این سیستم به شما امکان میدهد تا یک کوئری را در چندین پایگاه داده به صورت همزمان اجرا کرده و نتایج مرتبط را به دست آورید. Entrez بیش از 40 پایگاه داده مختلف را شامل میشود، از جمله:
- PubMed: مقالات علمی و چکیدهها.
- Gene: اطلاعات جامع در مورد ژنها.
- Nucleotide: توالیهای DNA و RNA (GenBank، RefSeq، PDB).
- Protein: توالیهای پروتئینی.
- SNP: پلیمورفیسمهای تکنوکلئوتیدی.
- Structure: ساختارهای سه بعدی ماکرومولکولها.
- و بسیاری دیگر.
Biopython از طریق ماژول Bio.Entrez، توابعی را برای تعامل با Entrez API در اختیار ما قرار میدهد. این توابع عبارتند از:
EInfo: برای دریافت اطلاعات کلی درباره یک پایگاه داده (تعداد رکوردها، تاریخ آخرین بهروزرسانی، فیلدهای قابل جستجو).ESearch: برای انجام یک جستجو و دریافت لیستی از شناسههای (UIDs) مرتبط با کوئری شما.EFetch: برای بازیابی رکورد کامل بر اساس شناسههای به دست آمده ازESearch.ELink: برای یافتن موجودیتهای مرتبط در پایگاههای داده دیگر. به عنوان مثال، یافتن مقالات PubMed مرتبط با یک ژن خاص.EPost: برای ارسال لیستی از شناسهها به سرور Entrez برای استفاده در عملیات بعدی (مثلاً برای EFetch دسته جمعی).ESummary: برای دریافت خلاصهای از اطلاعات برای لیستی از شناسهها، بدون بازیابی رکورد کامل.EGquery: برای اجرای یک کوئری جهانی در چندین پایگاه داده Entrez.
هر درخواست به Entrez API باید شامل یک آدرس ایمیل باشد تا NCBI بتواند در صورت بروز مشکل با شما تماس بگیرد و همچنین برای نظارت بر استفاده از API. استفاده از کلید API (در صورت وجود) نیز توصیه میشود تا محدودیتهای نرخ (rate limits) کاهش یابد و به NCBI در مدیریت ترافیک کمک کند.
پیشنیازها و تنظیمات اولیه: آمادهسازی محیط توسعه
قبل از اینکه بتوانیم شروع به کدنویسی کنیم، باید مطمئن شویم که محیط توسعه ما به درستی پیکربندی شده است. این بخش به نصب پایتون، Biopython و تنظیمات اولیه برای تعامل با NCBI میپردازد.
نصب پایتون
اگر پایتون (نسخه 3.6 یا بالاتر) را روی سیستم خود نصب ندارید، میتوانید آن را از وبسایت رسمی پایتون (python.org) دانلود و نصب کنید. توصیه میشود از آخرین نسخه پایدار پایتون 3 استفاده کنید.
پس از نصب، میتوانید با اجرای دستور زیر در ترمینال یا Command Prompt، از نصب صحیح و نسخه پایتون اطمینان حاصل کنید:
python --version
# یا در برخی سیستمها:
python3 --version
نصب Biopython
سادهترین راه برای نصب Biopython استفاده از pip، مدیر بسته پایتون است:
pip install biopython
# یا در برخی سیستمها:
pip3 install biopython
پس از اتمام نصب، میتوانید با باز کردن یک مفسر پایتون و تلاش برای وارد کردن ماژول Bio، صحت نصب را بررسی کنید:
import Bio
print(Bio.__version__)
اگر هیچ خطایی دریافت نکردید و شماره نسخه Biopython نمایش داده شد، Biopython با موفقیت نصب شده است.
تنظیم ایمیل و کلید API برای Entrez
همانطور که قبلاً ذکر شد، هر درخواست به Entrez API باید شامل یک آدرس ایمیل باشد. این کار برای کمک به NCBI در ردیابی استفاده از API و تماس با کاربران در صورت نیاز است. Biopython این امکان را فراهم میکند که ایمیل خود را به صورت سراسری برای ماژول Bio.Entrez تنظیم کنید.
from Bio import Entrez
# آدرس ایمیل خود را اینجا وارد کنید
# این ایمیل برای NCBI ارسال می شود تا در صورت نیاز با شما تماس بگیرند
Entrez.email = "Your.Email@example.com"
# در صورت داشتن کلید API از NCBI، آن را نیز تنظیم کنید. این کار به افزایش محدودیت نرخ کمک می کند.
# برای دریافت کلید API، باید یک حساب کاربری در NCBI ایجاد کنید.
# Entrez.api_key = "YOUR_NCBI_API_KEY"
توصیه میشود ایمیل واقعی خود را جایگزین “Your.Email@example.com” کنید. برای دریافت کلید API، میتوانید یک حساب کاربری در NCBI ایجاد کرده و آن را از بخش “API Keys” در داشبورد کاربری خود دریافت کنید. استفاده از کلید API به NCBI کمک میکند تا درخواستهای شما را بهتر مدیریت کند و ممکن است محدودیتهای نرخ شما را افزایش دهد، به خصوص اگر قصد دارید درخواستهای زیادی را در مدت زمان کوتاه ارسال کنید.
شروع به کار: جستجوی پایه ژن با ESearch
اکنون که محیط توسعه ما آماده است، میتوانیم اولین جستجوی ژن خود را با استفاده از Bio.Entrez.ESearch انجام دهیم. هدف این بخش، جستجو برای ژنها بر اساس یک کلمه کلیدی در پایگاه داده Gene NCBI و بازیابی شناسههای منحصر به فرد (UIDs) آنهاست.
ساختار ESearch
تابع Entrez.esearch() پارامترهای اصلی زیر را میپذیرد:
db: نام پایگاه دادهای که میخواهید در آن جستجو کنید. برای این پروژه، ما از"gene"استفاده خواهیم کرد.term: عبارت جستجوی شما. این میتواند یک کلمه کلیدی، نام ژن، نماد ژن، یا حتی یک عبارت پیچیدهتر با عملگرهای بولي (AND, OR, NOT) باشد.retmax: حداکثر تعداد رکوردهایی که میخواهید بازیابی کنید. پیشفرض معمولاً 20 است. اگر میخواهید تعداد بیشتری رکورد دریافت کنید، حتماً این مقدار را تنظیم کنید.retstart: نقطه شروع برای بازیابی رکوردها (برای صفحهبندی). پیشفرض 0 است.field: برای محدود کردن جستجو به یک فیلد خاص (مثلاً"organism"برای جستجو بر اساس موجود زنده).usehistory: اگرTrueباشد، نتایج جستجو در یک history سرور NCBI ذخیره میشوند و میتوانند باEFetchبعدی بازیابی شوند. این برای جستجوهای بزرگ و پردازش دستهای مفید است.
اولین جستجوی ما: ژن p53
بیایید با یک جستجوی ساده برای ژن p53 در انسان شروع کنیم. ما از پایگاه داده “gene” استفاده میکنیم و به دنبال “p53 human” میگردیم.
from Bio import Entrez
import time
# تنظیم ایمیل (همانطور که در بخش قبلی توضیح داده شد)
Entrez.email = "Your.Email@example.com"
# Entrez.api_key = "YOUR_NCBI_API_KEY" # اگر دارید، فعال کنید
def search_gene(query, retmax=10):
"""
جستجو برای ژن ها در پایگاه داده NCBI Gene.
:param query: عبارت جستجو (مثلاً "p53 human").
:param retmax: حداکثر تعداد نتایج برای بازگرداندن.
:return: لیستی از UIDs (شناسه های NCBI) ژن های یافت شده.
"""
try:
# انجام جستجو با ESearch
handle = Entrez.esearch(db="gene", term=query, retmax=retmax)
record = Entrez.read(handle) # خواندن XML خروجی و تبدیل به دیکشنری پایتون
handle.close()
# استخراج UIDs از رکورد
gene_ids = record["IdList"]
print(f"جستجو برای '{query}' انجام شد. تعداد نتایج یافت شده: {record['Count']}")
print(f"تعداد ID های بازیابی شده: {len(gene_ids)}")
print(f"ID های یافت شده: {gene_ids}")
return gene_ids
except Exception as e:
print(f"خطا در هنگام جستجو: {e}")
return []
# مثال استفاده: جستجو برای ژن p53 در انسان
p53_ids = search_gene("p53 human", retmax=5)
# برای رعایت محدودیت نرخ NCBI، بین درخواست ها مکث کنید
time.sleep(1)
# مثال دیگر: جستجو برای یک ژن دیگر
brca1_ids = search_gene("BRCA1 human", retmax=3)
time.sleep(1)
تحلیل خروجی ESearch
هنگامی که Entrez.esearch() فراخوانی میشود، یک “handle” (شیء فایلمانند) برمیگرداند که شامل پاسخ XML از سرور NCBI است. تابع Entrez.read(handle) این XML را تجزیه کرده و آن را به یک دیکشنری پایتون قابل فهم تبدیل میکند. خروجی نمونه از Entrez.read() برای یک جستجوی ESearch به شکل زیر خواهد بود:
{
"Count": "25",
"RetMax": "5",
"RetStart": "0",
"IdList": [
"7157",
"100289381",
"100311394",
"100340326",
"100860530"
],
"TranslationSet": [],
"TranslationStack": [
{
"Term": "p53[All Fields]",
"Field": "All Fields",
"Count": "42217",
"Explode": "N"
},
{
"Term": "human[All Fields]",
"Field": "All Fields",
"Count": "19943236",
"Explode": "N"
},
"AND"
],
"QueryTranslation": "p53[All Fields] AND human[All Fields]"
}
اجزای مهم این دیکشنری عبارتند از:
Count: کل تعداد نتایجی که با عبارت جستجوی شما مطابقت دارند (حتی اگرretmaxکمتر از این باشد).RetMax: حداکثر تعداد رکوردهای درخواستی.RetStart: نقطه شروع نتایج درخواستی.IdList: مهمترین بخش، لیستی از شناسههای منحصر به فرد (UIDs) مربوط به ژنهای یافت شده است. این شناسهها برای بازیابی اطلاعات تفصیلی ژنها در مرحله بعدی (باEFetch) استفاده خواهند شد.QueryTranslation: عبارت جستجوی ترجمه شده توسط Entrez، که میتواند برای اشکالزدایی مفید باشد.
با موفقیت در این مرحله، ما لیستی از شناسههای ژن داریم که اکنون میتوانیم از آنها برای بازیابی اطلاعات غنیتر استفاده کنیم.
بازیابی اطلاعات تفصیلی ژن با EFetch و تحلیل خروجی XML
پس از به دست آوردن شناسههای ژن با ESearch، گام بعدی بازیابی اطلاعات کامل و تفصیلی برای هر یک از این ژنهاست. این کار با استفاده از Bio.Entrez.EFetch انجام میشود. EFetch به شما امکان میدهد تا رکورد کامل را در فرمتهای مختلف (مانند XML، GenBank یا FASTA) بازیابی کنید.
ساختار EFetch
تابع Entrez.efetch() پارامترهای اصلی زیر را میپذیرد:
db: نام پایگاه داده (همان"gene").id: یک رشته یا لیستی از رشتهها (UIDs) که میخواهید اطلاعاتشان را بازیابی کنید. اینها همان UIDs هستند که ازESearchبه دست آوردیم.rettype: نوع رکورد برای بازگرداندن. برای پایگاه داده Gene، معمولاً"xml"برای اطلاعات ساختاریافته، یا"gene_pubmed"برای اطلاعات خلاصهشده ژن و PubMed مرتبط استفاده میشود.retmode: فرمت دادههای بازگردانده شده. برایrettype="xml"، این معمولاً"xml"است. برای توالیها ممکن است"text"برای FASTA یا GenBank باشد.
بازیابی و تحلیل اطلاعات XML ژن
بیایید از UIDs ژن p53 که قبلاً پیدا کردیم، برای بازیابی اطلاعات تفصیلی آنها استفاده کنیم. ما اطلاعات را در فرمت XML بازیابی میکنیم و سپس به صورت برنامهنویسی آن را تجزیه (parse) میکنیم تا فیلدهای مورد نظر را استخراج نماییم.
from Bio import Entrez
import time
Entrez.email = "Your.Email@example.com"
# Entrez.api_key = "YOUR_NCBI_API_KEY"
def fetch_gene_details(gene_ids):
"""
بازیابی جزئیات ژن برای لیستی از UIDs از پایگاه داده NCBI Gene.
:param gene_ids: لیستی از UIDs ژن ها.
:return: لیستی از دیکشنری ها که هر کدام شامل جزئیات یک ژن هستند.
"""
if not gene_ids:
print("لیست شناسههای ژن خالی است.")
return []
# تبدیل لیست UIDs به یک رشته با کاما برای EFetch
id_string = ",".join(gene_ids)
try:
# انجام EFetch برای بازیابی رکوردهای کامل در فرمت XML
handle = Entrez.efetch(db="gene", id=id_string, rettype="xml", retmode="xml")
records = Entrez.read(handle) # خواندن و تجزیه XML
handle.close()
# رکوردهای Gene در یک لیست به نام "Entrezgene_Set" قرار دارند
gene_records = records["Entrezgene_Set"]
extracted_details = []
for gene in gene_records:
details = {}
# استخراج اطلاعات کلیدی
details["GeneID"] = gene["Entrezgene_trackinfo"]["Entrezgene_trackinfo_geneid"]
# نماد ژن و نام
for gene_name in gene["Entrezgene_gene"]["Gene-ref"]["Gene-ref_locus"]:
if gene_name:
details["Symbol"] = gene_name
break
else:
details["Symbol"] = "N/A" # در صورت عدم یافتن نماد
for gene_desc in gene["Entrezgene_gene"]["Gene-ref"]["Gene-ref_desc"]:
if gene_desc:
details["Description"] = gene_desc
break
else:
details["Description"] = "N/A"
# نام موجود زنده
organism_info = gene["Entrezgene_source"]["BioSource"]["BioSource_org"]["Org-ref"]
details["Organism"] = organism_info["Org-ref_taxname"]
# سایر اسامی (aliases)
aliases = []
if "Org-ref_syn" in organism_info:
aliases.extend(organism_info["Org-ref_syn"])
details["Aliases"] = aliases
# کروموزوم و موقعیت (باید با دقت بیشتری بررسی شود زیرا ساختار پیچیده است)
# این قسمت بسته به ساختار XML می تواند متفاوت باشد و نیاز به تحلیل عمیق تری دارد.
# به عنوان مثال، برای Chromosome:
map_location = "N/A"
for locus in gene["Entrezgene_locus"]:
if "Gene-commentary_seqs" in locus and locus["Gene-commentary_seqs"]:
for seq in locus["Gene-commentary_seqs"]:
if "Seq-loc_int" in seq["Seq-loc"]:
seq_int = seq["Seq-loc"]["Seq-loc_int"]
if "Seq-interval_accession" in seq_int and "Seq-interval_from" in seq_int and "Seq-interval_to" in seq_int:
accession = seq_int["Seq-interval_accession"]
start = seq_int["Seq-interval_from"]
end = seq_int["Seq-interval_to"]
map_location = f"{accession}:{start}-{end}" # این یک مثال ساده است
break
if map_location != "N/A":
break
details["MapLocation"] = map_location
# لینک به صفحات NCBI
details["NCBI_Gene_Link"] = f"https://www.ncbi.nlm.nih.gov/gene/{details['GeneID']}"
extracted_details.append(details)
return extracted_details
except Exception as e:
print(f"خطا در هنگام بازیابی جزئیات ژن: {e}")
return []
# مثال استفاده:
# ابتدا با ESearch شناسهها را بدست آورید
p53_ids = search_gene("p53 human", retmax=2)
time.sleep(1) # مکث برای رعایت محدودیت نرخ
# سپس با EFetch جزئیات را استخراج کنید
if p53_ids:
p53_details = fetch_gene_details(p53_ids)
for detail in p53_details:
print("\n--- جزئیات ژن ---")
for key, value in detail.items():
print(f"{key}: {value}")
time.sleep(1)
brca1_ids = search_gene("BRCA1 human", retmax=1)
time.sleep(1)
if brca1_ids:
brca1_details = fetch_gene_details(brca1_ids)
for detail in brca1_details:
print("\n--- جزئیات ژن ---")
for key, value in detail.items():
print(f"{key}: {value}")
time.sleep(1)
تحلیل ساختار XML و استخراج دادهها
خروجی EFetch در فرمت XML، به خصوص برای پایگاه داده Gene، میتواند بسیار پیچیده و تودرتو باشد. Entrez.read() این XML را به یک ساختار دیکشنری/لیست پایتون تبدیل میکند که کار با آن را آسانتر میکند. برای استخراج اطلاعات خاص، باید با ساختار این دیکشنری آشنا باشید. بخشهایی مانند Entrezgene_gene، Entrezgene_source، Entrezgene_summary و Entrezgene_locus حاوی اطلاعات کلیدی هستند.
نکات مهم در مورد ساختار XML و تجزیه آن:
- لیستها و دیکشنریها:
Entrez.read()عناصر تکراری XML را به لیست و عناصر منفرد را به دیکشنری تبدیل میکند. باید با دقت ساختار را دنبال کنید. - بررسی وجود کلیدها: همیشه قبل از دسترسی به یک کلید در دیکشنری، وجود آن را بررسی کنید تا از خطاهای
KeyErrorجلوگیری شود. برای مثال،if "Org-ref_syn" in organism_info:. - تودرتویی: ساختار XML میتواند بسیار تودرتو باشد. باید مسیر صحیح را برای رسیدن به دادههای مورد نظر خود دنبال کنید.
- انعطافپذیری: ساختار XML NCBI ممکن است در طول زمان تغییر کند. کد شما باید به اندازه کافی انعطافپذیر باشد تا با تغییرات جزئی سازگار شود.
مثال بالا یک نمونه از چگونگی استخراج اطلاعات پایه است. برای استخراج اطلاعات پیچیدهتر مانند جزئیات عملکردی، مسیرهای بیولوژیکی، یا جزئیات ساختاری، نیاز به کاوش عمیقتری در ساختار رکورد XML خواهید داشت.
پیچیدهتر کردن جستجوها: فیلترینگ و پارامترهای پیشرفته
تا کنون، ما جستجوهای سادهای انجام دادهایم. اما قدرت واقعی Entrez API در توانایی آن برای انجام جستجوهای پیچیده و فیلتر کردن نتایج نهفته است. این بخش به بررسی نحوه استفاده از عملگرهای بولي، فیلدهای جستجوی خاص، و پارامترهای فیلترینگ پیشرفته میپردازد.
استفاده از عملگرهای بولي (Boolean Operators)
Entrez از عملگرهای بولي استاندارد (AND, OR, NOT) برای ترکیب عبارات جستجو پشتیبانی میکند. این عملگرها باید با حروف بزرگ نوشته شوند.
AND: نتایجی را برمیگرداند که شامل هر دو عبارت باشند.OR: نتایجی را برمیگرداند که شامل حداقل یکی از عبارات باشند.NOT: نتایجی را برمیگرداند که شامل عبارت اول باشند اما شامل عبارت دوم نباشند.
# جستجو برای ژن های مرتبط با سرطان در انسان
cancer_genes_human = search_gene("cancer AND human", retmax=5)
print(f"ژن های مرتبط با سرطان در انسان: {cancer_genes_human}")
time.sleep(1)
# جستجو برای ژن های مرتبط با p53 یا p63 در موس (mouse)
p53_or_p63_mouse = search_gene("(p53 OR p63) AND mouse", retmax=5)
print(f"ژن های p53 یا p63 در موس: {p53_or_p63_mouse}")
time.sleep(1)
# جستجو برای ژن های p53 که در انسان نیستند
p53_not_human = search_gene("p53 NOT human", retmax=5)
print(f"ژن های p53 (غیر انسانی): {p53_not_human}")
time.sleep(1)
فیلدهای جستجوی خاص
Entrez به شما امکان میدهد تا جستجوی خود را به فیلدهای خاصی از رکوردهای پایگاه داده محدود کنید. این کار دقت جستجو را به شدت افزایش میدهد. هر پایگاه داده مجموعهای از فیلدهای قابل جستجو دارد که میتوان آنها را با EInfo کشف کرد. برای پایگاه داده Gene، فیلدهای رایج عبارتند از:
[Gene Name]: نام کامل ژن.[Gene Symbol]: نماد ژن.[Organism]: نام علمی یا رایج موجود زنده.[Chromosome]: شماره کروموزوم.[Summary]: خلاصه عملکرد ژن.[Filter]: فیلترهای از پیش تعریف شده.[Properties]: ویژگیهای ژن.
برای استفاده از فیلدها، عبارت جستجوی خود را با نام فیلد در کروشه ([]) دنبال کنید.
# جستجو برای ژن BRCA1 در موجود زنده Homo sapiens
brca1_homo_sapiens = search_gene("BRCA1[Gene Symbol] AND Homo sapiens[Organism]", retmax=1)
print(f"BRCA1 در Homo sapiens: {brca1_homo_sapiens}")
time.sleep(1)
# جستجو برای ژن های روی کروموزوم 17 در انسان
chr17_human_genes = search_gene("Homo sapiens[Organism] AND 17[Chromosome]", retmax=5)
print(f"ژن های کروموزوم 17 در انسان: {chr17_human_genes}")
time.sleep(1)
فیلتر کردن بر اساس تاریخ و سایر پارامترها
Entrez همچنین امکان فیلتر کردن نتایج بر اساس تاریخ انتشار یا اصلاح را فراهم میکند. این کار با پارامترهای mindate، maxdate و datetype در ESearch انجام میشود. برای پایگاه داده Gene، معمولاً از فیلد PDAT (Publication Date) استفاده میشود.
mindate: حداقل تاریخ (فرمت YYYY/MM/DD).maxdate: حداکثر تاریخ (فرمت YYYY/MM/DD).datetype: نوع تاریخ برای فیلتر (مثلاً"pdat"برای تاریخ انتشار).
# جستجو برای ژن های جدید مرتبط با دیابت در انسان که پس از 2020 منتشر شده اند
diabetes_genes_recent = Entrez.esearch(
db="gene",
term="diabetes AND human",
mindate="2020/01/01",
datetype="pdat", # pdat برای تاریخ انتشار است
retmax=5
)
record_recent = Entrez.read(diabetes_genes_recent)
diabetes_genes_recent.close()
print(f"ژن های دیابت (بعد از 2020): {record_recent['IdList']}")
time.sleep(1)
علاوه بر این، میتوانید از sort برای مرتبسازی نتایج استفاده کنید (مثلاً "relevance"، "publication date").
استفاده از History (تاریخچه جستجو) برای EFetch دستهای
برای جستجوهایی با تعداد نتایج زیاد، به جای اینکه تمام UIDs را در یک رشته طولانی برای EFetch ارسال کنید، میتوانید از قابلیت history در Entrez استفاده کنید. با تنظیم usehistory=True در ESearch، نتایج جستجو در یک Session در سرور NCBI ذخیره میشوند و ESearch به جای UIDs، یک webenv و query_key برمیگرداند. سپس میتوانید از این اطلاعات برای بازیابی نتایج دستهای با EFetch استفاده کنید.
def search_and_fetch_large_set(query, retmax_search=100, batch_size=20):
"""
جستجو برای تعداد زیادی ژن و بازیابی جزئیات آنها به صورت دستهای با استفاده از history.
:param query: عبارت جستجو.
:param retmax_search: حداکثر تعداد نتایج برای جستجو.
:param batch_size: تعداد رکوردها برای بازیابی در هر EFetch.
:return: لیستی از دیکشنری ها شامل جزئیات ژن ها.
"""
try:
# گام 1: انجام جستجو با usehistory=True
print(f"در حال جستجو برای '{query}' با استفاده از تاریخچه...")
search_handle = Entrez.esearch(
db="gene",
term=query,
retmax=retmax_search,
usehistory="Y" # استفاده از تاریخچه
)
search_record = Entrez.read(search_handle)
search_handle.close()
count = int(search_record["Count"])
webenv = search_record["WebEnv"]
query_key = search_record["QueryKey"]
print(f"تعداد کل نتایج یافت شده: {count}")
if count == 0:
return []
all_gene_details = []
for start in range(0, count, batch_size):
end = min(count, start + batch_size)
print(f"در حال بازیابی رکوردها از {start + 1} تا {end}...")
# گام 2: بازیابی جزئیات به صورت دستهای با EFetch و استفاده از webenv و query_key
fetch_handle = Entrez.efetch(
db="gene",
rettype="xml",
retmode="xml",
retstart=start,
retmax=batch_size,
webenv=webenv,
query_key=query_key
)
records = Entrez.read(fetch_handle)
fetch_handle.close()
gene_records = records["Entrezgene_Set"]
for gene in gene_records:
details = {}
details["GeneID"] = gene["Entrezgene_trackinfo"]["Entrezgene_trackinfo_geneid"]
# افزودن سایر جزئیات مانند Symbol, Description, Organism...
for gene_name in gene["Entrezgene_gene"]["Gene-ref"]["Gene-ref_locus"]:
if gene_name:
details["Symbol"] = gene_name
break
else:
details["Symbol"] = "N/A"
details["Organism"] = gene["Entrezgene_source"]["BioSource"]["BioSource_org"]["Org-ref"]["Org-ref_taxname"]
all_gene_details.append(details)
time.sleep(0.5) # مکث کوتاه بین درخواست های دستهای
return all_gene_details
except Exception as e:
print(f"خطا در هنگام جستجوی دستهای: {e}")
return []
# مثال استفاده از جستجوی دستهای
large_query_results = search_and_fetch_large_set("apoptosis human", retmax_search=50, batch_size=10)
print(f"\nتعداد کل ژن های یافت شده و جزئیات استخراج شده: {len(large_query_results)}")
for i, gene in enumerate(large_query_results[:3]): # نمایش 3 تای اول برای نمونه
print(f"نمونه {i+1}: GeneID={gene['GeneID']}, Symbol={gene['Symbol']}, Organism={gene['Organism']}")
time.sleep(1)
استفاده از history برای جستجوهای بزرگ بسیار کارآمدتر است زیرا به جای ارسال لیست طولانی UIDs در هر درخواست EFetch، فقط به webenv و query_key ارجاع داده میشود که سربار (overhead) شبکه را کاهش میدهد و احتمال خطاهای مربوط به URLهای طولانی را از بین میبرد.
یکپارچهسازی و توسعه: فراتر از جستجوی پایه
ابزار جستجوی ژن ما تا اینجا قابلیت جستجو و بازیابی جزئیات پایه را دارد. اما Biopython و Entrez API قابلیتهای بیشتری را ارائه میدهند که میتوانند ابزار ما را بسیار قدرتمندتر کنند. در این بخش، به بررسی امکانات پیشرفتهتر مانند لینک کردن موجودیتها، بازیابی توالیها، مدیریت خطاها و بهترین روشها میپردازیم.
لینک کردن موجودیتها با ELink
یکی از قابلیتهای قدرتمند Entrez، توانایی لینک کردن موجودیتها بین پایگاههای داده مختلف است. Bio.Entrez.ELink به شما امکان میدهد تا موجودیتهای مرتبط را بر اساس یک UID در یک پایگاه داده، در پایگاه داده دیگری پیدا کنید. به عنوان مثال، میتوانید مقالات PubMed مرتبط با یک ژن خاص را پیدا کنید یا توالیهای نوکلئوتیدی/پروتئینی مربوط به آن ژن را بازیابی کنید.
تابع Entrez.elink() پارامترهای اصلی زیر را میپذیرد:
dbfrom: نام پایگاه داده مبدا (مانند"gene").db: نام پایگاه داده مقصد (مانند"pubmed"،"nuccore"برای Nucleotide،"protein").id: یک یا چند UID از پایگاه داده مبدا.term: عبارت جستجوی اضافی (اختیاری).linkname: نوع لینک مورد نظر (مثلاً"gene_pubmed").
def get_related_pubmed_ids(gene_id):
"""
بازیابی شناسههای PubMed مرتبط با یک GeneID.
:param gene_id: شناسه Gene.
:return: لیستی از شناسههای PubMed.
"""
try:
# استفاده از ELink برای یافتن لینک ها از Gene به PubMed
handle = Entrez.elink(dbfrom="gene", db="pubmed", id=gene_id, linkname="gene_pubmed")
record = Entrez.read(handle)
handle.close()
pubmed_ids = []
# ساختار خروجی ELink می تواند کمی پیچیده باشد
# باید به دنبال لیست لینک ها در IdLinkSet باشیم
if record and record[0]["LinkSetDb"]:
for link_set_db in record[0]["LinkSetDb"]:
if link_set_db["DbName"] == "pubmed":
pubmed_ids.extend([link["Id"] for link in link_set_db["Link"]])
return pubmed_ids
except Exception as e:
print(f"خطا در هنگام بازیابی مقالات PubMed مرتبط: {e}")
return []
def get_gene_sequence_accessions(gene_id, seq_type="nuccore"):
"""
بازیابی شناسههای توالی نوکلئوتیدی یا پروتئینی مرتبط با یک GeneID.
:param gene_id: شناسه Gene.
:param seq_type: نوع توالی ('nuccore' برای نوکلئوتید، 'protein' برای پروتئین).
:return: لیستی از شناسههای توالی.
"""
try:
link_name = f"gene_{seq_type}"
handle = Entrez.elink(dbfrom="gene", db=seq_type, id=gene_id, linkname=link_name)
record = Entrez.read(handle)
handle.close()
accession_ids = []
if record and record[0]["LinkSetDb"]:
for link_set_db in record[0]["LinkSetDb"]:
if link_set_db["DbName"] == seq_type:
accession_ids.extend([link["Id"] for link in link_set_db["Link"]])
return accession_ids
except Exception as e:
print(f"خطا در هنگام بازیابی توالی های مرتبط: {e}")
return []
# مثال استفاده:
p53_id_example = "7157" # GeneID برای TP53 در انسان
print(f"\nمقالات PubMed مرتبط با ژن {p53_id_example}:")
pubmed_results = get_related_pubmed_ids(p53_id_example)
print(pubmed_results[:5]) # نمایش 5 مورد اول
print(f"\nتوالی های نوکلئوتیدی مرتبط با ژن {p53_id_example}:")
nuccore_accessions = get_gene_sequence_accessions(p53_id_example, seq_type="nuccore")
print(nuccore_accessions[:5]) # نمایش 5 مورد اول
print(f"\nتوالی های پروتئینی مرتبط با ژن {p53_id_example}:")
protein_accessions = get_gene_sequence_accessions(p53_id_example, seq_type="protein")
print(protein_accessions[:5]) # نمایش 5 مورد اول
time.sleep(1)
بازیابی توالیها با EFetch (در فرمت FASTA یا GenBank)
پس از به دست آوردن شناسههای توالی (accessions) با ELink، میتوانید از EFetch برای بازیابی خود توالیها استفاده کنید. برای این کار، db را روی "nuccore" یا "protein" تنظیم کرده و rettype و retmode را به ترتیب روی "fasta" یا "gb" (GenBank) و "text" تنظیم کنید.
from Bio import SeqIO # برای خواندن فرمت FASTA/GenBank
from io import StringIO # برای کار با رشته به عنوان فایل
def fetch_sequence(accession_id, db="nuccore", rettype="fasta"):
"""
بازیابی یک توالی (نوکلئوتیدی یا پروتئینی) بر اساس شناسه.
:param accession_id: شناسه توالی (مثلاً RefSeq ID).
:param db: پایگاه داده ('nuccore' یا 'protein').
:param rettype: فرمت بازگشتی ('fasta' یا 'gb' برای GenBank).
:return: شیء SeqRecord Biopython (برای FASTA/GenBank) یا رشته متن.
"""
try:
handle = Entrez.efetch(db=db, id=accession_id, rettype=rettype, retmode="text")
sequence_data = handle.read()
handle.close()
if rettype == "fasta":
# استفاده از SeqIO برای تجزیه FASTA
return list(SeqIO.parse(StringIO(sequence_data), "fasta"))
elif rettype == "gb":
# استفاده از SeqIO برای تجزیه GenBank
return list(SeqIO.parse(StringIO(sequence_data), "genbank"))
else:
return sequence_data # برای فرمت های دیگر به صورت رشته
except Exception as e:
print(f"خطا در هنگام بازیابی توالی {accession_id}: {e}")
return None
# مثال استفاده:
if nuccore_accessions:
first_nuccore_accession = nuccore_accessions[0]
print(f"\nبازیابی توالی نوکلئوتیدی (FASTA) برای {first_nuccore_accession}:")
nuccore_seq_records = fetch_sequence(first_nuccore_accession, db="nuccore", rettype="fasta")
if nuccore_seq_records:
seq_record = nuccore_seq_records[0]
print(f"ID: {seq_record.id}")
print(f"Description: {seq_record.description}")
print(f"Sequence (first 50 bases): {seq_record.seq[:50]}...")
time.sleep(1)
if protein_accessions:
first_protein_accession = protein_accessions[0]
print(f"\nبازیابی توالی پروتئینی (FASTA) برای {first_protein_accession}:")
protein_seq_records = fetch_sequence(first_protein_accession, db="protein", rettype="fasta")
if protein_seq_records:
seq_record = protein_seq_records[0]
print(f"ID: {seq_record.id}")
print(f"Description: {seq_record.description}")
print(f"Sequence (first 50 amino acids): {seq_record.seq[:50]}...")
time.sleep(1)
مدیریت خطا و محدودیتهای نرخ
هنگام تعامل با APIهای خارجی، مدیریت خطا و رعایت محدودیتهای نرخ (rate limits) بسیار مهم است. NCBI محدودیتهایی را برای تعداد درخواستهایی که میتوانید در هر ثانیه ارسال کنید، اعمال میکند (معمولاً 3 درخواست در ثانیه بدون کلید API، و 10 درخواست در ثانیه با کلید API). عدم رعایت این محدودیتها میتواند منجر به مسدود شدن موقت یا دائم IP شما شود.
time.sleep(): همانطور که در مثالها دیدید، استفاده ازtime.sleep(X)بین درخواستها برای مکث و رعایت محدودیت نرخ ضروری است.try-except: تمام فراخوانیهای Entrez باید در بلوکtry-exceptقرار گیرند تا خطاهای شبکه، مشکلات سرور یا دادههای نامعتبر به درستی مدیریت شوند.- خطاهای خاص: Entrez ممکن است خطاهای خاصی مانند
HTTP Error 429: Too Many Requestsرا برگرداند. میتوانید منطق خود را برای مدیریت این خطاها (مثلاً با مکث طولانیتر و تلاش مجدد) گسترش دهید. Entrez.emailوEntrez.api_key: همیشه این موارد را تنظیم کنید. این کار به NCBI کمک میکند تا استفاده شما را مدیریت کند و در صورت لزوم با شما تماس بگیرد.
ذخیره نتایج
پس از بازیابی و پردازش دادهها، معمولاً میخواهید آنها را ذخیره کنید. میتوانید دادهها را در فرمتهای مختلفی مانند CSV، JSON یا حتی پایگاه دادههای رابطهای ذخیره کنید.
import csv
import json
def save_to_csv(data, filename="gene_details.csv"):
"""
ذخیره لیستی از دیکشنری ها در یک فایل CSV.
:param data: لیستی از دیکشنری ها.
:param filename: نام فایل CSV.
"""
if not data:
print("دادهای برای ذخیره سازی وجود ندارد.")
return
# استخراج تمام کلیدها برای سربرگ CSV
keys = list(data[0].keys())
with open(filename, 'w', newline='', encoding='utf-8') as output_file:
dict_writer = csv.DictWriter(output_file, fieldnames=keys)
dict_writer.writeheader()
dict_writer.writerows(data)
print(f"داده ها با موفقیت در {filename} ذخیره شدند.")
def save_to_json(data, filename="gene_details.json"):
"""
ذخیره لیستی از دیکشنری ها در یک فایل JSON.
:param data: لیستی از دیکشنری ها.
:param filename: نام فایل JSON.
"""
with open(filename, 'w', encoding='utf-8') as output_file:
json.dump(data, output_file, indent=4, ensure_ascii=False)
print(f"داده ها با موفقیت در {filename} ذخیره شدند.")
# مثال استفاده (پس از اجرای search_and_fetch_large_set)
# فرض کنید large_query_results پر شده است
if large_query_results:
save_to_csv(large_query_results, "apoptosis_human_genes.csv")
save_to_json(large_query_results, "apoptosis_human_genes.json")
ساخت تابع اصلی ابزار و ارائه رابط کاربری ساده
تا این مرحله، ما قطعات مختلف ابزار جستجوی ژن خود را ساختهایم. اکنون زمان آن است که این قطعات را در یک تابع اصلی یکپارچه کنیم و یک رابط کاربری ساده (خط فرمان) برای آن ایجاد کنیم تا کاربر نهایی بتواند به راحتی از آن استفاده کند.
طراحی تابع اصلی
تابع اصلی ما باید قابلیتهای زیر را ارائه دهد:
- دریافت عبارت جستجو از کاربر.
- اجرای جستجو در Entrez Gene.
- بازیابی جزئیات کامل برای ژنهای یافت شده.
- نمایش نتایج به کاربر.
- گزینه ای برای ذخیره نتایج.
- گزینه ای برای جستجوی مقالات PubMed مرتبط.
- گزینه ای برای بازیابی توالی ها.
import time
import csv
import json
from io import StringIO
from Bio import Entrez, SeqIO
# تنظیمات اولیه Entrez
Entrez.email = "Your.Email@example.com"
# Entrez.api_key = "YOUR_NCBI_API_KEY"
def search_gene_ids(query, retmax=10):
"""جستجو برای ژن ها و بازگرداندن UIDs."""
try:
handle = Entrez.esearch(db="gene", term=query, retmax=retmax)
record = Entrez.read(handle)
handle.close()
print(f"تعداد کل نتایج یافت شده برای '{query}': {record['Count']}")
return record["IdList"]
except Exception as e:
print(f"خطا در جستجوی ژن: {e}")
return []
def fetch_gene_details(gene_ids):
"""بازیابی و تجزیه جزئیات کامل ژن."""
if not gene_ids:
return []
id_string = ",".join(gene_ids)
try:
handle = Entrez.efetch(db="gene", id=id_string, rettype="xml", retmode="xml")
records = Entrez.read(handle)
handle.close()
extracted_details = []
for gene in records["Entrezgene_Set"]:
details = {}
details["GeneID"] = gene["Entrezgene_trackinfo"]["Entrezgene_trackinfo_geneid"]
# استخراج نماد ژن
for gene_name in gene["Entrezgene_gene"]["Gene-ref"]["Gene-ref_locus"]:
if gene_name:
details["Symbol"] = gene_name
break
else:
details["Symbol"] = "N/A"
# استخراج نام کامل ژن
for gene_desc in gene["Entrezgene_gene"]["Gene-ref"]["Gene-ref_desc"]:
if gene_desc:
details["Description"] = gene_desc
break
else:
details["Description"] = "N/A"
# موجود زنده
details["Organism"] = gene["Entrezgene_source"]["BioSource"]["BioSource_org"]["Org-ref"]["Org-ref_taxname"]
# کروموزوم و موقعیت (ساده سازی شده برای مثال)
map_location = "N/A"
for locus in gene.get("Entrezgene_locus", []):
for seq_commentary in locus.get("Gene-commentary_seqs", []):
if "Seq-loc_int" in seq_commentary["Seq-loc"]:
seq_int = seq_commentary["Seq-loc"]["Seq-loc_int"]
if "Seq-interval_accession" in seq_int and "Seq-interval_from" in seq_int:
map_location = f"{seq_int.get('Seq-interval_accession', '')}:{seq_int.get('Seq-interval_from', '')}-{seq_int.get('Seq-interval_to', '')}"
break
if map_location != "N/A":
break
details["MapLocation"] = map_location
# خلاصه عملکردی
details["Summary"] = gene.get("Entrezgene_summary", "N/A")
details["NCBI_Gene_Link"] = f"https://www.ncbi.nlm.nih.gov/gene/{details['GeneID']}"
extracted_details.append(details)
return extracted_details
except Exception as e:
print(f"خطا در بازیابی جزئیات: {e}")
return []
def get_pubmed_links(gene_id):
"""بازیابی و نمایش لینک های PubMed مرتبط."""
try:
handle = Entrez.elink(dbfrom="gene", db="pubmed", id=gene_id, linkname="gene_pubmed")
record = Entrez.read(handle)
handle.close()
pubmed_ids = []
if record and record[0]["LinkSetDb"]:
for link_set_db in record[0]["LinkSetDb"]:
if link_set_db["DbName"] == "pubmed":
pubmed_ids.extend([link["Id"] for link in link_set_db["Link"]])
if pubmed_ids:
print(f" -- مقالات PubMed مرتبط ({len(pubmed_ids)}):")
for i, pub_id in enumerate(pubmed_ids[:5]): # نمایش 5 مورد اول
print(f" - https://pubmed.ncbi.nlm.nih.gov/{pub_id}/")
else:
print(" -- مقاله PubMed مرتبطی یافت نشد.")
except Exception as e:
print(f"خطا در بازیابی لینک های PubMed: {e}")
def get_sequence_info(gene_id, db_type="nuccore"):
"""بازیابی و نمایش اطلاعات توالی (RefSeq ID)."""
try:
link_name = f"gene_{db_type}"
handle = Entrez.elink(dbfrom="gene", db=db_type, id=gene_id, linkname=link_name)
record = Entrez.read(handle)
handle.close()
accession_ids = []
if record and record[0]["LinkSetDb"]:
for link_set_db in record[0]["LinkSetDb"]:
if link_set_db["DbName"] == db_type:
accession_ids.extend([link["Id"] for link in link_set_db["Link"]])
if accession_ids:
print(f" -- توالی های {db_type.capitalize()} مرتبط ({len(accession_ids)}):")
for i, acc_id in enumerate(accession_ids[:3]): # نمایش 3 مورد اول
print(f" - Accession ID: {acc_id}")
# اگر بخواهیم خود توالی را نیز دریافت کنیم، باید efetch دیگری بزنیم
# seq_record = fetch_sequence(acc_id, db=db_type)
# if seq_record: print(f" Sequence (first 20): {str(seq_record[0].seq)[:20]}...")
else:
print(f" -- توالی {db_type.capitalize()} مرتبطی یافت نشد.")
except Exception as e:
print(f"خطا در بازیابی توالی های {db_type.capitalize()}: {e}")
def run_gene_search_tool():
"""تابع اصلی برای اجرای ابزار جستجوی ژن."""
print("--- ابزار جستجوی ژن NCBI با Biopython ---")
query = input("لطفاً عبارت جستجو (مثلاً 'p53 human' یا 'BRCA1 AND mouse') را وارد کنید: ")
num_results_str = input("حداکثر تعداد نتایج برای نمایش (پیشفرض: 10): ")
num_results = int(num_results_str) if num_results_str.isdigit() else 10
print(f"\nدر حال جستجو برای '{query}'...")
gene_ids = search_gene_ids(query, retmax=num_results)
time.sleep(1) # رعایت محدودیت نرخ
if not gene_ids:
print("هیچ ژنی با عبارت جستجوی شما یافت نشد.")
return
print(f"\nدر حال بازیابی جزئیات برای {len(gene_ids)} ژن...")
gene_details_list = fetch_gene_details(gene_ids)
time.sleep(1)
if not gene_details_list:
print("خطا در بازیابی جزئیات ژن ها.")
return
print("\n--- نتایج جستجو ---")
for i, detail in enumerate(gene_details_list):
print(f"\n{i+1}. GeneID: {detail['GeneID']}")
print(f" Symbol: {detail['Symbol']}")
print(f" Description: {detail['Description']}")
print(f" Organism: {detail['Organism']}")
print(f" Map Location: {detail['MapLocation']}")
print(f" Summary: {detail['Summary'][:100]}...") # نمایش 100 کاراکتر اول
print(f" NCBI Link: {detail['NCBI_Gene_Link']}")
# گزینه های اضافی
get_pubmed_links(detail['GeneID'])
time.sleep(0.5)
get_sequence_info(detail['GeneID'], db_type="nuccore")
time.sleep(0.5)
get_sequence_info(detail['GeneID'], db_type="protein")
time.sleep(0.5)
save_option = input("\nآیا مایلید نتایج را ذخیره کنید (csv/json/no)؟ ").lower()
if save_option == "csv":
save_to_csv(gene_details_list, "search_results.csv")
elif save_option == "json":
save_to_json(gene_details_list, "search_results.json")
print("\nعملیات جستجو به پایان رسید. از توجه شما متشکریم!")
# برای اجرای ابزار
if __name__ == "__main__":
run_gene_search_tool()
این تابع run_gene_search_tool() به عنوان نقطه ورودی اصلی ابزار ما عمل میکند. این تابع از توابعی که در بخشهای قبلی توسعه دادیم (مانند search_gene_ids و fetch_gene_details) استفاده میکند و آنها را به ترتیبی منطقی فراخوانی میکند تا گردش کار جستجوی ژن را برای کاربر نهایی فراهم کند.
توسعه و بهبود رابط کاربری
رابط کاربری ارائه شده در بالا یک رابط خط فرمان (CLI) بسیار ساده است. برای یک ابزار تولیدی، میتوانید آن را به روشهای زیر بهبود بخشید:
- استفاده از کتابخانههای CLI: کتابخانههایی مانند
argparseبرای مدیریت آرگومانهای خط فرمان پیچیدهتر، یاClickوTyperبرای ساخت CLIهای قدرتمندتر. - رابط کاربری گرافیکی (GUI): برای کاربرانی که با خط فرمان راحت نیستند، میتوان یک رابط کاربری گرافیکی با استفاده از
Tkinter،PyQt،Kivyیا فریمورکهای وب مانندFlaskیاStreamlitایجاد کرد. - اعتبارسنجی ورودی: اعتبارسنجی دقیقتر ورودیهای کاربر برای جلوگیری از خطاهای ناخواسته.
- نمایش پیشرفت: برای جستجوهای بزرگ، نمایش نوار پیشرفت میتواند تجربه کاربری را بهبود بخشد.
چالشها، بهترین روشها و ملاحظات آینده
ساخت ابزارهای بیوانفورماتیکی با Biopython و APIهای NCBI نه تنها کارآمد است بلکه با چالشهایی نیز همراه است. درک این چالشها و پیادهسازی بهترین روشها برای اطمینان از پایداری و کارایی ابزار شما ضروری است.
مدیریت محدودیتهای نرخ و سرور
- مکث مناسب: همیشه از
time.sleep()بین درخواستهای API استفاده کنید. محدودیت استاندارد NCBI (بدون API Key) تقریباً 3 درخواست در ثانیه است. با یک کلید API، این محدودیت به 10 درخواست در ثانیه افزایش مییابد. به عنوان یک قاعده کلی، بین درخواستهای متوالی حداقل 0.5 ثانیه مکث کنید و برای درخواستهای دستهای طولانیتر، این زمان را کمی بیشتر کنید. - استفاده از
Entrez.api_key: این کلید نه تنها محدودیت نرخ شما را افزایش میدهد بلکه به NCBI در مدیریت بهتر ترافیک کمک میکند. usehistoryبرای دستههای بزرگ: همانطور که دیدیم، استفاده ازwebenvوquery_keyدرESearchبرای بازیابی نتایج دستهای بسیار کارآمدتر از ارسال لیستی طولانی از IDها در هرEFetchاست.- پردازش موازی با احتیاط: در صورت نیاز به سرعت بسیار بالا، میتوانید از پردازش موازی یا چند رشتهای استفاده کنید، اما باید دقت کنید که از محدودیتهای نرخ NCBI تجاوز نکنید. استفاده از صفها (queues) و مدیریت دقیق مکثها در هر رشته ضروری است.
قابلیت اطمینان و مدیریت خطا
- بلوکهای
try-except: تمام فراخوانیهای API باید در بلوکهایtry-exceptمحصور شوند تا خطاهای شبکه، زمانبندی (timeout) و پاسخهای نامعتبر را مدیریت کنند. - تلاش مجدد (Retries): برای خطاهای موقت (مانند
HTTP 503 Service Unavailableیا429 Too Many Requests)، پیادهسازی مکانیزم تلاش مجدد با مکث افزایشی (exponential backoff) میتواند مفید باشد. - اعتبارسنجی دادهها: همیشه فرض کنید دادههای دریافتی ممکن است ناقص یا نامعتبر باشند. کدهای تجزیه XML شما باید این موارد را در نظر بگیرند (مثلاً با استفاده از
.get()برای دیکشنریها یا بررسی وجود کلیدها).
عملکرد و مقیاسپذیری
- حافظه پنهان (Caching): اگر مکرراً به دنبال اطلاعات یکسان هستید، نتایج را در یک حافظه پنهان محلی ذخیره کنید (مثلاً یک فایل JSON یا یک پایگاه داده SQLite) تا از درخواستهای تکراری به NCBI جلوگیری شود و سرعت ابزار شما افزایش یابد.
- فیلتر کردن در سمت سرور: تا حد امکان، از قابلیتهای فیلترینگ Entrez (مانند فیلدهای جستجو و عملگرهای بولي) در
ESearchاستفاده کنید تا حجم دادههای دریافتی و پردازشی در سمت کلاینت کاهش یابد. - بازیابی فقط اطلاعات لازم: از
EFetchباrettypeوretmodeمناسب برای بازیابی فقط آن دسته از اطلاعاتی که واقعاً نیاز دارید، استفاده کنید. بازیابی رکورد کامل XML برای هر ژن میتواند سربار زیادی داشته باشد اگر فقط به چند فیلد نیاز دارید.
ملاحظات قانونی و اخلاقی
- شرایط استفاده (Terms of Service) NCBI: همیشه شرایط استفاده از APIهای NCBI را مطالعه و رعایت کنید. این شرایط معمولاً شامل محدودیتهای نرخ و الزامات اخلاقی برای استفاده از دادههاست.
- حریم خصوصی و دادههای حساس: اگر ابزار شما با دادههای ژنتیکی انسانی کار میکند، مطمئن شوید که تمام قوانین و مقررات مربوط به حریم خصوصی و دادههای حساس (مانند HIPAA در ایالات متحده یا GDPR در اروپا) را رعایت میکنید.
قابلیتهای آینده و گسترش ابزار
- پایگاههای داده دیگر: این ابزار را میتوان به راحتی برای جستجو در پایگاههای داده دیگر NCBI (مانلاً PubMed برای مقالات، PDB برای ساختارهای پروتئین) گسترش داد.
- تحلیلهای downstream: نتایج استخراج شده میتوانند به عنوان ورودی برای تحلیلهای بعدی مانند غنیسازی مسیر (pathway enrichment)، تحلیل ژنهای کاندیدا، یا ساخت شبکههای تعامل پروتئین-پروتئین استفاده شوند.
- ادغام با ابزارهای دیگر: نتایج میتوانند به فرمتهای سازگار با سایر ابزارهای بیوانفورماتیکی صادر شوند (مثلاً GFF برای حاشیهنویسی ژنوم، VCF برای واریانتها).
- یادگیری ماشین: دادههای استخراج شده میتوانند برای آموزش مدلهای یادگیری ماشین به منظور پیشبینی عملکرد ژنها یا کشف الگوهای جدید استفاده شوند.
با رعایت این بهترین روشها و برنامهریزی برای گسترشهای آینده، ابزار جستجوی ژن Biopython شما میتواند به یک جزء ارزشمند و پایدار در جعبه ابزار بیوانفورماتیک شما تبدیل شود.
“تسلط به برنامهنویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT”
"تسلط به برنامهنویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT"
"با شرکت در این دوره جامع و کاربردی، به راحتی مهارتهای برنامهنویسی پایتون را از سطح مبتدی تا پیشرفته با کمک هوش مصنوعی ChatGPT بیاموزید. این دوره، با بیش از 6 ساعت محتوای آموزشی، شما را قادر میسازد تا به سرعت الگوریتمهای پیچیده را درک کرده و اپلیکیشنهای هوشمند ایجاد کنید. مناسب برای تمامی سطوح با زیرنویس فارسی حرفهای و امکان دانلود و تماشای آنلاین."
ویژگیهای کلیدی:
بدون نیاز به تجربه قبلی برنامهنویسی
زیرنویس فارسی با ترجمه حرفهای
۳۰ ٪ تخفیف ویژه برای دانشجویان و دانش آموزان