whole_func_string: function setupEditor() {
    /**
     *
     */
    function distanceBetween(point1, point2) {
      return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));
    }
  
    /**
     *
     */
    function angleBetween(point1, point2) {
      return Math.atan2(point2.x - point1.x, point2.y - point1.y);
    }
  
    /**
     *
     */
    function initEditorStats() {
      let nbVoxels = stack2._columns * stack2._rows * stack2._frame.length;
      let textureSize = 4096;
      let textureDimension = textureSize * textureSize;
  
      for (let i = 0; i < nbVoxels; i++) {
        let rawDataIndex = ~~(i / textureDimension);
        let inRawDataIndex = i % textureDimension;
        let value = stack2.rawData[rawDataIndex][inRawDataIndex];
        editorStats[value] += 1;
      }
  
      updateEditorStatsDom();
    }
  
    /**
     *
     */
    function updateEditorStatsDom() {
      for (let i = 0; i < 3; i++) {
        document.getElementById(`editorSegment${i}Label`).innerHTML = segmentsList[i];
        document.getElementById(`editorSegment${i}Value`).innerHTML = editorStats[i];
      }
    }
  
    /**
     *  Loop through IJK BBox and see if voxel can be mapped to screen
     */
    function mapCanvasToData() {
      for (let i = ijkBBox[0]; i < ijkBBox[1] + 1; i++) {
        for (let j = ijkBBox[2]; j < ijkBBox[3] + 1; j++) {
          for (let k = ijkBBox[4]; k < ijkBBox[5] + 1; k++) {
            // ijk to world
            // center of voxel
            let worldCoordinate = new THREE.Vector3(i, j, k).applyMatrix4(stack2._ijk2LPS);
            // world to screen coordinate
            let screenCoordinates = worldCoordinate.clone();
            screenCoordinates.project(camera);
  
            screenCoordinates.x = Math.round(((screenCoordinates.x + 1) * canvas.offsetWidth) / 2);
            screenCoordinates.y = Math.round(((-screenCoordinates.y + 1) * canvas.offsetHeight) / 2);
            screenCoordinates.z = 0;
  
            let pixel = context.getImageData(screenCoordinates.x, screenCoordinates.y, 1, 1).data;
            if (pixel[3] > 0 && i >= 0 && j >= 0 && k >= 0) {
              // find index and texture
              let voxelIndex = i + j * stack2._columns + k * stack2._rows * stack2._columns;
  
              let textureSize = 4096;
              let textureDimension = textureSize * textureSize;
  
              let rawDataIndex = ~~(voxelIndex / textureDimension);
              let inRawDataIndex = voxelIndex % textureDimension;
  
              // update value...
              let oldValue = stack2.rawData[rawDataIndex][inRawDataIndex];
              let newValue = cursor.value;
  
              if (oldValue != newValue) {
                // update raw data
                stack2.rawData[rawDataIndex][inRawDataIndex] = newValue;
  
                // update texture that is passed to shader
                textures2[rawDataIndex].image.data = stack2.rawData[rawDataIndex]; // tex;
                textures2[rawDataIndex].needsUpdate = true;
  
                // update stats
                editorStats[oldValue] -= 1;
                editorStats[newValue] += 1;
              }
            }
          }
        }
      }
    }
  
    /**
     *
     */
    function drawCircle(x, y) {
      context.beginPath();
      context.arc(x, y, cursor.size, false, Math.PI * 2, false);
      context.closePath();
      context.fill();
      context.stroke();
    }
  
    /**
     *
     */
    function clearCanvas() {
      context.clearRect(0, 0, context.canvas.width, context.canvas.height);
    }
  
    /**
     *
     */
    function addEventListeners() {
      /**
       *
       */
      function onMouseDown(e) {
        if (!isEditing) return;
  
        isDrawing = true;
        lastPoint = {
          x: e.pageX - canvasDiv.offsetLeft,
          y: e.pageY - canvasDiv.offsetTop,
        };
      }
  
      /**
       *
       */
      function onMouseMove(e) {
        if (!isEditing) return;
  
        currentPoint = {
          x: e.pageX - canvasDiv.offsetLeft,
          y: e.pageY - canvasDiv.offsetTop,
        };
  
        context.strokeStyle = cursor.color;
        context.globalCompositeOperation = 'xor';
        context.globalAlpha = 0.5;
        context.fillStyle = cursor.color;
  
        if (isDrawing) {
          let dist = distanceBetween(lastPoint, currentPoint);
          let angle = angleBetween(lastPoint, currentPoint);
  
          for (let i = 0; i < dist; i += 5) {
            let x = lastPoint.x + Math.sin(angle) * i;
            let y = lastPoint.y + Math.cos(angle) * i;
            drawCircle(x, y);
          }
  
          lastPoint = currentPoint;
        } else {
          clearCanvas();
        }
  
        // draw under the cursor
        context.globalCompositeOperation = 'source-over';
        context.globalAlpha = 1;
        context.fillStyle = 'rgba(0, 0, 0, 0)';
        drawCircle(currentPoint.x, currentPoint.y);
      }
  
      /**
       *
       */
      function onMouseUp(e) {
        if (!isEditing) return;
  
        isDrawing = false;
        mapCanvasToData();
        clearCanvas();
        updateEditorStatsDom();
        // draw cursor under mouse
        onMouseMove(e);
      }
  
      /**
       *
       */
      function updateDOM() {
        // lets events go through or not for scrolling, padding, zooming, etc.
        if (isEditing) {
          canvasDiv.className = 'editing';
          document.getElementById('help').style.display = 'none';
        } else {
          canvasDiv.className = 'exploring';
          document.getElementById('help').style.display = 'block';
        }
      }
  
      /**
       *
       */
      function onKeyDown(e) {
        if (e.keyCode === 17) {
          isEditing = true;
          isDrawing = false;
          updateDOM();
        }
      }
  
      /**
       *
       */
      function onKeyUp(e) {
        if (e.keyCode === 17) {
          isEditing = false;
          isDrawing = false;
          clearCanvas();
          updateDOM();
        }
      }
  
      /**
       *
       */
      function disableRightClick(e) {
        e.preventDefault();
        e.stopPropagation();
        return false;
      }
  
      // add events listeners
      canvasDiv.addEventListener('mousedown', onMouseDown, false);
      canvasDiv.addEventListener('mousemove', onMouseMove, false);
      canvasDiv.addEventListener('mouseup', onMouseUp, false);
      window.addEventListener('keydown', onKeyDown, false);
      window.addEventListener('keyup', onKeyUp, false);
      canvasDiv.addEventListener('contextmenu', disableRightClick, false);
    }
  
    addEventListeners();
    initEditorStats();
  }
