امیر محمدی
امیر محمدی
خواندن ۱۰ دقیقه·۵ سال پیش

مهندسی معکوس ویروس کرونا (SARS-COV2) | تلاش اول

نکته اولیه:
مرکز ملی اطلاعات زیست‌فناوری (NCBI) شروع کرده به منتشر کردن دیتابیس‌هایی مربوط به ژنوم ویروس SARS-COV-2 (مثلا این) و این مطلب فقط مجموعه مطالعاتم برای شناخت بهتر این ویروس در این روزها ست؛ یک جور مستندسازی از مجموعه فعالیت‌هایی که برای شناختش دارم انجام می‌دم؛
نه داده کاوی بلدم و نه شناخت قبلی از ساختار ویروس‌ها دارم؛ به پیروی از این پروژه جورج هاتز که کار مشابهی کرده با داده‌ها ور می‌ریم.

داده‌های ژنومی:

بالاتر گفتم سایت NCBI دیتابیس‌های اطلاعاتی کرونا رو منتشر کرده؛ بذارین یه نمونه از اون‌ها رو ببینیم:

https://www.ncbi.nlm.nih.gov/nuccore/MN908947
https://www.ncbi.nlm.nih.gov/nuccore/MN908947


اطلاعات بالا، ژنوم یک نمونه در ووهان چین رو نشون می‌ده.

ما توی تئوری اطلاعات، مفهومی داریم به اسم پیچیدگی کولموگروف؛ پیچیدگی کولموگروفِ یک متن، طول کوتاه‌ترین برنامه کامپیوتری هست که اون رو به عنوان خروجی تولید می‌کنه؛ به عبارت ساده‌تر: یک متن، چقدر اطلاعات داره!

یک روش ساده برای به دست آوردن تقریبی این مقدار، استفاده از الگوریتم‌های فشرده‌سازیه؛ مثلا اینکه متن رو zip کنیم که حجم نهایی می‌شه میزان اطلاعات خالص.

قبل از هر چیزی لازمه که اطلاعاتی که داریم رو به فرم معقول‌تری دربیاریم؛ مثلا یک رشته‌ی کاراکتریِ پشت سر هم (بدون عدد و رقم). من از پایتون استفاده می‌کنم:

import re corona = ''' 1 attaaaggtt tataccttcc caggtaacaa accaaccaac tttcgatctc ttgtagatct 61 gttctctaaa cgaactttaa aatctgtgtg gctgtcactc ggctgcatgc ttagtgcact 121 cacgcagtat aattaataac taattactgt cgttgacagg acacgagtaa ctcgtctatc 181 ttctgcaggc tgcttacggt ttcgtccgtg ttgcagccga tcatcagcac atctaggttt 241 cgtccgggtg tgaccgaaag gtaagatgga gagccttgtc cctggtttca acgagaaaac 301 acacgtccaa ctcagtttgc ctgttttaca ggttcgcgac gtgctcgtac gtggctttgg 361 agactccgtg gaggaggtct tatcagaggc acgtcaacat cttaaagatg gcacttgtgg 421 cttagtagaa gttgaaaaag gcgttttgcc tcaacttgaa cagccctatg tgttcatcaa .... ''' corona = ''.join(re.findall('[a-zA-Z]+', corona))

خروجی درسته:

attaaaggtttataccttcccaggtaacaaaccaaccaactttcgatctcttgtagatctgttctctaaacgaactttaaaatctgtgtggctgtcactcggctgcatgcttagtgcactcacgcagtataattaataactaattactgtcgttgacaggacacgagtaactcgtctatcttctgcaggctgcttacggtttcgtccgtgttgcagccgatcatcagcacatctaggtttcgtccgggtgtgaccgaaaggtaag...

بیایید سایزش رو با چیزی که ویکیپدیا گفته مقایسه کنیم:

۲۹۹۰۳
۲۹۹۰۳
۲۹۹۰۳
۲۹۹۰۳

پس ادامه بدیم؛ پیچیدگی کولموگروف رو حساب کنیم:

import zlib comp = zlib.compress(corona) print(len(comp))

اررررررور!

