0

I have a question regarding the use of segmentation LUTs in AMI JS (not XTK but there is no ami js tag yet!). Particularly what I want to do is to load a segmentation / labelmap layer and display it with the right colors, one for each label.

My labelmap layer consists of N integer labels that define different structures (e.g from 0 to 14000), which are also the voxel values of the labelmap. Each one of the labels has a different color associated (they are generated by Freesurfer and can be seen on: https://surfer.nmr.mgh.harvard.edu/fswiki/FsTutorial/AnatomicalROI/FreeSurferColorLUT ).

What I would like is a LUT that, for each different label, paints it with the correspondant color. I have had trouble finding the right way to do it and have not had success so far. What I have done is to get all the colors and store them into an array (colors normalized between 0 and 1 and the first component being the position inside the texture from 0 to 1, with a step of 1/total labels, which results in a really small step as there are 1200 labels!). From what I've seen then, the HelpersLUT class takes all the colors and maps them discretely into the texture, but the colors appear messed up and I can't seem to get the opacities right either...

I have seen also that the StackModels also have some functionalities such as prepareSegmentation() and such but do not know how to specify the LUT in there and cannot get it to work either (it is not used on the example).

Which is the best way to create a discrete LUT with a different color for each integer label and the 0 value being transparent and the other labels opaque?

The procedure used to generate the LUTs is: First I read a JSON with the information of the Freesurfer and store it into a variable, the first component of each one is the index of the label between 0 and 1, and the other ones are the associated color to the label between 0 and 1 as well. I have also generated a LUT of opacities.

let customLUT = {
  "fsLUT": [],
  "default": [[0, 0, 0, 0], [0.25, 0.3, 0.4, 0.5], [0.5, 0.2, 0.5, 0.4], 
  [0.75, 0.1, 0.2, 0.3], [1, 0.5, 0.5, 0.8]],
  "fsLUT0": [[0, 0], [0.01, 1], [0.6, 1], [1, 1]]
};

$.getJSON("https://cdn.rawgit.com/YorkeUtopy/ami-viewerData/e773d737/FreesurferInfo.json", function (data) {
  FsInfo = data;
  FsInfo.forEach(function (value, i) {
    customLUT.fsLUT.push([i / FsInfo.length, (value.color[0] / 255), (value.color[1] / 255.000), (value.color[2] / 255.000)]);
  });
});

Then I create a helpers LUT with the LUT0 defined and the LUT with the colors and apply it to the texture. Everythink else is just as the labelmap example createing the layer mix, etc...

lutLayerLblmap = new HelpersLut(
  "my-lut-canvases-l1",
  "default",
  "linear", [[0, 0, 0, 0], [1, 1, 1, 1]],
  customLUT.fsLUT0,
  false
);
lutLayerLblmap.luts = customLUT;
lutLayerLblmap.lut = "fsLUT";
refObj.uniformsLayerLblmap.uLut.value = 1;
refObj.uniformsLayerLblmap.uTextureLUT.value = lutLayerLblmap.texture;

With that some colors appear but there are not correct and the opacities are messed up (I know the LUT0 is not correct and that it is not discrete!). However, when I make the helpersLUT discrete and put a LUT0 like [0,0],[1,1], the colors are messed up and the opacities do not apply correctly... maybe it is that the voxel values are not between 0 and 1 but have values such as 1100,1200... ? or that I am not correctly generating the LUTs (step size too small?).... Here are some examples of the LUT.

        [0]: 0,0,0,0
        [1]:0.0008319467554076539,0.27450980392156865,0.5098039215686274,0.7058823529411765   
        [2]:0.0016638935108153079,0.9607843137254902,0.9607843137254902,0.9607843137254902
        [3]:0.0024958402662229617,0.803921568627451,0.24313725490196078,0.3058823529411765
    [last -2]:0.997504159733777,0.08235294117647059,0.7058823529411765,0.7058823529411765

    [last-1]:0.9983361064891847,0.8745098039215686,0.8627450980392157,0.23529411764705882 
   [last]:0.9991680532445923,0.8666666666666667,0.23529411764705882,0.23529411764705882

this is the sample data I use:

T1 Volume + Labelmap + Freesurfer JSON

Albert Alises
  • 1,018
  • 1
  • 8
  • 19
  • Can you add some code on how you currently generate the LUTs? Can you also share the (anonymized) data are trying to visualize? You should not worry about the `prepareSegmentation ` from the stack helper, it is only used for DICOM Seg object right now. – Nicolas Aug 21 '17 at 06:11
  • Hello! Added some code and the data. Thank you very much :) – Albert Alises Aug 21 '17 at 09:04
  • can you also show content of the custom LUT (at least first and last entries) ? The approach seems correct and I expect some issues with the normalization of the data. – Nicolas Aug 21 '17 at 11:14
  • Added examples of the LUT contents! – Albert Alises Aug 21 '17 at 13:21

1 Answers1

1

You seem to be making everything fine.

It is a current limitation in AMI side. It currently only supports 256 colors and on top of that, it requires values to be normalized.

In AMI, we need to support a new type of LUT (Segmentation LUT seems a good name).

Live fiddle based on you approach.

  const fsLUT = [];

  fetch("https://cdn.rawgit.com/YorkeUtopy/ami-viewerData/e773d737/FreesurferInfo.json")
 .then(response => response.json())
 .then(jsonLUT => {
    jsonLUT.forEach(function (value, i) {
    fsLUT.push([
      i / json.length,
      (value.color[0] / 255),
      (value.color[1] / 255.000),
      (value.color[2] / 255.000)]);
   });
   return fsLUT;
 })

http://jsfiddle.net/agoyre4e/20/

Nicolas
  • 2,191
  • 3
  • 29
  • 49
  • With your implementation, is it feasible to add support for a sagittal, coronal and axial view including respective label map? – Jyotirmay Apr 10 '19 at 14:23