See also: Controlling SBA Composer from a Jupyter notebook

Exchanging data with SBA Composer

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:

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.

Using the Composer.scatter3d command

The arguments that come with this command are:

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.

Using the Composer.import command

The arguments that come with this command are:

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.

Using the Composer.scene command

The arguments that come with this command are:

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

Using the Composer.message command

Given 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.

Using the Plotly.plot command

The 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:

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.

Using the Composer.scatter3d onclick field recursively

A 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