ami-cjs.js
Version:
<p align="center"> <img src="https://cloud.githubusercontent.com/assets/214063/23213764/78ade038-f90c-11e6-8208-4fcade5f3832.png" width="60%"> </p>
818 lines (718 loc) • 25.5 kB
JavaScript
/* globals dat*/
// general imports
import CamerasOrthographic from '../../src/cameras/cameras.orthographic';
import ControlsOrthographic from '../../src/controls/controls.trackballortho';
import HelpersLut from '../../src/helpers/helpers.lut';
import HelpersStack from '../../src/helpers/helpers.stack';
import LoadersVolume from '../../src/loaders/loaders.volume';
// shaders imports
import ShadersLayerUniform from '../../src/shaders/shaders.layer.uniform';
import ShadersLayerVertex from '../../src/shaders/shaders.layer.vertex';
import ShadersLayerFragment from '../../src/shaders/shaders.layer.fragment';
import ShadersDataUniform from '../../src/shaders/shaders.data.uniform';
import ShadersDataVertex from '../../src/shaders/shaders.data.vertex';
import ShadersDataFragment from '../../src/shaders/shaders.data.fragment';
// standard global variables
let controls;
let renderer;
let camera;
let threeD;
let sceneLayer0TextureTarget;
let sceneLayer1TextureTarget;
let sceneLayer0;
let lutLayer0;
let sceneLayer1;
let meshLayer1;
let uniformsLayer1;
let materialLayer1;
let lutLayer1;
let sceneLayerMix;
let meshLayerMix;
let uniformsLayerMix;
let materialLayerMix;
let stackHelper;
let stack2;
let textures2;
let ijkBBox = [99999999, 0, 9999999, 0, 999999999, 0];
let layerMix = {
opacity1: 1.0,
lut: null,
};
let canvas;
let canvasDiv;
let context;
let lastPoint = null;
let currentPoint = null;
let isEditing = false;
let isDrawing = false;
let cursor = {
color: '#d9d9d9',
value: 0,
size: 15,
shape: 'round',
segment: 'erase',
};
let segmentsList = [];
let segmentsDict = {};
let editorStats = {
'0': 0,
'1': 0,
'2': 0,
};
// FUNCTIONS
/**
*
*/
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();
}
/**
*
*/
function init() {
/**
*
*/
function animate() {
// render
controls.update();
// render first layer offscreen
renderer.render(sceneLayer0, camera, sceneLayer0TextureTarget, true);
// render second layer offscreen
renderer.render(sceneLayer1, camera, sceneLayer1TextureTarget, true);
// mix the layers and render it ON screen!
renderer.render(sceneLayerMix, camera);
// request new frame
requestAnimationFrame(function() {
animate();
});
}
// renderer
threeD = document.getElementById('r3d');
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
});
renderer.setSize(threeD.clientWidth, threeD.clientHeight);
renderer.setClearColor(0x607D8B, 1);
threeD.appendChild(renderer.domElement);
// canvas 2D
canvasDiv = document.getElementById('canvasDiv');
canvas = document.createElement('canvas');
canvas.setAttribute('width', canvasDiv.clientWidth);
canvas.setAttribute('height', canvasDiv.clientHeight);
canvas.setAttribute('id', 'canvas');
canvasDiv.appendChild(canvas);
context = canvas.getContext('2d');
// scene
sceneLayer0 = new THREE.Scene();
sceneLayer1 = new THREE.Scene();
sceneLayerMix = new THREE.Scene();
// render to texture!!!!
sceneLayer0TextureTarget = new THREE.WebGLRenderTarget(
threeD.clientWidth,
threeD.clientHeight,
{minFilter: THREE.LinearFilter,
magFilter: THREE.NearestFilter,
format: THREE.RGBAFormat,
});
sceneLayer1TextureTarget = new THREE.WebGLRenderTarget(
threeD.clientWidth,
threeD.clientHeight,
{minFilter: THREE.LinearFilter,
magFilter: THREE.NearestFilter,
format: THREE.RGBAFormat,
});
// camera
camera = new CamerasOrthographic(threeD.clientWidth / -2, threeD.clientWidth / 2, threeD.clientHeight / 2, threeD.clientHeight / -2, 0.1, 10000);
// controls
controls = new ControlsOrthographic(camera, threeD);
controls.staticMoving = true;
controls.noRotate = true;
camera.controls = controls;
animate();
}
window.onload = function() {
// init threeJS...
init();
/**
*
*/
function updateLayer1() {
// update layer1 geometry...
if (meshLayer1) {
meshLayer1.geometry.dispose();
meshLayer1.geometry = stackHelper.slice.geometry;
meshLayer1.geometry.verticesNeedUpdate = true;
}
}
/**
*
*/
function updateLayerMix() {
// update layer1 geometry...
if (meshLayerMix) {
sceneLayerMix.remove(meshLayerMix);
meshLayerMix.material.dispose();
meshLayerMix.material = null;
meshLayerMix.geometry.dispose();
meshLayerMix.geometry = null;
// add mesh in this scene with right shaders...
meshLayerMix = new THREE.Mesh(stackHelper.slice.geometry, materialLayerMix);
// go the LPS space
meshLayerMix.applyMatrix(stackHelper.stack._ijk2LPS);
sceneLayerMix.add(meshLayerMix);
}
}
/**
*
*/
function updateIJKBBox() {
ijkBBox = [stack2._columns, 0, stack2._rows, 0, stack2.frame.length, 0];
// IJK BBox of the plane
let slice = stackHelper._slice;
let vertices = slice._geometry.vertices;
// to LPS
for (let i = 0; i<vertices.length; i++) {
let wc = new THREE.Vector3(vertices[i].x, vertices[i].y, vertices[i].z).applyMatrix4(stackHelper.stack._ijk2LPS);
let dc = wc.applyMatrix4(stack2._lps2IJK);
dc.x = Math.round(dc.x * 10) / 10;
dc.y = Math.round(dc.y * 10) / 10;
dc.z = Math.round(dc.z * 10) / 10;
if (dc.x < ijkBBox[0]) {
ijkBBox[0] = dc.x;
}
if (dc.x > ijkBBox[1]) {
ijkBBox[1] = dc.x;
}
// Y
if (dc.y < ijkBBox[2]) {
ijkBBox[2] = dc.y;
}
if (dc.y > ijkBBox[3]) {
ijkBBox[3] = dc.y;
}
// Z
if (dc.z < ijkBBox[4]) {
ijkBBox[4] = dc.z;
}
if (dc.z > ijkBBox[5]) {
ijkBBox[5] = dc.z;
}
}
// round min up and max down
ijkBBox[0] = Math.ceil(ijkBBox[0]);
ijkBBox[2] = Math.ceil(ijkBBox[2]);
ijkBBox[4] = Math.ceil(ijkBBox[4]);
ijkBBox[1] = Math.floor(ijkBBox[1]);
ijkBBox[3] = Math.floor(ijkBBox[3]);
ijkBBox[5] = Math.floor(ijkBBox[5]);
}
/**
*
*/
function setupGUI() {
updateIJKBBox();
// BUILD THE GUI
let gui = new dat.GUI({
autoPlace: false,
});
let customContainer = document.getElementById('my-gui-container');
customContainer.appendChild(gui.domElement);
// PET FOLDER
let layer0Folder = gui.addFolder('PET');
let indexUpdate = layer0Folder.add(stackHelper, 'index', 245, 253).step(1).listen();
indexUpdate.onChange(function() {
updateLayer1();
updateLayerMix();
updateIJKBBox();
});
let updateInterpolation = layer0Folder.add(stackHelper.slice, 'interpolation');
updateInterpolation.onChange(function(value) {
if (value) {
stackHelper.slice.interpolation = 1;
} else {
stackHelper.slice.interpolation = 0;
}
});
layer0Folder.open();
// SEGMENTATION FOLDER
let layerMixFolder = gui.addFolder('Segmentation');
let opacityLayerMix1 = layerMixFolder.add(layerMix, 'opacity1', 0, 1).step(0.01);
opacityLayerMix1.onChange(function(value) {
uniformsLayerMix.uOpacity1.value = value;
});
layerMixFolder.open();
// EDITOR FODLER
let editorFolder = gui.addFolder('Editor');
editorFolder.add(cursor, 'size', 1, 50).step(1);
let brushSegment = editorFolder.add(cursor, 'segment', segmentsList);
brushSegment.onChange(function(value) {
// update color and value
cursor.value = segmentsDict[value].value;
cursor.color = segmentsDict[value].color;
});
editorFolder.open();
}
/**
*
*/
function addListeners() {
/**
*
*/
function onScroll(e) {
if (e.delta > 0) {
if (stackHelper.index >= 253) {
return false;
}
stackHelper.index += 1;
} else {
if (stackHelper.index <= 245) {
return false;
}
stackHelper.index -= 1;
}
updateLayer1();
updateLayerMix();
updateIJKBBox();
}
/**
*
*/
function onWindowResize() {
let threeD = document.getElementById('r3d');
camera.canvas = {
width: threeD.clientWidth,
height: threeD.clientHeight,
};
camera.fitBox(2);
renderer.setSize(threeD.clientWidth, threeD.clientHeight);
canvas.setAttribute('width', canvasDiv.clientWidth);
canvas.setAttribute('height', canvasDiv.clientHeight);
}
onWindowResize();
controls.addEventListener('OnScroll', onScroll);
window.addEventListener('resize', onWindowResize, false);
}
/**
*
*/
function handleSeries() {
//
//
// first stack of first series
let mergedSeries = loader.data[0].mergeSeries(loader.data);
loader.free();
loader = null;
let stack = mergedSeries[0].stack[0];
stack2 = mergedSeries[1].stack[0];
if (stack.modality === 'SEG') {
stack = mergedSeries[0].stack[0];
stack2 = mergedSeries[1].stack[0];
}
stackHelper = new HelpersStack(stack);
stackHelper.bbox.visible = false;
stackHelper.border.visible = false;
stackHelper.index = 247;
stackHelper.slice.interpolation = false;
sceneLayer0.add(stackHelper);
//
//
// create labelmap....
// we only care about the geometry....
// get first stack from series
// prepare it
// * ijk2LPS transforms
// * Z spacing
// * etc.
//
stack2.prepare();
// pixels packing for the fragment shaders now happens there
stack2.pack();
// store segments info
// add "eraser"
segmentsList = ['erase'];
segmentsDict = {
'erase': {
color: '#d9d9d9',
value: 0,
},
};
// add labels
for (let i = 0; i < stack2._segmentationSegments.length; i++) {
let label = stack2._segmentationSegments[i].segmentLabel;
let number = stack2._segmentationSegments[i].segmentNumber;
segmentsList.push(label);
segmentsDict[label] = {
color: `rgba(
${Math.round(stack2._segmentationLUT[number][1]*255)},
${Math.round(stack2._segmentationLUT[number][2]*255)},
${Math.round(stack2._segmentationLUT[number][3]*255)},
1)`,
value: number,
};
}
textures2 = [];
for (let m = 0; m < stack2._rawData.length; m++) {
let tex = new THREE.DataTexture(
stack2.rawData[m],
stack2.textureSize,
stack2.textureSize,
stack2.textureType,
THREE.UnsignedByteType,
THREE.UVMapping,
THREE.ClampToEdgeWrapping,
THREE.ClampToEdgeWrapping,
THREE.NearestFilter,
THREE.NearestFilter);
tex.needsUpdate = true;
tex.flipY = true;
textures2.push(tex);
}
// create material && mesh then add it to sceneLayer1
uniformsLayer1 = ShadersDataUniform.uniforms();
uniformsLayer1.uTextureSize.value = stack2.textureSize;
uniformsLayer1.uTextureContainer.value = textures2;
uniformsLayer1.uWorldToData.value = stack2.lps2IJK;
uniformsLayer1.uNumberOfChannels.value = stack2.numberOfChannels;
uniformsLayer1.uPixelType.value = stack2.pixelType;
uniformsLayer1.uBitsAllocated.value = stack2.bitsAllocated;
uniformsLayer1.uWindowCenterWidth.value = [stack2.windowCenter, stack2.windowWidth];
uniformsLayer1.uRescaleSlopeIntercept.value = [stack2.rescaleSlope, stack2.rescaleIntercept];
uniformsLayer1.uDataDimensions.value = [stack2.dimensionsIJK.x,
stack2.dimensionsIJK.y,
stack2.dimensionsIJK.z];
uniformsLayer1.uInterpolation.value = 0;
// generate shaders on-demand!
let fs = new ShadersDataFragment(uniformsLayer1);
let vs = new ShadersDataVertex();
materialLayer1 = new THREE.ShaderMaterial(
{side: THREE.DoubleSide,
uniforms: uniformsLayer1,
vertexShader: vs.compute(),
fragmentShader: fs.compute(),
});
// add mesh in this scene with right shaders...
meshLayer1 = new THREE.Mesh(stackHelper.slice.geometry, materialLayer1);
// go the LPS space
meshLayer1.applyMatrix(stack._ijk2LPS);
sceneLayer1.add(meshLayer1);
// Create the Mix layer
uniformsLayerMix = ShadersLayerUniform.uniforms();
uniformsLayerMix.uTextureBackTest0.value = sceneLayer0TextureTarget.texture;
uniformsLayerMix.uTextureBackTest1.value = sceneLayer1TextureTarget.texture;
let fls = new ShadersLayerFragment(uniformsLayerMix);
let vls = new ShadersLayerVertex();
materialLayerMix = new THREE.ShaderMaterial(
{side: THREE.DoubleSide,
uniforms: uniformsLayerMix,
vertexShader: vls.compute(),
fragmentShader: fls.compute(),
transparent: true,
});
// add mesh in this scene with right shaders...
meshLayerMix = new THREE.Mesh(stackHelper.slice.geometry, materialLayerMix);
// go the LPS space
meshLayerMix.applyMatrix(stack._ijk2LPS);
sceneLayerMix.add(meshLayerMix);
//
// set camera
let worldbb = stack.worldBoundingBox();
let lpsDims = new THREE.Vector3(
worldbb[1] - worldbb[0],
worldbb[3] - worldbb[2],
worldbb[5] - worldbb[4]
);
// box: {halfDimensions, center}
let box = {
center: stack.worldCenter().clone(),
halfDimensions: new THREE.Vector3(lpsDims.x + 10, lpsDims.y + 10, lpsDims.z + 10),
};
// init and zoom
let canvas = {
width: threeD.clientWidth,
height: threeD.clientHeight,
};
camera.directions = [stack.xCosine, stack.yCosine, stack.zCosine];
camera.box = box;
camera.canvas = canvas;
camera.update();
camera.fitBox(2);
// CREATE LUT
lutLayer0 = new HelpersLut(
'my-lut-canvases-l0',
'default',
'linear',
[[0, 0, 0, 0], [1, 1, 1, 1]],
[[0, 1], [1, 1]]);
lutLayer0.luts = HelpersLut.presetLuts();
lutLayer0.lut = 'random';
stackHelper.slice.lut = 1;
stackHelper.slice.lutTexture = lutLayer0.texture;
lutLayer1 = new HelpersLut(
'my-lut-canvases-l1',
'default',
'linear',
stack2.segmentationLUT,
stack2.segmentationLUTO,
true);
uniformsLayer1.uLut.value = 1;
uniformsLayer1.uTextureLUT.value = lutLayer1.texture;
}
let filenames = [
'000000.dcm', '000001.dcm', '000002.dcm', '000003.dcm', '000004.dcm', '000005.dcm', '000006.dcm', '000007.dcm', '000008.dcm', '000009.dcm', '000010.dcm',
'000011.dcm', '000012.dcm', '000013.dcm', '000014.dcm', '000015.dcm', '000016.dcm', '000017.dcm', '000018.dcm', '000019.dcm', '000020.dcm', '000021.dcm',
'000022.dcm', '000023.dcm', '000024.dcm', '000025.dcm', '000026.dcm', '000027.dcm', '000028.dcm', '000029.dcm', '000030.dcm', '000031.dcm', '000032.dcm',
'000033.dcm', '000034.dcm', '000035.dcm', '000036.dcm', '000037.dcm', '000038.dcm', '000039.dcm', '000040.dcm', '000041.dcm', '000042.dcm', '000043.dcm',
'000044.dcm', '000045.dcm', '000046.dcm', '000047.dcm', '000048.dcm', '000049.dcm', '000050.dcm', '000051.dcm', '000052.dcm', '000053.dcm', '000054.dcm',
'000055.dcm', '000056.dcm', '000057.dcm', '000058.dcm', '000059.dcm', '000060.dcm', '000061.dcm', '000062.dcm', '000063.dcm', '000064.dcm', '000065.dcm',
'000066.dcm', '000067.dcm', '000068.dcm', '000069.dcm', '000070.dcm', '000071.dcm', '000072.dcm', '000073.dcm', '000074.dcm', '000075.dcm', '000076.dcm',
'000077.dcm', '000078.dcm', '000079.dcm', '000080.dcm', '000081.dcm', '000082.dcm', '000083.dcm', '000084.dcm', '000085.dcm', '000086.dcm', '000087.dcm',
'000088.dcm', '000089.dcm', '000090.dcm', '000091.dcm', '000092.dcm', '000093.dcm', '000094.dcm', '000095.dcm', '000096.dcm', '000097.dcm', '000098.dcm',
'000099.dcm', '000100.dcm', '000101.dcm', '000102.dcm', '000103.dcm', '000104.dcm', '000105.dcm', '000106.dcm', '000107.dcm', '000108.dcm', '000109.dcm',
'000110.dcm', '000111.dcm', '000112.dcm', '000113.dcm', '000114.dcm', '000115.dcm', '000116.dcm', '000117.dcm', '000118.dcm', '000119.dcm', '000120.dcm',
'000121.dcm', '000122.dcm', '000123.dcm', '000124.dcm', '000125.dcm', '000126.dcm', '000127.dcm', '000128.dcm', '000129.dcm', '000130.dcm', '000131.dcm',
'000132.dcm', '000133.dcm', '000134.dcm', '000135.dcm', '000136.dcm', '000137.dcm', '000138.dcm', '000139.dcm', '000140.dcm', '000141.dcm', '000142.dcm',
'000143.dcm', '000144.dcm', '000145.dcm', '000146.dcm', '000147.dcm', '000148.dcm', '000149.dcm', '000150.dcm', '000151.dcm', '000152.dcm', '000153.dcm',
'000154.dcm', '000155.dcm', '000156.dcm', '000157.dcm', '000158.dcm', '000159.dcm', '000160.dcm', '000161.dcm', '000162.dcm', '000163.dcm', '000164.dcm',
'000165.dcm', '000166.dcm', '000167.dcm', '000168.dcm', '000169.dcm', '000170.dcm', '000171.dcm', '000172.dcm', '000173.dcm', '000174.dcm', '000175.dcm',
'000176.dcm', '000177.dcm', '000178.dcm', '000179.dcm', '000180.dcm', '000181.dcm', '000182.dcm', '000183.dcm', '000184.dcm', '000185.dcm', '000186.dcm',
'000187.dcm', '000188.dcm', '000189.dcm', '000190.dcm', '000191.dcm', '000192.dcm', '000193.dcm', '000194.dcm', '000195.dcm', '000196.dcm', '000197.dcm',
'000198.dcm', '000199.dcm', '000200.dcm', '000201.dcm', '000202.dcm', '000203.dcm', '000204.dcm', '000205.dcm', '000206.dcm', '000207.dcm', '000208.dcm',
'000209.dcm', '000210.dcm', '000211.dcm', '000212.dcm', '000213.dcm', '000214.dcm', '000215.dcm', '000216.dcm', '000217.dcm', '000218.dcm', '000219.dcm',
'000220.dcm', '000221.dcm', '000222.dcm', '000223.dcm', '000224.dcm', '000225.dcm', '000226.dcm', '000227.dcm', '000228.dcm', '000229.dcm', '000230.dcm',
'000231.dcm', '000232.dcm', '000233.dcm', '000234.dcm', '000235.dcm', '000236.dcm', '000237.dcm', '000238.dcm', '000239.dcm', '000240.dcm', '000241.dcm',
'000242.dcm', '000243.dcm', '000244.dcm', '000245.dcm', '000246.dcm', '000247.dcm', '000248.dcm', '000249.dcm', '000250.dcm', '000251.dcm', '000252.dcm',
'000253.dcm', '000254.dcm', '000255.dcm', '000256.dcm', '000257.dcm', '000258.dcm', '000259.dcm', '000260.dcm', '000261.dcm', '000262.dcm', '000263.dcm',
'000264.dcm', '000265.dcm', '000266.dcm', '000267.dcm', '000268.dcm', '000269.dcm', '000270.dcm', '000271.dcm', '000272.dcm', '000273.dcm', '000274.dcm',
'000275.dcm', '000276.dcm', '000277.dcm', '000278.dcm', '000279.dcm', '000280.dcm', '000281.dcm', '000282.dcm', '000283.dcm', '000284.dcm', '000285.dcm',
'000286.dcm', '000287.dcm', '000288.dcm', '000289.dcm', '000290.dcm', '000291.dcm', '000292.dcm', '000293.dcm', '000294.dcm', '000295.dcm', '000296.dcm',
'000297.dcm', '000298.dcm',
];
let files = filenames.map(function(v) {
return 'https://cdn.rawgit.com/FNNDSC/data/master/dicom/rsna_2/PET/' + v;
});
files.push('https://cdn.rawgit.com/FNNDSC/data/master/dicom/rsna_2/SEG/3DSlicer/tumor_User1_Manual_Trial1.dcm');
// load sequence for each file
// it loads and parses the dicom image
let loader = new LoadersVolume(threeD);
loader.load(files)
.then(function() {
handleSeries();
addListeners();
setupGUI();
setupEditor();
})
.catch(function(error) {
window.console.log('oops... something went wrong...');
window.console.log(error);
});
};