Slicer4:SliceInteractions

From NAMIC Wiki
Revision as of 12:27, 22 July 2011 by Pieper (talk | contribs) (→‎Performance Testing)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
Home < Slicer4:SliceInteractions
Back to Slicer 4 sprint

Background

In slicer3, the core GUI system base based on Tcl/Tk wrapped in KWWidgets, with Tcl as the native scripting system. Several key functions of slicer3 were implemented in Tcl using an architecture described, for example, here. The SWidget (slicer widgets) in slicer3 defined all the interaction modes of the 2D slice views such as fiducial manipulation, window/level control, slice pan/zoom, etc. In addition, other modules, such as the interactive Editor module and the EMSegmenter relied heavily on the Tcl interface in slicer3.

In slicer4 python has replaced Tcl as the core scripting interface and a set of adapter code allows the Tcl code to access VTK via python (using tpycl) and for the Tcl code to access a set of stand-in data structures that emulate slicer3's KWWidgets-based API (Slicer3Adapaters.tcl).

Performance Testing

The PerformanceTests module allows developers to probe the performance with the Tcl-based callbacks enabled or disabled. On some platforms (fast linux machines) the overhead related to processing events in Tcl is approximately 20-50 milliseconds (1/50th to 1/20th of a second). However on some windows machines timings as high as 150 milliseconds have been recorded, leading to a significant impact on interaction.

We also tried the following isolated tests to check the performance of the vtk API under various language interfaces.

tcl code

proc timeMult { {iters 1000} } {

  set log [vtkTimerLog New]

  set m [vtkMatrix4x4 New]
  $log StartTimer
  for {set i 0} {$i < $iters} {incr i} {
    $m MultiplyPoint 1 1 1 1
  }
  $log StopTimer
  puts "[expr 1000 * 1000 * [$log GetElapsedTime] / $iters] microseconds per iteration"
  $log Delete
  $m Delete
}

timeMult

python code

def timeMult (iters=1000):

  log = vtk.vtkTimerLog()

  m = vtk.vtkMatrix4x4()
  log.StartTimer()
  for i in xrange(iters):
    m.MultiplyPoint((1,1,1,1))
  log.StopTimer()
  print ("%f %s" % (1000 * 1000 * log.GetElapsedTime() / iters, "microseconds per iteration"))

if __name__ == "__main__":
  timeMult()

C++ code

// VTK includes
#include <vtkNew.h>
#include <vtkMatrix4x4.h>
#include <vtkTimerLog.h>

// STD includes
#include <stdlib.h>
#include <iostream>

#include "TestingMacros.h"

int testMult(int argc, char * argv[] )
{
  int iters = 1000;
  vtkNew<vtkTimerLog> log;

  vtkNew<vtkMatrix4x4> m;
  log->StartTimer();
  double p[] = {1,1,1,1};
  double pout[4];
  for (int i = 0; i < iters; ++i) {
    m->MultiplyPoint(p,pout);
  }
  log->StopTimer();
  std::cout << 1000 * 1000 * log->GetElapsedTime() / iters <<  " microseconds per iteration\n";
  return EXIT_SUCCESS;
}

Results:

  • tcl via tpycl (slicer4): 290 usecs
  • native tcl wrapped vtk (slicer3): 6 usecs
  • native python wrapped vtk (slicer4): 1.25 usecs
  • native C++: 0.0369 usecs

Note that this tests primarily the language overhead: if the scripted code sets up a large vtk pipeline that takes time to execute the performance differences might become negligible. Also for many purposes a few milliseconds here or there will not be noticed by the user. However, for time critical inner loops, such as mouse interactions in the base slicer code, the plan is to move this functionality into native C++ code.

Plans

The long-term goal is to implement a consistent and efficient interaction code base while maintaining flexibility so that developers have the ability to select the best programming tools for the jobs they undertake. This will mean that some interactive tools, such as the Editor, will migrate to a fully python-based interaction implementation to support rapid development while core functions of the interface will migrate to C++ for performance.

As of July 2011 and the Slicer4 programming sprint goal is to get a workable implementation in place that is not a huge bottleneck but doesn't require rewriting all code from scratch.

Targets

A big bottleneck in the slicer3 implementation of slice views turned out to be the rasterization of the corner annotation text. To avoid this, annotation text is turned off during interaction and only rendered when the mouse is idle for a short period. Slicer4 has a similar approach, but appears to have a further bottleneck in that the calculation of the corner annotations takes an appreciable period of time (10 milliseconds even on a fast machine). So a first task will be to defer calculation of corner annotations until actual redraw time.

Another direction to explore is the continued migration of functionality from the SliceSWidget into a corresponding C++ or python implementation in slicer4. Key functionality that will need to have a home includes:

  • creating/destroying instances of SWidget subclasses as slice viewers are created/destroyed (most of this functionality has migrated to the DisplayableManagerFactory already)
  • handle window resize events while preserving the aspect ratio and apparent size of the slice view (mostly transitioned to C++ already)
  • handle lightbox to window transformations (mostly now available in CTK's lightbox support)
  • calculation of corner annotations and deferred rendering
  • handling of special compare view annotation linkage
  • interaction modes that impact multiple slice views (communicated via vtkMRMLSliceNodes)
    • Shift-left drag to call sliceNode->jumpOtherSlices to the current RAS coordinate
  • Pan/zoom of slice node
  • Rotate of slice node when in Reformat mode
    • Orthogonal rotation of linked slice viewers
  • Fiducial place mode (now in Annotations displayable managers)
  • Coordinated Automatic/Prescribed slice spacing for linked viewers (using SliceLogic->GetLowestVolumeSliceSpacing)
  • Key events for slice navigation (Left/Right, F/B)
  • Hot Keys:
    • v to show/hide slice model
    • r to reset field of view
    • g to toggle label overlay opacity
    • T to toggle foreground opacity
    • s/S to set active slice within lightbox
  • CompareView specific functionality
    • linkedSliceLogics
    • linkedSliceGUIs

Other SWidget-based functionality TBD

  • SlicePlane (reformat widget)
  • Window/Level of background volume
  • Slice Intersections
  • Model Intersections
  • Crosshairs
  • Editor Effects