Skip to content

Commit b61b612

Browse files
committed
Update demonsReg.py
1 parent 0daf14d commit b61b612

1 file changed

Lines changed: 114 additions & 100 deletions

File tree

src/mirc/utils/demonsReg.py

Lines changed: 114 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,23 @@
55
66
Jamie McClelland
77
UCL
8+
9+
Changes has been done by:
10+
Zakaria Senousy
11+
ARC, UCL
812
"""
913
import matplotlib
1014
matplotlib.use('TkAgg')
1115
import matplotlib.pyplot as plt
1216

17+
1318
import numpy as np
1419
from skimage.transform import rescale, resize
1520
from scipy.ndimage import gaussian_filter
16-
from utils3 import dispImage, resampImageWithDefField, calcMSD, dispDefField
21+
from utils3 import dispImage, resampImageWithDefField, calcMSD, dispDefField, calcJacobian
1722

1823
def demonsReg(source, target, sigma_elastic=1, sigma_fluid=1, num_lev=3, use_composition=False,
19-
use_target_grad=False, max_it=1000, check_MSD=True, disp_freq=5, disp_spacing=2,
24+
use_target_grad=False, max_it=1000, check_MSD=True, disp_freq=3, disp_spacing=2,
2025
scale_update_for_display=10, disp_method_df='grid', disp_method_up='arrows'):
2126
"""
2227
SYNTAX:
@@ -64,7 +69,7 @@ def demonsReg(source, target, sigma_elastic=1, sigma_fluid=1, num_lev=3, use_com
6469
MSD will be evaluated at each iteration, and if there is no
6570
improvement since the previous iteration the registration will move
6671
to the next resolution level or finish if it is on the final level.
67-
disp_freq = 5
72+
disp_freq = 3
6873
the frequency with which to update the displayed images. the images
6974
will be updated every disp_freq iterations. If disp_freq is set to
7075
0 the images will not be updated during the registration
@@ -84,6 +89,10 @@ def demonsReg(source, target, sigma_elastic=1, sigma_fluid=1, num_lev=3, use_com
8489
source_full = source;
8590
target_full = target;
8691

92+
#Preparing function for live update during registration process
93+
fig, axs = plt.subplots(1, 3, figsize=(12, 6))
94+
iteration_text = fig.text(0.5, 0.92, '', ha='center', va='top', fontsize=10, color='black')
95+
8796
# loop over resolution levels
8897
for lev in range(1, num_lev + 1):
8998

@@ -131,55 +140,48 @@ def demonsReg(source, target, sigma_elastic=1, sigma_fluid=1, num_lev=3, use_com
131140
# not change during the registration
132141
if use_target_grad:
133142
[img_grad_x, img_grad_y] = np.gradient(target)
134-
135-
# DISPLAY RESULTS
136-
# figure 1 - source image (does not change during registration)
137-
# figure 2 - target image (does not change during registration)
138-
# figure 3 - source image transformed by current deformation field
139-
# figure 4 - deformation field
140-
# figure 5 - update
141-
142-
# Create a single figure with 5 subplots in one row
143-
fig, axs = plt.subplots(1, 5, figsize=(12, 5))
144143

145-
plt.sca(axs[0])
146-
dispImage(source, title='Source Image')
147144

148-
plt.sca(axs[1])
149-
dispImage(target, title='Target Image')
145+
146+
# Function to update the display
147+
def live_update():
148+
# Clear the axes
149+
for ax in axs:
150+
ax.clear()
150151

151-
plt.sca(axs[2])
152-
dispImage(warped_image, title='Warped Image')
153-
x_lims = plt.xlim()
154-
y_lims = plt.ylim()
152+
# Plotting the warped image in the first subplot
153+
plt.sca(axs[0])
154+
dispImage(warped_image, title='Warped Image')
155+
x_lims = plt.xlim()
156+
y_lims = plt.ylim()
157+
# Plotting the deformation field in the second subplot
158+
plt.sca(axs[1])
159+
dispDefField(def_field, spacing=disp_spacing, plot_type=disp_method_df)
160+
axs[1].set_xlim(x_lims)
161+
axs[1].set_ylim(y_lims)
162+
axs[1].set_title('Deformation Field')
155163

156-
# Plotting the deformation field in the second subplot
157-
plt.sca(axs[3])
158-
dispDefField(def_field, spacing=disp_spacing, plot_type=disp_method_df)
159-
plt.xlim(x_lims)
160-
plt.ylim(y_lims)
161-
plt.title('Deformation Field')
164+
# Plotting the updated deformation field in the third subplot
165+
plt.sca(axs[2])
166+
up_field_to_display = scale_update_for_display * np.dstack((update_x, update_y))
167+
up_field_to_display += np.dstack((X, Y))
168+
dispDefField(up_field_to_display, spacing=disp_spacing, plot_type=disp_method_up)
169+
axs[2].set_xlim(x_lims)
170+
axs[2].set_ylim(y_lims)
171+
axs[2].set_title('Update Field')
162172

163-
# Plotting the updated deformation field in the third subplot
164-
plt.sca(axs[4])
165-
up_field_to_display = scale_update_for_display * np.dstack((update_x, update_y))
166-
up_field_to_display += np.dstack((X, Y))
167-
dispDefField(up_field_to_display, spacing=disp_spacing, plot_type=disp_method_up)
168-
plt.xlim(x_lims)
169-
plt.ylim(y_lims)
170-
plt.title('Updated Deformation Field')
171-
172-
# Adjust layout for better spacing
173-
plt.tight_layout()
174-
plt.subplots_adjust(top=0.95)
173+
# Update the iteration text
174+
iteration_text.set_text('Level {0:d}, Iteration {1:d}: MSD = {2:.6f}'.format(lev, it, prev_MSD))
175+
176+
# Adjust layout for better spacing
177+
plt.tight_layout()
175178

176-
# Display the figure
177-
plt.show()
179+
# Redraw the figure
180+
fig.canvas.draw()
181+
fig.canvas.flush_events() # Ensure the figure updates immediately
178182

183+
plt.pause(0.5)
179184

180-
# if first level pause so user can position figure
181-
if lev == 1:
182-
input('position the figures as desired and then push enter to run the registration')
183185

184186
# main iterative loop - repeat until max number of iterations reached
185187
for it in range(max_it):
@@ -256,38 +258,7 @@ def demonsReg(source, target, sigma_elastic=1, sigma_fluid=1, num_lev=3, use_com
256258
# update images if required for this iteration
257259
if disp_freq > 0 and it % disp_freq == 0:
258260
# Create a single figure with 3 subplots in one row and three columns
259-
fig, axs = plt.subplots(1, 3, figsize=(12, 6))
260-
261-
# Plotting the warped image in the first subplot
262-
plt.sca(axs[0])
263-
dispImage(warped_image, title='Warped Image')
264-
plt.pause(0.05)
265-
266-
# Plotting the deformation field in the second subplot
267-
plt.sca(axs[1])
268-
dispDefField(def_field, spacing=disp_spacing, plot_type=disp_method_df)
269-
plt.xlim(x_lims)
270-
plt.ylim(y_lims)
271-
plt.title('Deformation Field')
272-
plt.pause(0.05)
273-
274-
# Plotting the updated deformation field in the third subplot
275-
plt.sca(axs[2])
276-
up_field_to_display = scale_update_for_display * np.dstack((update_x, update_y))
277-
up_field_to_display += np.dstack((X, Y))
278-
dispDefField(up_field_to_display, spacing=disp_spacing, plot_type=disp_method_up)
279-
plt.xlim(x_lims)
280-
plt.ylim(y_lims)
281-
plt.title('Updated Deformation Field')
282-
plt.pause(0.1)
283-
284-
plt.figtext(0.5, 0.92, 'Level {0:d}, Iteration {1:d}: MSD = {2:.6f}'.format(lev, it, prev_MSD), ha='center', va='top', fontsize=10, color='black')
285-
286-
# Adjust layout for better spacing
287-
plt.tight_layout()
288-
289-
# Display the figure
290-
plt.show()
261+
live_update()
291262

292263
# calculate MSD between target and warped image
293264
MSD = calcMSD(target, warped_image)
@@ -306,36 +277,79 @@ def demonsReg(source, target, sigma_elastic=1, sigma_fluid=1, num_lev=3, use_com
306277
# update previous values of def_field and MSD
307278
def_field_prev = def_field.copy()
308279
prev_MSD = MSD.copy()
280+
281+
#plt.show()
282+
283+
if lev == num_lev:
284+
# Initialise global variables for current index tracking
285+
current_image_index = [0]
286+
current_mode_index = [0]
287+
288+
# Define the images and titles
289+
images = [source, target, warped_image]
290+
image_titles = ['Source Image', 'Target Image', 'Warped Image']
291+
modes = ['Deformation Field', 'Jacobian']
292+
293+
294+
def on_key(event):
295+
if event.key == 'right':
296+
current_image_index[0] = (current_image_index[0] + 1) % len(images)
297+
elif event.key == 'left':
298+
current_image_index[0] = (current_image_index[0] - 1) % len(images)
299+
elif event.key == 'up' or event.key == 'down':
300+
current_mode_index[0] = (current_mode_index[0] + 1) % len(modes)
301+
update_display()
309302

310-
# display the final results
311-
# Create a single figure with 3 subplots in one row
312-
fig, axs = plt.subplots(1, 3, figsize=(12, 5))
313303

314-
# Plotting the warped image in the first subplot
315-
plt.sca(axs[0])
316-
dispImage(warped_image, title='Warped Image')
317304

318-
# Plotting the deformation field in the second subplot
319-
plt.sca(axs[1])
320-
dispDefField(def_field, spacing=disp_spacing, plot_type=disp_method_df)
321-
plt.xlim(x_lims)
322-
plt.ylim(y_lims)
323-
plt.title('Deformation Field')
305+
def update_display():
306+
axs_combined[0].clear()
307+
plt.sca(axs_combined[0])
308+
dispImage(images[current_image_index[0]], title=image_titles[current_image_index[0]])
309+
310+
axs_combined[1].clear()
311+
plt.sca(axs_combined[1])
312+
if modes[current_mode_index[0]] == 'Deformation Field':
313+
dispDefField(def_field, spacing=disp_spacing, plot_type=disp_method_df)
314+
axs_combined[1].set_title('Deformation Field')
315+
316+
else:
317+
[jacobian, _] = calcJacobian(def_field)
318+
dispImage(jacobian, title='Jacobian')
319+
plt.set_cmap('jet')
320+
#plt.colorbar()
321+
322+
axs_combined[2].clear()
323+
plt.sca(axs_combined[2])
324+
diff_image = images[current_image_index[0]] - target
325+
dispImage(diff_image, title='Difference Image')
326+
327+
fig_combined.canvas.draw()
328+
329+
330+
# Create a single figure with 3 subplots
331+
fig_combined, axs_combined = plt.subplots(1, 3, figsize=(12, 6))
332+
333+
# Display initial images
334+
plt.sca(axs_combined[0])
335+
dispImage(images[current_image_index[0]], title=image_titles[current_image_index[0]])
336+
337+
plt.sca(axs_combined[1])
338+
dispDefField(def_field, spacing=disp_spacing, plot_type=disp_method_df)
339+
axs_combined[1].set_title('Deformation Field')
340+
341+
plt.sca(axs_combined[2])
342+
diff_image = images[current_image_index[0]] - target
343+
dispImage(diff_image, title='Difference Image')
324344

325-
# Plotting the updated deformation field in the third subplot
326-
plt.sca(axs[2])
327-
up_field_to_display = scale_update_for_display * np.dstack((update_x, update_y))
328-
up_field_to_display += np.dstack((X, Y))
329-
dispDefField(up_field_to_display, spacing=disp_spacing, plot_type=disp_method_up)
330-
plt.xlim(x_lims)
331-
plt.ylim(y_lims)
332-
plt.title('Updated Deformation Field')
345+
# Add instructions for navigating images
346+
fig_combined.text(0.5, 0.02, 'Press <- or -> to navigate between source, target and warped images, Press Up or Down to switch between deformation field and Jacobian', ha='center', va='top', fontsize=12, color='black')
333347

334-
# Adjust layout for better spacing
335-
plt.tight_layout()
348+
# Connect the key event handler to the figure
349+
fig_combined.canvas.mpl_connect('key_press_event', on_key)
336350

337-
# Display the figure
338-
plt.show()
351+
plt.tight_layout()
352+
plt.show()
339353

340354
# return the transformed image and the deformation field
341355
return warped_image, def_field

0 commit comments

Comments
 (0)