@niivue/niivue 0.22.2 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -23
- package/dist/niivue.es.js +108187 -10401
- package/dist/niivue.umd.js +506 -94
- package/package.json +11 -2
- package/src/cmaps/index.js +1 -0
- package/src/cmaps/turbo.json +9 -0
- package/src/colortables.js +79 -0
- package/src/index.html +45 -27
- package/src/indexDraw.html +191 -0
- package/src/logger.js +5 -0
- package/src/meshes.html +161 -0
- package/src/niivue-object3D.js +243 -29
- package/src/niivue-shader3D.js +6 -0
- package/src/niivue.js +2577 -648
- package/src/nvimage.js +1821 -153
- package/src/nvmesh.js +3351 -0
- package/src/shader-srcs.js +565 -11
- package/src/shader.js +11 -2
- package/src/AIL.nii.gz +0 -0
- package/src/hippo.nii.gz +0 -0
- package/src/mni152.nii.gz +0 -0
package/package.json
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@niivue/niivue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"description": "minimal webgl2 nifti image viewer",
|
|
5
5
|
"main": "./src/niivue.js",
|
|
6
6
|
"unpkg": "./dist/niivue.umd.js",
|
|
7
|
+
"module": "./dist/niivue.es.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"require": "./dist/niivue.umd.js",
|
|
11
|
+
"import": "./dist/niivue.es.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
7
14
|
"scripts": {
|
|
8
15
|
"dev": "vite",
|
|
9
16
|
"build": "npx prettier --write src/ && npx vite build --emptyOutDir --base=./ && npm run copy-test && npm run copy-demo",
|
|
@@ -42,6 +49,8 @@
|
|
|
42
49
|
},
|
|
43
50
|
"homepage": "https://github.com/niivue/niivue#readme",
|
|
44
51
|
"dependencies": {
|
|
52
|
+
"daikon": "^1.2.42",
|
|
53
|
+
"fflate": "^0.7.3",
|
|
45
54
|
"gl-matrix": "^3.4.3",
|
|
46
55
|
"nifti-reader-js": "^0.5.4",
|
|
47
56
|
"rxjs": "^7.4.0",
|
|
@@ -51,7 +60,7 @@
|
|
|
51
60
|
"clean-jsdoc-theme": "^3.3.1",
|
|
52
61
|
"eslint": "^8.4.1",
|
|
53
62
|
"express": "^4.17.1",
|
|
54
|
-
"http-server": "^14.
|
|
63
|
+
"http-server": "^14.1.0",
|
|
55
64
|
"jest": "^27.4.4",
|
|
56
65
|
"jest-image-snapshot": "^4.5.1",
|
|
57
66
|
"jest-puppeteer": "^6.0.2",
|
package/src/cmaps/index.js
CHANGED
|
@@ -45,6 +45,7 @@ export { default as red } from "./red.json";
|
|
|
45
45
|
export { default as redyell } from "./redyell.json";
|
|
46
46
|
export { default as rocket } from "./rocket.json";
|
|
47
47
|
export { default as surface } from "./surface.json";
|
|
48
|
+
export { default as turbo } from "./turbo.json";
|
|
48
49
|
export { default as violet } from "./violet.json";
|
|
49
50
|
export { default as viridis } from "./viridis.json";
|
|
50
51
|
export { default as warm } from "./warm.json";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"min": 0,
|
|
3
|
+
"max": 0,
|
|
4
|
+
"R": [48, 48, 64, 70, 65, 25, 132, 195, 244, 254, 218, 122],
|
|
5
|
+
"G": [18, 18, 64, 107, 150, 226, 255, 241, 199, 158, 57, 4],
|
|
6
|
+
"B": [59, 59, 162, 227, 255, 187, 81, 52, 58, 47, 7, 3],
|
|
7
|
+
"A": [0, 22, 26, 30, 34, 43, 52, 57, 63, 67, 77, 86],
|
|
8
|
+
"I": [0, 1, 16, 32, 49, 83, 118, 140, 164, 181, 219, 255]
|
|
9
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as cmaps from "./cmaps";
|
|
2
|
+
|
|
3
|
+
export const colortables = function () {
|
|
4
|
+
this.version = 0.1;
|
|
5
|
+
this.gamma = 1.0;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
colortables.prototype.colorMaps = function (sort = true) {
|
|
9
|
+
let cm = [];
|
|
10
|
+
for (const [key] of Object.entries(cmaps)) {
|
|
11
|
+
cm.push(key);
|
|
12
|
+
}
|
|
13
|
+
return sort === true ? cm.sort() : cm;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// not included in public docs
|
|
17
|
+
colortables.prototype.colormap = function (lutName = "") {
|
|
18
|
+
//function colormap(lutName = "") {
|
|
19
|
+
let defaultLutName = "gray";
|
|
20
|
+
let availMaps = this.colorMaps();
|
|
21
|
+
for (let i = 0; i < availMaps.length; i++) {
|
|
22
|
+
let key = availMaps[i];
|
|
23
|
+
if (lutName.toLowerCase() === key.toLowerCase()) {
|
|
24
|
+
return this.makeLut(
|
|
25
|
+
cmaps[key].R,
|
|
26
|
+
cmaps[key].G,
|
|
27
|
+
cmaps[key].B,
|
|
28
|
+
cmaps[key].A,
|
|
29
|
+
cmaps[key].I
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// if no match the return the default gray lut
|
|
34
|
+
return this.makeLut(
|
|
35
|
+
cmaps[defaultLutName].R,
|
|
36
|
+
cmaps[defaultLutName].G,
|
|
37
|
+
cmaps[defaultLutName].B,
|
|
38
|
+
cmaps[defaultLutName].A,
|
|
39
|
+
cmaps[defaultLutName].I
|
|
40
|
+
);
|
|
41
|
+
}; // colormap()
|
|
42
|
+
|
|
43
|
+
colortables.prototype.colormapFromKey = function (name) {
|
|
44
|
+
let availMaps = luts.colorMaps(); //DoDo let availMaps = this.colorMaps();
|
|
45
|
+
for (let i = 0; i < availMaps.length; i++) {
|
|
46
|
+
let key = availMaps[i];
|
|
47
|
+
if (name.toLowerCase() === key.toLowerCase()) {
|
|
48
|
+
return cmaps[key];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// not included in public docs
|
|
54
|
+
colortables.prototype.makeLut = function (Rs, Gs, Bs, As, Is) {
|
|
55
|
+
//create color lookup table provided arrays of reds, greens, blues, alphas and intensity indices
|
|
56
|
+
//intensity indices should be in increasing order with the first value 0 and the last 255.
|
|
57
|
+
// this.makeLut([0, 255], [0, 0], [0,0], [0,128],[0,255]); //red gradient
|
|
58
|
+
var lut = new Uint8ClampedArray(256 * 4);
|
|
59
|
+
for (var i = 0; i < Is.length - 1; i++) {
|
|
60
|
+
//return a + f * (b - a);
|
|
61
|
+
var idxLo = Is[i];
|
|
62
|
+
var idxHi = Is[i + 1];
|
|
63
|
+
var idxRng = idxHi - idxLo;
|
|
64
|
+
var k = idxLo * 4;
|
|
65
|
+
for (var j = idxLo; j <= idxHi; j++) {
|
|
66
|
+
var f = (j - idxLo) / idxRng;
|
|
67
|
+
lut[k++] = Rs[i] + f * (Rs[i + 1] - Rs[i]); //Red
|
|
68
|
+
lut[k++] = Gs[i] + f * (Gs[i + 1] - Gs[i]); //Green
|
|
69
|
+
lut[k++] = Bs[i] + f * (Bs[i + 1] - Bs[i]); //Blue
|
|
70
|
+
lut[k++] = As[i] + f * (As[i + 1] - As[i]); //Alpha
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (this.gamma === 1.0) return lut;
|
|
74
|
+
for (var i = 0; i < 255 * 4; i++) {
|
|
75
|
+
//lut[i] = ((lut[i] / 255) ^ (1 / this.gamma)) * 255
|
|
76
|
+
lut[i] = Math.pow(lut[i] / 255, 1 / this.gamma) * 255;
|
|
77
|
+
}
|
|
78
|
+
return lut;
|
|
79
|
+
}; // makeLut()
|
package/src/index.html
CHANGED
|
@@ -23,23 +23,11 @@
|
|
|
23
23
|
<h1>
|
|
24
24
|
hot reloadable development preview
|
|
25
25
|
</h1>
|
|
26
|
-
<p>
|
|
27
|
-
<h3>Controls</h3>
|
|
28
|
-
<ul>
|
|
29
|
-
<li>move the crosshairs: left mouse click and drag (or click around)</li>
|
|
30
|
-
<li>slice scrolling: mouse or touch pad scroll up and down (pinch zoom for mobile)</li>
|
|
31
|
-
<li>change intensity range: right mouse click and drag a region (mobile not supported)</li>
|
|
32
|
-
<li>reset intensity: left mouse click double click (mobile not supported)</li>
|
|
33
|
-
<li><b>change the view mode by pressing the "v" key on your keyboard (mobile not supported yet)</b></li>
|
|
34
|
-
<li><b>cycle through clip planes by pressing the "c" key on your keyboard (mobile not supported yet)</b></li>
|
|
35
|
-
</ul>
|
|
36
|
-
</p>
|
|
37
26
|
</section>
|
|
38
|
-
|
|
39
27
|
<!-- demo 1 -->
|
|
40
28
|
<section>
|
|
41
|
-
<div id="demo1" style="width:90%; height:
|
|
42
|
-
<canvas id="gl1" height=
|
|
29
|
+
<div id="demo1" style="width:90%; height:640px;">
|
|
30
|
+
<canvas id="gl1" height=640 width=640>
|
|
43
31
|
</canvas>
|
|
44
32
|
</div>
|
|
45
33
|
</section>
|
|
@@ -50,47 +38,77 @@
|
|
|
50
38
|
|
|
51
39
|
<!-- <script type="module" src="./index.js">
|
|
52
40
|
</script> -->
|
|
53
|
-
<script type="module">
|
|
41
|
+
<script type="module" async>
|
|
54
42
|
import { Niivue } from './niivue.js'
|
|
55
43
|
import {NVImage} from './nvimage.js'
|
|
44
|
+
import {NVMesh} from './nvmesh.js'
|
|
56
45
|
let query = window.location.search
|
|
57
46
|
const params = new URLSearchParams(query);
|
|
58
47
|
let url = params.get('url')
|
|
59
|
-
console.log('url is: ',params.get('url'))
|
|
60
|
-
// console.log(Niivue)
|
|
61
48
|
var volumeList1 = [
|
|
62
49
|
// first item is brackground image
|
|
63
50
|
{
|
|
64
|
-
url: url ? url : "
|
|
51
|
+
//url: url ? url : "../demos/images/example4d+orig.HEAD",//"./AIL.nii.gz",//"./images/RAS.nii.gz", "./images/spm152.nii.gz",
|
|
52
|
+
url: url ? url : "../tests/images/mni152.nii.gz",//"./AIL.nii.gz",//"./images/RAS.nii.gz", "./images/spm152.nii.gz",
|
|
65
53
|
//url: "./mni152.nii.gz",
|
|
66
|
-
|
|
54
|
+
colorMap: "gray",
|
|
55
|
+
//urlImgData : "../demos/images/example4d+orig.BRIK.gz",
|
|
67
56
|
opacity: 1,
|
|
68
57
|
visible: true,
|
|
69
58
|
},
|
|
70
59
|
{
|
|
71
|
-
url:
|
|
72
|
-
colorMap:
|
|
60
|
+
url:'../tests/images/hippo.nii.gz',
|
|
61
|
+
colorMap: "winter"
|
|
73
62
|
}
|
|
74
63
|
]
|
|
75
64
|
var nv1 = new Niivue({
|
|
76
|
-
logging:
|
|
65
|
+
logging: false,
|
|
77
66
|
show3Dcrosshair: true,
|
|
78
67
|
loadingText: 'there are no images',
|
|
79
|
-
dragAndDropEnabled: true
|
|
68
|
+
dragAndDropEnabled: true,
|
|
69
|
+
backColor: [0.3, 0.2, 0.4, 1],
|
|
70
|
+
thumbnail: "../demos/images/DoG.png"
|
|
80
71
|
})
|
|
81
72
|
nv1.setRadiologicalConvention(false)
|
|
82
73
|
nv1.attachTo('gl1')
|
|
83
|
-
|
|
84
|
-
//nv1.setSliceType(nv1.sliceTypeMultiplanar)
|
|
74
|
+
|
|
85
75
|
nv1.setSliceType(nv1.sliceTypeRender)
|
|
76
|
+
nv1.setClipPlane([-0.1, 270, 0])
|
|
77
|
+
nv1.setRenderAzimuthElevation(90,10)
|
|
78
|
+
|
|
79
|
+
await nv1.loadVolumes(volumeList1)
|
|
80
|
+
|
|
81
|
+
var meshLayersList1 = [
|
|
82
|
+
//{url: "../demos/images/PJM-stc-lh.stc", colorMap: "rocket", opacity: 0.7},
|
|
83
|
+
//{url: "../demos/images/boggle.lh.annot", colorMap: "rocket", opacity: 0.9},
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
await nv1.loadMeshes([
|
|
87
|
+
{url: "../demos/images/dpsv.trx", rgba255 : [255, 255, 255, 255], layers : meshLayersList1},
|
|
88
|
+
//{url: "../demos/images/mni152_2009AO.mz3", rgba255 : [255, 255, 255, 255]},
|
|
89
|
+
//{url: "../demos/images/BrainMesh_ICBM152.lh.mz3", rgba255 : [255, 255, 255, 255], layers : meshLayersList1},
|
|
90
|
+
//{url: "../demos/images/PJM-example-lh.gii", rgba255 : [255, 255, 255, 255], layers : meshLayersList1},
|
|
91
|
+
])
|
|
92
|
+
|
|
86
93
|
// example of using the 'location' change event with a callback function
|
|
87
94
|
nv1.on('location', (data) => {
|
|
88
95
|
// data is an object with properties: {mm: [N N N], vox: [N N N], frac: [N N N]}
|
|
89
96
|
document.getElementById('location').innerHTML = 'voxel location: ' + data.vox + ' ' + data.values
|
|
90
|
-
|
|
91
97
|
})
|
|
92
98
|
|
|
93
|
-
|
|
99
|
+
nv1.on('imageLoaded', (image) => {
|
|
100
|
+
console.log('imageLoaded', image.name)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
nv1.on('intensityRange', (image) => {
|
|
104
|
+
console.log(image.cal_min, image.cal_max)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
setTimeout(() => {
|
|
108
|
+
//nv1.saveImage('test.nii.gz')
|
|
109
|
+
}, 2000)
|
|
110
|
+
|
|
111
|
+
</script>
|
|
94
112
|
</div>
|
|
95
113
|
</body>
|
|
96
114
|
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
7
|
+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
8
|
+
<title>NiiVue</title>
|
|
9
|
+
<style>
|
|
10
|
+
section {
|
|
11
|
+
margin: 20px;
|
|
12
|
+
}
|
|
13
|
+
</style>
|
|
14
|
+
</head>
|
|
15
|
+
|
|
16
|
+
<body style="font-family: sans-serif;">
|
|
17
|
+
<div id="app">
|
|
18
|
+
<noscript>
|
|
19
|
+
<strong>niivue doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
|
20
|
+
</noscript>
|
|
21
|
+
|
|
22
|
+
<section>
|
|
23
|
+
<h1>
|
|
24
|
+
hot reloadable development preview
|
|
25
|
+
</h1>
|
|
26
|
+
</section>
|
|
27
|
+
<section>
|
|
28
|
+
<div>
|
|
29
|
+
<label for="drawPen">Draw color:</label>
|
|
30
|
+
<select name="drawPen" id="drawPen">
|
|
31
|
+
<option value="-1">Off</option>
|
|
32
|
+
<option value="0">Erase</option>
|
|
33
|
+
<option value="1">Red</option>
|
|
34
|
+
<option value="2">Green</option>
|
|
35
|
+
<option value="3">Blue</option>
|
|
36
|
+
<option value="8">Filled Erase</option>
|
|
37
|
+
<option value="9">Filled Red</option>
|
|
38
|
+
<option value="10">Filled Green</option>
|
|
39
|
+
<option value="11">Filled Blue</option>
|
|
40
|
+
</select>
|
|
41
|
+
<button id="left">left</button>
|
|
42
|
+
<button id="right">right</button>
|
|
43
|
+
<button id="posterior">posterior</button>
|
|
44
|
+
<button id="anterior">anterior</button>
|
|
45
|
+
<button id="inferior">inferior</button>
|
|
46
|
+
<button id="superior">superior</button>
|
|
47
|
+
<button id="info">info</button>
|
|
48
|
+
<button id="save">save drawing</button>
|
|
49
|
+
<button id="undo">undo</button>
|
|
50
|
+
<button id="growcut">grow cut</button>
|
|
51
|
+
<input type="checkbox" id="check1" name="check1" checked>
|
|
52
|
+
<label for="check1">fill pen overwrites</label>
|
|
53
|
+
|
|
54
|
+
<div class="slidecontainer">
|
|
55
|
+
drawing opacity <input type="range" min="0" max="100" value="80" class="slider" id="drawOpacity">
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
</div>
|
|
59
|
+
</section>
|
|
60
|
+
<!-- demo 1 -->
|
|
61
|
+
<section>
|
|
62
|
+
<div id="demo1" style="width:90%; height:640px;">
|
|
63
|
+
<canvas id="gl1" height=640 width=640>
|
|
64
|
+
</canvas>
|
|
65
|
+
</div>
|
|
66
|
+
</section>
|
|
67
|
+
|
|
68
|
+
<section>
|
|
69
|
+
<p id="location"></p>
|
|
70
|
+
</section>
|
|
71
|
+
<!-- <script type="module" src="./index.js">
|
|
72
|
+
</script> -->
|
|
73
|
+
<script type="module" async>
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
document.getElementById("drawOpacity").addEventListener("change", doDrawOpacity);
|
|
77
|
+
function doDrawOpacity(){
|
|
78
|
+
nv1.setDrawOpacity(this.value * 0.01);
|
|
79
|
+
}
|
|
80
|
+
document.getElementById("check1").addEventListener("change", doCheckClick);
|
|
81
|
+
function doCheckClick() {
|
|
82
|
+
console.log(this.checked);
|
|
83
|
+
nv1.drawFillOverwrites = this.checked;
|
|
84
|
+
}
|
|
85
|
+
document.getElementById("drawPen").addEventListener("change", doDrawPen);
|
|
86
|
+
function doDrawPen(){
|
|
87
|
+
const mode = parseInt(document.getElementById("drawPen").value);
|
|
88
|
+
nv1.setDrawingEnabled(mode >= 0);
|
|
89
|
+
if (mode >= 0)
|
|
90
|
+
nv1.setPenValue( (mode & 7), mode > 7);
|
|
91
|
+
}
|
|
92
|
+
document.getElementById("left").addEventListener("click", doLeft);
|
|
93
|
+
function doLeft(){
|
|
94
|
+
nv1.moveCrosshairInVox(-1, 0, 0);
|
|
95
|
+
}
|
|
96
|
+
document.getElementById("right").addEventListener("click", doRight);
|
|
97
|
+
function doRight(){
|
|
98
|
+
nv1.moveCrosshairInVox(1, 0, 0);
|
|
99
|
+
}
|
|
100
|
+
document.getElementById("posterior").addEventListener("click", doPosterior);
|
|
101
|
+
function doPosterior(){
|
|
102
|
+
nv1.moveCrosshairInVox(0, -1, 0);
|
|
103
|
+
}
|
|
104
|
+
document.getElementById("anterior").addEventListener("click", doAnterior);
|
|
105
|
+
function doAnterior(){
|
|
106
|
+
nv1.moveCrosshairInVox(0, 1, 0);
|
|
107
|
+
}
|
|
108
|
+
document.getElementById("inferior").addEventListener("click", doInferior);
|
|
109
|
+
function doInferior(){
|
|
110
|
+
nv1.moveCrosshairInVox(0, 0, -1);
|
|
111
|
+
}
|
|
112
|
+
document.getElementById("info").addEventListener("click", doInfo);
|
|
113
|
+
function doInfo(){
|
|
114
|
+
let obj = nv1.getDescriptives(0, false);
|
|
115
|
+
let str = "Number of voxels: " +
|
|
116
|
+
obj.nvox +
|
|
117
|
+
"\nMin:" +
|
|
118
|
+
obj.min +
|
|
119
|
+
"\nMax:" +
|
|
120
|
+
obj.max +
|
|
121
|
+
"\nMean:" +
|
|
122
|
+
obj.mean +
|
|
123
|
+
"\nStandard deviation: " +
|
|
124
|
+
obj.stdev +
|
|
125
|
+
"\nRobust Min: " +
|
|
126
|
+
obj.robust_min +
|
|
127
|
+
"\nRobust Max: " +
|
|
128
|
+
obj.robust_max;
|
|
129
|
+
alert(str);
|
|
130
|
+
}
|
|
131
|
+
document.getElementById("superior").addEventListener("click", doSuperior);
|
|
132
|
+
function doSuperior(){
|
|
133
|
+
nv1.moveCrosshairInVox(0, 0, 1);
|
|
134
|
+
}
|
|
135
|
+
document.getElementById("undo").addEventListener("click", doUndo);
|
|
136
|
+
function doUndo(){
|
|
137
|
+
nv1.drawUndo();
|
|
138
|
+
}
|
|
139
|
+
document.getElementById("growcut").addEventListener("click", doGrowCut);
|
|
140
|
+
function doGrowCut(){
|
|
141
|
+
nv1.drawGrowCut();
|
|
142
|
+
}
|
|
143
|
+
document.getElementById("save").addEventListener("click", doSave);
|
|
144
|
+
function doSave(){
|
|
145
|
+
nv1.saveImage('test.nii', true);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
import { Niivue } from './niivue.js'
|
|
149
|
+
import {NVImage} from './nvimage.js'
|
|
150
|
+
import {NVMesh} from './nvmesh.js'
|
|
151
|
+
let query = window.location.search
|
|
152
|
+
const params = new URLSearchParams(query);
|
|
153
|
+
let url = params.get('url')
|
|
154
|
+
var volumeList1 = [
|
|
155
|
+
// first item is brackground image
|
|
156
|
+
{
|
|
157
|
+
//url: url ? url : "../demos/images/example4d+orig.HEAD",//"./AIL.nii.gz",//"./images/RAS.nii.gz", "./images/spm152.nii.gz",
|
|
158
|
+
url: url ? url : "../demos/images/FLAIR.nii.gz",//"./AIL.nii.gz",//"./images/RAS.nii.gz", "./images/spm152.nii.gz",
|
|
159
|
+
//url: url ? url : "../demos/images/mask.nii",//"./AIL.nii.gz",//"./images/RAS.nii.gz", "./images/spm152.nii.gz",
|
|
160
|
+
//url: "./mni152.nii.gz",
|
|
161
|
+
colorMap: "gray",
|
|
162
|
+
//urlImgData : "../demos/images/example4d+orig.BRIK.gz",
|
|
163
|
+
opacity: 1,
|
|
164
|
+
visible: true,
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
]
|
|
168
|
+
var nv1 = new Niivue({
|
|
169
|
+
logging: false,
|
|
170
|
+
show3Dcrosshair: true,
|
|
171
|
+
loadingText: 'there are no images',
|
|
172
|
+
dragAndDropEnabled: true,
|
|
173
|
+
backColor: [0.3, 0.2, 0.4, 1],
|
|
174
|
+
//thumbnail: "../demos/images/DoG.png"
|
|
175
|
+
})
|
|
176
|
+
nv1.setRadiologicalConvention(false)
|
|
177
|
+
nv1.attachTo('gl1')
|
|
178
|
+
//nv1.setInterpolation(1);
|
|
179
|
+
await nv1.loadVolumes(volumeList1)
|
|
180
|
+
nv1.getDescriptives(0, false);
|
|
181
|
+
nv1.loadDrawing("../demos/images/lesion.nii.gz");
|
|
182
|
+
// example of using the 'location' change event with a callback function
|
|
183
|
+
nv1.on('location', (data) => {
|
|
184
|
+
// data is an object with properties: {mm: [N N N], vox: [N N N], frac: [N N N]}
|
|
185
|
+
document.getElementById('location').innerHTML = 'voxel location: ' + data.vox + ' ' + data.values
|
|
186
|
+
})
|
|
187
|
+
</script>
|
|
188
|
+
</div>
|
|
189
|
+
</body>
|
|
190
|
+
|
|
191
|
+
</html>
|
package/src/logger.js
CHANGED
package/src/meshes.html
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
7
|
+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
8
|
+
<title>NiiVue</title>
|
|
9
|
+
<style>
|
|
10
|
+
section {
|
|
11
|
+
margin: 20px;
|
|
12
|
+
}
|
|
13
|
+
</style>
|
|
14
|
+
</head>
|
|
15
|
+
|
|
16
|
+
<body style="font-family: sans-serif;">
|
|
17
|
+
<div id="app">
|
|
18
|
+
<noscript>
|
|
19
|
+
<strong>niivue doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
|
20
|
+
</noscript>
|
|
21
|
+
|
|
22
|
+
<section>
|
|
23
|
+
<h1>
|
|
24
|
+
hot reloadable development preview
|
|
25
|
+
</h1>
|
|
26
|
+
</section>
|
|
27
|
+
<div class="slidecontainer">
|
|
28
|
+
intensity Max <input type="range" min="1" max="12" value="3" class="slider" id="fiberLengthSlider">
|
|
29
|
+
</div>
|
|
30
|
+
<div class="slidecontainer">
|
|
31
|
+
fiber dither <input type="range" min="0" max="10" value="1" class="slider" id="fiberDitherSlider">
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<!-- demo 1 -->
|
|
35
|
+
<section>
|
|
36
|
+
<div id="demo1" style="width:90%; height:640px;">
|
|
37
|
+
<canvas id="gl1" height=640 width=640>
|
|
38
|
+
</canvas>
|
|
39
|
+
</div>
|
|
40
|
+
</section>
|
|
41
|
+
|
|
42
|
+
<section>
|
|
43
|
+
<p id="location"></p>
|
|
44
|
+
</section>
|
|
45
|
+
|
|
46
|
+
<!-- <script type="module" src="./index.js">
|
|
47
|
+
</script> -->
|
|
48
|
+
<script type="module" async>
|
|
49
|
+
var slider = document.getElementById("fiberLengthSlider");
|
|
50
|
+
var sliderD = document.getElementById("fiberDitherSlider");
|
|
51
|
+
// Update the current slider value (each time you drag the slider handle)
|
|
52
|
+
slider.oninput = function() {
|
|
53
|
+
nv1.setMeshLayerProperty(nv1.meshes[0].id, 0, 'cal_min', this.value)
|
|
54
|
+
nv1.setMeshLayerProperty(nv1.meshes[0].id, 0, 'cal_max', this.value + 2)
|
|
55
|
+
}
|
|
56
|
+
sliderD.oninput = function() {
|
|
57
|
+
nv1.setMeshProperty(nv1.meshes[0].id, 'fiberDither', this.value * 0.1)
|
|
58
|
+
}
|
|
59
|
+
import { Niivue } from './niivue.js'
|
|
60
|
+
import {NVImage} from './nvimage.js'
|
|
61
|
+
import {NVMesh} from './nvmesh.js'
|
|
62
|
+
let query = window.location.search
|
|
63
|
+
const params = new URLSearchParams(query);
|
|
64
|
+
let url = params.get('url')
|
|
65
|
+
console.log('url is: ',params.get('url'))
|
|
66
|
+
// console.log(Niivue)
|
|
67
|
+
let connectome = {
|
|
68
|
+
"name": "simpleConnectome",
|
|
69
|
+
"nodeColormap": "viridis",
|
|
70
|
+
"nodeColormapNegative": "viridis",
|
|
71
|
+
"nodeMinColor": 2,
|
|
72
|
+
"nodeMaxColor": 4,
|
|
73
|
+
"nodeScale": 3, //scale factor for node, e.g. if 2 and a node has size 3, a 6mm ball is drawn
|
|
74
|
+
"edgeColormap": "warm",
|
|
75
|
+
"edgeColormapNegative": "winter",
|
|
76
|
+
"edgeMin": 2,
|
|
77
|
+
"edgeMax": 4,
|
|
78
|
+
"edgeScale": 1,
|
|
79
|
+
"nodes": {
|
|
80
|
+
"names":["RF", "LF", "RP","LP"], //currently unused
|
|
81
|
+
"X":[40, -40, 40, -40], //Xmm for each node
|
|
82
|
+
"Y":[40, 40, -40, -40], //Ymm for each node
|
|
83
|
+
"Z":[30, 20, 50, 50], //Zmm for each node
|
|
84
|
+
"Color":[2, 2, 3, 4], //Used to interpolate color
|
|
85
|
+
"Size":[2, 2, 3, 4], //Size of node
|
|
86
|
+
},
|
|
87
|
+
"edges": [1, 2, -3, 4,
|
|
88
|
+
0, 1, 0, 6,
|
|
89
|
+
0, 0, 1, 0,
|
|
90
|
+
0, 0, 0, 1,],
|
|
91
|
+
}
|
|
92
|
+
var volumeList1 = [
|
|
93
|
+
// first item is brackground image
|
|
94
|
+
{
|
|
95
|
+
//url: url ? url : "../demos/images/example4d+orig.HEAD",//"./AIL.nii.gz",//"./images/RAS.nii.gz", "./images/spm152.nii.gz",
|
|
96
|
+
url: url ? url : "../tests/images/mni152.nii.gz",//"./AIL.nii.gz",//"./images/RAS.nii.gz", "./images/spm152.nii.gz",
|
|
97
|
+
//url: "./mni152.nii.gz",
|
|
98
|
+
colorMap: "gray",
|
|
99
|
+
//urlImgData : "../demos/images/example4d+orig.BRIK.gz",
|
|
100
|
+
opacity: 1,
|
|
101
|
+
visible: true,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
url: "../demos/images/hippo.nii.gz",
|
|
105
|
+
colorMap: 'red'
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
var nv1 = new Niivue({
|
|
109
|
+
logging: true,
|
|
110
|
+
show3Dcrosshair: true,
|
|
111
|
+
loadingText: 'there are no images',
|
|
112
|
+
dragAndDropEnabled: true,
|
|
113
|
+
backColor: [0.3, 0.2, 0.4, 1],
|
|
114
|
+
//thumbnail: "../demos/images/DoG.png"
|
|
115
|
+
})
|
|
116
|
+
nv1.setRadiologicalConvention(false)
|
|
117
|
+
nv1.attachTo('gl1')
|
|
118
|
+
//await nv1.loadVolumes(volumeList1)
|
|
119
|
+
|
|
120
|
+
// nv1.createEmptyDrawing()
|
|
121
|
+
|
|
122
|
+
var meshLayersList1 = [
|
|
123
|
+
{url: "../demos/images/lh.curv", colorMap: "rocket", opacity: 0.7},
|
|
124
|
+
//{url: "../demos/images/boggle.lh.annot", colorMap: "rocket", opacity: 0.9},
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
nv1.loadMeshes([
|
|
129
|
+
{url: "../demos/images/lh.pial", rgba255 : [255, 255, 255, 255], layers : meshLayersList1},
|
|
130
|
+
//{url: "../demos/images/BrainMesh_ICBM152.lh.mz3", rgba255 : [255, 255, 255, 255], layers : meshLayersList1},
|
|
131
|
+
//{url: "../demos/images/PJM-example-lh.gii", rgba255 : [255, 255, 255, 255], layers : meshLayersList1},
|
|
132
|
+
])
|
|
133
|
+
|
|
134
|
+
//nv1.loadConnectome(connectome)
|
|
135
|
+
//nv1.setSliceType(nv1.sliceTypeMultiplanar)
|
|
136
|
+
nv1.setSliceType(nv1.sliceTypeRender)
|
|
137
|
+
nv1.setClipPlane([-0.1, 90, 0])
|
|
138
|
+
nv1.setRenderAzimuthElevation(90,10)
|
|
139
|
+
//nv1.volumes[0].frame4D = 5;
|
|
140
|
+
|
|
141
|
+
//nv1.updateGLVolume()
|
|
142
|
+
// example of using the 'location' change event with a callback function
|
|
143
|
+
nv1.on('location', (data) => {
|
|
144
|
+
// data is an object with properties: {mm: [N N N], vox: [N N N], frac: [N N N]}
|
|
145
|
+
document.getElementById('location').innerHTML = 'voxel location: ' + data.vox + ' ' + data.values
|
|
146
|
+
//nv1.volumes[0].frame4D = Math.floor(Math.random() * 9);
|
|
147
|
+
//nv1.updateGLVolume()
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
nv1.on('imageLoaded', (image) => {
|
|
151
|
+
console.log('imageLoaded', image.name)
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
nv1.on('intensityRange', (image) => {
|
|
155
|
+
console.log(image.cal_min, image.cal_max)
|
|
156
|
+
})
|
|
157
|
+
</script>
|
|
158
|
+
</div>
|
|
159
|
+
</body>
|
|
160
|
+
|
|
161
|
+
</html>
|