https://www.slicer.org/w/api.php?action=feedcontributions&user=Fernando&feedformat=atomSlicer Wiki - User contributions [en]2024-03-28T16:59:46ZUser contributionsMediaWiki 1.33.0https://www.slicer.org/w/index.php?title=Documentation/Labs/HomebrewCask&diff=63447Documentation/Labs/HomebrewCask2020-10-12T22:40:01Z<p>Fernando: Replace "nightly" with "preview"</p>
<hr />
<div>This page was created based on the discussions [https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Add Slicer Nightly to Homebrew (macOS)] and [https://discourse.slicer.org/t/slicer-installation-on-mac-using-homebrew/ Slicer installation on Mac using homebrew]<br />
<br />
==Introduction==<br />
<br />
The purpose of this Lab is to offer an alternative way to install / update Slicer for macOS users using the command line. The process is much more convenient than the traditional way, but it requires minimal computer skills that not all users might have. Therefore this alternative way is specially intended to be used by developers or engineers instead of medical staff and casual users. <br />
<br />
==Definitions==<br />
<br />
===Homebrew===<br />
[https://brew.sh/ Homebrew] is "the missing package manager for macOS". It is designed for installing UNIX tools and other open-source applications. It will quickly download and install them, compiling them from source. Homebrew can install stuff like:<br />
<br />
*<code>vim</code><br />
*<code>ffmpeg</code><br />
*<code>python</code><br />
<br />
===Homebrew Cask===<br />
[https://caskroom.github.io/ Homebrew Cask] extends Homebrew with support for installing binary apps — the kind you normally drag to your Applications folder from DMG files. For example:<br />
<br />
*3D Slicer<br />
*Google Chrome<br />
<br />
===Homebrew Versions===<br />
[https://github.com/caskroom/homebrew-versions Homebrew Versions] lets you install alternate versions of the apps from Homebrew Cask. For example:<br />
<br />
*3D Slicer ''Preview''<br />
*Google Chrome ''Canary''<br />
<br />
<br />
==Steps to update Slicer cask (for maintainers)==<br />
<br />
Adding an [https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/ SSH key] to GitHub and the KeyChain might be needed.<br />
<br />
===Setup===<br />
<pre><br />
# Install homebrew<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Install cask-repair<br />
brew install vitorgalvao/tiny-scripts/cask-repair<br />
</pre><br />
<br />
===Update===<br />
This automatically creates a pull request in [https://github.com/caskroom/homebrew-versions/ homebrew-versions] to update the [https://github.com/caskroom/homebrew-versions/blob/master/Casks/slicer-preview.rb <code>slicer-preview</code> cask] (a Ruby script) with the new version.<br />
<pre><br />
cask-repair --cask-version 4.7.0.26273,676538 --fail-on-error --blind-submit slicer-nightly<br />
</pre><br />
<br />
<br />
==Steps to upgrade Slicer app (for users)==<br />
<br />
===Setup===<br />
<pre><br />
# Install homebrew + homebrew-cask<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Tell brew to look also in homebrew-versions<br />
brew tap caskroom/versions<br />
<br />
# Install Slicer.app (nightly)<br />
brew cask install slicer-preview<br />
</pre><br />
<br />
===Upgrade===<br />
Download and install preview version of Slicer.app:<br />
<pre><br />
brew cask upgrade slicer-preview<br />
</pre></div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/Python_scripting&diff=61505Documentation/Nightly/Developers/Python scripting2019-10-24T12:43:34Z<p>Fernando: Replace xrange() by range()</p>
<hr />
<div><noinclude>{{documentation/versioncheck}}</noinclude><br />
<br />
= Start Here =<br />
<br />
Please read [https://docs.google.com/presentation/d/1JXIfs0rAM7DwZAho57Jqz14MRn2BIMrjB17Uj_7Yztc/edit?usp=sharing these slides] and [https://www.slicer.org/wiki/Documentation/Nightly/Training#PerkLab.27s_Slicer_bootcamp_training_materials these slides]. This will give you an overall idea what is possible, and you can use a binary download of Slicer to work through the example code. <br />
<br />
Refer to [http://www.na-mic.org/Wiki/index.php/2013_Project_Week_Breakout_Session:Slicer4Python this description that includes links to all the documentation].<br />
<br />
Look at the [[Documentation/{{documentation/version}}/ScriptRepository |Script Repository]] for examples and inspiration.<br />
<br />
= Background =<br />
<br />
This is an evolution of the [[Slicer3:Python|python implementation in slicer3]]. Slicer's APIs are now natively wrapped in python. <br />
<br />
Topics like plotting are still experimental in slicer4.<br />
<br />
See [http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python this 2012 presentation on the state of python in slicer4].<br />
<br />
'''See [[Documentation/{{documentation/currentversion}}/Training#Slicer4_Programming_Tutorial|the python slicer4 tutorial for more examples]].'''<br />
<br />
[[Documentation/{{documentation/version}}/Developers/Tutorials/SelfTestModule|Slicer Self Tests]] can be written in python, and provide a good source of examples for manipulating the data, logic, and gui of slicer.<br />
<br />
= Start Here for Scripted Module and Extension Development=<br />
An extensive tutorial and reference page was created [http://www.na-mic.org/Wiki/index.php/2013_Project_Week_Breakout_Session:Slicer4Python for the Slicer/Python breakout session at the NA-MIC 2013 Summer Project Week].<br />
<br />
= Usage options =<br />
<br />
==Python Interactor==<br />
<br />
Use the Window->Python Interactor (Control-3 on window/linux, Command-3 on mac) to bring up the Qt-based console with access to the vtk, Qt, and Slicer wrapped APIs.<br />
<br />
Most python code can be installed and run from this window, but because it exists in the event driven Qt GUI environment, some operations like, like parallel processing or headless operation, are not easily supported.<br />
<br />
=== Examples ===<br />
<br />
Start Slicer and bring up python console. Load a sample volume like this:<br />
<br />
<pre><br />
import SampleData<br />
sampleDataLogic = SampleData.SampleDataLogic()<br />
sampleDataLogic.downloadMRHead()<br />
</pre><br />
<br />
Get the volume node for that volume:<br />
<br />
<pre><br />
n = getNode('MRHead')<br />
</pre><br />
<br />
You can use Tab to see lists of methods for a class instance.<br />
<br />
==== Accessing Volume data as numpy array ====<br />
<br />
You can easily inspect and manipulate volume data using numpy and related code. In slicer you can do this:<br />
<br />
<pre><br />
a = array('MRHead')<br />
</pre><br />
<br />
and 'a' will be a pointer to the appropriate data (no data copying). If you get an error that 'array' is not defined then run 'import slicer.util' and use 'slicer.util.array'. Scalar volumes become three-dimensional arrays, while vector volumes become 4D, and tensor volumes are 5D. All arrays can be manipulated directly. After modification is completed, call Modified() method of the volume node to indicate that the image is modified and trigger display update.<br />
<br />
The '''array''' method is intended for quick testing only, as multiple nodes may have the same name and various arrays may be retrieved from MRML nodes. In Slicer modules, it is recommended to use '''arrayFromVolume''' instead, which takes a MRML node as input.<br />
<br />
<pre><br />
volumeNode = getNode('MRHead')<br />
a = arrayFromVolume(volumeNode)<br />
# Increase image contrast<br />
a[:] = a * 2.0<br />
arrayFromVolumeModified(volumeNode)<br />
</pre><br />
<br />
If you don't process the data in-place but you have computation results in a numpy array, then you have to copy the contents of a numpy array into a volume, using '''updateVolumeFromArray''':<br />
<br />
<pre><br />
import numpy as np<br />
import math<br />
<br />
def some_func(x, y, z):<br />
return 0.5*x*x + 0.3*y*y + 0.5*z*z<br />
<br />
a = np.fromfunction(some_func,(30,20,15))<br />
<br />
volumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode')<br />
volumeNode.CreateDefaultDisplayNodes()<br />
updateVolumeFromArray(volumeNode, a)<br />
setSliceViewerLayers(background=volumeNode)<br />
</pre><br />
<br />
==== Accessing Model data as numpy array ====<br />
<br />
You can easily inspect and manipulate point coordinates of a model using numpy and related code by calling `arrayFromModelPoints`. After modification is completed, call Modified() method on the polydata to indicate that the model is modified and trigger display update.<br />
<br />
<pre><br />
# Create a model containing a sphere<br />
sphere = vtk.vtkSphereSource()<br />
sphere.SetRadius(30.0)<br />
sphere.Update()<br />
modelNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelNode')<br />
modelNode.SetAndObservePolyData(sphere.GetOutput())<br />
modelNode.CreateDefaultDisplayNodes()<br />
a = arrayFromModelPoints(modelNode)<br />
# change Y scaling<br />
a[:,2] = a[:,2] * 2.5<br />
arrayFromModelPointsModified(modelNode)<br />
</pre><br />
<br />
==== Running a CLI from Python ====<br />
<br />
Here's an example to create a model from a volume using the [[Documentation/4.0/Modules/GrayscaleModelMaker|Grayscale Model Maker]]<br />
<pre><br />
def grayModel(volumeNode):<br />
parameters = {}<br />
parameters["InputVolume"] = volumeNode.GetID()<br />
outModel = slicer.vtkMRMLModelNode()<br />
slicer.mrmlScene.AddNode(outModel)<br />
parameters["OutputGeometry"] = outModel.GetID()<br />
grayMaker = slicer.modules.grayscalemodelmaker<br />
return slicer.cli.runSync(grayMaker, None, parameters)<br />
</pre><br />
<br />
To try this, download the MRHead dataset from the [[Documentation/4.0/Modules/SampleData|Sample Data]] and paste the code into the python console and then run this:<br />
<pre><br />
v = getNode('MRHead')<br />
cliNode = grayModel(v)<br />
</pre><br />
<br />
Here is an example for running a CLI module from a scripted module:<br />
https://github.com/fedorov/ChangeTrackerPy/blob/master/ChangeTracker/ChangeTrackerWizard/ChangeTrackerRegistrationStep.py#L56-L67<br />
<br />
'' Passing Fiducials to CLIs via a Python Script ''<br />
<br />
<pre><br />
<br />
import SampleData<br />
sampleDataLogic = SampleData.SampleDataLogic()<br />
head = sampleDataLogic.downloadMRHead()<br />
volumesLogic = slicer.modules.volumes.logic()<br />
headLabel = volumesLogic.CreateLabelVolume(slicer.mrmlScene, head, 'head-label')<br />
<br />
fiducialNode = slicer.vtkMRMLAnnotationFiducialNode()<br />
fiducialNode.SetFiducialWorldCoordinates((1,0,5))<br />
fiducialNode.SetName('Seed Point')<br />
fiducialNode.Initialize(slicer.mrmlScene)<br />
fiducialsList = getNode('Fiducials List')<br />
<br />
params = {'inputVolume': head.GetID(), 'outputVolume': headLabel.GetID(), 'seed' : fiducialsList.GetID(), 'iterations' : 2} <br />
<br />
cliNode = slicer.cli.runSync(slicer.modules.simpleregiongrowingsegmentation, None, params)<br />
<br />
</pre><br />
<br />
''Running CLI in the background''<br />
<br />
If the CLI module is executed using slicer.cli.run method then the CLI module runs in a background thread, so the call to grayModel will return right away and the user interface will not be blocked. The slicer.cli.run call returns a cliNode (an instance of [http://slicer.org/doc/html/classvtkMRMLCommandLineModuleNode.html vtkMRMLCommandLineModuleNode]) which can be used to monitor the progress of the module.<br />
<br />
In this example we create a simple callback that will be called whenever the cliNode is modified. The status will tell you if the nodes is Pending, Running, or Completed.<br />
<br />
<pre><br />
def printStatus(caller, event):<br />
print("Got a %s from a %s" % (event, caller.GetClassName()))<br />
if caller.IsA('vtkMRMLCommandLineModuleNode'):<br />
print("Status is %s" % caller.GetStatusString())<br />
<br />
cliNode.AddObserver('ModifiedEvent', printStatus)<br />
</pre><br />
<br />
If you need to cancel the CLI, call<br />
<pre><br />
cliNode.Cance()<br />
</pre><br />
<br />
To get the log info for the process you can call <pre>cliNode.GetOutputText()</pre> and <pre>cliNode.GetErrorText()</pre>.<br />
<br />
''Get list of parameter names''<br />
<br />
The following script prints all the parameter names of a CLI parameter node:<br />
<br />
<pre><br />
cliModule = slicer.modules.grayscalemodelmaker<br />
n=cliModule.cliModuleLogic().CreateNode()<br />
for groupIndex in range(n.GetNumberOfParameterGroups()):<br />
for parameterIndex in range(n.GetNumberOfParametersInGroup(groupIndex)):<br />
print('Parameter ({0}/{1}): {2} ({3})'.format(groupIndex, parameterIndex, n.GetParameterName(groupIndex, parameterIndex), n.GetParameterLabel(groupIndex, parameterIndex)))<br />
</pre><br />
<br />
==== Accessing slice vtkRenderWindows from slice views ====<br />
<br />
The example below shows how to get the rendered slice window.<br />
<br />
<pre><br />
lm = slicer.app.layoutManager()<br />
redWidget = lm.sliceWidget('Red')<br />
redView = redWidget.sliceView()<br />
wti = vtk.vtkWindowToImageFilter()<br />
wti.SetInput(redView.renderWindow())<br />
wti.Update()<br />
v = vtk.vtkImageViewer()<br />
v.SetColorWindow(255)<br />
v.SetColorLevel(128)<br />
v.SetInputConnection(wti.GetOutputPort())<br />
v.Render()<br />
</pre><br />
<br />
= Script Repository = <br />
<br />
See [[Documentation/Nightly/ScriptRepository|ScriptRepository]] for a larger collection of example code.<br />
<br />
{{:Documentation/{{documentation/version}}/Developers/FAQ/Python Scripting|Python Scripting}}</div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Nightly/ScriptRepository&diff=58292Documentation/Nightly/ScriptRepository2018-01-29T14:01:53Z<p>Fernando: Fix Capture snippet</p>
<hr />
<div><noinclude>{{documentation/versioncheck}}</noinclude><br />
__TOC__<br />
<br />
<br />
=Community-contributed modules=<br />
<br />
The examples in this section are [[Documentation/{{documentation/version}}/Developers/Modules#Scripted_Modules| Scripted Modules]] that provide a user interface in the module panel along with specialized implementation logic.<br />
<br />
Usage: save the .py file to a directory, add the directory to the additional module paths in the Slicer application settings (choose in the menu: Edit / Application settings, click Modules, click >> next to Additional module paths, click Add, and choose the .py file's location).<br />
<br />
==Filters==<br />
* [https://raw.github.com/pieper/VolumeMasker/master/VolumeMasker.py VolumeMasker.py]: Update a target volume with the results of setting all input volume voxels to 0 except for those that correspond to a selected label value in an input label map (Used for example in the volume rendering in [https://www.youtube.com/watch?v=dfu2gugHLHs this video).<br />
<br />
==DICOM==<br />
* [https://gist.github.com/pieper/6186477 dicom header browser] to easily scroll through dicom files using dcmdump.<br />
* [https://github.com/SlicerRt/SlicerRT/tree/master/BatchProcessing SlicerRT batch processing] to batch convert RT structure sets to labelmap NRRD files.<br />
<br />
==Informatics==<br />
* [https://gist.github.com/lassoan/bf0954d93cacc8cbe27cd4a3ad503f2f MarkupsInfo.py]: Compute the total length between all the points of a markup list.<br />
* [https://gist.github.com/lassoan/0e7acfbec36e4577f8b7b0e07ad53a2a LineProfile.py]: Compute intensity profile in a volume along a line.<br />
<br />
=Community-contributed examples=<br />
<br />
Usage: Copy-paste the shown code lines or linked .py file contents into Python console in Slicer. Or save them to a file and run them using execfile.<br />
<br />
==Capture==<br />
* Capture the full Slicer screen and save it into a file<br />
img = qt.QPixmap.grabWidget(slicer.util.mainWindow()).toImage()<br />
img.save('c:/tmp/test.png')<br />
* Capture all the views save it into a file:<br />
<pre><br />
import ScreenCapture<br />
cap = ScreenCapture.ScreenCaptureLogic()<br />
cap.showViewControllers(False)<br />
cap.captureImageFromView(None,'c:/tmp/test.png')<br />
cap.showViewControllers(True)<br />
</pre><br />
* Capture a single view:<br />
<pre><br />
viewNodeID = 'vtkMRMLViewNode1'<br />
import ScreenCapture<br />
cap = ScreenCapture.ScreenCaptureLogic()<br />
view = cap.viewFromNode(slicer.mrmlScene.GetNodeByID(viewNodeID))<br />
cap.captureImageFromView(view,'c:/tmp/test.png')<br />
</pre><br />
Common values for viewNodeID: vtkMRMLSliceNodeRed, vtkMRMLSliceNodeYellow, vtkMRMLSliceNodeGreen, vtkMRMLViewNode1, vtkMRMLViewNode2. <br />
The ScreenCapture module can also create video animations of rotating views, slice sweeps, etc.<br />
* Capture 3D view into PNG file with transparent background<br />
<pre><br />
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()<br />
renderWindow.SetAlphaBitPlanes(1)<br />
wti = vtk.vtkWindowToImageFilter()<br />
wti.SetInputBufferTypeToRGBA()<br />
wti.SetInput(renderWindow)<br />
writer = vtk.vtkPNGWriter()<br />
writer.SetFileName("c:/tmp/screenshot.png")<br />
writer.SetInputConnection(wti.GetOutputPort())<br />
writer.Write()<br />
</pre><br />
<br />
==Launching Slicer==<br />
* How to open an .mrb file with Slicer at the command line?<br />
Slicer.exe --python-code "slicer.util.loadScene( 'f:/2013-08-23-Scene.mrb' )"<br />
* How to run a script in the Slicer environment in batch mode (without showing any graphical user interface)?<br />
Slicer.exe --python-code "doSomething; doSomethingElse; etc." --testing --no-splash --no-main-window<br />
<br />
==Load volume from file==<br />
When loading a volume from file, it is recommended to set returnNode=True to retrieve the loaded volume node.<br />
<pre><br />
[success, loadedVolumeNode] = slicer.util.loadVolume('c:/Users/abc/Documents/MRHead.nrrd', returnNode=True)<br />
</pre><br />
<br />
* Get a MRML node in the scene based on the node name and call methods of that object. For the MRHead sample data:<br />
vol=slicer.util.getNode('MR*')<br />
vol.GetImageData().GetDimensions()<br />
<br />
==DICOM==<br />
=== How to access tags of DICOM images imported into Slicer? For example, to print the first patient's first study's first series' "0020,0032" field:===<br />
db=slicer.dicomDatabase<br />
patientList=db.patients()<br />
studyList=db.studiesForPatient(patientList[0])<br />
seriesList=db.seriesForStudy(studyList[0])<br />
fileList=db.filesForSeries(seriesList[0])<br />
print db.fileValue(fileList[0],'0020,0032')<br />
<br />
=== How to access tag of a volume loaded from DICOM? For example, get the patient position stored in a volume:===<br />
volumeName='2: ENT IMRT'<br />
n=slicer.util.getNode(volumeName)<br />
instUids=n.GetAttribute('DICOM.instanceUIDs').split()<br />
filename=slicer.dicomDatabase.fileForInstance(instUids[0])<br />
print slicer.dicomDatabase.fileValue(filename,'0018,5100')<br />
<br />
=== How to access tag of an item in the Subject Hierachy tree? For example, get the content time tag of a structure set:===<br />
rtStructName = '3: RTSTRUCT: PROS'<br />
rtStructNode = slicer.util.getNode(rtStructName)<br />
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)<br />
rtStructShItemID = shNode.GetItemByDataNode(rtStructNode)<br />
ctSliceInstanceUids = shNode.GetItemAttribute(rtStructShItemID, 'DICOM.ReferencedInstanceUIDs').split()<br />
filename = slicer.dicomDatabase.fileForInstance(ctSliceInstanceUids[0])<br />
print slicer.dicomDatabase.fileValue(filename,'0008,0033')<br />
<br />
=== How to get path and filename of a loaded DICOM volume?===<br />
def pathFromNode(node):<br />
storageNode=node.GetStorageNode()<br />
if storageNode is not None: # loaded via drag-drop<br />
filepath=storageNode.GetFullNameFromFileName()<br />
else: # loaded via DICOM browser<br />
instanceUIDs=node.GetAttribute('DICOM.instanceUIDs').split()<br />
filepath=slicer.dicomDatabase.fileForInstance(instUids[0])<br />
return filepath<br />
<br />
# example:<br />
node=slicer.util.getNode('volume1')<br />
path=self.pathFromNode(node)<br />
print("DICOM path=%s" % path)<br />
<br />
=== How can I convert DICOM to NRRD on the command line?===<br />
<br />
/Applications/Slicer-4.6.2.app/Contents/MacOS/Slicer --no-main-window --python-code "node=slicer.util.loadVolume('/tmp/series/im0.dcm', returnNode=True)[1]; slicer.util.saveNode(node, '/tmp/output.nrrd'); exit()"<br />
<br />
The same can be done on windows by using the top level Slicer.exe. Be sure to use forward slashes in the pathnames within quotes on the command line.<br />
<br />
==Toolbar functions==<br />
* How to turn on slice intersections in the crosshair menu on the toolbar:<br />
viewNodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLSliceCompositeNode')<br />
viewNodes.UnRegister(slicer.mrmlScene)<br />
viewNodes.InitTraversal()<br />
viewNode = viewNodes.GetNextItemAsObject()<br />
while viewNode:<br />
viewNode.SetSliceIntersectionVisibility(1)<br />
viewNode = viewNodes.GetNextItemAsObject()<br />
<br />
How to find similar functions? For this one I searched for "slice intersections" text in the whole slicer source code, found that the function is implemented in Base\QTGUI\qSlicerViewersToolBar.cxx, then translated the qSlicerViewersToolBarPrivate::setSliceIntersectionVisible(bool visible) method to Python.<br />
<br />
==Manipulating objects in the slice viewer==<br />
* How to define/edit a circular region of interest in a slice viewer?<br />
<br />
Drop two markup points on a slice view and copy-paste the code below into the Python console. After this, as you move the markups you’ll see a circle following the markups.<br />
<br />
<pre><br />
# Update the sphere from the fiducial points<br />
def UpdateSphere(param1, param2): <br />
import math<br />
centerPointCoord = [0.0, 0.0, 0.0]<br />
markups.GetNthFiducialPosition(0,centerPointCoord)<br />
circumferencePointCoord = [0.0, 0.0, 0.0]<br />
markups.GetNthFiducialPosition(1,circumferencePointCoord)<br />
sphere.SetCenter(centerPointCoord)<br />
radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)<br />
sphere.SetRadius(radius)<br />
sphere.SetPhiResolution(30)<br />
sphere.SetThetaResolution(30)<br />
sphere.Update()<br />
<br />
# Get markup node from scene<br />
markups=slicer.util.getNode('F')<br />
sphere = vtk.vtkSphereSource()<br />
UpdateSphere(0,0)<br />
<br />
# Create model node and add to scene<br />
modelsLogic = slicer.modules.models.logic()<br />
model = modelsLogic.AddModel(sphere.GetOutput())<br />
model.GetDisplayNode().SetSliceIntersectionVisibility(True)<br />
model.GetDisplayNode().SetSliceIntersectionThickness(3)<br />
model.GetDisplayNode().SetColor(1,1,0)<br />
<br />
# Call UpdateSphere whenever the fiducials are changed<br />
markups.AddObserver("ModifiedEvent", UpdateSphere, 2)<br />
</pre><br />
<br />
== Switching to markup fiducial placement mode ==<br />
<br />
To activate a fiducial placement mode, both interaction mode has to be set and a fiducial node has to be selected:<br />
<br />
<pre><br />
interactionNode = slicer.app.applicationLogic().GetInteractionNode()<br />
selectionNode = slicer.app.applicationLogic().GetSelectionNode()<br />
selectionNode.SetReferenceActivePlaceNodeClassName("vtkMRMLMarkupsFiducialNode")<br />
fiducialNode = slicer.vtkMRMLMarkupsFiducialNode()<br />
slicer.mrmlScene.AddNode(fiducialNode)<br />
fiducialNode.CreateDefaultDisplayNodes() <br />
selectionNode.SetActivePlaceNodeID(fiducialNode.GetID())<br />
interactionNode.SetCurrentInteractionMode(interactionNode.Place)<br />
</pre><br />
<br />
== Show a context menu when a markup point is clicked in a slice or 3D view ==<br />
<br />
<pre><br />
<br />
# Example actions to perform<br />
<br />
def action1():<br />
print('Action1 on markup '+str(slicer.clickedMarkupIndex))<br />
<br />
def action2():<br />
print('Action2 on markup '+str(slicer.clickedMarkupIndex))<br />
<br />
def action3():<br />
print('Action3 on markup '+str(slicer.clickedMarkupIndex))<br />
<br />
# Clicked markup index is saved here to let the action<br />
# know which markup needs to be manipulated.<br />
slicer.clickedMarkupIndex = -1<br />
<br />
# Create a simple menu<br />
<br />
menu = qt.QMenu()<br />
a1 = qt.QAction("Test", slicer.util.mainWindow())<br />
a1.connect('triggered()', action1)<br />
menu.addAction(a1)<br />
a2 = qt.QAction("Action", slicer.util.mainWindow())<br />
a2.connect('triggered()', action1)<br />
menu.addAction(a2)<br />
a3 = qt.QAction("Here", slicer.util.mainWindow())<br />
a3.connect('triggered()', action1)<br />
menu.addAction(a3)<br />
<br />
# Add observer to a markup fiducial list<br />
<br />
@vtk.calldata_type(vtk.VTK_INT)<br />
def markupClickedCallback(caller, eventId, callData):<br />
slicer.clickedMarkupIndex = callData<br />
print('Open menu on markup '+str(slicer.clickedMarkupIndex))<br />
menu.move(qt.QCursor.pos())<br />
menu.show()<br />
<br />
markupsNode = getNode('F')<br />
observerTag = markupsNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointClickedEvent, markupClickedCallback)<br />
<br />
</pre><br />
<br />
== Add a texture mapped plane to the scene as a model ==<br />
Note that model textures are not exposed in the GUI and are not saved in the scene<br />
<pre><br />
# use dummy image data here<br />
e = vtk.vtkImageEllipsoidSource()<br />
<br />
scene = slicer.mrmlScene<br />
<br />
# Create model node<br />
model = slicer.vtkMRMLModelNode()<br />
model.SetScene(scene)<br />
model.SetName(scene.GenerateUniqueName("2DImageModel"))<br />
<br />
planeSource = vtk.vtkPlaneSource()<br />
model.SetAndObservePolyData(planeSource.GetOutput())<br />
<br />
# Create display node<br />
modelDisplay = slicer.vtkMRMLModelDisplayNode()<br />
modelDisplay.SetColor(1,1,0) # yellow<br />
modelDisplay.SetBackfaceCulling(0)<br />
modelDisplay.SetScene(scene)<br />
scene.AddNode(modelDisplay)<br />
model.SetAndObserveDisplayNodeID(modelDisplay.GetID())<br />
<br />
# Add to scene<br />
modelDisplay.SetAndObserveTextureImageData(e.GetOutput())<br />
scene.AddNode(model) <br />
<br />
<br />
transform = slicer.vtkMRMLLinearTransformNode()<br />
scene.AddNode(transform) <br />
model.SetAndObserveTransformNodeID(transform.GetID())<br />
<br />
vTransform = vtk.vtkTransform()<br />
vTransform.Scale(50,50,50)<br />
vTransform.RotateX(30)<br />
transform.SetAndObserveMatrixTransformToParent(vTransform.GetMatrix())<br />
</pre><br />
<br />
<br />
== Export entire scene as VRML ==<br />
<br />
Save all surface meshes displayed in the scene (models, markups, etc). Solid colors and coloring by scalar is preserved. Textures are not supported.<br />
<br />
<pre><br />
exporter = vtk.vtkVRMLExporter()<br />
exporter.SetRenderWindow(slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow())<br />
exporter.SetFileName('C:/tmp/something.wrl')<br />
exporter.Write()<br />
</pre><br />
<br />
== Export model to Blender, including color by scalar ==<br />
<br />
<pre><br />
modelNode = getNode("Model")<br />
plyFilePath = "c:/tmp/model.ply"<br />
<br />
modelDisplayNode = modelNode.GetDisplayNode()<br />
triangles = vtk.vtkTriangleFilter()<br />
triangles.SetInputConnection(modelDisplayNode.GetOutputPolyDataConnection())<br />
<br />
plyWriter = vtk.vtkPLYWriter()<br />
plyWriter.SetInputConnection(triangles.GetOutputPort())<br />
lut = vtk.vtkLookupTable()<br />
lut.DeepCopy(modelDisplayNode.GetColorNode().GetLookupTable())<br />
lut.SetRange(modelDisplayNode.GetScalarRange())<br />
plyWriter.SetLookupTable(lut)<br />
plyWriter.SetArrayName(modelDisplayNode.GetActiveScalarName())<br />
<br />
plyWriter.SetFileName(plyFilePath)<br />
plyWriter.Write()<br />
</pre><br />
<br />
== Export a fiber tracts to Blender, including color ==<br />
<br />
<pre><br />
lineDisplayNode = getNode("*LineDisplay*")<br />
plyFilePath = "/tmp/fibers.ply"<br />
<br />
tuber = vtk.vtkTubeFilter()<br />
tuber.SetInputData(lineDisplayNode.GetOutputPolyData())<br />
tuber.Update()<br />
tubes = tuber.GetOutputDataObject(0)<br />
scalars = tubes.GetPointData().GetArray(0)<br />
scalars.SetName("scalars")<br />
<br />
triangles = vtk.vtkTriangleFilter()<br />
triangles.SetInputData(tubes)<br />
triangles.Update()<br />
<br />
colorNode = lineDisplayNode.GetColorNode()<br />
lookupTable = vtk.vtkLookupTable()<br />
lookupTable.DeepCopy(colorNode.GetLookupTable())<br />
lookupTable.SetTableRange(0,1)<br />
<br />
plyWriter = vtk.vtkPLYWriter()<br />
plyWriter.SetInputData(triangles.GetOutput())<br />
plyWriter.SetLookupTable(lookupTable)<br />
plyWriter.SetArrayName("scalars")<br />
<br />
plyWriter.SetFileName(plyFilePath)<br />
plyWriter.Write()<br />
</pre><br />
<br />
== Clone a volume ==<br />
This example shows how to clone the MRHead sample volume, including its pixel data and display settings.<br />
<pre><br />
sourceVolumeNode = slicer.util.getNode('MRHead')<br />
volumesLogic = slicer.modules.volumes.logic()<br />
clonedVolumeNode = volumesLogic.CloneVolume(slicer.mrmlScene, sourceVolumeNode, 'Cloned volume')<br />
</pre><br />
<br />
== Create a new volume ==<br />
This example shows how to create a new empty volume.<br />
<pre><br />
imageSize=[512, 512, 512]<br />
imageSpacing=[1.0, 1.0, 1.0]<br />
voxelType=vtk.VTK_UNSIGNED_CHAR<br />
# Create an empty image volume<br />
imageData=vtk.vtkImageData()<br />
imageData.SetDimensions(imageSize)<br />
imageData.AllocateScalars(voxelType, 1)<br />
thresholder=vtk.vtkImageThreshold()<br />
thresholder.SetInputData(imageData)<br />
thresholder.SetInValue(0)<br />
thresholder.SetOutValue(0)<br />
# Create volume node<br />
volumeNode=slicer.vtkMRMLScalarVolumeNode()<br />
volumeNode.SetSpacing(imageSpacing)<br />
volumeNode.SetImageDataConnection(thresholder.GetOutputPort())<br />
# Add volume to scene<br />
slicer.mrmlScene.AddNode(volumeNode)<br />
displayNode=slicer.vtkMRMLScalarVolumeDisplayNode()<br />
slicer.mrmlScene.AddNode(displayNode)<br />
colorNode = slicer.util.getNode('Grey')<br />
displayNode.SetAndObserveColorNodeID(colorNode.GetID())<br />
volumeNode.SetAndObserveDisplayNodeID(displayNode.GetID())<br />
volumeNode.CreateDefaultStorageNode()<br />
</pre><br />
<br />
== Modify voxels in a volume ==<br />
<br />
Typically the fastest and simplest way of modifying voxels is by using numpy operators. Voxels can be retrieved in a numpy array using the `array` method and modified using standard numpy methods. For example, threshold a volume:<br />
<br />
<pre><br />
nodeName = 'MRHead'<br />
thresholdValue = 100<br />
voxelArray = array(nodeName) # get voxels as numpy array<br />
voxelArray[voxelArray < thresholdValue] = 0 # modify voxel values<br />
getNode(nodeName).Modified() # at the end of all processing, notify Slicer that the image modification is completed<br />
</pre><br />
<br />
This example shows how to change voxels values of the MRHead sample volume.<br />
The values will be computed by function f(r,a,s,) = (r-10)*(r-10)+(a+15)*(a+15)+s*s.<br />
<pre><br />
volumeNode=slicer.util.getNode('MRHead')<br />
ijkToRas = vtk.vtkMatrix4x4()<br />
volumeNode.GetIJKToRASMatrix(ijkToRas)<br />
imageData=volumeNode.GetImageData()<br />
extent = imageData.GetExtent()<br />
for k in xrange(extent[4], extent[5]+1):<br />
for j in xrange(extent[2], extent[3]+1):<br />
for i in xrange(extent[0], extent[1]+1):<br />
position_Ijk=[i, j, k, 1]<br />
position_Ras=ijkToRas.MultiplyPoint(position_Ijk)<br />
r=position_Ras[0]<br />
a=position_Ras[1]<br />
s=position_Ras[2] <br />
functionValue=(r-10)*(r-10)+(a+15)*(a+15)+s*s<br />
imageData.SetScalarComponentFromDouble(i,j,k,0,functionValue)<br />
imageData.SetScalarComponentFromFloat(distortionVectorPosition_Ijk[0], distortionVectorPosition_Ijk[1], distortionVectorPosition_Ijk[2], 0, fillValue)<br />
imageData.Modified()<br />
</pre><br />
<br />
== Get the values of all voxels for a label value ==<br />
<br />
If you have a background image called ‘Volume’ and a mask called ‘Volume-label’ created with the Editor you could do something like this:<br />
<br />
<pre><br />
<br />
import numpy<br />
volume = array(‘Volume’)<br />
label = array(‘Volume-label’)<br />
points = numpy.where( label == 1 ) # or use another label number depending on what you segmented<br />
values = volume[points] # this will be a list of the label values<br />
values.mean() # should match the mean value of LabelStatistics calculation as a double-check<br />
numpy.savetxt(‘values.txt’, values)<br />
</pre><br />
<br />
== Access values in a DTI tensor volume ==<br />
This example shows how to access individual tensors at the voxel level.<br />
<br />
First load your DWI volume and estimate tensors to produce a DTI volume called ‘Output DTI Volume’<br />
<br />
Then open the python window: View->Python interactor<br />
<br />
Use this command to access tensors through numpy:<br />
<br />
<pre><br />
tensors = array('Output DTI Volume')<br />
</pre><br />
<br />
Type the following code into the Python window to access all tensor components using vtk commands:<br />
<br />
<pre><br />
volumeNode=slicer.util.getNode('Output DTI Volume')<br />
imageData=volumeNode.GetImageData()<br />
tensors = imageData.GetPointData().GetTensors()<br />
extent = imageData.GetExtent()<br />
idx = 0<br />
for k in xrange(extent[4], extent[5]+1):<br />
for j in xrange(extent[2], extent[3]+1):<br />
for i in xrange(extent[0], extent[1]+1):<br />
tensors.GetTuple9(idx)<br />
idx += 1<br />
</pre><br />
<br />
== Change window/level (brightness/contrast) or colormap of a volume ==<br />
This example shows how to change window/level of the MRHead sample volume.<br />
<pre><br />
volumeNode = getNode('MRHead')<br />
displayNode = volumeNode.GetDisplayNode()<br />
displayNode.AutoWindowLevelOff()<br />
displayNode.SetWindow(50)<br />
displayNode.SetLevel(100)<br />
</pre><br />
<br />
Change color mapping from grayscale to rainbow:<br />
<pre><br />
displayNode.SetAndObserveColorNodeID('vtkMRMLColorTableNodeRainbow')<br />
</pre><br />
<br />
== Manipulate a Slice View ==<br />
<br />
<pre><br />
lm = slicer.app.layoutManager()<br />
red = lm.sliceWidget('Red')<br />
redLogic = red.sliceLogic()<br />
# Print current slice offset position<br />
print redLogic.GetSliceOffset()<br />
# Change slice position<br />
redLogic.SetSliceOffset(20)<br />
</pre><br />
<br />
== Fit slice plane to markup fiducials ==<br />
<br />
<pre><br />
sliceNode = slicer.mrmlScene.GetNodeByID("vtkMRMLSliceNodeRed")<br />
markupsNode = slicer.mrmlScene.GetFirstNodeByName("F")<br />
# Get markup point positions as numpy arrays<br />
import numpy as np<br />
p1 = np.array([0,0,0])<br />
p2 = np.array([0,0,0])<br />
p3 = np.array([0,0,0])<br />
markupsNode.GetNthFiducialPosition(0, p1)<br />
markupsNode.GetNthFiducialPosition(1, p2)<br />
markupsNode.GetNthFiducialPosition(2, p3)<br />
# Get plane axis directions<br />
n = np.cross(p2-p1, p2-p3) # plane normal direction<br />
n = n/np.linalg.norm(n)<br />
t = np.cross([0, 0, 1], n) # plane transverse direction<br />
t = t/np.linalg.norm(t)<br />
# Set slice plane orientation and position<br />
sliceNode.SetSliceToRASByNTP(n[0], n[1], n[2], t[0], t[1], t[2], p1[0], p1[1], p1[2], 0)<br />
</pre><br />
<br />
== Save a series of images from a Slice View ==<br />
<br />
You can use ScreenCapture module to capture series of images. To do it programmatically, save the following into a file such as '/tmp/record.py' and then in the slicer python console type "execfile('/tmp/record.py')"<br />
<br />
<pre><br />
layoutName = 'Green'<br />
imagePathPattern = '/tmp/image-%03d.png'<br />
steps = 10<br />
<br />
widget = slicer.app.layoutManager().sliceWidget(layoutName)<br />
view = widget.sliceView()<br />
logic = widget.sliceLogic()<br />
bounds = [0,]*6<br />
logic.GetSliceBounds(bounds)<br />
<br />
for step in range(steps):<br />
offset = bounds[4] + step/(1.*steps) * (bounds[5]-bounds[4])<br />
logic.SetSliceOffset(offset)<br />
view.forceRender()<br />
image = qt.QPixmap.grabWidget(view).toImage()<br />
image.save(imagePathPattern % step)<br />
</pre><br />
<br />
== Save the scene into a new directory ==<br />
<br />
<pre><br />
# Create a new directory where the scene will be saved into<br />
import time<br />
sceneSaveDirectory = slicer.app.temporaryPath + "/saved-scene-" + time.strftime("%Y%m%d-%H%M%S")<br />
if not os.access(sceneSaveDirectory, os.F_OK):<br />
os.makedirs(sceneSaveDirectory)<br />
<br />
# Save the scene<br />
if slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(sceneSaveDirectory, None):<br />
logging.info("Scene saved to: {0}".format(sceneSaveDirectory))<br />
else:<br />
logging.error("Scene saving failed") <br />
</pre><br />
<br />
== Save the scene into a single MRB file ==<br />
<pre><br />
# Generate file name<br />
import time<br />
sceneSaveFilename = slicer.app.temporaryPath + "/saved-scene-" + time.strftime("%Y%m%d-%H%M%S") + ".mrb"<br />
<br />
# Save scene<br />
if slicer.util.saveScene(sceneSaveFilename):<br />
logging.info("Scene saved to: {0}".format(sceneSaveFilename))<br />
else:<br />
logging.error("Scene saving failed") <br />
</pre><br />
<br />
== Show a volume in the Slice Views ==<br />
<br />
<pre><br />
volumeNode = slicer.util.getNode('YourVolumeNode')<br />
applicationLogic = slicer.app.applicationLogic()<br />
selectionNode = applicationLogic.GetSelectionNode()<br />
selectionNode.SetSecondaryVolumeID(volumeNode.GetID())<br />
applicationLogic.PropagateForegroundVolumeSelection(0) <br />
</pre><br />
<br />
or<br />
<br />
<pre><br />
n = slicer.util.getNode('YourVolumeNode')<br />
for color in ['Red', 'Yellow', 'Green']:<br />
slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetForegroundVolumeID(n.GetID())<br />
</pre><br />
<br />
== Change opacity of foreground volume in the Slice Views ==<br />
<br />
<pre><br />
lm = slicer.app.layoutManager()<br />
sliceLogic = lm.sliceWidget('Red').sliceLogic()<br />
compositeNode = sliceLogic.GetSliceCompositeNode()<br />
compositeNode.SetForegroundOpacity(0.4)<br />
</pre><br />
<br />
== Center the 3D View on the Scene ==<br />
<pre><br />
layoutManager = slicer.app.layoutManager()<br />
threeDWidget = layoutManager.threeDWidget(0)<br />
threeDView = threeDWidget.threeDView()<br />
threeDView.resetFocalPoint()<br />
</pre><br />
<br />
== Display text in a 3D view or slice view ==<br />
<br />
The easiest way to show information overlaid on a viewer is to use corner annotations.<br />
<br />
<pre><br />
view=slicer.app.layoutManager().threeDWidget(0).threeDView()<br />
# Set text to "Something"<br />
view.cornerAnnotation().SetText(vtk.vtkCornerAnnotation.UpperRight,"Something")<br />
# Set color to red<br />
view.cornerAnnotation().GetTextProperty().SetColor(1,0,0)<br />
# Update the view<br />
view.forceRender()<br />
</pre><br />
<br />
== Turning off interpolation ==<br />
<br />
You can turn off interpolation for newly loaded volumes with this script from Steve Pieper.<br />
<br />
<pre><br />
def NoInterpolate(caller,event):<br />
for node in slicer.util.getNodes('*').values():<br />
if node.IsA('vtkMRMLScalarVolumeDisplayNode'):<br />
node.SetInterpolate(0)<br />
<br />
slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, NoInterpolate)<br />
</pre><br />
<br />
The below link explains how to put this in your startup script.<br />
<br />
http://www.na-mic.org/Wiki/index.php/AHM2012-Slicer-Python#Refining_the_code_and_UI_with_slicerrc<br />
<br />
<br />
== Customize viewer layout ==<br />
<br />
Show a custom layout of a 3D view on top of the red slice view:<br />
<br />
<pre><br />
customLayout = ("<layout type=\"vertical\" split=\"true\" >"<br />
" <item>"<br />
" <view class=\"vtkMRMLViewNode\" singletontag=\"1\">"<br />
" <property name=\"viewlabel\" action=\"default\">1</property>"<br />
" </view>"<br />
" </item>"<br />
" <item>"<br />
" <view class=\"vtkMRMLSliceNode\" singletontag=\"Red\">"<br />
" <property name=\"orientation\" action=\"default\">Axial</property>"<br />
" <property name=\"viewlabel\" action=\"default\">R</property>"<br />
" <property name=\"viewcolor\" action=\"default\">#F34A33</property>"<br />
" </view>"<br />
" </item>"<br />
"</layout>")<br />
<br />
customLayoutId=501<br />
<br />
layoutManager = slicer.app.layoutManager()<br />
layoutManager.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout) <br />
layoutManager.setLayout(customLayoutId)<br />
</pre><br />
<br />
See description of standard layouts (that can be used as examples) here:<br />
https://github.com/Slicer/Slicer/blob/master/Libs/MRML/Logic/vtkMRMLLayoutLogic.cxx<br />
<br />
== Disable certain user interactions in slice views ==<br />
<br />
For example, disable slice browsing using mouse wheel and keyboard shortcuts in the red slice viewer:<br />
<br />
<pre><br />
interactorStyle = slicer.app.layoutManager().sliceWidget('Red').sliceView().sliceViewInteractorStyle()<br />
interactorStyle.SetActionEnabled(interactorStyle.BrowseSlice, False)<br />
</pre><br />
<br />
Hide all slice view controllers:<br />
<pre><br />
lm = slicer.app.layoutManager()<br />
for sliceViewName in lm.sliceViewNames():<br />
lm.sliceWidget(sliceViewName).sliceController().setVisible(False)<br />
</pre><br />
<br />
Hide all 3D view controllers:<br />
<pre><br />
lm = slicer.app.layoutManager()<br />
for viewIndex in range(slicer.app.layoutManager().threeDViewCount):<br />
lm.threeDWidget(0).threeDController().setVisible(False)<br />
</pre><br />
<br />
== Set up custom units in slice view ruler ==<br />
<br />
For microscopy or micro-CT images you may want to switch unit to micrometer instead of the default mm. To do that, 1. change the unit in Application settings / Units and 2. update ruler display settings using the script below (it can be copied to your Application startup script):<br />
<br />
<pre><br />
lm = slicer.app.layoutManager()<br />
for sliceViewName in lm.sliceViewNames():<br />
sliceView = lm.sliceWidget(sliceViewName).sliceView()<br />
displayableManagerCollection = vtk.vtkCollection()<br />
sliceView.getDisplayableManagers(displayableManagerCollection)<br />
for dmIndex in xrange(displayableManagerCollection.GetNumberOfItems()):<br />
displayableManager = displayableManagerCollection.GetItemAsObject(dmIndex)<br />
if not displayableManager.IsA("vtkMRMLRulerDisplayableManager"):<br />
continue<br />
displayableManager.RemoveAllRulerScalePresets()<br />
displayableManager.AddRulerScalePreset( 0.001, 5, 2, "nm", 1000.0)<br />
displayableManager.AddRulerScalePreset( 0.010, 5, 2, "nm", 1000.0)<br />
displayableManager.AddRulerScalePreset( 0.100, 5, 2, "nm", 1000.0)<br />
displayableManager.AddRulerScalePreset( 0.500, 5, 1, "nm", 1000.0)<br />
displayableManager.AddRulerScalePreset( 1.0, 5, 2, "um", 1.0)<br />
displayableManager.AddRulerScalePreset( 5.0, 5, 1, "um", 1.0)<br />
displayableManager.AddRulerScalePreset( 10.0, 5, 2, "um", 1.0)<br />
displayableManager.AddRulerScalePreset( 50.0, 5, 1, "um", 1.0)<br />
displayableManager.AddRulerScalePreset( 100.0, 5, 2, "um", 1.0)<br />
displayableManager.AddRulerScalePreset( 500.0, 5, 1, "um", 1.0)<br />
displayableManager.AddRulerScalePreset(1000.0, 5, 2, "mm", 0.001)<br />
</pre><br />
<br />
== Running an ITK filter in Python using SimpleITK ==<br />
Open the "Sample Data" module and download "MR Head", then paste the following snippet in Python interactor:<br />
<pre><br />
import SimpleITK as sitk<br />
import sitkUtils<br />
inputImage = sitkUtils.PullFromSlicer('MRHead')<br />
filter = sitk.SignedMaurerDistanceMapImageFilter()<br />
outputImage = filter.Execute(inputImage)<br />
sitkUtils.PushToSlicer(outputImage,'outputImage')<br />
</pre><br />
<br />
More information:<br />
* See the SimpleITK documentation for SimpleITK examples: http://www.itk.org/SimpleITKDoxygen/html/examples.html<br />
* sitkUtils in Slicer is used for pushing and pulling images from Slicer to SimpleITK: https://github.com/Slicer/Slicer/blob/master/Base/Python/sitkUtils.py<br />
<br />
== Get current mouse coordinates in a slice view ==<br />
<br />
You can get 3D (RAS) coordinates of the current mouse cursor from the crosshair singleton node as shown in the example below:<br />
<br />
<pre><br />
def onMouseMoved(observer,eventid): <br />
ras=[0,0,0]<br />
crosshairNode.GetCursorPositionRAS(ras)<br />
print(ras)<br />
<br />
crosshairNode=slicer.util.getNode('Crosshair') <br />
crosshairNode.AddObserver(slicer.vtkMRMLCrosshairNode.CursorPositionModifiedEvent, onMouseMoved)<br />
</pre><br />
<br />
== Get DataProbe text ==<br />
<br />
You can get the mouse location in pixel coordinates along with the pixel value at the mouse by hitting the '.' (period) key in a slice view after pasting in the following code.<br />
<br />
<pre><br />
def printDataProbe():<br />
infoWidget = slicer.modules.DataProbeInstance.infoWidget<br />
for layer in ('B', 'F', 'L'):<br />
print(infoWidget.layerNames[layer].text, infoWidget.layerIJKs[layer].text, infoWidget.layerValues[layer].text)<br />
<br />
s = qt.QShortcut(qt.QKeySequence('.'), mainWindow())<br />
s.connect('activated()', printDataProbe)<br />
</pre><br />
<br />
== Thick slab reconstruction and maximum/minimum intensity volume projections ==<br />
<br />
Set up 'red' slice viewer to show thick slab reconstructed from 3 slices:<br />
<pre><br />
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')<br />
appLogic = slicer.app.applicationLogic()<br />
sliceLogic = appLogic.GetSliceLogic(sliceNode)<br />
sliceLayerLogic = sliceLogic.GetBackgroundLayer()<br />
reslice = sliceLayerLogic.GetReslice()<br />
reslice.SetSlabModeToMean()<br />
reslice.SetSlabNumberOfSlices(10) # mean of 10 slices will computed<br />
reslice.SetSlabSliceSpacingFraction(0.3) # spacing between each slice is 0.3 pixel (total 10 * 0.3 = 3 pixel neighborhood)<br />
sliceNode.Modified()<br />
</pre><br />
<br />
Set up 'red' slice viewer to show maximum intensity projection (MIP):<br />
<pre><br />
sliceNode = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed')<br />
appLogic = slicer.app.applicationLogic()<br />
sliceLogic = appLogic.GetSliceLogic(sliceNode)<br />
sliceLayerLogic = sliceLogic.GetBackgroundLayer()<br />
reslice = sliceLayerLogic.GetReslice()<br />
reslice.SetSlabModeToMax()<br />
reslice.SetSlabNumberOfSlices(600) # use a large number of slices (600) to cover the entire volume<br />
reslice.SetSlabSliceSpacingFraction(0.5) # spacing between slices are 0.5 pixel (supersampling is useful to reduce interpolation artifacts)<br />
sliceNode.Modified()<br />
</pre><br />
<br />
The projected image is available in a ''vtkImageData'' object by calling ''reslice.GetOutput()''.<br />
<br />
== Change default file type for nodes (that have never been saved yet) ==<br />
Default node can be specified that will be used as a basis of all new storage nodes. This can be used for setting default file extension. For example, change file format to STL for model nodes:<br />
<pre><br />
defaultModelStorageNode = slicer.vtkMRMLModelStorageNode()<br />
defaultModelStorageNode.SetDefaultWriteFileExtension('stl')<br />
slicer.mrmlScene.AddDefaultNode(defaultModelStorageNode)<br />
</pre><br />
<br />
To permanently change default file extension on your computer, copy-paste the code above into your application startup script (you can find its location in menu: Edit / Application settings / General / Application startup script).<br />
<br />
== Change file type for saving for all volumes (with already existing storage nodes) ==<br />
<br />
If it is not necessary to preserve file paths then the simplest is to configure default storage node (as shown in the example above), then delete all existing storage nodes. When save dialog is opened, default storage nodes will be recreated.<br />
<br />
<pre><br />
# Delete existing model storage nodes so that they will be recreated with default settings<br />
existingModelStorageNodes = slicer.util.getNodesByClass('vtkMRMLModelStorageNode')<br />
for modelStorageNode in existingModelStorageNodes:<br />
slicer.mrmlScene.RemoveNode(modelStorageNode)<br />
</pre><br />
<br />
To update existing storage nodes to use new file extension (but keep all other parameters unchanged) you can use this approach (example is for volume storage):<br />
<br />
<pre><br />
requiredFileExtension = '.nia'<br />
originalFileExtension = '.nrrd'<br />
volumeNodes = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')<br />
for volumeNode in volumeNodes:<br />
volumeStorageNode = volumeNode.GetStorageNode()<br />
if not volumeStorageNode:<br />
volumeNode.AddDefaultStorageNode()<br />
volumeStorageNode = volumeNode.GetStorageNode()<br />
volumeStorageNode.SetFileName(volumeNode.GetName()+requiredFileExtension)<br />
else:<br />
volumeStorageNode.SetFileName(volumeStorageNode.GetFileName().replace(originalFileExtension, requiredFileExtension))<br />
</pre><br />
<br />
== Segmentations ==<br />
<br />
=== Create a segmentation from a labelmap volume and display in 3D ===<br />
<br />
<pre><br />
labelmapVolumeNode = getNode('label')<br />
seg = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLSegmentationNode')<br />
slicer.modules.segmentations.logic().ImportLabelmapToSegmentationNode(labelmapVolumeNode, seg)<br />
seg.CreateClosedSurfaceRepresentation()<br />
slicer.mrmlScene.RemoveNode(labelmapVolumeNode)<br />
</pre><br />
<br />
The last line is optional. It removes the original labelmap volume so that the same information is not shown twice.<br />
<br />
=== Export labelmap node from segmentation node ===<br />
<br />
<pre><br />
seg = getNode('Segmentation')<br />
labelmapVolumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode')<br />
slicer.modules.segmentations.logic().ExportAllSegmentsToLabelmapNode(seg, labelmapVolumeNode)<br />
</pre><br />
<br />
=== Show a segmentation in 3D ===<br />
Segmentation can only be shown in 3D if closed surface representation (or other 3D-displayable representation) is available. To create closed surface representation:<br />
<pre><br />
segmentation.CreateClosedSurfaceRepresentation()<br />
</pre><br />
<br />
=== Get a representation of a segment ===<br />
Access binary labelmap stored in a segmentation node (without exporting it to a volume node) - if it does not exist, it will return None:<br />
<pre><br />
image = segmentationNode.GetBinaryLabelmapRepresentation(segmentID)<br />
</pre><br />
Get closed surface, if it does not exist, it will return None:<br />
<pre><br />
polydata = segmentationNode.GetClosedSurfaceRepresentation(segmentID)<br />
</pre><br />
Get binary labelmap representation. If it does not exist then it will be created for that single segment. Applies parent transforms by default (if not desired, another argument needs to be added to the end: false):<br />
<pre><br />
import vtkSegmentationCorePython as vtkSegmentationCore<br />
outputOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()<br />
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentBinaryLabelmapRepresentation(segmentationNode, segmentID, outputOrientedImageData)<br />
</pre><br />
Same as above, for closed surface representation:<br />
<pre><br />
outputPolyData = vtk.vtkPolyData()<br />
slicer.vtkSlicerSegmentationsModuleLogic.GetSegmentClosedSurfaceRepresentation(segmentationNode, segmentID, outputPolyData)<br />
</pre><br />
<br />
=== Convert all segments using default path and conversion parameters ===<br />
<pre><br />
segmentationNode.CreateBinaryLabelmapRepresentation()<br />
</pre><br />
<br />
=== Convert all segments using custom path or conversion parameters ===<br />
Change reference image geometry parameter based on an existing referenceImageData image:<br />
<pre><br />
import vtkSegmentationCorePython as vtkSegmentationCore<br />
referenceGeometry = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(referenceImageData)<br />
segmentation.SetConversionParameter(vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), referenceGeometry)<br />
</pre><br />
<br />
=== Re-convert using a modified conversion parameter ===<br />
Changing smoothing factor for closed surface generation:<br />
<pre><br />
import vtkSegmentationCorePython as vtkSegmentationCore<br />
segmentation = getNode('Segmentation').GetSegmentation()<br />
<br />
# Turn of surface smoothing<br />
segmentation.SetConversionParameter('Smoothing factor','0.0')<br />
<br />
# Recreate representation using modified parameters (and default conversion path)<br />
segmentation.RemoveRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())<br />
segmentation.CreateRepresentation(vtkSegmentationCore.vtkSegmentationConverter.GetSegmentationClosedSurfaceRepresentationName())<br />
</pre><br />
<br />
=== How to run segment editor effects from a script ===<br />
<br />
Editor effects are complex because they need to handle changing master volumes, undo/redo, masking operations, etc. Therefore, instead of using a segment editor effect, it is simpler to run the underlying filters directly from script.<br />
<br />
This example demonstrates how to use Segment editor effects (without GUI, using qMRMLSegmentEditorWidget):<br />
<br />
* [https://gist.github.com/lassoan/2d5a5b73645f65a5eb6f8d5f97abf31b brain tumor segmentation using grow from seeds effect]<br />
* [https://gist.github.com/lassoan/1673b25d8e7913cbc245b4f09ed853f9 skin surface extraction using thresholding and smoothing]<br />
<br />
This example shows how to perform operations on segmentations using VTK filters:<br />
* [https://gist.github.com/lassoan/7c94c334653010696b2bf96abc0ac8e7 brain tumor segmentation using grow from seeds effect]<br />
<br />
== Accessing views, renderers, and cameras ==<br />
<br />
Iterate through all 3D views in current layout:<br />
<br />
<pre><br />
layoutManager = slicer.app.layoutManager()<br />
for threeDViewIndex in range(layoutManager.threeDViewCount) :<br />
view = layoutManager.threeDWidget(threeDViewIndex).threeDView()<br />
threeDViewNode = view.mrmlViewNode()<br />
cameraNode = slicer.modules.cameras.logic().GetViewActiveCameraNode(threeDViewNode)<br />
print('View node for 3D widget ' + str(threeDViewIndex))<br />
print(' Name: ' + threeDViewNode .GetName())<br />
print(' ID: ' + threeDViewNode .GetID())<br />
print(' Camera ID: ' + cameraNode.GetID())<br />
</pre><br />
<br />
Iterate through all slice views in current layout:<br />
<br />
<pre><br />
layoutManager = slicer.app.layoutManager()<br />
for sliceViewName in layoutManager.sliceViewNames():<br />
view = layoutManager.sliceWidget(sliceViewName).sliceView()<br />
sliceNode = view.mrmlSliceNode()<br />
sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)<br />
compositeNode = sliceLogic.GetSliceCompositeNode()<br />
print('Slice view ' + str(sliceViewName))<br />
print(' Name: ' + sliceNode.GetName())<br />
print(' ID: ' + sliceNode.GetID())<br />
print(' Background volume: {0}'.format(compositeNode.GetBackgroundVolumeID()))<br />
print(' Foreground volume: {0} (opacity: {1})'.format(compositeNode.GetForegroundVolumeID(), compositeNode.GetForegroundOpacity()))<br />
print(' Label volume: {0} (opacity: {1})'.format(compositeNode.GetLabelVolumeID(), compositeNode.GetLabelOpacity()))<br />
</pre><br />
<br />
For low-level manipulation of views, it is possible to access VTK render windows, renderers and cameras of views in the current layout.<br />
<pre><br />
renderWindow = view.renderWindow()<br />
renderers = renderWindow.GetRenderers()<br />
renderer = renderers.GetItemAsObject(0)<br />
camera = cameraNode.GetCamera()<br />
</pre><br />
<br />
== Change 3D view background color ==<br />
<br />
<pre><br />
renderWindow = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow()<br />
renderer = renderWindow.GetRenderers().GetFirstRenderer()<br />
renderer.SetBackground(1,0,0)<br />
renderer.SetBackground2(1,0,0)<br />
renderWindow.Render()<br />
</pre><br />
<br />
== Subject hierarchy == <br />
==== Get the pseudo-singleton subject hierarchy node ====<br />
It manages the whole hierarchy and provides functions to access and manipulate<br />
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)<br />
<br />
==== Create subject hierarchy item ====<br />
# If it is for a data node, it is automatically created, but the create function can be used to set parent:<br />
shNode.CreateItem(parentItemID, dataNode)<br />
# If it is a hierarchy item without a data node, then the create function must be used:<br />
shNode.CreateSubjectItem(parentItemID, name)<br />
shNode.CreateFolderItem(parentItemID, name)<br />
shNode.CreateHierarchyItem(parentItemID, name, level) # Advanced method to set level attribute manually (usually subject, study, or folder, but it can be a virtual branch for example)<br />
<br />
==== Get subject hierarchy item ====<br />
Items in subject hierarchy are uniquely identified by integer IDs<br />
# Get scene item ID first because it is the root item:<br />
sceneItemID = shNode.GetSceneItemID()<br />
# Get direct child by name<br />
subjectItemID = shNode.GetItemChildWithName(sceneItemID, 'Subject_1')<br />
# Get item for data node<br />
itemID = shNode.GetItemByDataNode(dataNode)<br />
# Get item by UID (such as DICOM)<br />
itemID = shNode.GetItemByUID(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMUIDName(), seriesInstanceUid)<br />
itemID = shNode.GetItemByUIDList(slicer.vtkMRMLSubjectHierarchyConstants.GetDICOMInstanceUIDName(), instanceUID)<br />
# Invalid item ID for checking validity of a given ID (most functions return the invalid ID when item is not found)<br />
invalidItemID = slicer.vtkMRMLSubjectHierarchyNode.GetInvalidItemID()<br />
<br />
==== Traverse children of a subject hierarchy item ====<br />
children = vtk.vtkIdList()<br />
shNode.GetItemChildren(parent, children)<br />
for i in xrange(children.GetNumberOfIds()):<br />
child = children.GetId(i)<br />
...<br />
<br />
==== Manipulate subject hierarchy item ====<br />
Instead of node operations on the individual subject hierarchy nodes, item operations are performed on the one subject hierarchy node.<br />
# Set item name<br />
shNode.SetItemName(itemID, 'NewName')<br />
# Set item parent (reparent)<br />
shNode.SetItemParent(itemID, newParentItemID)<br />
# Set visibility of data nodes associated to items in a branch (or a leaf item)<br />
shNode.SetDisplayVisibilityForBranch(itemID, 1)<br />
<br />
==== Filter items in TreeView or ComboBox ====<br />
Displayed items can be filtered using ''setAttributeFilter'' method. An example of the usage can be found in the [https://github.com/Slicer/Slicer/blob/e66e3b08e35384526528e6ae678e9ec9f079f286/Applications/SlicerApp/Testing/Python/SubjectHierarchyGenericSelfTest.py#L352-L360 unit test]. Modified version here:<br />
print shTreeView.displayedItemCount() # 5<br />
shTreeView.setAttributeFilter('DICOM.Modality') # Nodes must have this attribute<br />
print shTreeView.displayedItemCount() # 3<br />
shTreeView.setAttributeFilter('DICOM.Modality','CT') # Have attribute and equal 'CT'<br />
print shTreeView.displayedItemCount() # 1<br />
shTreeView.removeAttributeFilter()<br />
print shTreeView.displayedItemCount() # 5<br />
<br />
== Plotting ==<br />
<br />
=== Create histogram plot of a volume ===<br />
<br />
<pre><br />
volumeNode = getNode('MRHead')<br />
<br />
# Compute histogram values<br />
import numpy as np<br />
histogram = np.histogram(arrayFromVolume(volumeNode), bins=300)<br />
<br />
# Save results to a new table node<br />
tableNode=slicer.mrmlScene.AddNewNodeByClass("vtkMRMLTableNode", volumeNode.GetName() + " histogram")<br />
updateTableFromArray(tableNode, histogram)<br />
tableNode.GetTable().GetColumn(0).SetName("Count")<br />
tableNode.GetTable().GetColumn(1).SetName("Intensity")<br />
<br />
# Create plot<br />
<br />
plotDataNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLPlotDataNode")<br />
plotDataNode.SetAndObserveTableNodeID(tableNode.GetID())<br />
plotDataNode.SetXColumnName("Intensity")<br />
plotDataNode.SetYColumnName("Count")<br />
<br />
plotChartNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLPlotChartNode")<br />
plotChartNode.AddAndObservePlotDataNodeID(plotDataNode.GetID())<br />
plotChartNode.SetAttribute("Type", "Bar") # delete this line for line plot<br />
<br />
# Show plot in layout<br />
<br />
layoutManager = slicer.app.layoutManager()<br />
layoutManager.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutFourUpPlotView)<br />
plotWidget = layoutManager.plotWidget(0)<br />
<br />
plotViewNode = plotWidget.mrmlPlotViewNode()<br />
plotViewNode.SetPlotChartNodeID(plotChartNode.GetID())<br />
</pre></div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Labs/HomebrewCask&diff=54855Documentation/Labs/HomebrewCask2017-08-31T01:41:58Z<p>Fernando: Add intro</p>
<hr />
<div>This page was created based on the discussions [https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Add Slicer Nightly to Homebrew (macOS)] and [https://discourse.slicer.org/t/slicer-installation-on-mac-using-homebrew/ Slicer installation on Mac using homebrew]<br />
<br />
== Introduction ==<br />
<br />
The purpose of this Lab is to offer an alternative way to install / update Slicer for macOS users using the command line. The process is much more convenient than the traditional way, but it requires minimal computer skills that not all users might have. Therefore this alternative way is specially intended to be used by developers or engineers instead of medical staff and casual users. <br />
<br />
== Definitions ==<br />
<br />
=== Homebrew ===<br />
[https://brew.sh/ Homebrew] is "the missing package manager for macOS". It is designed for installing UNIX tools and other open-source applications. It will quickly download and install them, compiling them from source. Homebrew can install stuff like:<br />
* <code>vim</code><br />
* <code>ffmpeg</code><br />
* <code>python</code><br />
<br />
=== Homebrew Cask ===<br />
[https://caskroom.github.io/ Homebrew Cask] extends Homebrew with support for installing binary apps — the kind you normally drag to your Applications folder from DMG files. For example:<br />
* 3D Slicer<br />
* Google Chrome<br />
<br />
=== Homebrew Versions ===<br />
[https://github.com/caskroom/homebrew-versions Homebrew Versions] lets you install alternate versions of the apps from Homebrew Cask. For example:<br />
* 3D Slicer ''Nightly''<br />
* Google Chrome ''Canary''<br />
<br />
<br />
== Steps to update Slicer cask (for maintainers) ==<br />
<br />
Adding an [https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/ SSH key] to GitHub and the KeyChain might be needed.<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Install cask-repair<br />
brew install vitorgalvao/tiny-scripts/cask-repair<br />
</pre><br />
<br />
=== Update ===<br />
This automatically creates a pull request in [https://github.com/caskroom/homebrew-versions/ homebrew-versions] to update the [https://github.com/caskroom/homebrew-versions/blob/master/Casks/slicer-nightly.rb <code>slicer-nightly</code> cask] (a Ruby script) with the new version.<br />
<pre><br />
cask-repair --cask-version 4.7.0.26273,676538 --fail-on-error --blind-submit slicer-nightly<br />
</pre><br />
<br />
<br />
== Steps to upgrade Slicer app (for users) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew + homebrew-cask<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Tell brew to look also in homebrew-versions<br />
brew tap caskroom/versions<br />
<br />
# Install Slicer.app (nightly)<br />
brew cask install slicer-nightly<br />
<br />
# Install cask-upgrade<br />
brew tap buo/cask-upgrade<br />
</pre><br />
<br />
=== Upgrade ===<br />
Download and install nightly version of Slicer.app:<br />
<pre><br />
brew cu slicer-nightly -y<br />
</pre></div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Labs/HomebrewCask&diff=54850Documentation/Labs/HomebrewCask2017-08-30T16:26:20Z<p>Fernando: </p>
<hr />
<div>This page was created based on the discussions [https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Add Slicer Nightly to Homebrew (macOS)] and [https://discourse.slicer.org/t/slicer-installation-on-mac-using-homebrew/ Slicer installation on Mac using homebrew]<br />
<br />
== Definitions ==<br />
<br />
=== Homebrew ===<br />
<br />
[https://brew.sh/ Homebrew] is "the missing package manager for macOS". It is designed for installing UNIX tools and other open-source applications. It will quickly download and install them, compiling them from source. Homebrew can install stuff like:<br />
* <code>vim</code><br />
* <code>ffmpeg</code><br />
* <code>python</code><br />
<br />
=== Homebrew Cask ===<br />
[https://caskroom.github.io/ Homebrew Cask] extends Homebrew with support for installing binary apps — the kind you normally drag to your Applications folder from DMG files. For example:<br />
* 3D Slicer<br />
* Google Chrome<br />
<br />
=== Homebrew Versions ===<br />
<br />
[https://github.com/caskroom/homebrew-versions Homebrew Versions] lets you install alternate versions of the apps from Homebrew Cask. For example:<br />
* 3D Slicer ''Nightly''<br />
* Google Chrome ''Canary''<br />
<br />
<br />
== Steps to update Slicer cask (for maintainers) ==<br />
<br />
Adding an [https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/ SSH key] to GitHub and the KeyChain might be needed.<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Install cask-repair<br />
brew install vitorgalvao/tiny-scripts/cask-repair<br />
</pre><br />
<br />
=== Update ===<br />
This automatically creates a pull request in [https://github.com/caskroom/homebrew-versions/ homebrew-versions] to update the [https://github.com/caskroom/homebrew-versions/blob/master/Casks/slicer-nightly.rb <code>slicer-nightly</code> cask] (a Ruby script) with the new version.<br />
<pre><br />
cask-repair --cask-version 4.7.0.26273,676538 --fail-on-error --blind-submit slicer-nightly<br />
</pre><br />
<br />
== Steps to upgrade Slicer app (for users) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew + homebrew-cask<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Tell brew to look also in homebrew-versions<br />
brew tap caskroom/versions<br />
<br />
# Install Slicer.app (nightly)<br />
brew cask install slicer-nightly<br />
<br />
# Install cask-upgrade<br />
brew tap buo/cask-upgrade<br />
</pre><br />
<br />
=== Upgrade ===<br />
Download and install nightly version of Slicer.app:<br />
<pre><br />
brew cu slicer-nightly -y<br />
</pre></div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Labs/HomebrewCask&diff=54539Documentation/Labs/HomebrewCask2017-08-23T23:19:49Z<p>Fernando: Add second discussion in Discourse.org</p>
<hr />
<div>This page was created based on the discussions [https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Add Slicer Nightly to Homebrew (macOS)] and [https://discourse.slicer.org/t/slicer-installation-on-mac-using-homebrew/ Slicer installation on Mac using homebrew]<br />
<br />
== Definitions ==<br />
<br />
=== Homebrew ===<br />
<br />
[https://brew.sh/ Homebrew] is "the missing package manager for macOS". It is designed for installing UNIX tools and other open-source applications. It will quickly download and install them, compiling them from source. Homebrew can install stuff like:<br />
* <code>vim</code><br />
* <code>ffmpeg</code><br />
* <code>python</code><br />
<br />
=== Homebrew Cask ===<br />
[https://caskroom.github.io/ Homebrew Cask] extends Homebrew with support for installing binary apps — the kind you normally drag to your Applications folder from DMG files. For example:<br />
* 3D Slicer<br />
* Google Chrome<br />
<br />
=== Homebrew Versions ===<br />
<br />
[https://github.com/caskroom/homebrew-versions Homebrew Versions] lets you install alternate versions of the apps from Homebrew Cask. For example:<br />
* 3D Slicer ''Nightly''<br />
* Google Chrome ''Canary''<br />
<br />
<br />
== Steps to update Slicer cask (for maintainers) ==<br />
<br />
Adding an [https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/ SSH key] to GitHub and the KeyChain might be needed.<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Install cask-repair<br />
brew install vitorgalvao/tiny-scripts/cask-repair<br />
</pre><br />
<br />
=== Update ===<br />
This automatically creates a pull request in [https://github.com/caskroom/homebrew-versions/ homebrew-versions] to update the [https://github.com/caskroom/homebrew-versions/blob/master/Casks/slicer-nightly.rb <code>slicer-nightly</code> cask] (a Ruby script) with the new version.<br />
<pre><br />
cask-repair --cask-version 4.7.0.26273,676538 --fail-on-error --blind-submit slicer-nightly<br />
</pre><br />
<br />
== Steps to upgrade Slicer app (for users) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew + homebrew-cask<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Tell brew to look also in homebrew-versions<br />
brew tap caskroom/versions<br />
<br />
# Install Slicer.app (nightly)<br />
brew cask install slicer-nightly<br />
<br />
# Install cask-upgrade<br />
brew tap buo/cask-upgrade<br />
</pre><br />
<br />
=== Upgrade ===<br />
Download and install nightly version of Slicer.app:<br />
<pre><br />
brew cu slicer-nightly<br />
</pre></div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Labs/HomebrewCask&diff=54500Documentation/Labs/HomebrewCask2017-08-19T00:02:39Z<p>Fernando: /* Steps to update Slicer cask (for maintainers) */</p>
<hr />
<div>This page was created based on the discussion [https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Add Slicer Nightly to Homebrew (macOS)]<br />
<br />
== Definitions ==<br />
<br />
=== Homebrew ===<br />
<br />
[https://brew.sh/ Homebrew] is "the missing package manager for macOS". It is designed for installing UNIX tools and other open-source applications. It will quickly download and install them, compiling them from source. Homebrew can install stuff like:<br />
* <code>vim</code><br />
* <code>ffmpeg</code><br />
* <code>python</code><br />
<br />
=== Homebrew Cask ===<br />
[https://caskroom.github.io/ Homebrew Cask] extends Homebrew with support for installing binary apps — the kind you normally drag to your Applications folder from DMG files. For example:<br />
* 3D Slicer<br />
* Google Chrome<br />
<br />
=== Homebrew Versions ===<br />
<br />
[https://github.com/caskroom/homebrew-versions Homebrew Versions] lets you install alternate versions of the apps from Homebrew Cask. For example:<br />
* 3D Slicer ''Nightly''<br />
* Google Chrome ''Canary''<br />
<br />
<br />
== Steps to update Slicer cask (for maintainers) ==<br />
<br />
Adding an [https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/ SSH key] to GitHub and the KeyChain might be needed.<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Install cask-repair<br />
brew install vitorgalvao/tiny-scripts/cask-repair<br />
</pre><br />
<br />
=== Update ===<br />
This automatically creates a pull request in [https://github.com/caskroom/homebrew-versions/ homebrew-versions] to update the [https://github.com/caskroom/homebrew-versions/blob/master/Casks/slicer-nightly.rb <code>slicer-nightly</code> cask] (a Ruby script) with the new version.<br />
<pre><br />
cask-repair --cask-version 4.7.0.26273,676538 --fail-on-error --blind-submit slicer-nightly<br />
</pre><br />
<br />
== Steps to upgrade Slicer app (for users) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew + homebrew-cask<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Tell brew to look also in homebrew-versions<br />
brew tap caskroom/versions<br />
<br />
# Install Slicer.app (nightly)<br />
brew cask install slicer-nightly<br />
<br />
# Install cask-upgrade<br />
brew tap buo/cask-upgrade<br />
</pre><br />
<br />
=== Upgrade ===<br />
Download and install nightly version of Slicer.app:<br />
<pre><br />
brew cu slicer-nightly<br />
</pre></div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Labs/HomebrewCask&diff=54497Documentation/Labs/HomebrewCask2017-08-19T00:01:02Z<p>Fernando: /* Steps to update Slicer cask (for maintainers) */</p>
<hr />
<div>This page was created based on the discussion [https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Add Slicer Nightly to Homebrew (macOS)]<br />
<br />
== Definitions ==<br />
<br />
=== Homebrew ===<br />
<br />
[https://brew.sh/ Homebrew] is "the missing package manager for macOS". It is designed for installing UNIX tools and other open-source applications. It will quickly download and install them, compiling them from source. Homebrew can install stuff like:<br />
* <code>vim</code><br />
* <code>ffmpeg</code><br />
* <code>python</code><br />
<br />
=== Homebrew Cask ===<br />
[https://caskroom.github.io/ Homebrew Cask] extends Homebrew with support for installing binary apps — the kind you normally drag to your Applications folder from DMG files. For example:<br />
* 3D Slicer<br />
* Google Chrome<br />
<br />
=== Homebrew Versions ===<br />
<br />
[https://github.com/caskroom/homebrew-versions Homebrew Versions] lets you install alternate versions of the apps from Homebrew Cask. For example:<br />
* 3D Slicer ''Nightly''<br />
* Google Chrome ''Canary''<br />
<br />
<br />
== Steps to update Slicer cask (for maintainers) ==<br />
<br />
Configure <code>git</code> and GitHub [https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/ SSH keys].<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Install cask-repair<br />
brew install vitorgalvao/tiny-scripts/cask-repair<br />
</pre><br />
<br />
=== Update ===<br />
This automatically creates a pull request in [https://github.com/caskroom/homebrew-versions/ homebrew-versions] to update the [https://github.com/caskroom/homebrew-versions/blob/master/Casks/slicer-nightly.rb <code>slicer-nightly</code> cask] (a Ruby script) with the new version.<br />
<pre><br />
cask-repair --cask-version 4.7.0.26273,676538 --fail-on-error --blind-submit slicer-nightly<br />
</pre><br />
<br />
== Steps to upgrade Slicer app (for users) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew + homebrew-cask<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Tell brew to look also in homebrew-versions<br />
brew tap caskroom/versions<br />
<br />
# Install Slicer.app (nightly)<br />
brew cask install slicer-nightly<br />
<br />
# Install cask-upgrade<br />
brew tap buo/cask-upgrade<br />
</pre><br />
<br />
=== Upgrade ===<br />
Download and install nightly version of Slicer.app:<br />
<pre><br />
brew cu slicer-nightly<br />
</pre></div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Labs/HomebrewCask&diff=54494Documentation/Labs/HomebrewCask2017-08-18T13:31:46Z<p>Fernando: </p>
<hr />
<div>This page was created based on the discussion [https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Add Slicer Nightly to Homebrew (macOS)]<br />
<br />
== Definitions ==<br />
<br />
=== Homebrew ===<br />
<br />
[https://brew.sh/ Homebrew] is "the missing package manager for macOS". It is designed for installing UNIX tools and other open-source applications. It will quickly download and install them, compiling them from source. Homebrew can install stuff like:<br />
* <code>vim</code><br />
* <code>ffmpeg</code><br />
* <code>python</code><br />
<br />
=== Homebrew Cask ===<br />
[https://caskroom.github.io/ Homebrew Cask] extends Homebrew with support for installing binary apps — the kind you normally drag to your Applications folder from DMG files. For example:<br />
* 3D Slicer<br />
* Google Chrome<br />
<br />
=== Homebrew Versions ===<br />
<br />
[https://github.com/caskroom/homebrew-versions Homebrew Versions] lets you install alternate versions of the apps from Homebrew Cask. For example:<br />
* 3D Slicer ''Nightly''<br />
* Google Chrome ''Canary''<br />
<br />
<br />
== Steps to update Slicer cask (for maintainers) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Install cask-repair<br />
brew install vitorgalvao/tiny-scripts/cask-repair<br />
</pre><br />
<br />
=== Update ===<br />
This automatically creates a pull request in [https://github.com/caskroom/homebrew-versions/ homebrew-versions] to update the [https://github.com/caskroom/homebrew-versions/blob/master/Casks/slicer-nightly.rb <code>slicer-nightly</code> cask] (a Ruby script) with the new version.<br />
<pre><br />
cask-repair --cask-version 4.7.0.26273,676538 --fail-on-error --blind-submit slicer-nightly<br />
</pre><br />
<br />
<br />
== Steps to upgrade Slicer app (for users) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew + homebrew-cask<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Tell brew to look also in homebrew-versions<br />
brew tap caskroom/versions<br />
<br />
# Install Slicer.app (nightly)<br />
brew cask install slicer-nightly<br />
<br />
# Install cask-upgrade<br />
brew tap buo/cask-upgrade<br />
</pre><br />
<br />
=== Upgrade ===<br />
Download and install nightly version of Slicer.app:<br />
<pre><br />
brew cu slicer-nightly<br />
</pre></div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Labs/HomebrewCask&diff=54491Documentation/Labs/HomebrewCask2017-08-18T13:08:05Z<p>Fernando: Fix setup scripts</p>
<hr />
<div>This page was created based on the discussion [https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Add Slicer Nightly to Homebrew (macOS)]<br />
<br />
== Definitions ==<br />
<br />
=== Homebrew ===<br />
<br />
[https://brew.sh/ Homebrew] is "the missing package manager for macOS". It is designed for installing UNIX tools and other open-source applications. It will quickly download and install them, compiling them from source. It can install stuff like:<br />
* <code>vim</code><br />
* <code>ffmpeg</code><br />
* <code>python</code><br />
<br />
=== Homebrew Cask ===<br />
[https://caskroom.github.io/ Homebrew Cask] extends Homebrew with support for installing binary apps — the kind you normally drag to your Applications folder from DMG files. For example:<br />
* 3D Slicer<br />
* Google Chrome<br />
<br />
=== Homebrew Versions ===<br />
<br />
[https://github.com/caskroom/homebrew-versions Homebrew Versions] lets you install alternate versions of the apps from Homebrew Cask. For example:<br />
* 3D Slicer ''Nightly''<br />
* Google Chrome ''Canary''<br />
<br />
<br />
== Steps to update Slicer cask (for maintainers) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Install cask-repair<br />
brew install vitorgalvao/tiny-scripts/cask-repair<br />
</pre><br />
<br />
=== Update ===<br />
This automatically creates a pull request in [https://github.com/caskroom/homebrew-versions/ homebrew-versions] to update the [https://github.com/caskroom/homebrew-versions/blob/master/Casks/slicer-nightly.rb <code>slicer-nightly</code> cask] (a Ruby script) with the new version.<br />
<pre><br />
cask-repair --cask-version 4.7.0.26273,676538 --fail-on-error --blind-submit slicer-nightly<br />
</pre><br />
<br />
<br />
== Steps to upgrade Slicer app (for users) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew + homebrew-cask<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Tell brew to look also in homebrew-versions<br />
brew tap caskroom/versions<br />
<br />
# Install Slicer.app (nightly)<br />
brew cask install slicer-nightly<br />
<br />
# Install cask-upgrade<br />
brew tap buo/cask-upgrade<br />
</pre><br />
<br />
=== Upgrade ===<br />
Download and install nightly version of Slicer.app:<br />
<pre><br />
brew cu slicer-nightly<br />
</pre></div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Labs/HomebrewCask&diff=54400Documentation/Labs/HomebrewCask2017-08-15T22:57:43Z<p>Fernando: </p>
<hr />
<div>This page was created based on the discussion [https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Add Slicer Nightly to Homebrew (macOS)]<br />
<br />
== Definitions ==<br />
<br />
=== Homebrew ===<br />
<br />
[https://brew.sh/ Homebrew] is "the missing package manager for macOS". It is designed for installing UNIX tools and other open-source applications. It will quickly download and install them, compiling them from source. It can install stuff like:<br />
* <code>vim</code><br />
* <code>ffmpeg</code><br />
* <code>python</code><br />
<br />
=== Homebrew Cask ===<br />
[https://caskroom.github.io/ Homebrew Cask] extends Homebrew with support for installing binary apps — the kind you normally drag to your Applications folder from DMG files. For example:<br />
* 3D Slicer<br />
* Google Chrome<br />
<br />
=== Homebrew Versions ===<br />
<br />
[https://github.com/caskroom/homebrew-versions Homebrew Versions] lets you install alternate versions of the apps from Homebrew Cask. For example:<br />
* 3D Slicer ''Nightly''<br />
* Google Chrome ''Canary''<br />
<br />
<br />
== Steps to update Slicer cask (for maintainers) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Install cask-upgrade<br />
brew tap buo/cask-upgrade<br />
</pre><br />
<br />
=== Update ===<br />
This automatically creates a pull request in [https://github.com/caskroom/homebrew-versions/ homebrew-versions] to update the [https://github.com/caskroom/homebrew-versions/blob/master/Casks/slicer-nightly.rb <code>slicer-nightly</code> cask] (a Ruby script) with the new version.<br />
<pre><br />
cask-repair --cask-version 4.7.0.26273,676538 --fail-on-error --blind-submit slicer-nightly<br />
</pre><br />
<br />
<br />
== Steps to upgrade Slicer app (for users) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew + homebrew-cask<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Tell brew to look also in homebrew-versions<br />
brew tap caskroom/versions<br />
<br />
# Install Slicer.app (nightly)<br />
brew cask install slicer-nightly<br />
</pre><br />
<br />
=== Upgrade ===<br />
Download and install nightly version of Slicer.app:<br />
<pre><br />
brew cask upgrade slicer-nightly<br />
</pre></div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Labs/HomebrewCask&diff=54397Documentation/Labs/HomebrewCask2017-08-15T22:57:09Z<p>Fernando: brew is updated by "brew cask upgrade"</p>
<hr />
<div>This page was created based on the discussion [https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Add Slicer Nightly to Homebrew (macOS)]<br />
<br />
== Definitions ==<br />
<br />
=== Homebrew ===<br />
<br />
[https://brew.sh/ Homebrew] is "the missing package manager for macOS". It is designed for installing UNIX tools and other open-source applications. It will quickly download and install them, compiling them from source. It can install stuff like:<br />
* <code>vim</code><br />
* <code>ffmpeg</code><br />
* <code>python</code><br />
<br />
=== Homebrew Cask ===<br />
[https://caskroom.github.io/ Homebrew Cask] extends Homebrew with support for installing binary apps — the kind you normally drag to your Applications folder from DMG files. For example:<br />
* 3D Slicer<br />
* Google Chrome<br />
<br />
=== Homebrew Versions ===<br />
<br />
[https://github.com/caskroom/homebrew-versions Homebrew Versions] lets you install alternate versions of the apps from Homebrew Cask. For example:<br />
* 3D Slicer ''Nightly''<br />
* Google Chrome ''Canary''<br />
<br />
<br />
== Steps to update Slicer cask (for maintainers) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Install cask-upgrade<br />
brew tap buo/cask-upgrade<br />
</pre><br />
<br />
=== Update ===<br />
This automatically creates a pull request in [https://github.com/caskroom/homebrew-versions/ homebrew-versions] to update the [https://github.com/caskroom/homebrew-versions/blob/master/Casks/slicer-nightly.rb <code>slicer-nightly</code> cask] (a Ruby script) with the new version.<br />
<pre><br />
cask-repair --cask-version 4.7.0.26273,676538 --fail-on-error --blind-submit slicer-nightly<br />
</pre><br />
<br />
<br />
== Steps to upgrade Slicer app (for users) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew + homebrew-cask<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Tell brew to look also in homebrew-versions<br />
brew tap caskroom/versions<br />
<br />
# Install Slicer.app (nightly)<br />
brew cask install slicer-nightly<br />
</pre><br />
<br />
=== Upgrade ===<br />
<pre><br />
# Download and install nightly version of Slicer.app<br />
brew cask upgrade slicer-nightly<br />
</pre></div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Labs/HomebrewCask&diff=54394Documentation/Labs/HomebrewCask2017-08-15T22:34:45Z<p>Fernando: Improve comments</p>
<hr />
<div>This page was created based on the discussion [https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Add Slicer Nightly to Homebrew (macOS)]<br />
<br />
== Definitions ==<br />
<br />
=== Homebrew ===<br />
<br />
[https://brew.sh/ Homebrew] is "the missing package manager for macOS". It is designed for installing UNIX tools and other open-source applications. It will quickly download and install them, compiling them from source. It can install stuff like:<br />
* <code>vim</code><br />
* <code>ffmpeg</code><br />
* <code>python</code><br />
<br />
=== Homebrew Cask ===<br />
[https://caskroom.github.io/ Homebrew Cask] extends Homebrew with support for installing binary apps — the kind you normally drag to your Applications folder from DMG files. For example:<br />
* 3D Slicer<br />
* Google Chrome<br />
<br />
=== Homebrew Versions ===<br />
<br />
[https://github.com/caskroom/homebrew-versions Homebrew Versions] lets you install alternate versions of the apps from Homebrew Cask. For example:<br />
* 3D Slicer ''Nightly''<br />
* Google Chrome ''Canary''<br />
<br />
<br />
== Steps to update Slicer cask (for maintainers) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Install cask-upgrade<br />
brew tap buo/cask-upgrade<br />
</pre><br />
<br />
=== Update ===<br />
This automatically creates a pull request in [https://github.com/caskroom/homebrew-versions/ homebrew-versions] to update the [https://github.com/caskroom/homebrew-versions/blob/master/Casks/slicer-nightly.rb <code>slicer-nightly</code> cask] (a Ruby script) with the new version.<br />
<pre><br />
cask-repair --cask-version 4.7.0.26273,676538 --fail-on-error --blind-submit slicer-nightly<br />
</pre><br />
<br />
<br />
== Steps to upgrade Slicer app (for users) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew + homebrew-cask<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Tell brew to look also in homebrew-versions<br />
brew tap caskroom/versions<br />
<br />
# Install Slicer.app (nightly)<br />
brew cask install slicer-nightly<br />
</pre><br />
<br />
=== Upgrade ===<br />
<pre><br />
# Update brew taps and formulae<br />
brew update<br />
<br />
# Download and install nightly version of Slicer.app<br />
brew cask upgrade slicer-nightly<br />
</pre></div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Labs/HomebrewCask&diff=54391Documentation/Labs/HomebrewCask2017-08-15T22:00:32Z<p>Fernando: Add steps to use Homebrew and Slicer</p>
<hr />
<div>This page was created based on the discussion [https://discourse.slicer.org/t/add-slicer-nightly-to-homebrew-macos/811 Add Slicer Nightly to Homebrew (macOS)]<br />
<br />
== Definitions ==<br />
<br />
=== Homebrew ===<br />
<br />
[https://brew.sh/ Homebrew] is "the missing package manager for macOS". It is designed for installing UNIX tools and other open-source applications. It will quickly download and install them, compiling them from source. It can install stuff like:<br />
* <code>vim</code><br />
* <code>ffmpeg</code><br />
* <code>python</code><br />
<br />
=== Homebrew Cask ===<br />
[https://caskroom.github.io/ Homebrew Cask] extends Homebrew with support for installing binary apps — the kind you normally drag to your Applications folder from DMG files. For example:<br />
* 3D Slicer<br />
* Google Chrome<br />
<br />
=== Homebrew Versions ===<br />
<br />
[https://github.com/caskroom/homebrew-versions Homebrew Versions] lets you install alternate versions of the apps from Homebrew Cask. For example:<br />
* 3D Slicer ''Nightly''<br />
* Google Chrome ''Canary''<br />
<br />
<br />
== Steps to update Slicer cask (for maintainers) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Install cask-upgrade<br />
brew tap buo/cask-upgrade<br />
</pre><br />
<br />
=== Update ===<br />
This automatically creates a pull request in [https://github.com/caskroom/homebrew-versions/ homebrew-versions] to update the [https://github.com/caskroom/homebrew-versions/blob/master/Casks/slicer-nightly.rb <code>slicer-nightly</code> cask] (a Ruby script) with the new version.<br />
<pre><br />
cask-repair --cask-version 4.7.0.26273,676538 --fail-on-error --blind-submit slicer-nightly<br />
</pre><br />
<br />
<br />
== Steps to upgrade Slicer app (for users) ==<br />
<br />
=== Setup ===<br />
<pre><br />
# Install homebrew + homebrew-cask<br />
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
<br />
# Install homebrew-versions<br />
brew tap caskroom/versions<br />
<br />
# Install slicer-nightly<br />
brew cask install slicer-nightly<br />
</pre><br />
<br />
=== Upgrade ===<br />
<pre><br />
# Update brew taps and formulae<br />
brew update<br />
<br />
# Download and install nightly version<br />
brew cask upgrade slicer-nightly<br />
</pre></div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/Build_Instructions&diff=49950Documentation/Nightly/Developers/Build Instructions2017-02-23T10:59:27Z<p>Fernando: Add 'error: Missing Qt module QTWEBKIT' to Common errors</p>
<hr />
<div><noinclude>{{documentation/versioncheck}}</noinclude><br />
{{:{{FULLPAGENAME}}/Prerequisites}}<br />
<br />
<br><br><br><br><br />
<br />
{{:{{FULLPAGENAME}}/CheckoutSourceCode}}<br />
<br />
<br><br><br><br><br />
<br />
{{:{{FULLPAGENAME}}/Configure}}<br />
<br />
<br><br><br><br><br />
<br />
{{:{{FULLPAGENAME}}/Compile}}<br />
<br />
<br><br><br><br><br />
<br />
{{:{{FULLPAGENAME}}/Run}}<br />
<br />
<br><br><br><br><br />
<br />
{{:{{FULLPAGENAME}}/Test}}<br />
<br />
<br><br><br><br><br />
<br />
{{:{{FULLPAGENAME}}/Package}}<br />
<br />
<!--<br />
== DEBUG Slicer ==<br />
<br />
To be able to debug Slicer application, you are expected to build it with Debug symbols in a clean directory.<br />
<br />
{|width = "100%"<br />
! width="50%" style="border-bottom: 1px solid darkgrey;font-size: 75%;"| Linux or MacOSX<br />
! width="50%" style="border-bottom: 1px solid darkgrey;font-size: 75%;"| Windows (Visual Studio)<br />
|-<br />
| valign="top" |<br />
Configure Slicer using <code>-DCMAKE_BUILD_TYPE:STRING=Debug</code><br />
| valign="top" |<br />
Selecting <code>Debug</code> configuration in Visual Studio.<br />
|}<br />
<br />
{|width = "100%"<br />
! width="50%" style="border-bottom: 1px solid darkgrey;font-size: 75%;"| Linux or MacOSX<br />
! width="50%" style="border-bottom: 1px solid darkgrey;font-size: 75%;"| Windows (Visual Studio)<br />
|-<br />
| valign="top" |<br />
<br><br />
{{wip}} TBD<br />
<br><br />
| valign="top" |<br />
<ol start="1" style="list-style-type: decimal;"><br />
<li>Press "Win-R," type "cmd" and press "Enter" to open a Command Prompt session.</li><br />
<li><br />
<p>Start Visual Studio with Slicer environment:</p><br />
<pre>&gt; cd \path\to\Slicer-SuperBuild\Slicer-build<br />
&gt; Slicer.exe --VisualStudio Slicer.sln</pre><br />
</li><br />
</ol><br />
|}<br />
<br />
<br><br><br><br><br />
--><br />
<br />
== Common errors ==<br />
<br />
=== CMake complains during configuration ===<br />
CMake may not directly show what's wrong; try to look for log files of the form BUILD/CMakeFiles/*.log (where BUILD is your build directory) to glean further information.<br />
<br />
=== A tool returned an error code from "Generating vtksysProcessFwd9xEnc.c" ===<br />
The application has failed to start because its side-by-side configuration is incorrect.<br />
Please see the application event log or use the command-line sxstrace.exe tool for more detail.<br />
Project : error PRJ0019: A tool returned an error code from "Generating<br />
vtksysProcessFwd9xEnc.c"<br />
'''Suggested solution: [[Documentation/{{documentation/version}}/Developers/Build_Instructions/Prerequisites#Windows|Install SP1 of Visual Studio]]'''<br />
<br />
See also:<br />
<br />
* [http://www.kitware.com/blog/home/post/4|"Deploying on Windows with DLL Manifest Issues"] (Bill Hoffman, Kitware blog).<br />
* [https://stackoverflow.com/questions/13217174/how-to-properly-setup-vs2008-for-x64-programing/13222870#13222870| How to create a custom installer to correct a missing WinSXS manifest entry] (StackOverflow).<br />
<br />
=== error: ‘class QList<QString>’ has no member named ‘reserve’ ===<br />
/nfs/Users/blowekamp/QtSDK/Desktop/Qt/474/gcc/include/QtCore/qdatastream.h: In function ‘QDataStream& operator>>(QDataStream&, QList<T>&) [with T = QString]’:<br />
/nfs/Users/blowekamp/QtSDK/Desktop/Qt/474/gcc/include/QtCore/qstringlist.h:247: instantiated from here<br />
/nfs/Users/blowekamp/QtSDK/Desktop/Qt/474/gcc/include/QtCore/qdatastream.h:246: error: ‘class QList<QString>’ has no member named ‘reserve’<br />
You have multiple Qt versions installed on your machine. Try removing the Qt version installed on the system.<br />
<br />
=== libarchive.so: undefined reference to `SHA256_Update' ===<br />
<br />
Linking CXX executable ../../../../../bin/MRMLLogicCxxTests<br />
/home/benjaminlong/work/slicer/Slicer-SuperBuild-Debug/LibArchive-install/lib/libarchive.so: undefined reference to `SHA256_Update'<br />
/home/benjaminlong/work/slicer/Slicer-SuperBuild-Debug/LibArchive-install/lib/libarchive.so: undefined reference to `SHA256_Final'<br />
/home/benjaminlong/work/slicer/Slicer-SuperBuild-Debug/LibArchive-install/lib/libarchive.so: undefined reference to `SHA256_Init'<br />
/home/benjaminlong/work/slicer/Slicer-SuperBuild-Debug/LibArchive-install/lib/libarchive.so: undefined reference to `MD5_Init'<br />
<br />
Solution:<br />
cd Slicer-SuperBuild<br />
rm -rf LibArchive-*<br />
make -j4<br />
<br />
Details:<br />
* http://na-mic.org/Mantis/view.php?id=1616<br />
* http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&revision=18923<br />
* http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&revision=18969<br />
<br />
=== No rule to make target `/usr/lib/x86_64-linux-gnu/libGL.so' ===<br />
See http://techtidings.blogspot.com/2012/01/problem-with-libglso-on-64-bit-ubuntu.html<br />
<br />
=== X11 Window errors at start time ===<br />
<pre><br />
X Error: BadWindow (invalid Window parameter) 3<br />
Extension: 137 (Uknown extension)<br />
Minor opcode: 4 (Unknown request)<br />
Resource id: 0x4200199<br />
X Error: BadWindow (invalid Window parameter) 3<br />
Extension: 137 (Uknown extension)<br />
Minor opcode: 4 (Unknown request)<br />
Resource id: 0x42001a6<br />
X Error: BadWindow (invalid Window parameter) 3<br />
Extension: 137 (Uknown extension)<br />
Minor opcode: 4 (Unknown request)<br />
Resource id: 0x42001b3<br />
</pre><br />
<br />
Solution: <br />
* Reinstall Nvidia drivers (that also rewrite the xorg.conf file).<br />
<br />
=== error C2061: syntax error : identifier 'ssize_t' ===<br />
<pre><br />
4>1>Compiling...<br />
4>1>version.c<br />
4>1>c:\chene\winbin64\slicer4\cmcurl\urldata.h(585) : error C2061: syntax error : identifier 'ssize_t'<br />
4>1>c:\chene\winbin64\slicer4\cmcurl\urldata.h(593) : error C2365: 'fread' : redefinition; previous definition was 'function'<br />
4>1> C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\stdio.h(248) : see declaration of 'fread'<br />
4>1>c:\chene\winbin64\slicer4\cmcurl\urldata.h(610) : error C2059: syntax error : '}'<br />
</pre><br />
<br />
Solution:<br />
* See [[#A_tool_returned_an_error_code_from_.22Performing_configure_step_for_....22]]<br />
<br />
=== ld: framework not found QtWebKit ===<br />
<br />
<pre><br />
[...]<br />
Linking CXX shared library libPythonQt.dylib<br />
ld: framework not found QtWebKit<br />
clang: error: linker command failed with exit code 1 (use -v to see invocation)<br />
make[8]: *** [libPythonQt.dylib] Error 1<br />
[...]<br />
</pre><br />
<br />
See Slicer issue [http://na-mic.org/Mantis/view.php?id=2860 #2860]<br />
<br />
Workaround:<br />
* See http://public.kitware.com/Bug/view.php?id=13765#c31824<br />
<br />
Solution:<br />
* Use a [http://www.cmake.org/files/dev/?C=M;O=D recent nightly build of CMake]. It includes patch [http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cc676c3a cc676c3a]. Note also that the coming version of CMake 2.8.11 will work as expected.<br />
<br />
=== On MacOSX 10.8, CMake hangs forever ===<br />
<br />
Issue: http://www.na-mic.org/Bug/view.php?id=2957<br />
<br />
Solution: Use CMake build >= 2.8.10.20130220-g53b279. See http://www.cmake.org/files/dev/cmake-2.8.10.20130220-g53b279-Darwin-universal.tar.gz<br />
<br />
Details:<br />
<br />
CMake folks (Thanks Brad King :)) fixed an issue that was preventing the most recent nightly from being used to successfully compile Slicer. The fix has been tested and is known to work. Tomorrow nightly build of CMake and by extension the coming release of CMake 2.8.11 will work.<br />
<br />
If you are curious about the details, check the commit message:<br />
<br />
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1df09e57 [^]<br />
<br />
The associated CMake test have also been updated: <br />
<br />
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bff3d9ce [^]<br />
<br />
<br><br><br />
<br />
=== On MacOSX 10.8/10.9 with XQuartz, 'X11/Xlib.h' file not found ===<br />
<br />
Issue: http://www.na-mic.org/Bug/view.php?id=3405<br />
<br />
Workaround: Build with -DSlicer_USE_PYTHONQT_WITH_TCL:BOOL=OFF<br />
<br />
Tcl is required only for EMSegment module.<br />
<br />
Details: See http://www.na-mic.org/Bug/view.php?id=3405<br />
<br><br><br />
<br />
=== svn: E175002: Unable to connect to a repository at URL XXX ===<br />
<br />
Issue: Cisco AnyConnect is installed with the "Web Security" option checked (default), which blocks Subversion checkouts even when inactive!<br />
<br />
Solution: Uninstall and reinstall Cisco AnyConnect, deselecting the "Web Security" feature during install<br />
<br />
[[File:CiscoAnyConnectInstallOptions.png]]<br />
<br />
=== My antivirus software reports that files in my build directory are infected ===<br />
<br />
Although usually antivirus software does not interfere with the build process, it is recommended to disable antivirus and search indexing for build directories to improve performance and minimize the chance of concurrent file access problems.<br />
<br />
=== Visual Studio compiler crashes ===<br />
<br />
* If you use Visual Studio 2008, make sure Visual Studio 2008 service pack 1 is installed<br />
* Build Slicer in a short directory, for example source code in C:\S4, binary directory C:\S4D or C:\S4R<br />
<br />
=== 'QSslSocket' : is not a class or namespace name ===<br />
<br />
This error message occurs if Slicer is configured to use SSL but Qt is built without SSL support.<br />
<br />
Either set Slicer_USE_PYTHONQT_WITH_OPENSSL to OFF when configuring Slicer build in CMake, or build Qt with SSL support.<br />
<br />
=== error: Missing Qt module QTWEBKIT ===<br />
<br />
CMake Error at CMake/SlicerBlockFindQtAndCheckVersion.cmake:43 (message):<br />
error: Missing Qt module QTWEBKIT<br />
Call Stack (most recent call first):<br />
CMake/SlicerBlockFindQtAndCheckVersion.cmake:88 (__SlicerBlockFindQtAndCheckVersion_find_qt)<br />
CMakeLists.txt:607 (include)<br />
<br />
Solution:<br />
sudo apt-get -y install libqtwebkit-dev<br />
<br />
Details:<br />
* http://slicer-devel.65872.n3.nabble.com/Re-slicer-devel-Digest-Vol-143-Issue-39-td4037122.html<br />
<br />
<br />
== Quick Build on Debian ==<br />
sudo aptitude update<br />
sudo aptitude install subversion git gcc g++ make cmake-curses-gui libqt4-dev<br />
svn co http://svn.slicer.org/Slicer4/trunk Slicer<br />
mkdir Slicer-SuperBuild-Debug<br />
cd Slicer-SuperBuild-Debug<br />
cmake ../Slicer<br />
make -j5<br />
<br />
# runtime dependency:<br />
sudo aptitude install python-tk<br />
<br />
<br />
== Quick Build on Fedora 20 ==<br />
<br />
Thanks to Bill Lorensen, you will find below the instruction to quickly build Slicer on Fedora 20:<br />
<br />
yum groupinstall "C Development Tools"<br />
yum install git-core<br />
yum install svn<br />
yum install libX11-devel<br />
yum install libXt-devel<br />
yum install mesa-libGL-devel<br />
yum install mesa-libGLU-devel<br />
yum install cmake<br />
yum install tcl-devel<br />
yum install python-devel<br />
yum install qt-devel<br />
yum install qt-webkit-devel<br />
<br />
svn co http://svn.slicer.org/Slicer4/trunk Slicer<br />
mkdir Slicer-SuperBuild-Debug<br />
cd Slicer-SuperBuild-Debug<br />
cmake ../Slicer<br />
make -j5<br />
<br />
Reference: http://slicer-devel.65872.n3.nabble.com/Fedora-20-Slicer-Experience-tt4030845.html</div>Fernandohttps://www.slicer.org/w/index.php?title=Documentation/Nightly/Developers/Charts&diff=48313Documentation/Nightly/Developers/Charts2016-11-14T08:53:44Z<p>Fernando: Completed some missing array properties with the info from the docs</p>
<hr />
<div><noinclude>{{documentation/versioncheck}}</noinclude><br />
<gallery widths=400px heights=225px><br />
Image:SlicerRT-0.2 screenshot.png|Charting in radiation therapy.<br />
Image:3D Slicer 4.0.1.2012-02-03 180.png|Charting regional statistics. <br />
</gallery><br />
{{Clear|right}}{{TOC right}}<br />
<br />
= Slicer Charting Overview = <br />
Slicer provides Charting facilities that include a special Chart View that can be packed in the layout, similar to the Slice Views and 3D Views. The architecture also includes nodes that represent the data to be displayed in the chart as well as nodes to represent the display properties of the data and the chart itself. Charts can be serialized with the MRML scene, including the chart data and display properties.<br />
<br />
= Chart capabilities =<br />
* Charts are represented in the MRML scene<br />
* Charts can be serialized with the MRML scene<br />
* Multiple Chart Views can be in a layout<br />
* Each Chart View can display any Chart in the MRML scene<br />
* Each Chart can display multiple Arrays of data<br />
* Chart Views can [[#Signals|emit signals]] back to the application as the user interacts with a Chart<br />
* Multiple chart types (Line, Bar, Scatter)<br />
* Data can be quantitative or categorical<br />
* Zooming using the mouse<br />
* Highlighting data points under the mouse<br />
* Axis labels<br />
* Legends<br />
* Color tables can be used to define the cycle of colors assigned to arrays in a chart<br />
* Colors can be assigned individually to each Array in a Chart<br />
* [[#Bar charts with categorical data | Bar charts with categorical data]] can use a color table to define colors and labels for each data point in the chart.<br />
<br />
=Architecture=<br />
== Chart View == <br />
<br />
; [{{doxygen-class-url|qMRMLChartWidget}} qMRMLChartWidget]<br />
: The toplevel charting widget that is packed in layout. Subclass of qMRMLWidget. Contains a qMRMLChartView and a qMRMLChartViewControllerWidget. There can be several Chart Widgets in a single layout.<br />
; [{{doxygen-class-url|qMRMLChartView}} qMRMLChartView]<br />
: Display canvas of the chart. This is currently a subclass of QWebView as the charting facilities is based on a [http://jquery.com jQuery] library called [http://www.jqplot.com jqPlot].<br />
; [{{doxygen-class-url|qMRMLChartViewControllerWidget}} qMRMLChartViewControllerWidget]<br />
: Widget to control the content and display of a chart.<br />
<br />
== MRML Nodes ==<br />
; [{{doxygen-class-url|vtkMRMLChartViewNode}} vtkMRMLChartViewNode]<br />
: Node associated with a Chart View. Keeps track of which chart to display in a Chart View. There can be multiple charts in a scene and a given Chart View can display any of the charts.<br />
; [{{doxygen-class-url|vtkMRMLChartNode}} vtkMRMLChartNode]<br />
: Represents the content and properties of a chart. Manages a list of Array Nodes to display in the chart. Provides methods to set the properties of a chart or the properties of each Array Node. <br />
; [{{doxygen-class-url|vtkMRMLDoubleArrayNode}} vtkMRMLDoubleArrayNode]<br />
: Represents the data that can be displayed in a chart. Array nodes contain a series of 3-tuples representing the (X, Y, Error) measurement values.<br />
<br />
= Constructing a chart = <br />
Below is an example in python to construct and display a chart communicating completely at the level of MRML.<br />
<pre lang="python"><br />
import slicer<br />
import math<br />
<br />
# Switch to a layout (24) that contains a Chart View to initiate the construction of the widget and Chart View Node<br />
lns = slicer.mrmlScene.GetNodesByClass('vtkMRMLLayoutNode')<br />
lns.InitTraversal()<br />
ln = lns.GetNextItemAsObject()<br />
ln.SetViewArrangement(24)<br />
<br />
# Get the Chart View Node<br />
cvns = slicer.mrmlScene.GetNodesByClass('vtkMRMLChartViewNode')<br />
cvns.InitTraversal()<br />
cvn = cvns.GetNextItemAsObject()<br />
<br />
# Create an Array Node and add some data<br />
dn = slicer.mrmlScene.AddNode(slicer.vtkMRMLDoubleArrayNode())<br />
a = dn.GetArray()<br />
a.SetNumberOfTuples(600)<br />
x = range(0, 600)<br />
for i in range(len(x)):<br />
a.SetComponent(i, 0, x[i]/50.0)<br />
a.SetComponent(i, 1, math.sin(x[i]/50.0))<br />
a.SetComponent(i, 2, 0)<br />
<br />
# Create a second Array node<br />
dn2 = slicer.mrmlScene.AddNode(slicer.vtkMRMLDoubleArrayNode())<br />
a = dn2.GetArray()<br />
a.SetNumberOfTuples(600)<br />
x = range(0, 600)<br />
for i in range(len(x)):<br />
a.SetComponent(i, 0, x[i]/50.0)<br />
a.SetComponent(i, 1, math.cos(x[i]/50.0))<br />
a.SetComponent(i, 2, 0)<br />
<br />
# Create a Chart Node.<br />
cn = slicer.mrmlScene.AddNode(slicer.vtkMRMLChartNode())<br />
<br />
# Add the Array Nodes to the Chart. The first argument is a string used for the legend and to refer to the Array when setting properties.<br />
cn.AddArray('A double array', dn.GetID())<br />
cn.AddArray('Another double array', dn2.GetID())<br />
<br />
# Set a few properties on the Chart. The first argument is a string identifying which Array to assign the property. <br />
# 'default' is used to assign a property to the Chart itself (as opposed to an Array Node).<br />
cn.SetProperty('default', 'title', 'A simple chart with 2 curves')<br />
cn.SetProperty('default', 'xAxisLabel', 'Something in x')<br />
cn.SetProperty('default', 'yAxisLabel', 'Something in y')<br />
<br />
# Tell the Chart View which Chart to display<br />
cvn.SetChartNodeID(cn.GetID())<br />
</pre><br />
<br />
This code produces the chart below.<br />
<br />
[[Image:SimpleChartExamplePython.png|A simple chart.|600px]]<br />
<br />
= Properties =<br />
Properties can be assigned to a Chart or to a specific Array in the Chart. The API for setting a property on a Chart Node is<br />
void SetProperty(const char *arrname, const char *property, const char *value);<br />
The first argument is a string for the name of the Array to apply the property. This name was established when the array was added to the Chart using the <tt>AddArray(name, array)</tt> method. The array name <tt>'default'</tt> is used to specify (1) properties that apply to the Chart and not to an Array, and (2) to establish a default setting for a property for all Arrays. Default properties assigned to Arrays can be overridden by properties assigned to a specific array.<br />
<br />
==Chart level properties==<br />
;type: Line, Bar, Scatter<br />
;title: title displayed on the chart<br />
;showTitle: show title "on" or "off"<br />
;xAxisLabel: label displayed on the x-axis<br />
;showXAxisLabel: show x-axis label "on" or "off"<br />
;xAxisType: type of data on x-axis, "quantitative", "categorical", "date"<br />
;yAxisLabel: label displayed on the y-axis<br />
;showYAxisLabel: show y-axis label "on" or "off"<br />
;yAxisType: type of data on y-axis, "quantitative", "categorical", "date"<br />
;showGrid: show grid "on" or "off"<br />
;showLegend: show legend "on" or "off"<br />
;lookupTable: MRMLID of a ColorNode to use to color series<br />
<br />
==Array level properties==<br />
Array level properties (can be assigned to "default" to apply to entire chart.<br />
;showLines: show lines "on" or "off"<br />
;showMarkers: show markers "on" or "off"<br />
;color: color to use for the array lines and points (#RRGGBB)<br />
;lookupTable: MRMLID of a ColorNode to use to color individual bars in bar chart (useful with categorical data)<br />
;size: size of the markers for the scatter plot represented by an integer<br />
;linePattern: can be "solid", "dashed", "dotted", "dashed-dotted"<br />
;lineWidth: line width represented by an integer<br />
<br />
= Signals =<br />
Chart Views provide signals that allow Slicer to respond to user interactions with the Chart canvas.<br />
<br />
;void dataMouseOver(const char *mrmlArrayID, int pointidx, double x, double y)<br />
:Signal emitted when the mouse moves over a data point. Returns the id of the MRMLDoubleArrayNode, the index of the point, and the values.<br />
; void dataPointClicked(const char *mrmlArrayID, int pointidx, double x, double y)<br />
:Signal emitted when a data point has been clicked. Returns the id of the MRMLDoubleArrayNode, the index of the point, and the values.<br />
<br />
= Bar charts with categorical data =<br />
When the x-axis data in an Array is categorical, for example when the Array represents the average intensity of an image region under specific labels in a label map, a bar chart of the Array can extract information automatically from a color table assigned as a property of the Array in the Chart. Here, the Charting will interpret the x-axis values in the Array as "labels" and cross-reference the "labels" in the color table to extract the label as well as the color assigned to each bar in the chart.<br />
<br />
<pre><br />
chartNode.SetProperty('default', 'type', 'Bar')<br />
chartNode.SetProperty('default', 'xAxisType', 'categorical')<br />
chartNode.SetProperty('My Array', 'lookupTable', colorNodeID)<br />
</pre> <br />
<br />
[[Image:BarChartWithCategoricalData.png|400px|Bar chart with categorical data]]<br />
<br />
Currently, this capability is not provided for line charts.<br />
<br />
= Under the hood =<br />
The architecture of the Charting is divided into two layers. The first layer is the public layer available to Slicer developers consisting of the MRML nodes and associated Widgets. This layer can be used by module writers to construct charts and orchestrate their display. The second layer is the rendering architecture for the Chart. The rendering of Chart utilizes a [http://jquery.com jQuery] library called [http://www.jqplot.com jqPlot] to generate a plot. The Chart View is actually a QWebView Widget that displays a web page that is generated on the fly by Slicer to display a Chart.<br />
<br />
The method qMRMLChartViewPrivate::updateWidgetFromMRML() generates the HTML and javascript to display a Chart, passes the generated code to the QWebView, calls the QWebView::show() method, and then exposes a Qt object to the javascript layer to support signals and slots. The HTML and javascript generation includes<br />
* HTML page header, css, javascript<br />
* Div element to hold the chart<br />
* Script element for the chart<br />
* Conversion of the Array nodes to javascript arrays suitable for jqPlot<br />
* Construction of the jqPlot options from the Chart properties<br />
* Call to jqPlot to generate the plot<br />
* Slots and hooks for resizing the Chart and handling the mouse over and data point click signals<br />
* HTML page postscript, additional javascript references<br />
<br />
==Resources==<br />
jqPlot is package into the Slicer executable as Qt Resources. The generated HTML pages reference the javascript and css files from the Qt Resource, not from a web server. Only the jqPlot and jQuery javascript and css files needed to implement the current features are embedded as Qt Resources. If additional jqPlot or jQuery features are needed in the future (for instance, different jqPlot renderers), the associated javascript and css files will need to be added to the Qt Resources. See [http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Libs/MRML/Widgets/Resources/jqPlot.qrc.in?view=markup jqPlot.qrc.in].<br />
<br />
==Build process==<br />
jqPlot is downloaded and installed locally in the Slicer build tree as part of the SuperBuild process.<br />
<br />
= To do = <br />
* Refactor the generation of the javascript representation of the chart to allow data to be modified without recreating the page.<br />
* Line styles<br />
* Add more signals<br />
* Write a bar chart renderer, improving the layout.<br />
* Add error bars<br />
* Add tags to Array nodes specify a "label" which will allow line plots to be automatically colored based on a color table. Similar to how bar charts can automatically color the bars in a plot when the x-axis data is categorical.<br />
* Presentation quality printing</div>Fernando