Введенные координаты x, y и z выведут три графика: график x-z, скользящий по оси y, график x-y, скользящий по оси z, и график y-z, скользящий по оси x. Я размещаю линии на основе процента, на который пользователь сдвинул соответствующую координату на инструменте ползунка. См. ниже (не пугайтесь того, как переключаются корональная и поперечная проекции):
Однако, как видите, координата y мала, поэтому линия выходит за пределы рисунка. Проблема в том, что строки расположены относительно окна, а не относительно графика. Поэтому я хотел бы получить размер фигуры в окне, чтобы исправить эту проблему. Я не нашел никакой документации о том, как найти размеры фигуры в окне, а не во всем окне — как мне подойти к этому? Благодарю вас! См. мой код ниже, чтобы увидеть, как визуализируется каждый отдельный график:
fig = plt.figure(d+1, figsize = (maxX, maxY))
xCoord = -1
yCoord = -1
if d == 0:
thisSlice = fData[newVoxel.s, :, :, 0]
plt.title("Saggital")
xCoord = newVoxel.t / maxT
yCoord = newVoxel.c / maxC
elif d == 1:
thisSlice = fData[:, newVoxel.t, :, 0]
plt.title("Transverse")
xCoord = newVoxel.s / maxS
yCoord = newVoxel.c / maxC
elif d == 2:
thisSlice = fData[:, :, newVoxel.c, 0]
plt.title("Coronal")
xCoord = newVoxel.s / maxS
yCoord = newVoxel.t / maxT
artists.append(fig.add_artist(lines.Line2D([0, 1], [yCoord, yCoord])))
artists.append(fig.add_artist(lines.Line2D([xCoord, xCoord], [0, 1])))
plt.axis('off')
plt.imshow(thisSlice.T, cmap = 'inferno', origin = 'lower')
Можно преобразовать точки фигуры в данные осей; В matplotlib для этого есть вся структура. Впрочем, зачем усложнять себе жизнь? Я предлагаю структурировать фигуры по-разному вокруг пределов осей нанесенных изображений:
import matplotlib.pyplot as plt
#random data
import numpy as np
rng = np.random.default_rng(123)
maxX = rng.integers(10, 20)
maxY = rng.integers(5, 10)
thisSlice = rng.random((maxX, maxY))
def define_figure(d, thisSlice):
fig = plt.figure(d+1, figsize=(maxX, maxY))
ax = fig.add_subplot()
artists = []
my_title = ["Saggital", "Transverse", "Coronal"][d]
ax.set_title(my_title)
ax.axis('off')
img = ax.imshow(thisSlice.T, cmap = 'inferno', origin = 'lower')
view_x_max, view_y_max = thisSlice.shape
viewlimits = [view_x_max, view_y_max]
artists.append(ax.axhline(y=view_y_max//2, xmin=-10, xmax=10, clip_on = False))
artists.append(ax.axvline(x=view_x_max//2, ymin=-10, ymax=10, clip_on = False))
return fig, ax, img, artists, viewlimits
#create figure and capture essential figure elements you will need for later updates
current_figure, current_axis, current_image, current_lineartists, current_viewlimits = define_figure(1, thisSlice)
#now limit the slider range to integer values not exceeding current_viewlimits
#or update the image in axis if the corresponding slider is moved
def update_image(img_object, newimage):
img_object.set_data(newimage.T)
plt.pause(5)
update_image(current_image, rng.random(thisSlice.shape))
plt.pause(5)
plt.show()
Это просто предложение облегчить вам жизнь, но я не знаю, какие у вас есть ограничения и требования, поэтому другие варианты могут быть предпочтительнее. Также обратите внимание на изменение функции update_image
— обновление свойств существующих объектов обычно выполняется быстрее и требует меньше ресурсов, чем создание нового объекта.
Спасибо за ваш подробный ответ! Я попытаюсь реструктурировать свой код в соответствии с вашими рекомендациями и загружу эти изменения.