یه بار دیگه؛ اطلاعات قبل از فشرده‌سازی باید encode می‌شدن:

comp = zlib.compress(corona.encode('utf-8')) print(len(comp))

خروجی می‌گه: 8858
یعنی ویروس کرونا حدود ۸ کیلوبایت اطلاعات داره؛ نکته بامزه اینکه sql slammer (کرم کامپیوتری) فقط حدود ۳۷۶ بایت حجم داشت!

یک مقایسه:

ظاهرا می‌تونستیم دیتای مرتب شده رو هم از NCBI دانلود کنیم؛ بهرحال!
اینجا نوشته که شباهت زیادی بین Bat Coronavirus و SARS-COV-2 وجود داره؛ از این لینک می‌شه رشته‌های ژنومی مختلف رو سرچ کرد.

https://www.ncbi.nlm.nih.gov/labs/virus
https://www.ncbi.nlm.nih.gov/labs/virus

دنبال اطلاعات کرونا ویروس‌هایی که بین خفاش، مرغ، سگ و شتر دیده شده بگردیم و با نمونه‌ای که داریم مقایسه کنیم.
لازمه یک سری اطلاعات (virus و host) رو به سایت بالاییه بدیم تا دیتا رو پیدا کنه و دانلودش کنیم؛ کرونا ویروس‌ها عضو خانواده Coronaviridae حساب می‌شند. فیلد Virus رو Coronaviridae می‌ذاریم و Host رو bat، chicken، dog و camel.

چجوری مقایسه‌شون کنیم؟! |:

فاصله لون‌اشتاین:

بله بله! روش‌های بهتری هم برای مقایسه رشته‌های ژنتیکی وجود داره، بذارین فعلا از همین استفاده کنم.

فرض کنید دوتا رشته داشته باشیم؛ مثلا

s1 = 'amir' s2 = 'mina'

کمترین تعداد تغییراتی که می‌تونه s1 رو به s2 تبدیل کنه، فاصله لون‌اشتاین اونهاست.
می‌شه گفت: اندازه‌گیری فرق بین دو تا رشته؛

فاصله لون‌اشتاین، با حضور خودم در پس‌زمینه D:
فاصله لون‌اشتاین، با حضور خودم در پس‌زمینه D:

من چهار تا فایل دارم با یک عالمه رشته ژنتیکی از یک سری جونوَر؛ یه نگاه به این فایل بندازیم:

هر فایل، یک سری رشته داره که خط اولِ هر کدوم اینجوری شروع شده:

> blah blah blah |blah blah blah blah blah| blah blah blah

توی قدم اول، فایل رو باز می‌کنیم و نمونه‌ها رو توی لیست نگه می‌داریم:

file = open('bat.fasta', 'r') lines = file.read().split('\n') current_sequence = '' genomes = [] for line in lines[1:]: # ignore first lines if line[0] == '>': genomes.append(current_sequence.lower()) current_sequence = '' continue # append lines to current sequence until end of the sequence current_sequence += line

حالا هر کدوم از اونها رو با رشته‌ای که داشتیم مقایسه می‌کنیم و میانگین می‌گیریم:

from editdistance import distance # install with pip install editdistance avg = 0 for genome in genomes: avg += distance(corona, genome) print(avg / len(genomes))

همین روند رو برای هر چهار تا فایلی که داریم انجام می‌دیم و نتیجه:

ظاهرا شبیه‌ترین کرونا ویروسی که بین این حیوون‌ها وجود داشته نسبت به نمونه‌ای که داریم، bat coronavirus هست؛ همین مقایسه با انفولانزای A و B هم نشون می‌ده نمونه‌ای که داریم از نظر ساختاری با آنفولانزا کلی تفاوت داره؛ کرونا، آنفولانزا نیست.

کمی عمیق‌تر:

ویکی‌پدیا می‌گه:

