Measure which objects colocalise in ImarisXT

@NicoKiaru @oburri @simonfn @aarpon

Within Imaris we have two Surfaces (A and B) which partially overlap. Each Surface contains several objects (connected components). We would now like to measure for each object in Surface A with which objects it overlaps in Surface B (we would need the object label indices as a list). And we would like to solve this within ImarisXT.

Could you give me a hint how to achieve this? Related, is the ImarisXT API somewhere online?


There is a MATLAB XT that does create a new colocalization Surface object, but it does that only on the binary masks.

%Generate surface mask for each surface over time - currently using
%GetDataVolumeBytes, as other methods suchas 1DArrayBytes were not working
for vTimeIndex= 0:aSizeT-1
    vSurfaces1Mask = vSurfaces1.GetMask(aExtendMinX,aExtendMinY,aExtendMinZ,aExtendMaxX,aExtendMaxY,aExtendMaxZ,aSizeX, aSizeY,aSizeZ,vTimeIndex);
    vSurfaces2Mask = vSurfaces2.GetMask(aExtendMinX,aExtendMinY,aExtendMinZ,aExtendMaxX,aExtendMaxY,aExtendMaxZ,aSizeX, aSizeY,aSizeZ,vTimeIndex);
    
    ch1 = vSurfaces1Mask.GetDataVolumeAs1DArrayBytes(0,vTimeIndex);
    ch2 = vSurfaces2Mask.GetDataVolumeAs1DArrayBytes(0,vTimeIndex);
    
    %Determine the Voxels that are colocalized
    Coloc=ch1+ch2;
    Coloc(Coloc<2)=0;
    Coloc(Coloc>1)=1;
    
    vDataSet.SetDataVolumeAs1DArrayBytes(Coloc, vLastChannel, vTimeIndex);
1 Like

A specific question I would have is whether there also is something like vSurfaces1.GetLabelMask? Or some other way to get the surface object indices?

I finally managed:
XTSurfaceSurfaceColoc2.m (8.2 KB)

This XTension adds overlap information to the second to the two Surface objects. One can see how much volume overlap there was for each object with any other object, e.g. here with object ID 1:

Thanks to @oburri for pointing me towards how to handle string arrays in MATLAB :smiley:

The code that I added is:

// Measure the volume overlap of Surface objects with each another
for vTimeIndex= 0:aSizeT-1
    n1 = vSurfaces1.GetNumberOfSurfaces();
    n2 = vSurfaces2.GetNumberOfSurfaces();
    ids1 = vSurfaces1.GetIds();
    ids2 = vSurfaces2.GetIds();
    
    for i1 = 1 : n1
        vOverlaps = 1:n2;
        vNames = strings(1,n2);
        vFactorNames = "Category";
        vFactors = strings(1,n2);
        vOverlapUnits = strings(1,n2);
        vIds = 1:n2;
        vStatName = strcat("Overlap with ", string(vSurfaces1.GetName), " ID ", string(ids1(i1)));
        
        for i2 = 1 : n2
            vSingleMask1 = vSurfaces1.GetSingleMask(i1-1,aExtendMinX,aExtendMinY,aExtendMinZ,aExtendMaxX,aExtendMaxY,aExtendMaxZ,aSizeX,aSizeY,aSizeZ);
            vSingleMask2 = vSurfaces2.GetSingleMask(i2-1,aExtendMinX,aExtendMinY,aExtendMinZ,aExtendMaxX,aExtendMaxY,aExtendMaxZ,aSizeX,aSizeY,aSizeZ);
            ch1 = vSingleMask1.GetDataVolumeAs1DArrayBytes(0,vTimeIndex);
            ch2 = vSingleMask2.GetDataVolumeAs1DArrayBytes(0,vTimeIndex);
            coloc = ch1 .* ch2 ;
            
            vOverlaps(i2) = sum(coloc); 
            vIds(i2) = ids2(i2);
            vOverlapUnits(i2) = "voxel";
            vNames(i2) = vStatName;
            vFactors(i2) = "Custom";
        end
        
        vSurfaces2.RemoveStatistics( vStatName ); 
        vSurfaces2.AddStatistics(vNames, vOverlaps, vOverlapUnits, vFactors, vFactorNames, vIds);        
    
    end
end    

TODO:

  • Make this more efficient by only cropping out the volumes where the surface objects are present. Right now, e.g. this code always fetches the whole image: vSurfaces1.GetSingleMask(i1-1,aExtendMinX,aExtendMinY,aExtendMinZ,aExtendMaxX,aExtendMaxY,aExtendMaxZ,aSizeX,aSizeY,aSizeZ);
3 Likes