Contents

CAJAL3D Demo Script

Set xyz starting point. Since anyone can use this script you may want to "move" to a different region to run.

xstart = 3000;
ystart = 6000;
zstart = 400;

Create OCP Interface and set tokens

% Create an OCP Object.  This is the main class used for talking with OCP
% services. If you want to create an OCP object that will use the
% distributed semaphore (assuming you've set it up) use OCP('semaphore')
% instead.
oo = OCP();

% Set the server location.  This is the default server and most likely the
% one you should be using.
oo.setServerLocation('http://openconnecto.me/');

% Set the image token.  This is the database for image data reading.
oo.setImageToken('kasthuri11cc');

% Set the image token.  This is the database for image data reading. You
% can also read this from a file using setAnnoTokenFile. Also update
% propagate status to make the annotation project writeable.
% Note: We do not propagate in the demo script.
oo.setAnnoToken('cajal_demo');
oo.setAnnoChannel('anno');
oo.makeAnnoWritable();

% Information about the databases are accessible
oo.annoInfo.DATASET
oo.annoInfo.DATASET.IMAGE_SIZE(1)

% Set the default resolution.  This is the resolution at which operations
% should occur unless otherwise specified.
oo.setDefaultResolution(1);

% There are other options to further tweak the OCP object.
% oo.setBatchSize - This sets the maximum number of objects the API will
% group into a single batch write.  You shouldn't have to change this.
% oo.setMaxAnnoSize - This is the maximum size an annotation can be before
% the API automatically chunks it up into multiple writes. You shouldn't
% have to touch this.
% oo.setErrorPageLocation - this is where OCP errors will be written.  The
% server generates an html response that can be viewed for debugging.
ans = 

    CUBE_DIMENSION: [8x1 containers.Map]
        IMAGE_SIZE: [8x1 containers.Map]
              NAME: {'kasthuri11cc'}
            OFFSET: [8x1 containers.Map]
       RESOLUTIONS: [0 1 2 3 4 5 6 7]
         TIMERANGE: [0 0]
          VOXELRES: [8x1 containers.Map]


ans =

       10752       13312        1850

Get Some Image Data

The OCPQuery object is the basis for building queries for the database. The constructors accept multiple options so check out the code.

% Build query to cutout IMAGE data.
q = OCPQuery(eOCPQueryType.imageDense);

% The validate method can be used to check if the query has any errors
[pf, msg] = q.validate()

% setCutoutArgs sets all the required fields for a cutout query.
q.setCutoutArgs([xstart xstart+500],...
                [ystart ystart+500],...
                [zstart zstart+5],...
                1);

% Query is now valid
[pf, msg] = q.validate()

% Download the data into a RAMONVolume. The RAMONVolume stores the image
% data in the .data property.  There are other useful bits of information,
% specifically the xyzOffset value which indicates where the data came
% from.
cutout = oo.query(q);
cutout

% The image method has been overloaded to launch the API's simple data
% viewer.  '?' prints the shortcuts
image(cutout);
pf =

     0


msg =

[E] X Range is required for dense cutouts
[E] Y Range is required for dense cutouts
[E] Z Range is required for dense cutouts
[W] Resolution is empty.  Default resolution will be used at runtime.



pf =

     1


msg =

     ''



cutout = 

  500x500x5 RAMONVolume array with properties:

            xyzOffset: [3000 6000 400]
           resolution: 1
                 name: 'image'
    sliceDisplayIndex: 1
           dataFormat: [1x1 eRAMONDataFormat]
                 data: [500x500x5 uint8]
                   id: []
              channel: []
           confidence: 1
      dynamicMetadata: [0x1 containers.Map]
               status: [1x1 eRAMONAnnoStatus]
               author: 'unspecified'
             dataType: [1x1 eRAMONChannelDataType]
          channelType: [1x1 eRAMONChannelType]

Create a Synapse

Create some 'dummy' labels

d = zeros(200,200,5);
d(30:170,30:170,:) = 1;

% Create an empty RAMONSynapse object
s1 = RAMONSynapse()

% Set the objects properties as desired.
s1.setCutout(uint32(d));
s1.setXyzOffset([xstart ystart zstart]);
s1.setResolution(1);

s1.setSynapseType(eRAMONSynapseType.excitatory);
s1.setSeeds([2 4 6 3]);
s1.setConfidence(.8);
s1 = 

  0x0 RAMONSynapse array with properties:

          synapseType: [1x1 eRAMONSynapseType]
               weight: []
             segments: [0x1 containers.Map]
                seeds: []
            xyzOffset: []
           resolution: []
                 name: 'Volume1'
    sliceDisplayIndex: 1
           dataFormat: [1x1 eRAMONDataFormat]
                 data: []
                   id: []
              channel: []
           confidence: 1
      dynamicMetadata: [0x1 containers.Map]
               status: [1x1 eRAMONAnnoStatus]
               author: 'unspecified'
             dataType: []
          channelType: []

Upload a Synapse

%Simply passing the RAMON object (or any RAMON object really...) will upload
%the data and create an annotation.  The database will assign an ID as long
%as the ID was empty in the RAMON object.
id1 = oo.createAnnotation(s1);

Download a Synapse

The server can't get objects that don't exist THIS LINE SHOULD THROW AN EXCEPTION AS AN EXAMPLE

%sbad = oo.query(OCPQuery(eOCPQueryType.RAMONDense,4565564531));

% Download the synapse we just uploaded. s1 and s2 should now contain the
% same data, but s2 has been spatially aligned to the backend storage cuboids and has
% been assigned an ID.
s2 = oo.query(OCPQuery(eOCPQueryType.RAMONDense,id1));

Update a Synapse

You can directly update metadata fields

f = OCPFields();
oo.getField(id1,f.synapse.author)
oo.setField(id1,f.synapse.author,'demo_test');
oo.getField(id1,f.synapse.author)

% You can also update the object locally and then push the changes.  if
% you're changing the annotation data this is how it is done as well.
oo.getField(id1,f.synapse.weight)
s2.setWeight(.5);
id1 = oo.updateAnnotation(s2);
oo.getField(id1,f.synapse.weight)
ans =

unspecified


ans =

demo_test


ans =

     0


ans =

    0.5000

Query for Synapses

You can query the database for IDs that match some list of predicates. This can also be done spatially!

q = OCPQuery(eOCPQueryType.RAMONIdList);
q.addIdListPredicate(eOCPPredicate.type,eRAMONAnnoType.synapse);

idList = oo.query(q) %#ok<*NASGU,*NOPTS>
idList =

           1           3          14

Delete a Synapse

Delete and annotation by its ID

oo.deleteAnnotation(id1)

idList = oo.query(q)
ans =

Success


idList =

           1           3

Re-Upload the Synapse

% Create some 'dummy' labels
d = zeros(200,200,5);
d(30:170,30:170,:) = 1;

% Create an RAMONSynapse object with a single call.
s3 = RAMONSynapse(d,eRAMONDataFormat.dense,[xstart+450 ystart+540 zstart+65],1);
id3 = oo.createAnnotation(s3);

Download a server side rendered overlay image (2D only)

q = OCPQuery(eOCPQueryType.overlaySlice);
q.setSliceArgs(eOCPSlicePlane.xy,...
    [s1.xyzOffset(1) - 250, s1.xyzOffset(1) + 250],...
    [s1.xyzOffset(2) - 250, s1.xyzOffset(2) + 250],...
    s1.xyzOffset(3) + 2,...
    1)

slice = oo.query(q);
figure;
imshow(slice);

% You can set the alpha too.
q.setOverlayAlpha(.7);
slice = oo.query(q);
figure;
imshow(slice);


% You can set the alpha too.
q.setOverlayAlpha(.3);
slice = oo.query(q);
figure;
imshow(slice);
ans = 

  OCPQuery with properties:

                type: [1x1 eOCPQueryType]
                  id: []
          resolution: 1
              xRange: []
              yRange: []
              zRange: []
          slicePlane: [1x1 eOCPSlicePlane]
              aRange: [2750 3250]
              bRange: [5750 6250]
              cIndex: 402
        overlayAlpha: []
    idListPredicates: [0x1 containers.Map]
         idListLimit: []
            xyzCoord: []
           filterIds: []
            channels: []

Download Image and Anno Cutouts

Finally lets cutout both an image and annotation volume around the annotation we created and view them together using the basic viewer.

% You can do it the hard manual way.
q = OCPQuery(eOCPQueryType.annoDense);
q.setCutoutArgs([s3.xyzOffset(1) - 250 s3.xyzOffset(1) + 250],...
                [s3.xyzOffset(2) - 150 s3.xyzOffset(2) + 250],...
                [s3.xyzOffset(3) - 3 s3.xyzOffset(3) + 3],...
                1);
cutoutAnno = oo.query(q);

q = OCPQuery(eOCPQueryType.imageDense);
q.setCutoutArgs([s3.xyzOffset(1) - 250 s3.xyzOffset(1) + 250],...
                [s3.xyzOffset(2) - 150 s3.xyzOffset(2) + 250],...
                [s3.xyzOffset(3) - 3 s3.xyzOffset(3) + 3],...
                1);
cutoutImage = oo.query(q);

h = image(cutoutImage);

% Press the 'a' key to toggle the annotation overlay on and off.
h.associate(cutoutAnno);

% You can also do it the easy automatic way if you are trying to just
% visualize a specific RAMON Object.
q = OCPQuery(eOCPQueryType.RAMONDense,id3)
cutoutAnno = oo.query(q);

q_anno = cutoutAnno.toImageDenseQuery();
cutoutImg = oo.query(q_anno);


h = image(cutoutImg);
h.associate(cutoutAnno);
q = 

  OCPQuery with properties:

                type: [1x1 eOCPQueryType]
                  id: 15
          resolution: []
              xRange: []
              yRange: []
              zRange: []
          slicePlane: []
              aRange: []
              bRange: []
              cIndex: []
        overlayAlpha: []
    idListPredicates: [0x1 containers.Map]
         idListLimit: []
            xyzCoord: []
           filterIds: []
            channels: []

More...

This example script provides some initial code to get you started, but there is much more to the API. The unit tests more comprehensively describe the full functionality.