func_code_string: function setupEditor() {
    /**
     *
     */
    function distanceBetween(point1, point2) {
      return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));
    }
  
    /**
     *
     */
    function angleBetween(point1, point2) {
      return Math.atan2(point2.x - point1.x, point2.y - point1.y);
    }
  
    /**
     *
     */
    function initEditorStats() {
      let nbVoxels = stack2._columns * stack2._rows * stack2._frame.length;
      let textureSize = 4096;
      let textureDimension = textureSize * textureSize;
  
      for (let i = 0; i < nbVoxels; i++) {
        let rawDataIndex = ~~(i / textureDimension);
        let inRawDataIndex = i % textureDimension;
        let value = stack2.rawData[rawDataIndex][inRawDataIndex];
        editorStats[value] += 1;
      }
  
      updateEditorStatsDom();
    }
  
    /**
     *
     */
    function updateEditorStatsDom() {
      for (let i = 0; i < 3; i++) {
        document.getElementById(`editorSegment${i}Label`).innerHTML = segmentsList[i];
        document.getElementById(`editorSegment${i}Value`).innerHTML = editorStats[i];
      }
    }
  
    /**
     *  Loop through IJK BBox and see if voxel can be mapped to screen
     */
    function mapCanvasToData() {
      for (let i = ijkBBox[0]; i < ijkBBox[1] + 1; i++) {
        for (let j = ijkBBox[2]; j < ijkBBox[3] + 1; j++) {
          for (let k = ijkBBox[4]; k < ijkBBox[5] + 1; k++) {
            // ijk to world
            // center of voxel
            let worldCoordinate = new THREE.Vector3(i, j, k).applyMatrix4(stack2._ijk2LPS);
            // world to screen coordinate
            let screenCoordinates = worldCoordinate.clone();
            screenCoordinates.project(camera);
  
            screenCoordinates.x = Math.round(((screenCoordinates.x + 1) * canvas.offsetWidth) / 2);
            screenCoordinates.y = Math.round(((-screenCoordinates.y + 1) * canvas.offsetHeight) / 2);
            screenCoordinates.z = 0;
  
            let pixel = context.getImageData(screenCoordinates.x, screenCoordinates.y, 1, 1).data;
            if (pixel[3] > 0 && i >= 0 && j >= 0 && k >= 0) {
              // find index and texture
              let voxelIndex = i + j * stack2._columns + k * stack2._rows * stack2._columns;
  
              let textureSize = 4096;
              let textureDimension = textureSize * textureSize;
  
              let rawDataIndex = ~~(voxelIndex / textureDimension);
              let inRawDataIndex = voxelIndex % textureDimension;
  
              // update value...
              let oldValue = stack2.rawData[rawDataIndex][inRawDataIndex];
              let newValue = cursor.value;
  
              if (oldValue != newValue) {
                // update raw data
                stack2.rawData[rawDataIndex][inRawDataIndex] = newValue;
  
                // update texture that is passed to shader
                textures2[rawDataIndex].image.data = stack2.rawData[rawDataIndex]; // tex;
                textures2[rawDataIndex].needsUpdate = true;
  
                // update stats
                editorStats[oldValue] -= 1;
                editorStats[newValue] += 1;
              }
            }
          }
        }
      }
    }
  
    /**
     *
     */
    function drawCircle(x, y) {
      context.beginPath();
      context.arc(x, y, cursor.size, false, Math.PI * 2, false);
      context.closePath();
      context.fill();
      context.stroke();
    }
  
    /**
     *
     */
    function clearCanvas() {
      context.clearRect(0, 0, context.canvas.width, context.canvas.height);
    }
  
    /**
     *
     */
    function addEventListeners() {
      /**
       *
       */
      function onMouseDown(e) {
        if (!isEditing) return;
  
        isDrawing = true;
        lastPoint = {
          x: e.pageX - canvasDiv.offsetLeft,
          y: e.pageY - canvasDiv.offsetTop,
        };
      }
  
      /**
       *
       */
      function onMouseMove(e) {
        if (!isEditing) return;
  
        currentPoint = {
          x: e.pageX - canvasDiv.offsetLeft,
          y: e.pageY - canvasDiv.offsetTop,
        };
  
        context.strokeStyle = cursor.color;
        context.globalCompositeOperation = 'xor';
        context.globalAlpha = 0.5;
        context.fillStyle = cursor.color;
  
        if (isDrawing) {
          let dist = distanceBetween(lastPoint, currentPoint);
          let angle = angleBetween(lastPoint, currentPoint);
  
          for (let i = 0; i < dist; i += 5) {
            let x = lastPoint.x + Math.sin(angle) * i;
            let y = lastPoint.y + Math.cos(angle) * i;
            drawCircle(x, y);
          }
  
          lastPoint = currentPoint;
        } else {
          clearCanvas();
        }
  
        // draw under the cursor
        context.globalCompositeOperation = 'source-over';
        context.globalAlpha = 1;
        context.fillStyle = 'rgba(0, 0, 0, 0)';
        drawCircle(currentPoint.x, currentPoint.y);
      }
  
      /**
       *
       */
      function onMouseUp(e) {
        if (!isEditing) return;
  
        isDrawing = false;
        mapCanvasToData();
        clearCanvas();
        updateEditorStatsDom();
        // draw cursor under mouse
        onMouseMove(e);
      }
  
      /**
       *
       */
      function updateDOM() {
        // lets events go through or not for scrolling, padding, zooming, etc.
        if (isEditing) {
          canvasDiv.className = 'editing';
          document.getElementById('help').style.display = 'none';
        } else {
          canvasDiv.className = 'exploring';
          document.getElementById('help').style.display = 'block';
        }
      }
  
      /**
       *
       */
      function onKeyDown(e) {
        if (e.keyCode === 17) {
          isEditing = true;
          isDrawing = false;
          updateDOM();
        }
      }
  
      /**
       *
       */
      function onKeyUp(e) {
        if (e.keyCode === 17) {
          isEditing = false;
          isDrawing = false;
          clearCanvas();
          updateDOM();
        }
      }
  
      /**
       *
       */
      function disableRightClick(e) {
        e.preventDefault();
        e.stopPropagation();
        return false;
      }
  
      // add events listeners
      canvasDiv.addEventListener('mousedown', onMouseDown, false);
      canvasDiv.addEventListener('mousemove', onMouseMove, false);
      canvasDiv.addEventListener('mouseup', onMouseUp, false);
      window.addEventListener('keydown', onKeyDown, false);
      window.addEventListener('keyup', onKeyUp, false);
      canvasDiv.addEventListener('contextmenu', disableRightClick, false);
    }
  
    addEventListeners();
    initEditorStats();
  }
func_documentation_string: FUNCTIONS