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.