View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0002579 | Slicer4 | Core: GUI | public | 2012-09-28 12:25 | 2018-05-28 09:45 |
Reporter | sbillin | Assigned To | jcfr | ||
Priority | normal | Severity | feature | Reproducibility | always |
Status | acknowledged | Resolution | fixed | ||
Product Version | Slicer 4.1.1 | ||||
Target Version | backlog | Fixed in Version | |||
Summary | 0002579: Transform Widget: easy enhancements for more user-friendly manual registrations | ||||
Description | I am using the Transform Widget to perform a manual registration between two images and there are a few things making this module extremely difficult to use for this purpose: 1) Transform Matrix: Need ability to directly specify matrix values with adequate precision Although the elements of the transform matrix show several decimal places when updating the transform using the sliders, the matrix elements can only be directly specified up to 2 decimal places. As a result, I am unable to directly specify the matrix value for a known transform. Note: 2 decimal precision isn't terrible for the translation part of the matrix (column 4), but 2 decimals are by far not accurate enough for the rotation elements. At least 8 decimal places would be good. 2) Translation & Rotation Sliders: Step size is too large The default step size (1.0) is much to large for fine-tuned manual registration. Because of this, moving the sliders causes jumps in the position rather than smooth position changes. A step size of (0.01) is much better. It appears that no where in the code is this step size actually specified, so it defaults to 1.0. I changed my Slicer code, to call setSingleStep(0.01) in the constructor of the qMRMLTransformSliders class. 3) Rotation Sliders: enable Min/Max control The rotation sliders would be more convenient to use if the min/max control were enabled, as is done for the Translation sliders. This allows one to control the sensitivity of the sliders when doing manual registrations. I tried to enable this in my code by selecting "minMaxVisible" in the options for the RotationSliders in the file: This enabled the min/max controls for the rotation sliders, however, whenever I moved a rotation slider it caused the corresponding translation slider to move with it! The vice-versa was not true, however (i.e. moving the translation slider did not cause the rotation slider to move). I couldn't figure out the reason for this, and so I'm left without min/max control for Rotation. | ||||
Additional Information | My Slicer Version: 4.1.0-2012-09-06 r20936 | ||||
Tags | No tags attached. | ||||
Tried looking into how the translation sliders change when changing rotation sliders. It seems the bug arises from vtkTransform. When calculating the rotation matrix, the translation values in the transformation matrix are also changed. Need to check using a dummy project using vtkTransform. Will report back more on this later. |
|
Found the reason: https://github.com/sankhesh/Slicer/blob/master/Libs/MRML/Widgets/qMRMLUtils.cxx#L89 The reason translation values change when changing rotation values is we post-multiply the transformation matrix. This is done (instead of the usual pre-multiplication) in cases of euler angles where the axes are not fixed but moving. I am not clear why we make this assumption for Slicer. I will check with JC, the original author of this code to get more info. |
|
@sankhesh: Consider discussion with Alex Yarmarkovich, the original author of the code available in Slicer3. See http://viewvc.slicer.org/viewvc.cgi/Slicer3/trunk/Base/GUI/vtkSlicerTransformEditorWidget.cxx?r1=1435&r2=1434&pathrev=1435 |
|
As a hacky workaround you can paste this line into the python console to set the properties of the sliders. Go into the transforms module first to create the widgets and then run this: for s in findChildren(findChildren(text='LR')[0].parent().parent().parent(),className='qMRMLLinearTransformSlider'): s.singleStep = 0.0001; s.decimals = 5; s.pageStep = 0.001 |
|
Fixed 1) in r22152 |
|
Resolving this issue since two child issues have been resolved. See 0002480 and 0002584 |
|
Closing resolved issues that have not been updated in more than 3 months |
|
May I suggest to re-open this issue? I don't think it's fixed and people have asked about it over the years. I forgot, too, about the incantation that'll do the trick, the one by @pieper above, or for s in findChildren(className='qMRMLLinearTransformSlider'): s.singleStep = 0.1; s.decimals = 2; s.pageStep = 1 Still, I suggest something like adding two buttons: Stepx10 and Step/10 with an indication of current increment (1mm as default). There's plenty of room on the line with the Min and Max (that still apparently may mess up your transformation if you change them). Rotation is less important in my opinion because default is 0.1 degree and PgUp/PgDn does 1 degree. (The other annoyance is that the "Identity" button should be "Default" , which should reset to the original loaded transform (or identity). I couldn't find the ticket for that.) |
|
Thanks @nick_silzer - you are right there's a lot of room for improvement here and I like the design you propose. This would be a good task for a new developer wanting to learn while doing something useful. |
|
Probably this issue has not got enough attention because manual translation by adjusting a slider is so much worse, compared to registration using landmarks (or automatic intensity-based image registration). Fundamental issues with slider-based manual registration process:
Landmark registration (Landmark registration module in Slicer core; Fiducial registration wizard module in SlicerIGT) does not have any of the issues: you specify a set of anatomical landmarks (3 or more) on each image or model and you are guaranteed to get the final, correct, rigid or non-rigid registration directly , without the need for any iterations. You may also use fully automatic intensity-based image registration, which similarly do not have any of the above-described fundamental issues. Do you have any specific reason to use sliders for manual registration? |
|
@lassoan There are three use cases in my work that depend on manual transforms: a) Defining a ROI box aligned with an arbitrary plane -- for say MIP inspection of volume of interest or mimicking a thick slice setting. [If possible I avoid using the reformat widget because of the UI problem that the 3D viewer becomes electrified: in practice, I can't tumble/rotate without messing up carefully placed reformat vectors because I always loose track in my mind of all the current lock and activate mode status of widgets and what -- and in any case it's cumbersome to toggle them on and off. In this sense, manual transforms are frustration-free!] b) The initial transform for automated registration in case of volumes that are clipped (on purpose, or by clinical use such as CT sinus v. CT head). With a little practice, a rough initial transform is easy to make. c) Fiddling with calculated transforms and masks; I stuff the calculated transform under a temporary tuner transform or play with it directly. |
|
Date Modified | Username | Field | Change |
---|---|---|---|
2012-09-28 12:25 | sbillin | New Issue | |
2012-09-28 12:25 | sbillin | Status | new => assigned |
2012-09-28 12:25 | sbillin | Assigned To | => kikinis |
2012-12-08 06:16 | kikinis | Assigned To | kikinis => alexy |
2012-12-08 10:13 | jcfr | Assigned To | alexy => sankhesh |
2012-12-08 10:14 | jcfr | Target Version | => Slicer 4.3.0 |
2012-12-10 07:02 | sankhesh | Relationship added | related to 0002584 |
2012-12-10 07:02 | sankhesh | Relationship added | related to 0002480 |
2012-12-26 06:58 | sankhesh | Status | assigned => confirmed |
2012-12-26 08:47 | sankhesh | Note Added: 0007584 | |
2012-12-26 14:35 | sankhesh | Note Added: 0007586 | |
2013-01-02 10:56 | sankhesh | Note Edited: 0007586 | |
2013-01-07 07:02 | jcfr | Note Added: 0007617 | |
2013-03-12 14:16 | pieper | Note Added: 0008115 | |
2013-06-03 05:15 | jcfr | Status | confirmed => assigned |
2013-06-03 05:15 | jcfr | Assigned To | sankhesh => jcfr |
2013-07-08 12:31 | finetjul | Note Added: 0008908 | |
2013-08-27 11:53 | jcfr | Note Added: 0009639 | |
2013-08-27 11:53 | jcfr | Status | assigned => resolved |
2013-08-27 11:53 | jcfr | Fixed in Version | => Slicer 4.3.0 |
2013-08-27 11:53 | jcfr | Resolution | open => fixed |
2014-03-06 05:00 | jcfr | Note Added: 0010841 | |
2014-03-06 05:02 | jcfr | Status | resolved => closed |
2018-05-03 15:00 | nick_slizer | Note Added: 0015697 | |
2018-05-04 09:24 | pieper | Note Added: 0015701 | |
2018-05-08 20:48 | jcfr | Status | closed => acknowledged |
2018-05-08 20:49 | jcfr | Fixed in Version | Slicer 4.3.0 => |
2018-05-08 20:49 | jcfr | Target Version | Slicer 4.3.0 => backlog |
2018-05-28 01:05 | lassoan | Note Added: 0015756 | |
2018-05-28 09:45 | nick_slizer | Note Added: 0015759 |