В аквариуме: вычислительная генетика на Python и Mathcad (часть 1)
Пусть в аквариуме живут рыбки двух цветов.
Начнем с визуализации. Зададим число рыбок n=100 и договоримся что каждая из них имеет случайный цвет color №0 или №1, а также находится в случайной точке (x,y). Т.е. x, y, и color — это три вектора длины n, а третью (z-) координату мы не рассматриваем.
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
n = 100
x, y = np.random.rand(n), np.random.rand(n)
color = np.random.randint(0, 2, n)
plt.scatter(x, y, c=color)
Те же три вектора в Mathcad Express можно сгенерировать так:
Для векторов x,y используем генератор случайных чисел с равномерным распределением на отрезке (0, 1), а для вектора color — биномиального распределения, моделирующего, в том числе, однократное подбрасывание монеты. В данном конкретном розыгрыше в Mathcad получилось 47 рыбок №1 и 100-47=53 рыбок нулевого цвета.
Теперь перейдем к главному вопросу: почему разные рыбки обладают цветом номер 0 или 1?
Все дело здесь в генетической информации, заключенной в биологическом материале, из которого состоит тело рыбки. Грубо говоря, живые существа, даже одного вида, различаются по химическому составу, причем в "длинных" молекулах биологических полимеров, из которых состоит все живое, зашифрована определенная информация, единицу которой обычно называют геном.
Совокупность генов каждого живого существа, называемая генотипом, определяет его внешний вид. В частности, генотип каждой рыбки определяет ее цвет. В простейшем случае, модель которого мы и будем дальше программировать, цвет рыбки (0 или 1) определяет один конкретный ген ("ген цвета"). Аналогичная ситуация (один ген определяет цвет) имела место в классических опытах Грегора Менделя, основоположника современной генетики, с растениями гороха, а в других случаях (например, для окраса собак-такс) на цвет отдельной особи влияет сочетание нескольких генов.
Как именно гены кодируют цвет? Прежде всего, ген цвета рыбки может существовать в двух вариантах, которые называются аллелями (я буду избегать этого и некоторых других важных для биолога терминов, чтобы сосредоточиться на информатике). В генетике их принято обозначать прописной и строчной буквами (например, А и а). Я буду чаще пользоваться цифрой А=0, а=1.
Каждое растение гороха в опытах Менделя и каждая рыбка из нашего аквариума несет в себе информацию о двух аллелях, т.е. описывается одной из трех возможных комбинаций:
АА или 00
Аа (то же самое, что аА) или 01
аа или 11
Если рыбка несет ген цвета АА или Аа, то она серая, а если аа — желтая. Т.е. тип гена А полностью блокирует тип а, поэтому вариант А (0) называют доминатным, а а (1) — рецессивным.
Давайте реализуем расчет цвета рыбки по ее генетическому коду, который для i-й рыбки будем описывать вектором из двух компонентов, а генетический состав всей популяции — соответственно, матрицей, которую назовем Аа. Пусть у нас есть три рыбки, каждая из которых с равной вероятностью несет генетический код 00, 10, 01 или 11. В первых трех случаях цвет рыбки будет серым, а в четвертом — желтым.
n = 3
Aa = np.zeros((n,2))
color = np.zeros(n)
for i in range(n):
Aa[i,0] = np.random.randint(0, 2, 1)
Aa[i,1] = np.random.randint(0, 2, 1)
color[i] = Aa[i,0] * Aa[i,1]
print (Aa)
print (color)
Результат работы программы вы видите на картинке:
Очевидно, при такой модели, если рыбок будет много, то цветных будет около 25%. Аналогичные вычисления в Mathcad для популяции из n=1000 рыбок приведены на следующем рисунке.
Все эти расчеты я виду в режиме стримов на своем YouTube канале , т.е. фактически, данная статья — это краткий дайджест первых двух роликов по вычислительной генетике. А в следующих сериях я планирую организовать пересчет генотипа рыбок от поколения к поколению, причем, видимо, мне придется перейти к ООП и описывать рыбок при помощи классов в Python, а Mathcad использовать, как средство вспомогательных расчетов. В качестве опорного материала я использую Википедию и вот этот курс на Степике.