Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug on manual registration after reloading images #247

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 60 additions & 40 deletions src/idvc/dvc_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ def __init__(self):
else:
self.CreateSessionSelector("new window")

self.translate = vtk.vtkImageTranslateExtent()
self.subtract = vtk.vtkImageMathematics()
self.vis_widget_reg = VisualisationWidget(self, viewer2D)

def createPopupMenu(self):
'''return an empty menu for the main window to use as a popup menu.

Expand Down Expand Up @@ -378,7 +382,7 @@ def CreateViewerSettingsPanel(self):
def updateCoordinates(self):
viewers_2D = [self.vis_widget_2D.frame.viewer]
vs_widgets = self.visualisation_setting_widgets
if hasattr(self, 'vis_widget_reg'):
if self.vis_widget_reg.image_data != []:
viewers_2D.append(self.vis_widget_reg.frame.viewer)

for viewer in viewers_2D:
Expand Down Expand Up @@ -531,7 +535,8 @@ def CreateSelectImagePanel(self):

def view_and_load_images(self):
self.view_image()
self.resetRegistration()
self.cancelRegistration()
self.resetRegistrationForSession()

def SelectImage(self, image_var, image, label=None, next_button=None):
#print("In select image")
Expand Down Expand Up @@ -771,6 +776,12 @@ def save_image_info(self, image_type):
self.visualise()

def visualise(self):
"""If no data is visualised it outputs an error.
Creates a loading progress window.
Uploads and sdisplays the ref image in the 2D and 3D viewers.
Adds observers to 2D viewer.
Links the viewers.
Resets attributes `current slice` and `orintation`."""
if self.ref_image_data is None:
#self.progress_window.setValue(100)
self.warningDialog('Unable to load image.','Error', 'Image is in incorrect format to perform run of DVC. Please load a different image.')
Expand Down Expand Up @@ -1040,7 +1051,9 @@ def setup3DPointCloudPipeline(self):

# Registration Panel:
def CreateRegistrationPanel(self):
"""Create the Registration Dockable Widget"""
"""Create the Registration Dockable Widget

When the visibility changes calls displayRegistrationViewer"""

self.registration_panel = generateUIDockParameters(self, '2 - Manual Registration')
dockWidget = self.registration_panel[0]
Expand Down Expand Up @@ -1168,13 +1181,13 @@ def CreateRegistrationPanel(self):
widgetno += 1

# Add cancel automatic registration button
rp['cancel_auto_reg_button'] = QPushButton(groupBox)
rp['cancel_auto_reg_button'].setText("Reset")
rp['cancel_auto_reg_button'].setEnabled(True)
rp['cancel_auto_reg_button'].clicked.connect(self.cancelAutomaticRegistration)
formLayout.insertRow(widgetno - 1, '', rp['cancel_auto_reg_button'])
rp['reset_reg_button'] = QPushButton(groupBox)
rp['reset_reg_button'].setText("Reset")
rp['reset_reg_button'].setEnabled(True)
rp['reset_reg_button'].clicked.connect(self.resetRegistration)
formLayout.insertRow(widgetno - 1, '', rp['reset_reg_button'])
widgetno += 1
rp['cancel_auto_reg_button'].setVisible(False)
rp['reset_reg_button'].setVisible(False)

# Add set to automatic registration button
rp['set_auto_reg_button'] = QPushButton(groupBox)
Expand Down Expand Up @@ -1203,12 +1216,20 @@ def CreateRegistrationPanel(self):
self.registration_parameters = rp

def createRegistrationViewer(self):
"""Creates the viewer for the registration
i.e. the diff image is shown for the selected area
Sets the viewer 2D and 3D to not visible.
Adds observer forward and backwards mouse wheel to span the slice.
Adds observer press key to updates the plane.
Adds observer press key to change orientation.
Adds observer press key to shift images with respect to each other.
"""
# print("Create reg viewer")
#Get current orientation and slice of 2D viewer, registration viewer will be set up to have these
self.orientation = self.vis_widget_2D.frame.viewer.getSliceOrientation()
self.current_slice = self.vis_widget_2D.frame.viewer.getActiveSlice()

self.vis_widget_reg = VisualisationWidget(self, viewer2D)



reg_viewer_dock = QDockWidget("Image Registration",self.RightDockWindow)
Expand Down Expand Up @@ -1244,14 +1265,15 @@ def createRegistrationViewer(self):

self.vis_widget_reg.frame.viewer.style.AddObserver('KeyPressEvent', self.OnKeyPressEventForRegistration, 1.5) #Happens before viewer KeyPressEvent (higher priority)
self.vis_widget_reg.frame.viewer.style.AddObserver('KeyPressEvent', self.AfterKeyPressEventForRegistration, 0.5) #Happens after viewer KeyPressEvent (lower priority)
print(self.vis_widget_reg.frame.viewer.style)

def displayRegistrationViewer(self,registration_open):

if hasattr(self, 'ref_image_data'):
#check for image data else do nothing
if registration_open:
self.help_label.setText(self.help_text[1])
if not hasattr(self, 'vis_widget_reg'):
if self.vis_widget_reg.image_data == []:
# print("Creating reg viewer")
self.viewer2D_dock.setVisible(False)
self.viewer3D_dock.setVisible(False)
Expand Down Expand Up @@ -1399,7 +1421,7 @@ def centerOnPointZero(self):
display slice Z=7.
Produces a warning dialog if point0 has not yet been selected.
"""
if hasattr(self, 'vis_widget_reg'):
if self.vis_widget_reg.image_data != []:
v = self.vis_widget_reg.frame.viewer

if hasattr(self, 'point0_world_coords'):
Expand All @@ -1419,7 +1441,7 @@ def centerOnPointZero(self):
self.warningDialog("Choose a Point 0 first.", "Error")

def displayRegistrationSelection(self):
if hasattr(self, 'vis_widget_reg'):
if self.vis_widget_reg.image_data != []:
#print ("displayRegistrationSelection")
rp = self.registration_parameters
v = self.vis_widget_reg.frame.viewer
Expand Down Expand Up @@ -1544,7 +1566,7 @@ def OnStartStopRegistrationPushed(self):
rp['translate_Y_entry'].setText("0")
rp['translate_Z_entry'].setText("0")

if hasattr(self, 'vis_widget_reg'):
if self.vis_widget_reg.image_data != []:
self.UpdateViewerSettingsPanelForRegistration()
if rp['start_registration_button'].isChecked(): # "Start Registration" has been pressed
self.startRegistration()
Expand Down Expand Up @@ -1585,10 +1607,7 @@ def startRegistration(self):
rp['translate_Y_entry'].setEnabled(False)
rp['translate_Z_entry'].setEnabled(False)
# setup the appropriate stuff to run the registration
if not hasattr(self, 'translate'):
self.translate = vtk.vtkImageTranslateExtent()
elif self.translate is None:
self.translate = vtk.vtkImageTranslateExtent()
self.translate = vtk.vtkImageTranslateExtent()
#self.translate.SetTranslation(-int(rp['translate_X_entry'].text()),-int(rp['translate_Y_entry'].text()),-int(rp['translate_Z_entry'].text()))
self.LoadImagesAndCompleteRegistration()

Expand All @@ -1608,7 +1627,7 @@ def confirmRegistration(self):
#rp['translate_X_entry'].setEnabled(True)
#rp['translate_Y_entry'].setEnabled(True)
#rp['translate_Z_entry'].setEnabled(True)
rp['cancel_auto_reg_button'].setVisible(False)
rp['reset_reg_button'].setVisible(False)
rp['set_auto_reg_button'].setVisible(False)
rp['set_auto_reg_label'].setVisible(False)
v.setInput3DData(self.ref_image_data)
Expand Down Expand Up @@ -1756,7 +1775,7 @@ def setRegistrationWidgetsFromWorker(self,result):
self.setRegistrationWidgets(self.auto_reg_result)
rp = self.registration_parameters
rp['set_auto_reg_label'].setText(f'Automatic registration {[self.auto_reg_result[0],self.auto_reg_result[1],self.auto_reg_result[2]]}')
rp['cancel_auto_reg_button'].setVisible(True)
rp['reset_reg_button'].setVisible(True)
rp['set_auto_reg_label'].setVisible(True)
rp['set_auto_reg_button'].setVisible(True)

Expand Down Expand Up @@ -1797,14 +1816,13 @@ def getRegistrationTranslation(self):
current_translation = np.array([int(rp['translate_X_entry'].text()),int(rp['translate_Y_entry'].text()),int(rp['translate_Z_entry'].text())])
return current_translation

def cancelAutomaticRegistration(self):
def resetRegistration(self):
"""Resets the widgets and the viewer to no translation."""
rp = self.registration_parameters
self.setRegistrationWidgets(np.array([0,0,0]))

def cancelRegistration(self):
"""Resets the widgets and the wiever to no translation and confirms the registration. Updates the buttons."""
self.cancelAutomaticRegistration()
self.resetRegistration()
self.confirmRegistration()
self.registration_parameters['cancel_reg_button'].setVisible(False)
self.registration_parameters['start_registration_button'].setChecked(False)
Expand All @@ -1827,8 +1845,9 @@ def manualRegistration(self):
self.reg_viewer_update(type = 'starting registration')
self.centerOnPointZero()

def resetRegistration(self):
if hasattr(self, 'vis_widget_reg'):
def resetRegistrationForSession(self):
"""Calls displayRegistrationViewer and sets False."""
if self.vis_widget_reg != []:
#print("About to del image reg viewer")
self.displayRegistrationViewer(False)
self.vis_widget_reg.createEmptyFrame()
Expand Down Expand Up @@ -1874,23 +1893,21 @@ def translateImages(self, progress_callback = None):
cast2.SetInputConnection(self.translate.GetOutputPort())
cast2.SetOutputScalarTypeToFloat()
#progress_callback.emit(50)
subtract = vtk.vtkImageMathematics()
subtract.SetOperationToSubtract()
subtract.SetInputConnection(1,cast1.GetOutputPort())
subtract.SetInputConnection(0,cast2.GetOutputPort())
self.subtract.SetOperationToSubtract()
self.subtract.SetInputConnection(1,cast1.GetOutputPort())
self.subtract.SetInputConnection(0,cast2.GetOutputPort())
#progress_callback.emit(70)

subtract.Update()
self.subtract.Update()
#progress_callback.emit(80)

# print ("subtract type", subtract.GetOutput().GetScalarTypeAsString(), subtract.GetOutput().GetDimensions())

stats = vtk.vtkImageHistogramStatistics()
stats.SetInputConnection(subtract.GetOutputPort())
stats.SetInputConnection(self.subtract.GetOutputPort())
stats.Update()
#progress_callback.emit(90)
# print ("stats ", stats.GetMinimum(), stats.GetMaximum(), stats.GetMean(), stats.GetMedian())
self.subtract = subtract
self.cast = [cast1, cast2]
#progress_callback.emit(95)

Expand Down Expand Up @@ -1974,17 +1991,21 @@ def reg_viewer_update(self, type = None):
self.progress_window.close()

def OnKeyPressEventForRegistration(self, interactor, event):

key_code = interactor.GetKeyCode()
print("OnKeyPressEventForRegistrations",key_code)

rp = self.registration_parameters
if key_code in ['j','n','b','m'] and \
rp['start_registration_button'].isChecked():
self.translate_image_reg(key_code, event)
self.reg_viewer_update(type = 'manual registration')
print("key pressed")

def AfterKeyPressEventForRegistration(self, interactor, event):
#Have to re-adjust registration VOI after the orientation has been switched by the viewer.
key_code = interactor.GetKeyCode()
print("AfterKeyPressEventForRegistration",key_code)
rp = self.registration_parameters

if key_code in ['x','y','z'] and rp['start_registration_button'].isChecked():
Expand Down Expand Up @@ -3926,7 +3947,7 @@ def _createLookupTable(self, cmap='magma'):
def OnKeyPressEventForVectors(self, interactor, event):
#Vectors have to be recreated on the 2D viewer when switching orientation
key_code = interactor.GetKeyCode()
#print("OnKeyPressEventForVectors", key_code)
print("OnKeyPressEventForVectors", key_code)
if key_code in ['x','y','z'] and \
interactor._viewer.GetActor('arrow_shaft_actor') and interactor._viewer.GetActor('arrowhead_actor'):
if interactor._viewer.GetActor('arrow_shaft_actor').GetVisibility() and interactor._viewer.GetActor('arrowhead_actor').GetVisibility():
Expand Down Expand Up @@ -4347,10 +4368,9 @@ def select_roi(self, label, next_button):
next_button.setEnabled(True)

def create_config_worker(self):
if hasattr(self, 'translate'):
if self.translate is None:
self.warningDialog("Complete image registration first.", "Error")
return
if self.translate is None:
self.warningDialog("Complete image registration first.", "Error")
return
if not hasattr(self, 'translate'):
self.warningDialog("Complete image registration first.", "Error")
return
Expand Down Expand Up @@ -4516,7 +4536,7 @@ def create_run_config(self, **kwargs):
run_config['obj'] = self.rdvc_widgets['run_objf_entry'].currentText()
run_config['interp_type'] = self.rdvc_widgets['run_iterp_type_entry'].currentText().lower()

if (hasattr(self, 'translate')):
if self.translate is not None:
run_config['rigid_trans'] = str(self.translate.GetTranslation()[0]*-1) + " " + str(self.translate.GetTranslation()[1]*-1) + " " + str(self.translate.GetTranslation()[2]*-1)
else:
run_config['rigid_trans']= "0.0 0.0 0.0"
Expand Down Expand Up @@ -5312,7 +5332,7 @@ def NewSession(self):
self.CreateWorkingTempFolder()
self.InitialiseSessionVars()
self.LoadSession() #Loads blank session
#self.resetRegistration()
#self.resetRegistrationForSession()

#other possibility for loading new session is closing and opening window:
# self.close()
Expand Down Expand Up @@ -5399,7 +5419,7 @@ def LoadConfigWorker(self, **kwargs):

def LoadSession(self):
os.chdir(tempfile.tempdir)
self.resetRegistration()
self.resetRegistrationForSession()

self.loading_session = True

Expand Down
1 change: 1 addition & 0 deletions src/idvc/ui/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def __init__(self, parent, viewer=viewer2D, interactorStyle=vlink.Linked2DIntera
self.createEmptyFrame()
self.threadpool = QThreadPool()
self._consume_CharEvent = ['s', 'w']
self.image_data = []

def getViewer(self):
return self.frame.viewer
Expand Down