بیان ژن (gene expression) فرایندی است که در آن اطلاعات درون ژن استفاده می‌شود تا یک محصول کاربردی از آن بدست آید. محصول ژن‌ها عمدتاً آمینو اسیدی هستند.
مراحل مختلفی را می‌توان برای فرایند بیان ژن در نظر گرفت که عموماً شامل رونویسی، اتصال RNA، ترجمه و تغییرات بعد از ترجمه یک پروتئین می‌باشد.
از آنجا که تمام سلول‌های بدن ما از یک سلول مشتق شده‌اند تفاوت‌ها و تمایزات بین سلول‌ها حاصل از بیان شدن یا نشدن قسمت‌هایی از ژن است.

تا جایی که متوجه شدم یک رشته DNA توی دو مرحله به پروتئین تبدیل می‌شه:
۱- رونویسی‌ (transcription): اطلاعات خاصی از DNA یک ژن به RNA کپی میشه
۲- ترجمه (translation): که دنباله نوکلئیدهای mRNA به دنباله amino acid پروتئین تبدیل می‌شه

taken from www.khanacademy.org
taken from www.khanacademy.org

اینجا گفته که:

و ظاهرا فقط لازمه که مرحله ۲ (ترجمه یا translation) رو انجام بدیم.
بذارین یه خورده دقیق‌تر ببینیم که ترجمه چجوری انجام می‌شه:
در واقع یک سری ساختار به اسم ریبوزوم مسئول ساخت پروتئین هستند که mRNA ها رو چک می‌کنه، کدونِ (codon) شروع رو پیدا می‌کنه و کل اون mRNA رو چک می‌کنه (یک کدون در هر لحظه چک می‌شه).

یادم رفت بگم! mRNA ساختارش این شکلیه:

taken from www.khanacademy.org
taken from www.khanacademy.org

اگه یک رشته mRNA رو به بخش‌های سه تایی تقسیم کنیم، به هر کدوم از این بخش‌ها می‌گن یک کدون (codon)؛ یک کدون شروعِ رشته رو مشخص می‌کنه و یکی هم آخر رشته رو.

ریبوزوم از کدون اول شروع می‌کنه به ترجمه کردن؛ از کجا می‌دونه که هر کُدون رو به چه آمینو اسیدی ترجمه کنه؟! اطراف سلول، یک سری tRNA وجود داره و هر tRNA یک نوع آمینو اسید رو مشخص می‌کنه؛ ریبوزوم کدون‌هایی که می‌خونه رو با هر کدوم از این tRNAها مقایسه می‌کنه و اگه match بود انتخابش می‌کنه؛ دقیقا مثل اینکه دستورات سه بایتیِ زبان ماشین داشته باشیم!

taken from www.khanacademy.org
taken from www.khanacademy.org

جدول کدون‌ها رو داریم:

https://en.wikipedia.org/wiki/DNA_codon_table
https://en.wikipedia.org/wiki/DNA_codon_table

بیایید یک جور دیس‌اسمبلر کوچیک بنویسیم:

import re # genetic code codon_table = { 'ttt': 'F', 'ttc': 'F', 'tta': 'L', 'ttg': 'L', 'ctt': 'L', 'ctc': 'L', 'cta': 'L', 'ctg': 'L', 'att': 'I', 'atc': 'I', 'ata': 'I', 'atg': 'M', 'gtt': 'V', 'gtc': 'V', 'gta': 'V', 'gtg': 'V', 'tct': 'S', 'tcc': 'S', 'tca': 'S', 'tcg': 'S', 'cct': 'P', 'ccc': 'P', 'cca': 'P', 'ccg': 'P', 'act': 'T', 'acc': 'T', 'aca': 'T', 'acg': 'T', 'gct': 'A', 'gcc': 'A', 'gca': 'A', 'gcg': 'A', 'tat': 'Y', 'tac': 'Y', 'taa': '$', 'tag': '$', 'cat': 'H', 'cac': 'H', 'caa': 'Q', 'cag': 'Q', 'aat': 'N', 'aac': 'N', 'aaa': 'K', 'aag': 'K', 'gat': 'D', 'gac': 'D', 'gaa': 'E', 'gag': 'E', 'tgt': 'C', 'tgc': 'C', 'tga': '$', 'tgg': 'W', 'cgt': 'R', 'cgc': 'R', 'cga': 'R', 'cgg': 'R', 'agt': 'S', 'agc': 'S', 'aga': 'R', 'agg': 'R', 'ggt': 'G', 'ggc': 'G', 'gga': 'G', 'ggg': 'G', } def disassemble(genome): global codon_table codons = re.findall('.{1,3}', genome) # split genome to triplets (codons) pteins = ''.join(map(lambda x: codon_table[x], codons)) return pteins

