ami
ami copied to clipboard
AMI.CamerasOrthographic is not a constructor
I am making a project which is a website that used as a Dicom viewer. I used the AMI library with an Angular 8 project.
I tried viewers_upload example but this error occurred when I used viewers_upload.js. the error is "AMI.CamerasOrthographic is not a constructor"
I will tell you what I did
1- I made a new Angular 8 project.
2- I run yarn add ami.js
3- Put viewers_upload.html in app.component.html
4- Put viewers_upload.js code inside a function and put it in the assets folder and I added
"scripts": [ "src/assets/js/viewers_upload.js" ]
in the angular.json file.
5- I called the function that contains viewers_upload.js code inside app.component.ts.
Please can you help me because I was trying in this error for 3 days? Thanks a lot
Browsers Affected
- [ ] All
- [x] Chrome
- [ ] Firefox
- [ ] Edge
- [ ] Safari 9
- [ ] Safari 8
- [ ] IE 11
Versions
- AMI: vX.X.X
- THREEJS: vX.X.X
Code of viewers_update.js
/* globals dat*/
// standard global variables
let controls;
let renderer;
let scene;
let camera;
let threeD;
let lut;
let ctrlDown = false;
let drag = {
start: {
x: null,
y: null,
},
};
// probe
let camUtils = {
invertRows: false,
invertColumns: false,
rotate: false,
orientation: 'default',
convention: 'radio',
};
function loadScene()
{
alert("awaaaa");
/**
* Init the scene
*/
function init() {
/**
* Animation loop
*/
function animate() {
// render
controls.update();
renderer.render(scene, camera);
// request new frame
requestAnimationFrame(function() {
animate();
});
}
// renderer
threeD = document.getElementById('r3d');
renderer = new THREE.WebGLRenderer({
antialias: true,
});
renderer.setSize(threeD.clientWidth, threeD.clientHeight);
renderer.setClearColor(0x212121, 1);
threeD.appendChild(renderer.domElement);
// scene
scene = new THREE.Scene();
// camera
camera = new AMI.CamerasOrthographic(
threeD.clientWidth / -2,
threeD.clientWidth / 2,
threeD.clientHeight / 2,
threeD.clientHeight / -2,
0.1,
10000
);
// controls
controls = new AMI.ControlsOrthographic(camera, threeD);
controls.staticMoving = true;
controls.noRotate = true;
camera.controls = controls;
animate();
}
window.onload = function() {
// notify puppeteer to take screenshot
const puppetDiv = document.createElement('div');
puppetDiv.setAttribute('id', 'puppeteer');
document.body.appendChild(puppetDiv);
// hookup load button
document.getElementById('buttoninput').onclick = function() {
document.getElementById('filesinput').click();
};
// init threeJS...
init();
function updateLabels(labels, modality) {
if (modality === 'CR' || modality === 'DX') return;
let top = document.getElementById('top');
top.innerHTML = labels[0];
let bottom = document.getElementById('bottom');
bottom.innerHTML = labels[1];
let right = document.getElementById('right');
right.innerHTML = labels[2];
let left = document.getElementById('left');
left.innerHTML = labels[3];
}
function buildGUI(stackHelper) {
let stack = stackHelper._stack;
let gui = new dat.GUI({
autoPlace: false,
});
let customContainer = document.getElementById('my-gui-container');
customContainer.appendChild(gui.domElement);
let stackFolder = gui.addFolder('Stack');
stackFolder
.add(stackHelper.slice, 'windowWidth', 1, stack.minMax[1] - stack.minMax[0])
.step(1)
.listen();
stackFolder
.add(stackHelper.slice, 'windowCenter', stack.minMax[0], stack.minMax[1])
.step(1)
.listen();
stackFolder
.add(stackHelper.slice, 'lowerThreshold', stack.minMax[0], stack.minMax[1])
.step(1)
.listen();
stackFolder
.add(stackHelper.slice, 'upperThreshold', stack.minMax[0], stack.minMax[1])
.step(1)
.listen();
stackFolder.add(stackHelper.slice, 'intensityAuto').listen();
stackFolder.add(stackHelper.slice, 'invert');
stackFolder
.add(stackHelper.slice, 'interpolation', 0, 1)
.step(1)
.listen();
// CREATE LUT
lut = new HelpersLut(
'my-lut-canvases',
'default',
'linear',
[[0, 0, 0, 0], [1, 1, 1, 1]],
[[0, 1], [1, 1]]
);
lut.luts = HelpersLut.presetLuts();
let lutUpdate = stackFolder.add(stackHelper.slice, 'lut', lut.lutsAvailable());
lutUpdate.onChange(function(value) {
lut.lut = value;
stackHelper.slice.lutTexture = lut.texture;
});
let lutDiscrete = stackFolder.add(lut, 'discrete', false);
lutDiscrete.onChange(function(value) {
lut.discrete = value;
stackHelper.slice.lutTexture = lut.texture;
});
let index = stackFolder
.add(stackHelper, 'index', 0, stack.dimensionsIJK.z - 1)
.step(1)
.listen();
stackFolder.open();
// camera
let cameraFolder = gui.addFolder('Camera');
let invertRows = cameraFolder.add(camUtils, 'invertRows');
invertRows.onChange(function() {
camera.invertRows();
updateLabels(camera.directionsLabel, stack.modality);
});
let invertColumns = cameraFolder.add(camUtils, 'invertColumns');
invertColumns.onChange(function() {
camera.invertColumns();
updateLabels(camera.directionsLabel, stack.modality);
});
let angle = cameraFolder
.add(camera, 'angle', 0, 360)
.step(1)
.listen();
angle.onChange(function() {
updateLabels(camera.directionsLabel, stack.modality);
});
let rotate = cameraFolder.add(camUtils, 'rotate');
rotate.onChange(function() {
camera.rotate();
updateLabels(camera.directionsLabel, stack.modality);
});
let orientationUpdate = cameraFolder.add(camUtils, 'orientation', [
'default',
'axial',
'coronal',
'sagittal',
]);
orientationUpdate.onChange(function(value) {
camera.orientation = value;
camera.update();
camera.fitBox(2);
stackHelper.orientation = camera.stackOrientation;
updateLabels(camera.directionsLabel, stack.modality);
index.__max = stackHelper.orientationMaxIndex;
stackHelper.index = Math.floor(index.__max / 2);
});
let conventionUpdate = cameraFolder.add(camUtils, 'convention', ['radio', 'neuro']);
conventionUpdate.onChange(function(value) {
camera.convention = value;
camera.update();
camera.fitBox(2);
updateLabels(camera.directionsLabel, stack.modality);
});
}
/**
* Connect all callbevent observesrs
*/
function hookCallbacks(stackHelper) {
let stack = stackHelper._stack;
// hook up callbacks
controls.addEventListener('OnScroll', function(e) {
if (e.delta > 0) {
if (stackHelper.index >= stackHelper.orientationMaxIndex - 1) {
return false;
}
stackHelper.index += 1;
} else {
if (stackHelper.index <= 0) {
return false;
}
stackHelper.index -= 1;
}
});
/**
* On window resize callback
*/
function onWindowResize() {
let threeD = document.getElementById('r3d');
camera.canvas = {
width: threeD.clientWidth,
height: threeD.clientHeight,
};
camera.fitBox(2);
renderer.setSize(threeD.clientWidth, threeD.clientHeight);
// update info to draw borders properly
stackHelper.slice.canvasWidth = threeD.clientWidth;
stackHelper.slice.canvasHeight = threeD.clientHeight;
}
window.addEventListener('resize', onWindowResize, false);
onWindowResize();
/**
* On key pressed callback
*/
function onWindowKeyPressed(event) {
ctrlDown = event.ctrlKey;
if (!ctrlDown) {
drag.start.x = null;
drag.start.y = null;
}
}
document.addEventListener('keydown', onWindowKeyPressed, false);
document.addEventListener('keyup', onWindowKeyPressed, false);
/**
* On mouse move callback
*/
function onMouseMove(event) {
if (ctrlDown) {
if (drag.start.x === null) {
drag.start.x = event.clientX;
drag.start.y = event.clientY;
}
let threshold = 15;
stackHelper.slice.intensityAuto = false;
let dynamicRange = stack.minMax[1] - stack.minMax[0];
dynamicRange /= threeD.clientWidth;
if (Math.abs(event.clientX - drag.start.x) > threshold) {
// window width
stackHelper.slice.windowWidth += dynamicRange * (event.clientX - drag.start.x);
drag.start.x = event.clientX;
}
if (Math.abs(event.clientY - drag.start.y) > threshold) {
// window center
stackHelper.slice.windowCenter -= dynamicRange * (event.clientY - drag.start.y);
drag.start.y = event.clientY;
}
}
}
document.addEventListener('mousemove', onMouseMove);
}
/**
* Visulaize incoming data
*/
function handleSeries(seriesContainer) {
// cleanup the loader and its progress bar
loader.free();
loader = null;
// prepare for slice visualization
// first stack of first series
let stack = seriesContainer[0].mergeSeries(seriesContainer)[0].stack[0];
let stackHelper = new HelpersStack(stack);
stackHelper.bbox.visible = false;
stackHelper.borderColor = '#2196F3';
stackHelper.border.visible = false;
scene.add(stackHelper);
// set camera
let worldbb = stack.worldBoundingBox();
let lpsDims = new THREE.Vector3(
(worldbb[1] - worldbb[0]) / 2,
(worldbb[3] - worldbb[2]) / 2,
(worldbb[5] - worldbb[4]) / 2
);
// 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);
updateLabels(camera.directionsLabel, stack.modality);
buildGUI(stackHelper);
hookCallbacks(stackHelper);
}
let loader = new AMI.LoadersVolume(threeD);
let seriesContainer = [];
/**
* Filter array of data by extension
* extension {String}
* item {Object}
* @return {Boolean}
*/
function _filterByExtension(extension, item) {
if (item.extension.toUpperCase() === extension.toUpperCase()) {
return true;
}
return false;
}
/**
* Parse incoming files
*/
function readMultipleFiles(evt) {
// hide the upload button
if (evt.target.files.length) {
document.getElementById('home-container').style.display = 'none';
}
/**
* Load sequence
*/
function loadSequence(index, files) {
return (
Promise.resolve()
// load the file
.then(function() {
return new Promise(function(resolve, reject) {
let myReader = new FileReader();
// should handle errors too...
myReader.addEventListener('load', function(e) {
resolve(e.target.result);
});
myReader.readAsArrayBuffer(files[index]);
});
})
.then(function(buffer) {
return loader.parse({ url: files[index].name, buffer });
})
.then(function(series) {
seriesContainer.push(series);
})
.catch(function(error) {
window.console.log('oops... something went wrong...');
window.console.log(error);
})
);
}
/**
* Load group sequence
*/
function loadSequenceGroup(files) {
const fetchSequence = [];
for (let i = 0; i < files.length; i++) {
fetchSequence.push(
new Promise((resolve, reject) => {
const myReader = new FileReader();
// should handle errors too...
myReader.addEventListener('load', function(e) {
resolve(e.target.result);
});
myReader.readAsArrayBuffer(files[i].file);
}).then(function(buffer) {
return { url: files[i].file.name, buffer };
})
);
}
return Promise.all(fetchSequence)
.then(rawdata => {
return loader.parse(rawdata);
})
.then(function(series) {
seriesContainer.push(series);
})
.catch(function(error) {
window.console.log('oops... something went wrong...');
window.console.log(error);
});
}
const loadSequenceContainer = [];
const data = [];
const dataGroups = [];
// convert object into array
for (let i = 0; i < evt.target.files.length; i++) {
let dataUrl = CoreUtils.parseUrl(evt.target.files[i].name);
if (
dataUrl.extension.toUpperCase() === 'MHD' ||
dataUrl.extension.toUpperCase() === 'RAW' ||
dataUrl.extension.toUpperCase() === 'ZRAW'
) {
dataGroups.push({
file: evt.target.files[i],
extension: dataUrl.extension.toUpperCase(),
});
} else {
data.push(evt.target.files[i]);
}
}
// check if some files must be loaded together
if (dataGroups.length === 2) {
// if raw/mhd pair
const mhdFile = dataGroups.filter(_filterByExtension.bind(null, 'MHD'));
const rawFile = dataGroups.filter(_filterByExtension.bind(null, 'RAW'));
const zrawFile = dataGroups.filter(_filterByExtension.bind(null, 'ZRAW'));
if (mhdFile.length === 1 && (rawFile.length === 1 || zrawFile.length === 1)) {
loadSequenceContainer.push(loadSequenceGroup(dataGroups));
}
}
// load the rest of the files
for (let i = 0; i < data.length; i++) {
loadSequenceContainer.push(loadSequence(i, data));
}
// run the load sequence
// load sequence for all files
Promise.all(loadSequenceContainer)
.then(function() {
handleSeries(seriesContainer);
})
.catch(function(error) {
window.console.log('oops... something went wrong...');
window.console.log(error);
});
}
// hook up file input listener
document.getElementById('filesinput').addEventListener('change', readMultipleFiles, false);
};
}
Hello, unfortunatly I am not familiar with angular - I have no clue what assets are and so on, in the angular context.
It sounds like the error is related to angular not finding AMI.
- Does a simple
threejs
app work in your setup? - It seems like you are missing imports in you JS file, something like the following at the beginning of the file may help:
import * as THREE from 'three';
import * as AMI from 'ami.js';
Good luck,
I solved the error thanks a lot. But there is an error occurred while using viewers_update.js
Here is the error: "do not know how to order the frames..." Can you help me
@SarahMohamedLotfy please can you tell us how you solved the previously mentioned error. Thanks Best regards