Difference between revisions of "Documentation/Nightly/Developers/Slice Orientation Presets"

From Slicer Wiki
Jump to: navigation, search
(Created page with " == Overview == Slicer provides an API to manage slice orientation presets. By default, three slice orientation presets representing the Coordinate_systems#Anatomical_coor...")
 
 
(12 intermediate revisions by 2 users not shown)
Line 6: Line 6:
 
By default, three slice orientation presets representing the [[Coordinate_systems#Anatomical_coordinate_system|anatomical coordinate system]] are available in Slicer: <code>Axial</code>, <code>Coronal</code> and <code>Sagittal</code>.
 
By default, three slice orientation presets representing the [[Coordinate_systems#Anatomical_coordinate_system|anatomical coordinate system]] are available in Slicer: <code>Axial</code>, <code>Coronal</code> and <code>Sagittal</code>.
  
 +
Feature originally integrated to Slicer core in [http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&revision=25171 r25171] and contributed by:
 +
* Davide Punzo (Kapteyn astronomical institute)
 +
* Jean-Christophe Fillion-Robin (Kitware)
 +
* Andras Lasso (PerkLab, Queen's University).
 +
 +
== API ==
 +
 +
The [{{doxygen-class-url|vtkMRMLSliceNode}} vtkMRMLSliceNode] class provides the following API for managing slice orientation presets:
 +
 +
<pre>
 +
bool SetOrientationToAxial()
 +
bool SetOrientationToSagittal()
 +
bool SetOrientationToCoronal()
 +
 +
std::string GetOrientation()
 +
bool SetOrientation(const char* orientation)
 +
 +
std::string GetOrientation(vtkMatrix4x4* sliceToRAS)
 +
vtkMatrix4x4 *GetSliceToRAS()
 +
void SetSliceToRAS(vtkMatrix4x4* sliceToRAS)
 +
 +
bool AddSliceOrientationPreset(const std::string &name, vtkMatrix3x3 *orientationMatrix)
 +
bool RemoveSliceOrientationPreset(const std::string& name)
 +
bool RenameSliceOrientationPreset(const std::string& name, const std::string& updatedName)
 +
bool HasSliceOrientationPreset(const std::string& name)
 +
 +
vtkMatrix3x3 *GetSliceOrientationPreset(const std::string& name)
 +
std::string GetSliceOrientationPresetName(vtkMatrix3x3* orientationMatrix)
 +
 +
void GetSliceOrientationPresetNames(vtkStringArray* presetOrientationNames)
 +
 +
int GetNumberOfSliceOrientationPresets() const
 +
 +
# Convenience static methods
 +
static void InitializeAxialMatrix(vtkMatrix3x3* orientationMatrix)
 +
static void InitializeSagittalMatrix(vtkMatrix3x3* orientationMatrix)
 +
static void InitializeCoronalMatrix(vtkMatrix3x3* orientationMatrix)
 +
static void AddDefaultSliceOrientationPresets(vtkMRMLScene* scene)
 +
</pre>
 +
 +
== FAQ ==
 +
 +
=== Where are slice orientation presets stored ? ===
 +
 +
Every <code>vtkMRMLSliceNode</code> contains an ordered list of <code>(orientationPresetName, orientationMatrix)</code> tuples.
 +
 +
The list is automatically initialized with the list of default presets each time a node is created using <code>vtkMRMLScene::CreateNodeByClass(const char* className)</code>.
  
== Under the hood ==
 
  
 
=== Where are default presets defined ? ===
 
=== Where are default presets defined ? ===
  
Each time <code>vtkMRMLApplicationLogic::SetMRMLScene</code> is invoked, method <code>AddDefaultSliceOrientationPresets(vtkMRMLScene *scene)</code>  is called.
+
Each time <code>vtkMRMLApplicationLogic::SetMRMLScene</code> is invoked, method <code>vtkMRMLSliceNode::AddDefaultSliceOrientationPresets(vtkMRMLScene *scene)</code>  is called.
 +
 
 +
Then, method <code>vtkMRMLSliceNode::AddDefaultSliceOrientationPresets(vtkMRMLScene *scene)</code> ends up adding a default [{{doxygen-class-url|vtkMRMLSliceNode}} vtkMRMLSliceNode] that will be used a template each time <code>vtkMRMLScene::CreateNodeByClass(const char* className)</code>.
 +
 
 +
=== Why default presets are not added in the vtkMRMLSliceNode contructor ? ===
 +
 
 +
Associating the list of default presets to the default <code>vtkMRMLSliceNode</code> allows to customize the template once and ensure any new node created using <code>vtkMRMLScene::CreateNodeByClass(const char* className)</code> will have the expected list of presets.
 +
 
 +
=== How to ensure slice orientation presets are defined in unit tests ? ===
 +
 
 +
When writing tests that depend on <code>MRMLLogic</code>, instantiating [{{doxygen-class-url|vtkMRMLApplicationLogic}} vtkMRMLApplicationLogic] is sufficient:
 +
 
 +
<pre>
 +
vtkNew<vtkMRMLScene> scene;
 +
vtkNew<vtkMRMLApplicationLogic> appLogic;
 +
appLogic->SetMRMLScene(scene.GetPointer());
 +
</pre>
 +
 
 +
When writing test within that only depend on <code>MRMLCore</code>, the static method <code>vtkMRMLSliceNode::AddDefaultSliceOrientationPresets(vtkMRMLScene *scene)</code> is available:
 +
 
 +
<pre>
 +
vtkNew<vtkMRMLScene> scene;
 +
vtkMRMLSliceNode::AddDefaultSliceOrientationPresets(scene.GetPointer());
 +
</pre>
 +
 
 +
=== How to instantiate a new vtkMRMLSliceNode ? ===
 +
 
 +
<pre>
 +
vtkMRMLSliceNode* sliceNode = scene->CreateNodeByClass("vtkMRMLSliceNode");
 +
</pre>
 +
 
 +
=== What is "Reformat" orientation ? ===
 +
 
 +
"Reformat" is a reserved orientation name describing an arbitrary orientation matrix that do not correspond to an existing orientation preset.
 +
 
 +
This means that a preset can '''NOT''' be named "Reformat".
 +
 
 +
=== How to modify and set the orientation presets in Extensions ? ===
 +
 
 +
Given an extension XXX, it is possible to set, globally, the orientation presets for the SliceNode using:
 +
 
 +
<pre>
 +
  vtkSmartPointer<vtkMRMLNode> defaultNode = vtkMRMLSliceNode::SafeDownCast
 +
      (this->mrmlScene()->GetDefaultNodeByClass("vtkMRMLSliceNode"));
 +
  if (!defaultNode)
 +
    {
 +
    vtkMRMLNode * foo = this->mrmlScene()->CreateNodeByClass("vtkMRMLSliceNode");
 +
    defaultNode.TakeReference(foo);
 +
    this->mrmlScene()->AddDefaultNode(defaultNode);
 +
    }
 +
  vtkMRMLSliceNode * defaultSliceNode = vtkMRMLSliceNode::SafeDownCast(defaultNode);
 +
  defaultSliceNode->RenameSliceOrientationPreset("Axial", "XZ");
 +
  defaultSliceNode->RemoveSliceOrientationPreset("Sagittal");
 +
  etc..
 +
</pre>
 +
 
 +
To be noted is that SliceNodes already instantiated must be updated as follow:
 +
 
 +
<pre>
 +
  vtkSmartPointer<vtkCollection> sliceNodes = vtkSmartPointer<vtkCollection>::Take
 +
      (this->mrmlScene()->GetNodesByClass("vtkMRMLSliceNode"));
  
Then, method <code>AddDefaultSliceOrientationPresets(vtkMRMLScene *scene)</code> ends up adding a default [{{doxygen-class-url|vtkMRMLSliceNode}} vtkMRMLSliceNode] that will be used a template each time <code>vtkMRMLScene::CreateNodeByClass(const char* className)</code>.
+
  for(int i = 0; i < sliceNodes->GetNumberOfItems(); i++)
 +
    {
 +
    vtkMRMLSliceNode* sliceNode =
 +
        vtkMRMLSliceNode::SafeDownCast(sliceNodes->GetItemAsObject(i));
 +
    if (sliceNode)
 +
      {
 +
      sliceNode->DisableModifiedEventOn();
 +
      sliceNode->RenameSliceOrientationPreset("Axial", "XZ");
 +
      sliceNode->RemoveSliceOrientationPreset("Sagittal");
 +
      etc...
 +
      sliceNode->DisableModifiedEventOff();
 +
      }
 +
    }
 +
</pre>

Latest revision as of 20:18, 8 June 2016

Home < Documentation < Nightly < Developers < Slice Orientation Presets

Overview

Slicer provides an API to manage slice orientation presets.

By default, three slice orientation presets representing the anatomical coordinate system are available in Slicer: Axial, Coronal and Sagittal.

Feature originally integrated to Slicer core in r25171 and contributed by:

  • Davide Punzo (Kapteyn astronomical institute)
  • Jean-Christophe Fillion-Robin (Kitware)
  • Andras Lasso (PerkLab, Queen's University).

API

The vtkMRMLSliceNode class provides the following API for managing slice orientation presets:

bool SetOrientationToAxial()
bool SetOrientationToSagittal()
bool SetOrientationToCoronal()

std::string GetOrientation()
bool SetOrientation(const char* orientation)

std::string GetOrientation(vtkMatrix4x4* sliceToRAS)
vtkMatrix4x4 *GetSliceToRAS()
void SetSliceToRAS(vtkMatrix4x4* sliceToRAS)

bool AddSliceOrientationPreset(const std::string &name, vtkMatrix3x3 *orientationMatrix)
bool RemoveSliceOrientationPreset(const std::string& name)
bool RenameSliceOrientationPreset(const std::string& name, const std::string& updatedName)
bool HasSliceOrientationPreset(const std::string& name)

vtkMatrix3x3 *GetSliceOrientationPreset(const std::string& name)
std::string GetSliceOrientationPresetName(vtkMatrix3x3* orientationMatrix)

void GetSliceOrientationPresetNames(vtkStringArray* presetOrientationNames)

int GetNumberOfSliceOrientationPresets() const

# Convenience static methods
static void InitializeAxialMatrix(vtkMatrix3x3* orientationMatrix)
static void InitializeSagittalMatrix(vtkMatrix3x3* orientationMatrix)
static void InitializeCoronalMatrix(vtkMatrix3x3* orientationMatrix)
static void AddDefaultSliceOrientationPresets(vtkMRMLScene* scene)

FAQ

Where are slice orientation presets stored ?

Every vtkMRMLSliceNode contains an ordered list of (orientationPresetName, orientationMatrix) tuples.

The list is automatically initialized with the list of default presets each time a node is created using vtkMRMLScene::CreateNodeByClass(const char* className).


Where are default presets defined ?

Each time vtkMRMLApplicationLogic::SetMRMLScene is invoked, method vtkMRMLSliceNode::AddDefaultSliceOrientationPresets(vtkMRMLScene *scene) is called.

Then, method vtkMRMLSliceNode::AddDefaultSliceOrientationPresets(vtkMRMLScene *scene) ends up adding a default vtkMRMLSliceNode that will be used a template each time vtkMRMLScene::CreateNodeByClass(const char* className).

Why default presets are not added in the vtkMRMLSliceNode contructor ?

Associating the list of default presets to the default vtkMRMLSliceNode allows to customize the template once and ensure any new node created using vtkMRMLScene::CreateNodeByClass(const char* className) will have the expected list of presets.

How to ensure slice orientation presets are defined in unit tests ?

When writing tests that depend on MRMLLogic, instantiating vtkMRMLApplicationLogic is sufficient:

vtkNew<vtkMRMLScene> scene;
vtkNew<vtkMRMLApplicationLogic> appLogic;
appLogic->SetMRMLScene(scene.GetPointer());

When writing test within that only depend on MRMLCore, the static method vtkMRMLSliceNode::AddDefaultSliceOrientationPresets(vtkMRMLScene *scene) is available:

vtkNew<vtkMRMLScene> scene;
vtkMRMLSliceNode::AddDefaultSliceOrientationPresets(scene.GetPointer());

How to instantiate a new vtkMRMLSliceNode ?

vtkMRMLSliceNode* sliceNode = scene->CreateNodeByClass("vtkMRMLSliceNode");

What is "Reformat" orientation ?

"Reformat" is a reserved orientation name describing an arbitrary orientation matrix that do not correspond to an existing orientation preset.

This means that a preset can NOT be named "Reformat".

How to modify and set the orientation presets in Extensions ?

Given an extension XXX, it is possible to set, globally, the orientation presets for the SliceNode using:

  vtkSmartPointer<vtkMRMLNode> defaultNode = vtkMRMLSliceNode::SafeDownCast
      (this->mrmlScene()->GetDefaultNodeByClass("vtkMRMLSliceNode"));
  if (!defaultNode)
    {
    vtkMRMLNode * foo = this->mrmlScene()->CreateNodeByClass("vtkMRMLSliceNode");
    defaultNode.TakeReference(foo);
    this->mrmlScene()->AddDefaultNode(defaultNode);
    }
  vtkMRMLSliceNode * defaultSliceNode = vtkMRMLSliceNode::SafeDownCast(defaultNode);
  defaultSliceNode->RenameSliceOrientationPreset("Axial", "XZ");
  defaultSliceNode->RemoveSliceOrientationPreset("Sagittal");
  etc..

To be noted is that SliceNodes already instantiated must be updated as follow:

  vtkSmartPointer<vtkCollection> sliceNodes = vtkSmartPointer<vtkCollection>::Take
      (this->mrmlScene()->GetNodesByClass("vtkMRMLSliceNode"));

  for(int i = 0; i < sliceNodes->GetNumberOfItems(); i++)
    {
    vtkMRMLSliceNode* sliceNode =
        vtkMRMLSliceNode::SafeDownCast(sliceNodes->GetItemAsObject(i));
    if (sliceNode)
      {
      sliceNode->DisableModifiedEventOn();
      sliceNode->RenameSliceOrientationPreset("Axial", "XZ");
      sliceNode->RemoveSliceOrientationPreset("Sagittal");
      etc...
      sliceNode->DisableModifiedEventOff();
      }
    }