это мой первый пост в стеке, поэтому, пожалуйста, будьте осторожны.
Вот моя проблема: я нашел на сайте очень хороший скрипт на python, который мне пришлось немного изменить, чтобы он соответствовал моим потребностям, и теперь яхотел бы изменить его еще раз, но я не знаю, как
Сначала код
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
def bullseye_plot(ax, data, segBold=None, cmap=None, norm=None):
"""
Bullseye representation for the left ventricle.
Parameters
----------
ax : axes
data : list of int and float
The intensity values for each of the 17 segments
segBold: list of int, optional
A list with the segments to highlight
cmap : ColorMap or None, optional
Optional argument to set the desired colormap
norm : Normalize or None, optional
Optional argument to normalize data into the [0.0, 1.0] range
Notes
-----
This function create the 17 segment model for the left ventricle according
to the American Heart Association (AHA) [1]_
References
----------
.. [1] M. D. Cerqueira, N. J. Weissman, V. Dilsizian, A. K. Jacobs,
S. Kaul, W. K. Laskey, D. J. Pennell, J. A. Rumberger, T. Ryan,
and M. S. Verani, "Standardized myocardial segmentation and
nomenclature for tomographic imaging of the heart",
Circulation, vol. 105, no. 4, pp. 539-542, 2002.
"""
if segBold is None:
segBold = []
linewidth = 2
data = np.array(data).ravel()
if cmap is None:
cmap = plt.cm.viridis
if norm is None:
norm = mpl.colors.Normalize(vmin=data.min(), vmax=data.max())
theta = np.linspace(0, 2*np.pi, 768)
r = np.linspace(0, 1, 4)
# Create the bound for the segment 17
for i in range(r.shape[0]):
ax.plot(theta, np.repeat(r[i], theta.shape), '-k', lw=linewidth)
# Create the bounds for the segments 1-12
for i in range(6):
theta_i = i*60*np.pi/180
ax.plot([theta_i, theta_i], [r[1], 1], '-k', lw=linewidth)
# Create the bounds for the segments 13-16
for i in range(4):
theta_i = i*90*np.pi/180 - 45*np.pi/180
ax.plot([theta_i, theta_i], [r[0], r[1]], '-k', lw=linewidth)
# Fill the segments 1-6
r0 = r[2:4]
r0 = np.repeat(r0[:, np.newaxis], 128, axis=1).T
for i in range(6):
# First segment start at 60 degrees
theta0 = theta[i*128:i*128+128] + 60*np.pi/180
theta0 = np.repeat(theta0[:, np.newaxis], 2, axis=1)
z = np.ones((128, 2))*data[i]
ax.pcolormesh(theta0, r0, z, cmap=cmap, norm=norm)
if i+1 in segBold:
ax.plot(theta0, r0, '-k', lw=linewidth+2)
ax.plot(theta0[0], [r[2], r[3]], '-k', lw=linewidth+1)
ax.plot(theta0[-1], [r[2], r[3]], '-k', lw=linewidth+1)
# Fill the segments 7-12
r0 = r[1:3]
r0 = np.repeat(r0[:, np.newaxis], 128, axis=1).T
for i in range(6):
# First segment start at 60 degrees
theta0 = theta[i*128:i*128+128] + 60*np.pi/180
theta0 = np.repeat(theta0[:, np.newaxis], 2, axis=1)
z = np.ones((128, 2))*data[i+6]
ax.pcolormesh(theta0, r0, z, cmap=cmap, norm=norm)
if i+7 in segBold:
ax.plot(theta0, r0, '-k', lw=linewidth+2)
ax.plot(theta0[0], [r[1], r[2]], '-k', lw=linewidth+1)
ax.plot(theta0[-1], [r[1], r[2]], '-k', lw=linewidth+1)
# Fill the segments 13-16
r0 = r[0:2]
r0 = np.repeat(r0[:, np.newaxis], 192, axis=1).T
for i in range(4):
# First segment start at 45 degrees
theta0 = theta[i*192:i*192+192] + 45*np.pi/180
theta0 = np.repeat(theta0[:, np.newaxis], 2, axis=1)
z = np.ones((192, 2))*data[i+12]
ax.pcolormesh(theta0, r0, z, cmap=cmap, norm=norm)
if i+13 in segBold:
ax.plot(theta0, r0, '-k', lw=linewidth+2)
ax.plot(theta0[0], [r[0], r[1]], '-k', lw=linewidth+1)
ax.plot(theta0[-1], [r[0], r[1]], '-k', lw=linewidth+1)
ax.set_ylim([0, 1])
ax.set_yticklabels([])
ax.set_xticklabels([])
# Create the fake data
data = np.array(range(17)) + 1
# Make a figure and axes with dimensions as desired.
fig, ax = plt.subplots(figsize=(12, 8), nrows=1, ncols=1,
subplot_kw=dict(projection='polar'))
fig.canvas.set_window_title('Left Ventricle Bulls Eyes (AHA)')
# Set the colormap and norm to correspond to the data for which
# the colorbar will be used.
cmap = mpl.cm.viridis
norm = mpl.colors.Normalize(vmin=1, vmax=17)
# Create the 17 segment model
bullseye_plot(ax, data, cmap=cmap, norm=norm)
ax.set_title('Bulls Eye (AHA)')
plt.show()
Он производит то, что мы называем картой булли, смотри полученный результат: Карта Bulleye
То, что я хочу сделать, довольно просто объяснить:
- я хотел бы добавить правильно, красиво, число или два числа (макс.) В каждом сегменте (на этом рисунке 16 сегментов).
- В зависимости от значения числа (если число только одно), я хотел бы иметь возможность связать каждый сегмент с различным оттенком / цветом.Например, если у меня есть «2», цвет соответствующего сегмента будет красным.Если у меня есть «4», цвет соответствующего сегмента также может быть красным, но темнее.Что-то в этом роде.
Если такая вещь невозможна, по крайней мере, я бы хотел иметь другой цвет в зависимости от номера, связанного с данным сегментом.
Я не настолько осведомленв Python, поэтому я не знаю, как это сделать, и мои вопросы настолько специфичны, что я не знаю, где искать ответ.Если бы вы могли мне помочь, я был бы очень признателен.
PS: Кроме того, если вы думаете, что код можно как-то улучшить (или что есть какие-то бесполезные части), пожалуйста, сообщите мне об этом.
Заранее спасибо.
PS: для того, чтобы отдать должное тому, кто создал код в первом месте, вот оригинальная ссылка Как сгенерировать карту булли
Пока что я делал нечто подобное с латексом, вот картинка, которую я получил, когда они представляют собой 2 числа для каждого сегмента.Надеюсь, мне будет проще «представить» то, что я хотел бы. Карта Bulleye - LateX версия
Обновление: объединяя принятый ответ и некоторую идею из оригинального сценария, я наконец получил именно то, что хотел.Вот скрипт
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
def bullseye_plot(ax, data, segBold=None, cmap=None, norm=None, labels=[], labelProps={}):
if segBold is None:
segBold = []
linewidth = 2
data = np.array(data).ravel()
if cmap is None:
cmap = plt.cm.viridis
if norm is None:
norm = mpl.colors.Normalize(vmin=data.min(), vmax=data.max())
theta = np.linspace(0, 2*np.pi, 768)
r = np.linspace(0, 1, 4)
# Create the bound for the segment 17
for i in range(r.shape[0]):
ax.plot(theta, np.repeat(r[i], theta.shape), '-k', lw=linewidth)
# Create the bounds for the segments 1-12
for i in range(6):
theta_i = i*60*np.pi/180
ax.plot([theta_i, theta_i], [r[1], 1], '-k', lw=linewidth)
# Create the bounds for the segments 13-16
for i in range(4):
theta_i = i*90*np.pi/180 - 45*np.pi/180
ax.plot([theta_i, theta_i], [r[0], r[1]], '-k', lw=linewidth)
# Fill the segments 1-6
r0 = r[2:4]
r0 = np.repeat(r0[:, np.newaxis], 128, axis=1).T
for i in range(6):
# First segment start at 60 degrees
theta0 = theta[i*128:i*128+128] + 60*np.pi/180
theta0 = np.repeat(theta0[:, np.newaxis], 2, axis=1)
z = np.ones((128, 2))*data[i]
ax.pcolormesh(theta0, r0, z, cmap=cmap, norm=norm)
if labels:
ax.annotate(labels[i], xy=(theta0[0,0]+30*np.pi/180,np.mean(r[2:4])), ha='center', va='center', **labelProps)
if i+1 in segBold:
ax.plot(theta0, r0, '-k', lw=linewidth+2)
ax.plot(theta0[0], [r[2], r[3]], '-k', lw=linewidth+1)
ax.plot(theta0[-1], [r[2], r[3]], '-k', lw=linewidth+1)
# Fill the segments 7-12
r0 = r[1:3]
r0 = np.repeat(r0[:, np.newaxis], 128, axis=1).T
for i in range(6):
# First segment start at 60 degrees
theta0 = theta[i*128:i*128+128] + 60*np.pi/180
theta0 = np.repeat(theta0[:, np.newaxis], 2, axis=1)
z = np.ones((128, 2))*data[i+6]
ax.pcolormesh(theta0, r0, z, cmap=cmap, norm=norm)
if labels:
ax.annotate(labels[i+6], xy=(theta0[0,0]+30*np.pi/180,np.mean(r[1:3])), ha='center', va='center', **labelProps)
if i+7 in segBold:
ax.plot(theta0, r0, '-k', lw=linewidth+2)
ax.plot(theta0[0], [r[1], r[2]], '-k', lw=linewidth+1)
ax.plot(theta0[-1], [r[1], r[2]], '-k', lw=linewidth+1)
# Fill the segments 13-16
r0 = r[0:2]
r0 = np.repeat(r0[:, np.newaxis], 192, axis=1).T
for i in range(4):
# First segment start at 45 degrees
theta0 = theta[i*192:i*192+192] + 45*np.pi/180
theta0 = np.repeat(theta0[:, np.newaxis], 2, axis=1)
z = np.ones((192, 2))*data[i+12]
ax.pcolormesh(theta0, r0, z, cmap=cmap, norm=norm)
if labels:
ax.annotate(labels[i+12], xy=(theta0[0,0]+45*np.pi/180,np.mean(r[0:2])), ha='center', va='center', **labelProps)
if i+13 in segBold:
ax.plot(theta0, r0, '-k', lw=linewidth+2)
ax.plot(theta0[0], [r[0], r[1]], '-k', lw=linewidth+1)
ax.plot(theta0[-1], [r[0], r[1]], '-k', lw=linewidth+1)
ax.set_ylim([0, 1])
ax.set_yticklabels([])
ax.set_xticklabels([])
# Create the fake data
labels = ['1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
'12',
'13',
'14',
'15',
'16']
data=[]
for i in range(len(labels)):
x=int(labels[i])
data.append(x)
# Make a figure and axes with dimensions as desired.
fig, ax = plt.subplots(figsize=(8, 8), nrows=1, ncols=1,
subplot_kw=dict(projection='polar'))
fig.canvas.set_window_title('Left Ventricle Bulls Eyes (AHA)')
# Create the axis for the colorbars
axl = fig.add_axes([0.14, 0.15, 0.2, 0.05])
# Set the colormap and norm to correspond to the data for which
# the colorbar will be used.
cmap = mpl.cm.viridis
norm = mpl.colors.Normalize(vmin=min(data), vmax=max(data))
# ColorbarBase derives from ScalarMappable and puts a colorbar
# in a specified axes, so it has everything needed for a
# standalone colorbar. There are many more kwargs, but the
# following gives a basic continuous colorbar with ticks
# and labels.
cb1 = mpl.colorbar.ColorbarBase(axl, cmap=cmap, norm=norm,
orientation='horizontal')
cb1.set_label('Some Units')
# Create the 16 segment model
bullseye_plot(ax, data, cmap=cmap, norm=norm, labels=labels, labelProps={'size':15, "weight":'bold'})
ax.set_title('Bulls Eye (AHA)')
plt.show()
Что касается результата, то вот он Конечный результат