See also: Controlling SBA Composer from a Jupyter notebook
If you are a website builder or Jupyter notebook developer, you can use SBA Composer as a front end to display data in a secure and private way. The mechanism for this is that you open SBA Composer in a new tab from within your web application. This instance of SBA Composer will be listening for incoming messages. Your website can send a command with data to display, and SBA Composer will carry it out. The data-exchange mechanism is such that no data gets sent to the SBA Composer server; all communication takes place in the browser on the client's computer. Therefore, the method is safe to use for privacy-sensitive data.
Impatient? skip the tutorial example
Five types of commands are currently supported:
Composer.scatter3d
for plotting a set of markers at specified brain-coordinates.Composer.import
for importing a data file into SBA Composer. In principle, any file that you can load manually with
the "Import file from my computer" button can be displayed in this way.Composer.scene
for displaying a set of brain region models with specified colors and transparenciesComposer.message
for displaying a simple message.Plotly.plot
for plotting interactive plots using the plotly.js library.These commands can also be combined into a recursive structure.
Commands to SBA Composer are sent according to the json-rpc 2.0 protocol.
This means that each command message is a JSON structure with fields id
(message-id), method
(one of the supported commands), params
(command parameters), and that SBA Composer responds with a JSON structure that specifies the result
or error
.
In this tutorial we give examples on how to use each of the above commands.
The first step for each example is to open SBA Composer in a new window/tab. Managing multiple tabs is tricky, and we provide a library sba-interface.js that takes care of the details:
You can clone the library or use it as it is:
<script type="text/javascript" src="https://scalablebrainatlas.incf.org/js/sba-interface.js"></script>
In the examples, we create a button with an onclick field that calls the function onclickHandler
.
This function needs just two lines of code to invoke SBA Composer:
var sbaInterface;
function onclickHandler() {
// define sbaUrl here, it contains the address of the SBA Composer page that you want to load,
// such as `https://scalablebrainatlas.incf.org/composer-dev/?template=ABA_v3`
(...)
// reuse sbaInterface if it exists
sbaInterface = sbaInterface || new sbaInterface_class(sbaUrl);
// define sbaCommand here
(...)
sbaInterface.send(sbaCommand);
}
Calling new sbaInterface_class(sbaUrl)
opens a new SBA Composer window. Under some circumstances, this may trigger the browser's popup blocker.
This is not a problem. As soon as you use sbaInterface.send(...)
, the user will be prompted to re-open SBA Composer,
and this time the popup blocker will not kick in since the opening of the new window is a direct consequence of user interaction.
To bypass the popup blocker completely, make sure to place new sbaInterface_class
inside an event handler that responds to a mouse click or key press.
Once sbaInterface has been created, keep it in memory so that it can be used to send multiple messages to SBA Composer.
Composer.scatter3d
commandThe arguments that come with this command are:
style
, to set for example the default marker size in the same units as the data.bas
, to specify the Brain Addressing System settings for the data. If omitted, all coordinates must exactly match the coordinate system of the selected atlas template.markers
, the list of markers, each with a coord
and (optional) value
field.The following object defines eight markers that form a cube:
const sbaCommand = {
"method":"Composer.scatter3d",
"params": {
"style": {
"marker": {
"size": 0.2
}
},
"markers":[{
"coord":[-1,-1,-1]
},{
"coord":[1,-1,-1]
},{
"coord":[-1,1,-1]
},{
"coord":[1,1,-1]
},{
"coord":[-1,-1,1]
},{
"coord":[1,-1,1]
},{
"coord":[-1,1,1]
},{
"coord":[1,1,1]
}]
}
};
Try it yourself: scatter3d example
The website http://yourdomain.org wants to control SBA Composer. OK?
This is a security measure, to prevent rogue websites from using SBA Composer
to display inappropriate content. To get rid of this dialogue, apply by email
to feedback@scalablebrainatlas.org
to have your site added to the list of trusted domains.
Composer.import
commandThe arguments that come with this command are:
name
: the name of the imported file.mime
: the mime-type of the imported file.contents
: the contents of the imported file.If you leave out the mime
field, the mime type is detected from the (file)name extension.
Let's consider a simple file of the type 'X3D', defining a three-dimensional cube.
The contents of this file are:
<X3D profile="Interchange" version="3.3" xmlns:xsd="http://www.web3d.org/specifications/x3d-3.3.xsd">
<Scene>
<Shape>
<Appearance><Material diffuseColor="#FF0000"></Material></Appearance>
<Box></Box>
</Shape>
</Scene>
</X3D>
Let's first assume that your website already retrieved the file,
and that it stored the file contents in a string named x3dFileContents
.
The command to display the file is:
const sbaCommand = {
"method": "Composer.import",
"params": {
"name": "A red cube",
"mime": "model/x3d+xml",
"contents": x3dFileContents
}
}
Try it yourself: import x3d content example
For binary files, the contents should be passed as an ArrayBuffer,
which can be obtained directly from an XMLHttpRequest
by setting its
responseType
field to arraybuffer
:
// create the sbaInterface first to counter the browser's popup-blocker
const sbaUrl = '/composer/?template=ABA_v3';
const sbaInterface = new sbaInterface_class(sbaUrl);
const binaryFileUrl = 'http://yourdomain.org/binaryfile.nii.gz';
const request = new XMLHttpRequest();
request.open("GET", binaryFileUrl, true);
request.responseType = 'arraybuffer';
request.onreadystatechange = function() {
if (request.readyState == 4) {
const fileContents = request.response;
const sbaCommand = {
"method": "Composer.import",
"params": {
"name": binaryFileUrl,
"mime": "image/nii+gzip",
"contents": fileContents
}
}
sbaInterface.send(sbaCommand);
}
}
request.send(null);
Try it yourself: import binary content example
The code for importing a file by URL, as shown above, is already included in the sbaInterface library.
It is invoked when you send a Composer.import command, and replace the contents
field by a url
field.
So the code can be simplified to
const sbaUrl = '/composer/?template=ABA_v3';
const sbaInterface = new sbaInterface_class(sbaUrl);
const sbaCommand = {
"method": "Composer.import",
"params": {
"name": binaryFileUrl,
"mime": "image/nii+gzip",
"url": 'http://yourdomain.org/binaryfile.nii.gz'
}
}
sbaInterface.send(sbaCommand);
Try it yourself: import by URL example
Note that not all file types can be imported in this way yet, supported are x3d, nifti, nrrd, mgh, json;
Support for 2d images, QuickNii, meta-image and minc-2 is under way.
Composer.scene
commandThe arguments that come with this command are:
name
: the name of the scene.regions
: a key-value list of brain regions to be displayed, with the brain region acronyms as keys, and the values being either
colormap
: a list of (color,value) pairs, whereby value must increase from left to right. The colors must be hexadecimal rgb strings. This map is used to lookup colors for a given value by linear interpolation of the nearest color-value pairs.background
: hexadecimal rgb string to set the background color of the scene.The command to show colored regions is:
sbaCommand = {
"method":"Composer.scene",
"params" : {
"name": "somatosensory areas",
"regions":{
"SSp":["#FFFF00",1],
"SSs":["#FF0000",1]
}
}
}
The following command maps region values to colors with a colormap that goes from black via blue and green to white:
sbaCommand = {
"method": "Composer.scene",
"params": {
"name": "somatosensory areas",
"regions": {
"SSp":0.1,
"SSs":2.7,
"MOp":1.5
},
"colormap":[["000000",0], ["000088",0.1], ["00FF00",1.6], ["FFFFFF",3.0]]
}
}
Try it yourself: compose a scene example
Composer.message
commandGiven its simplicity, we go straight to the example code:
var messageObject = {
"method": "Composer.message",
"params": {
"name": "Message",
"message": 'Hello, world.'
}
}
sbaComposerWindow.addEventListener('load', function() {
sbaComposerWindow.send(messageObject,'*');
}, false);
Try it yourself: hello world example
Note that this command is not very useful to call directly, but rather it is
intended to be used in an onclick-handler of a Composer.scatter3d
plot.
Plotly.plot
commandThe plotly.js library is a open source package to add beaufiful and interactive graphics to a website. You can see an advertorial of its capabilities at its home page. In general, plotly plots take three arguments:
<div>
-element that is used to contain the plot.Of these three arguments, SBA Composer takes care of the first. You need
to specify the data
and layout
fields, following the plotly.js
tutorials and reference manual.
The plotly website contains the following example to generate a 2d scatter plot.
const trace1 = {
x: [1, 2, 3, 4, 5],
y: [1, 6, 3, 6, 1],
mode: 'markers',
type: 'scatter',
name: 'Team A',
text: ['A-1', 'A-2', 'A-3', 'A-4', 'A-5'],
marker: { size: 12 }
};
const data = [ trace1 ];
const layout = {
xaxis: {
range: [ 0.75, 5.25 ]
},
yaxis: {
range: [0, 8]
},
title:'Data Labels Hover'
};
Plotly.newPlot('myDiv', data, layout);
To display this plot in SBA Composer, remove the Plotly.newPlot command and use the following code instead to create the command object:
const sbaCommand = {
"method": "Plotly.plot",
"params": {
"name": "Example 2d Scatter",
"data": data,
"layout": layout
}
}
Try it yourself: plotly example
If the resulting plot is partly off-screen, you can move its container by grabbing it by the title bar.
Note that this command is not so useful to call directly, but rather it is
intended to be used in an onclick-handler of a Composer.scatter3d
plot.
Composer.scatter3d
onclick field recursivelyA key extension of the Composer.scatter3d
command is that you can make
the markers responsive by adding an onclick
field to them. The syntax of
what to put in the onclick field is the same as the syntax already explained
in this tutorial. You just apply it recursively.
The code below displays two markers. It assumes that the variables trace1, data and layout from example 3 are still in memory. One marker will display a message when clicked, the other a plotly-plot.
const sbaCommand = {
"method":"Composer.scatter3d",
"params": {
"style": {
"marker": {
"size": 0.3
}
},
"markers":[{
"coord":[0,0,0],
"color":"#FF0000",
"onclick":{
"method": "Composer.message",
"params": {
"name": "Message",
"message": 'Hello, world.'
}
}
},{
"coord":[1,1,1],
"onclick":{
"method": "Plotly.plot",
"params": {
"name": "Example 2d Scatter",
"data": data,
"layout": layout
}
}
}]
}
};
Try it yourself: recursive scatter3d example