Как отобразить значения массива в виде цветных точек решетки? - PullRequest
2 голосов
/ 29 мая 2020

Я создаю программу python, которая имитирует сворачивание белков. Мой белок состоит из 19 элементов (аминокислот), каждый из которых обозначен числом от 1 до 20. Я использовал randint() для создания белка и создал массив нулей.

Первоначально белок развернут. и центрированы по горизонтали в массиве 21 на 21. Таким образом, ненулевые значения массива находятся в 10-й строке. Я импортировал matplotlib и использовал matshow(), чтобы отобразить это расположение:

here.

Что мне нравится в этой цифре, так это то, что очевидно, что белок состоит из разных аминокислот. / элементов, как показано цветом каждого квадрата. Я бы хотел сохранить эту функцию. Однако вместо квадратов я хотел бы, чтобы каждый элемент отображался как цветная точка, соединенная со своим соседом ссылкой или в сетке:

link image on a grid like this image.

Я предоставил свой код ниже. Подытоживая мои вопросы:

1) Как мне отобразить элементы в массиве в виде кругов или точек решетки со связями, соединяющими точки?

2) Как мне сделать это, сохраняя одинаковые цвета для каждого элемента?

3) Как указать, что нулевые значения (в настоящее время фиолетовые) должны быть белыми? Я не предпочитаю другие цвета, мне нужен белый фон.

import numpy as np
import matplotlib.pyplot as plt
import random
from matplotlib.colors import ListedColormap

###create grid
rows = 21 
columns = 21
x = np.zeros(rows) #create arrays for the x- and y-positions
y = np.zeros(columns)
middle = (rows-1)/2

grid = np.zeros((rows,columns)) #grid = [row][columns] = value = grid[j][i]

###create protein:
n = 20
protein = []
while len(protein) < n:
     a = random.randint(1, 20)
     protein = np.append(protein, a)

###specify initial condition with protein unfolded along y=0
j = int(middle)
i = 1
while i < rows-1:
    grid[j][i] = protein[i]
    i = i+1
print(grid)
plt.matshow(grid)

Ответы [ 2 ]

4 голосов
/ 29 мая 2020

Q1 и 2 - Я думаю, вы хотите добавить диаграмму рассеяния с разными цветовыми маркерами поверх текущего графика. Может быть сложно добавить и линейные, и разные цветовые маркеры, поэтому лучше всего будет просто добавить линейный график, основанный на одинаковых значениях x / y, чтобы они обновлялись одновременно (при условии, что вы обновляете их до складывание дисплея). Данный код - это просто разброс, но он поддерживает вашу текущую цветовую систему.

Изменить: отличный пример этого (разброс и график) см. В другом ответе.

import matplotlib.colors as mcolors
from matplotlib import cm
normalize = mcolors.Normalize(vmin=0, vmax=20)
mapping = cm.viridis(normalize(protein))  # maintain current colours
plt.scatter(range(20), np.broadcast_to(10, 20), c=mapping, marker='o')

Q3- Вы может установить значения для указанной c цветовой карты для отображения определенных цветов с помощью .set_under, см., например, этот ответ - { ссылка } Это должно сделать фон вашего отображения белым.

cm.viridis.set_under(c='w')
plt.matshow(grid, vim=1e-9)  # Arbitrary low value.

Если это отрицательно сказывается на цвете белков, рассмотрите возможность использования numpy NaN или infinty или чего-то подобного и вместо этого set_bad.

3 голосов
/ 29 мая 2020

Цветные точки можно нарисовать с помощью plt.scatter(). Сегменты прямых линий с plt.plot().

Для представления сгиба массив из 0 s, 1 s и -1 s может представлять сгибание по прямой, с поворотом вправо или с поворотом влево.

Чтобы нарисовать график, создайте позиции x и y, применяя направления сгиба. Эти позиции служат для рисования отрезков линии (plt.plot), а также цветных точек (plt.scatter). Чтобы иметь 20 разных цветов, можно использовать 'tab20' colormap .

Вот пример кода для начала.

import numpy as np
from matplotlib import pyplot as plt

n = 20
protein = np.random.randint(1, 20, n) # n numbers between 1 and 19
folds = np.zeros(n, dtype=np.int) # default there are no turns
folds[9] = -1 # turn left after protein 9
folds[11] = 1 # turn right after protein 11
folds[15] = -1 # turn left after protein 15

dir = (1, 0)
pos = (0, 0)
x = np.zeros_like(protein)
y = np.zeros_like(protein)
for i, (p, f) in enumerate(zip(protein, folds)):
    x[i], y[i] = pos
    if f == 1:  # turn right
        dir = (dir[1], -dir[0])
    elif f == -1:  # turn left
        dir = (-dir[1], dir[0])
    pos = (pos[0] + dir[0], pos[1] + dir[1])
plt.plot(x, y, 'k-', zorder=0)  # straight lines
# large dots colored via the 'tab20' colormap, set zorder=3 to draw the dots on top of the lines
plt.scatter(x, y, c=protein, cmap='tab20', s=200, zorder=3) 

plt.axis('off') # don't show the axes
plt.margins(0.1) # enough margin so that the large scatter dots don't touch the borders
plt.gca().set_aspect('equal') # equal distances in x and y direction 
plt.show()

example plot

Чтобы нарисовать что-то похожее на пример 'd':

n = 15
protein = np.random.randint(1, 20, n)
folds = [1, -1, 1, -1, 0, 0, 0, 1, -1, 0, 0, 1, -1, -1, 0]

similar to example d

PS: Со следующим адаптации, показаны линии сетки:

from matplotlib.ticker import MultipleLocator, NullFormatter

plt.axis('on')
ax = plt.gca()
ax.xaxis.set_major_locator(MultipleLocator(1))
ax.xaxis.set_major_formatter(NullFormatter())
ax.yaxis.set_major_locator(MultipleLocator(1))
ax.yaxis.set_major_formatter(NullFormatter())
ax.tick_params(axis='both', length=0)
plt.grid(True, ls=':')

with grid

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...