بعدا این باید بهش اضافه بشه؛ فعلا کار راه اندازه.

یه نگاه به این بندازین:


اینجا هم اطلاعات کامل‌تر نمونه‌ای که داریم اومده؛ بیایید مثل یک سری فانکشن مدلش کنیم:

sars_cov_2 = {} sars_cov_2['5utr'] = corona[0:265] sars_cov_2['orf1a'] = disassemble(corona[265:13483]) sars_cov_2['orf1b'] = disassemble(corona[13467:21555]) sars_cov_2['S'] = disassemble(corona[21562:25384]) sars_cov_2['orf3a'] = disassemble(corona[25392:26220]) sars_cov_2['E'] = disassemble(corona[26244:26472]) sars_cov_2['M'] = disassemble(corona[26522:27191]) sars_cov_2['orf6'] = disassemble(corona[27201:27387]) sars_cov_2['orf7a'] = disassemble(corona[27393:27759]) sars_cov_2['orf7b'] = disassemble(corona[27755:27887]) sars_cov_2['orf8'] = disassemble(corona[27893:28259]) sars_cov_2['nucleocapsid_phosphoprotein'] = disassemble(corona[28273:29533]) sars_cov_2['orf10'] = disassemble(corona[29557:29674])

خوبه! حالا ببینیم هر کدوم چیکار می‌کنند.

هممم.. طولانی شد... نفس بگیرید، ادامه بدیم D:

relax, relax, relax
relax, relax, relax


اگه کرونا رو مثل یک ویروس کامپیوتری تصور کنیم:

  • دوتا orf اول یعنی orf1a و orf1b مثل ماشین کپی یا quine عمل می‌کنند
  • پروتئین S همون چیزی هست که کرونا برای چسبیدن به غشای سلول و نفوذ بهش استفاده می‌کنه؛ مثل اکسپلویتِ کامپیوتری!
    می‌گن ACE2، نقطه ورود بعضی از ویروس‌های کرونا به سلول‌ و همون چیزیه که S بهش می‌چسبه؛ علت اینکه می‌گفتن داروهای قلبی یا فشار خون روی ویروس تاثیر داره هم ظاهرا کم و زیاد شدن همین ACE2 هست.
  • پوشش ویروسی (M و E) هم یک لایه بیرونی هست که وقتی ویروس وارد سلول شده، اون رو پوشش می‌ده؛ تا جایی که متوجه شدم هم باعث می‌شه که ویروس از دید دستگاه ایمنی بدن مخفی بمونه و هم وظیفه شناسایی و چسبیدن به گیرنده‌های اون سلول رو داره

با این شرایط، بد نیست به این دو موضوع فکر کنیم:

  • چجوری اکسپلویت رو از کار بندازیم؛ یا اینکه سلول رو در برابرش ایمن کنیم
  • چجوری ماشین کپی رو متوقف کنیم


قدم‌های بعدی:

لازمه درک بهتر این ویروس، شناخت دقیقتر اجزای تشکیل دهنده‌ اونه؛ تلاش بعدی می‌تونه شناخت ساختار و عملکرد پروتئین‌های سازنده، استفاده از فانکشن‌هایی که نوشتیم و رسم نمودارهاشون باشه.

همونطور که گفتم، این‌ها صرفا تلاشم برای درک بهتر ویروس کرونا ست و هدف دیگه‌ای نداره؛ اگه حس کنم چیزی که نوشتم مفید بوده ادامه‌ اون رو هم اینجا منتشر می‌کنم (:

مرتبط:

coronavirusکروناویروسپایتونبرنامه نویسی
مطالبی که می‌خوانید حاصل ذهن مغشوش یک دانشجوی کامپیوتر بوده و مسئولیت هرگونه خطای احتمالی به عهده ساکنین سیاره "کپلر ۶۹ سی" می باشد!
شاید از این پست‌ها خوشتان بیاید