RAMON and RAMONifying DataΒΆ

An overview of the RAMON Data Standard can be found here. For more detailed examples, please see the examples folder. One good starting point is the Getting Started Script. CAJAL implements the RAMON data standard. These data types can be seamlessly used with NeuroData/OCP, or as standalone objects.

To interact with a RAMONObject, first initialize it:

syn = RAMONSynapse;

Fields can be set using setters. Fields can be retrieved directly (no getters).

syn.setWeight(0.5);
syn.weight

ID is usually set by the database as the primary key; do not set this field as a user unless you have a reason.

Some fields have enumerated types. More on these types can be found on the RAMON overview page:

syn.setType(eRAMONSynapseType.excitatory);

Examples of using RAMON exist throughout the documentation and examples. One good references is code to RAMONify AC4 (a small EM volume); this procedure uses spatial overlap to infer connections and proceeds based only on raw labels. The code is reproduced here, and can be found in the examples folder (ramonify_basic.m)

% RAMONify AC4 and generate a graph
% Version 1:  Without the algorithms
% This is essentially a step-by-step method demonstrating the utility of
% CAJAL, RAMON, and NeuroData.

% Depending on the case, bidirectional links are not required; in practice,
% the neuron abstraction may be skipped for processing efficiency if all
% segments are merged via another process.  Here we include both of these
% steps to demonstrate functionality.

% Prerequisite:  Project and tokens
% Channels should be neuron, synapse

% This is not cube aligned because AC4 maps to a manually annoted
% dataset.  We block upload for efficiency.

% Assume that server is openconnecto.me

%
token = 'test_ramonify_public';
%% Setup server connection
clear SYN SEG NEU

odown = OCP();
odown.setImageToken('kasthuri11cc');
odown.setAnnoToken('ac4_raw');

%% Find Synapses

% Here we download from an existing database
%http://openconnecto.me/ocp/overlay/0.7/openconnecto.me/kasthuri11cc/image/openconnecto.me/ac4_raw/neuron/xy/1/4400,5424/5440,6464/1105/
odown.setAnnoChannel('synapse');

q = OCPQuery;
q.setType(eOCPQueryType.annoDense);
q.setCutoutArgs([4400,5424],[5440,6464],[1100,1200],1);

synPaint = odown.query(q);


%% Find Neuron Segments

% Here we download raw data from an existing database
odown.setAnnoChannel('neuron');

neuPaint = odown.query(q);

%% Associate Segments and Synapses

% Simple image processing function

% [seg1, seg2, synapse, direction]
eList = neusyn_associate_simple(neuPaint,synPaint);

   for ii = 1:size(eList,1)
            ee = eList(ii,1:2);
            eList(ii,1) = min(ee);
            eList(ii,2) = max(ee);
   end

usyn = unique(synPaint.data); %unique values, disregard 0
usyn(usyn == 0) = [];
nsyn = length(usyn);

uneu = unique(neuPaint.data);
uneu(uneu == 0) = [];
nneu = length(uneu);

rps = regionprops(synPaint.data,'Centroid');
rpn = regionprops(neuPaint.data,'Centroid');

for i = 1:nsyn
    syn = RAMONSynapse();
    syn.setAuthor('test upload');
    syn.setId(usyn(i));

    cVal = round(rps(i).Centroid+synPaint.xyzOffset)-[1,1,1];

    syn.addDynamicMetadata('centroid',cVal);

    idx = find(eList(:,3) == usyn(i));

    for j = 1:length(idx)
        if eList(j,1) > 0
            syn.addSegment(eList(idx(j),1), eRAMONFlowDirection.unknown);
        end
        if eList(j,2) > 0
            syn.addSegment(eList(idx(j),2), eRAMONFlowDirection.unknown);
        end
    end
    SYN{i} = syn;
    clear syn
end

oup = OCP();
oup.setImageToken('kasthuri11cc');
oup.setAnnoToken(token);
oup.setAnnoChannel('synapse');

synPaint.setChannel('synapse');
oup.createAnnotation(synPaint);

oup.createAnnotation(SYN);

%% Create segment metadata

for i = 1:nneu
    seg = RAMONSegment();
    seg.setAuthor('test upload');
    seg.setId(uneu(i));

    idx = find(eList(:,1) == uneu(i));

    for j = 1:length(idx)
        seg.setSynapses([seg.synapses, eList(idx(j),3)]);
    end

    idx = find(eList(:,2) == uneu(i));
    for j = 1:length(idx)
        seg.setSynapses([seg.synapses, eList(idx(j),3)]);
    end

    SEG{i} = seg;
    clear seg
end

oup = OCP();
oup.setImageToken('kasthuri11cc');
oup.setAnnoToken(token);
oup.setAnnoChannel('neuron');

neuPaint.setChannel('neuron');
oup.createAnnotation(neuPaint);

oup.createAnnotation(SEG);


%% Need to create neurons and assign segments to neurons

% This step is artificial here; we assign neuron IDs = segID + 100000

for i = 1:length(SEG)
    neu = RAMONNeuron;
    neu.setId(SEG{i}.id + 100000);

    NEU{i} = neu;
    clear neu
end

oup.createAnnotation(NEU);

%% Need to add segments to neurons
% Could have been done in previous step.  Demonstrating updateAnnotation

q = OCPQuery;
q.setType(eOCPQueryType.RAMONMetaOnly);

for i = 1:length(NEU)

    q.setId(NEU{i}.id);
    neu = oup.query(q);

    neu.setSegments([neu.segments, SEG{i}.id]); %true by construction
    oup.updateAnnotation(neu);
end

%% Need to add neurons to segments
% Demonstrating OCPFields

f = OCPFields();

for i = 1:length(NEU)
% i
    segMap =  oup.getField(NEU{i}.id,f.neuron.segments);

    for j = 1:length(segMap)

        oup.setField(segMap(j),f.segment.neuron,NEU{i}.id);  %segments belong to only one neuron
    end
end

A second example is the RAMONification of the Kasthuri2015 cell paper (found here https://github.com/openconnectome/kasthuri2015/blob/master/ramonify/ramonify_kasthuri.m). This is similar in spirit, but leverages manually curated associations and metadata to parse the hierarchy and associate objects.