@niivue/niivue 0.16.0 → 0.17.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 +1 -1
- package/dist/niivue.es.js +73 -46
- package/dist/niivue.umd.js +15 -15
- package/package.json +1 -1
- package/src/hippo.nii.gz +0 -0
- package/src/index.html +8 -3
- package/src/logger.js +13 -15
- package/src/niivue.js +47 -34
- package/src/nvimage.js +16 -0
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ We host many NiiVue examples via github pages. These are updated and deployed au
|
|
|
38
38
|
|
|
39
39
|
## existing html page
|
|
40
40
|
```html
|
|
41
|
-
<script src="https://unpkg.com/@niivue/niivue@0.
|
|
41
|
+
<script src="https://unpkg.com/@niivue/niivue@0.17.0/dist/niivue.umd.js"></script>
|
|
42
42
|
|
|
43
43
|
<canvas id="gl" height=480 width=640></canvas>
|
|
44
44
|
|
package/dist/niivue.es.js
CHANGED
|
@@ -10559,6 +10559,16 @@ NVImage.prototype.vox2mm = function(XYZ, mtx) {
|
|
|
10559
10559
|
let pos3 = fromValues$1(pos[0], pos[1], pos[2]);
|
|
10560
10560
|
return pos3;
|
|
10561
10561
|
};
|
|
10562
|
+
NVImage.prototype.mm2vox = function(mm) {
|
|
10563
|
+
let sform = fromValues$2(...this.hdr.affine.flat());
|
|
10564
|
+
let out = clone(sform);
|
|
10565
|
+
transpose(out, sform);
|
|
10566
|
+
invert(out, out);
|
|
10567
|
+
let pos = fromValues(mm[0], mm[1], mm[2], 1);
|
|
10568
|
+
transformMat4(pos, pos, out);
|
|
10569
|
+
let pos3 = fromValues$1(pos[0], pos[1], pos[2]);
|
|
10570
|
+
return [Math.round(pos3[0]), Math.round(pos3[1]), Math.round(pos3[2])];
|
|
10571
|
+
};
|
|
10562
10572
|
NVImage.prototype.arrayEquals = function(a, b) {
|
|
10563
10573
|
return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((val, index) => val === b[index]);
|
|
10564
10574
|
};
|
|
@@ -10785,35 +10795,37 @@ String.prototype.getBytes = function() {
|
|
|
10785
10795
|
}
|
|
10786
10796
|
return bytes;
|
|
10787
10797
|
};
|
|
10798
|
+
NVImage.prototype.getValue = function(x, y, z) {
|
|
10799
|
+
const { nx, ny } = this.getImageMetadata();
|
|
10800
|
+
return this.img[x + y * nx + z * nx * ny];
|
|
10801
|
+
};
|
|
10788
10802
|
const Log = function(logLevel) {
|
|
10789
|
-
this.
|
|
10790
|
-
this.
|
|
10791
|
-
this.
|
|
10792
|
-
this.ERROR = "error";
|
|
10793
|
-
this.LOG_PREFIX = "NiiVue: ";
|
|
10803
|
+
this.LOGGING_ON = true;
|
|
10804
|
+
this.LOGGING_OFF = false;
|
|
10805
|
+
this.LOG_PREFIX = "NiiVue:";
|
|
10794
10806
|
this.logLevel = logLevel;
|
|
10795
10807
|
};
|
|
10796
10808
|
Log.prototype.getTimeStamp = function() {
|
|
10797
|
-
return `${this.LOG_PREFIX}
|
|
10809
|
+
return `${this.LOG_PREFIX} `;
|
|
10798
10810
|
};
|
|
10799
10811
|
Log.prototype.debug = function() {
|
|
10800
|
-
if (this.logLevel === this.
|
|
10801
|
-
console.log(this.getTimeStamp(), ...arguments);
|
|
10812
|
+
if (this.logLevel === this.LOGGING_ON) {
|
|
10813
|
+
console.log(this.getTimeStamp(), "DEBUG", ...arguments);
|
|
10802
10814
|
}
|
|
10803
10815
|
};
|
|
10804
10816
|
Log.prototype.info = function() {
|
|
10805
|
-
if (this.logLevel === this.
|
|
10806
|
-
console.log(this.getTimeStamp(), ...arguments);
|
|
10817
|
+
if (this.logLevel === this.LOGGING_ON) {
|
|
10818
|
+
console.log(this.getTimeStamp(), "INFO", ...arguments);
|
|
10807
10819
|
}
|
|
10808
10820
|
};
|
|
10809
10821
|
Log.prototype.warn = function() {
|
|
10810
|
-
if (this.logLevel === this.
|
|
10811
|
-
console.warn(this.getTimeStamp(), ...arguments);
|
|
10822
|
+
if (this.logLevel === this.LOGGING_ON) {
|
|
10823
|
+
console.warn(this.getTimeStamp(), "WARN", ...arguments);
|
|
10812
10824
|
}
|
|
10813
10825
|
};
|
|
10814
10826
|
Log.prototype.error = function() {
|
|
10815
|
-
if (this.logLevel === this.
|
|
10816
|
-
console.error(this.getTimeStamp(), ...arguments);
|
|
10827
|
+
if (this.logLevel === this.LOGGING_ON) {
|
|
10828
|
+
console.error(this.getTimeStamp(), "ERROR", ...arguments);
|
|
10817
10829
|
}
|
|
10818
10830
|
};
|
|
10819
10831
|
Log.prototype.setLogLevel = function(logLevel) {
|
|
@@ -12370,7 +12382,7 @@ const Niivue = function(options = {}) {
|
|
|
12370
12382
|
viewModeHotKey: "KeyV",
|
|
12371
12383
|
keyDebounceTime: 50,
|
|
12372
12384
|
isRadiologicalConvention: false,
|
|
12373
|
-
|
|
12385
|
+
logging: false
|
|
12374
12386
|
};
|
|
12375
12387
|
this.canvas = null;
|
|
12376
12388
|
this.gl = null;
|
|
@@ -12440,7 +12452,7 @@ const Niivue = function(options = {}) {
|
|
|
12440
12452
|
this.intensityRange$ = new Subject();
|
|
12441
12453
|
this.scene.location$ = new Subject();
|
|
12442
12454
|
this.scene.loading$ = new Subject();
|
|
12443
|
-
this.loadingText = "
|
|
12455
|
+
this.loadingText = "waiting for images...";
|
|
12444
12456
|
this.currentClipPlaneIndex = 0;
|
|
12445
12457
|
this.lastCalled = new Date().getTime();
|
|
12446
12458
|
this.multiTouchGesture = false;
|
|
@@ -12453,7 +12465,7 @@ const Niivue = function(options = {}) {
|
|
|
12453
12465
|
for (let prop in this.defaults) {
|
|
12454
12466
|
this.opts[prop] = options[prop] === void 0 ? this.defaults[prop] : options[prop];
|
|
12455
12467
|
}
|
|
12456
|
-
log.setLogLevel(this.opts.
|
|
12468
|
+
log.setLogLevel(this.opts.logging);
|
|
12457
12469
|
this.eventsToSubjects = {
|
|
12458
12470
|
location: this.scene.location$,
|
|
12459
12471
|
loading: this.scene.loading$
|
|
@@ -12462,7 +12474,7 @@ const Niivue = function(options = {}) {
|
|
|
12462
12474
|
};
|
|
12463
12475
|
Niivue.prototype.attachTo = async function(id) {
|
|
12464
12476
|
await this.attachToCanvas(document.getElementById(id));
|
|
12465
|
-
log.debug("attached to
|
|
12477
|
+
log.debug("attached to element with id: ", id);
|
|
12466
12478
|
return this;
|
|
12467
12479
|
};
|
|
12468
12480
|
Niivue.prototype.on = function(event, callback) {
|
|
@@ -12587,14 +12599,14 @@ function intensityRaw2Scaled(hdr, raw) {
|
|
|
12587
12599
|
hdr.scl_slope = 1;
|
|
12588
12600
|
return raw * hdr.scl_slope + hdr.scl_inter;
|
|
12589
12601
|
}
|
|
12590
|
-
Niivue.prototype.calculateNewRange = function() {
|
|
12602
|
+
Niivue.prototype.calculateNewRange = function(volIdx = 0) {
|
|
12591
12603
|
if (this.sliceType === this.sliceTypeRender) {
|
|
12592
12604
|
return;
|
|
12593
12605
|
}
|
|
12594
12606
|
let frac = this.canvasPos2frac([this.dragStart[0], this.dragStart[1]]);
|
|
12595
|
-
let startVox = this.frac2vox(frac);
|
|
12607
|
+
let startVox = this.frac2vox(frac, volIdx);
|
|
12596
12608
|
frac = this.canvasPos2frac([this.dragEnd[0], this.dragEnd[1]]);
|
|
12597
|
-
let endVox = this.frac2vox(frac);
|
|
12609
|
+
let endVox = this.frac2vox(frac, volIdx);
|
|
12598
12610
|
let hi = -Number.MAX_VALUE, lo = Number.MAX_VALUE;
|
|
12599
12611
|
let xrange;
|
|
12600
12612
|
let yrange;
|
|
@@ -12609,8 +12621,8 @@ Niivue.prototype.calculateNewRange = function() {
|
|
|
12609
12621
|
} else if (startVox[2] - endVox[2] === 0) {
|
|
12610
12622
|
zrange[1] = startVox[2] + 1;
|
|
12611
12623
|
}
|
|
12612
|
-
const hdr = this.volumes[
|
|
12613
|
-
const img = this.volumes[
|
|
12624
|
+
const hdr = this.volumes[volIdx].hdr;
|
|
12625
|
+
const img = this.volumes[volIdx].img;
|
|
12614
12626
|
const xdim = hdr.dims[1];
|
|
12615
12627
|
const ydim = hdr.dims[2];
|
|
12616
12628
|
for (let z = zrange[0]; z < zrange[1]; z++) {
|
|
@@ -12630,8 +12642,8 @@ Niivue.prototype.calculateNewRange = function() {
|
|
|
12630
12642
|
}
|
|
12631
12643
|
var mnScale = intensityRaw2Scaled(hdr, lo);
|
|
12632
12644
|
var mxScale = intensityRaw2Scaled(hdr, hi);
|
|
12633
|
-
this.volumes[
|
|
12634
|
-
this.volumes[
|
|
12645
|
+
this.volumes[volIdx].cal_min = mnScale;
|
|
12646
|
+
this.volumes[volIdx].cal_max = mxScale;
|
|
12635
12647
|
this.intensityRange$.next([mnScale, mxScale]);
|
|
12636
12648
|
};
|
|
12637
12649
|
Niivue.prototype.mouseUpListener = function() {
|
|
@@ -12986,12 +12998,11 @@ Niivue.prototype.loadVolumes = async function(volumeList) {
|
|
|
12986
12998
|
this.loadingText = "loading...";
|
|
12987
12999
|
this.drawScene();
|
|
12988
13000
|
} else {
|
|
12989
|
-
this.loadingText = "
|
|
13001
|
+
this.loadingText = "waiting for images...";
|
|
12990
13002
|
}
|
|
12991
13003
|
});
|
|
12992
|
-
if (!this.initialized)
|
|
12993
|
-
|
|
12994
|
-
}
|
|
13004
|
+
if (!this.initialized)
|
|
13005
|
+
;
|
|
12995
13006
|
this.volumes = [];
|
|
12996
13007
|
this.gl.clearColor(0, 0, 0, 1);
|
|
12997
13008
|
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
|
@@ -13107,6 +13118,11 @@ Niivue.prototype.initText = async function() {
|
|
|
13107
13118
|
this.drawLoadingText(this.loadingText);
|
|
13108
13119
|
};
|
|
13109
13120
|
Niivue.prototype.init = async function() {
|
|
13121
|
+
let rendererInfo = this.gl.getExtension("WEBGL_debug_renderer_info");
|
|
13122
|
+
let vendor = this.gl.getParameter(rendererInfo.UNMASKED_VENDOR_WEBGL);
|
|
13123
|
+
let renderer = this.gl.getParameter(rendererInfo.UNMASKED_RENDERER_WEBGL);
|
|
13124
|
+
log.info("renderer vendor: ", vendor);
|
|
13125
|
+
log.info("renderer: ", renderer);
|
|
13110
13126
|
this.gl.enable(this.gl.CULL_FACE);
|
|
13111
13127
|
this.gl.cullFace(this.gl.FRONT);
|
|
13112
13128
|
this.gl.enable(this.gl.BLEND);
|
|
@@ -13534,7 +13550,13 @@ Niivue.prototype.mouseClick = function(x, y, posChange = 0, isDelta = true) {
|
|
|
13534
13550
|
this.scene.location$.next({
|
|
13535
13551
|
mm: this.frac2mm(this.scene.crosshairPos),
|
|
13536
13552
|
vox: this.frac2vox(this.scene.crosshairPos),
|
|
13537
|
-
frac: this.scene.crosshairPos
|
|
13553
|
+
frac: this.scene.crosshairPos,
|
|
13554
|
+
values: this.volumes.map((v, index) => {
|
|
13555
|
+
let mm = this.frac2mm(this.scene.crosshairPos);
|
|
13556
|
+
let vox = v.mm2vox(mm);
|
|
13557
|
+
let val = v.getValue(...vox);
|
|
13558
|
+
return val;
|
|
13559
|
+
})
|
|
13538
13560
|
});
|
|
13539
13561
|
return;
|
|
13540
13562
|
}
|
|
@@ -13554,7 +13576,13 @@ Niivue.prototype.mouseClick = function(x, y, posChange = 0, isDelta = true) {
|
|
|
13554
13576
|
this.scene.location$.next({
|
|
13555
13577
|
mm: this.frac2mm(this.scene.crosshairPos),
|
|
13556
13578
|
vox: this.frac2vox(this.scene.crosshairPos),
|
|
13557
|
-
frac: this.scene.crosshairPos
|
|
13579
|
+
frac: this.scene.crosshairPos,
|
|
13580
|
+
values: this.volumes.map((v, index) => {
|
|
13581
|
+
let mm = this.frac2mm(this.scene.crosshairPos);
|
|
13582
|
+
let vox = v.mm2vox(mm);
|
|
13583
|
+
let val = v.getValue(...vox);
|
|
13584
|
+
return val;
|
|
13585
|
+
})
|
|
13558
13586
|
});
|
|
13559
13587
|
return;
|
|
13560
13588
|
} else {
|
|
@@ -13848,16 +13876,16 @@ Niivue.prototype.draw3D = function() {
|
|
|
13848
13876
|
this.sync();
|
|
13849
13877
|
return posString;
|
|
13850
13878
|
};
|
|
13851
|
-
Niivue.prototype.mm2frac = function(mm) {
|
|
13879
|
+
Niivue.prototype.mm2frac = function(mm, volIdx = 0) {
|
|
13852
13880
|
let mm4 = fromValues(mm[0], mm[1], mm[2], 1);
|
|
13853
|
-
let d = this.
|
|
13881
|
+
let d = this.volumes[volIdx].hdr.dims;
|
|
13854
13882
|
let frac = [0, 0, 0];
|
|
13855
13883
|
if (typeof d === "undefined") {
|
|
13856
13884
|
return frac;
|
|
13857
13885
|
}
|
|
13858
13886
|
if (d[1] < 1 || d[2] < 1 || d[3] < 1)
|
|
13859
13887
|
return frac;
|
|
13860
|
-
let sform = clone(this.
|
|
13888
|
+
let sform = clone(this.volumes[volIdx].matRAS);
|
|
13861
13889
|
transpose(sform, sform);
|
|
13862
13890
|
invert(sform, sform);
|
|
13863
13891
|
transformMat4(mm4, mm4, sform);
|
|
@@ -13866,32 +13894,31 @@ Niivue.prototype.mm2frac = function(mm) {
|
|
|
13866
13894
|
frac[2] = (mm4[2] + 0.5) / d[3];
|
|
13867
13895
|
return frac;
|
|
13868
13896
|
};
|
|
13869
|
-
Niivue.prototype.vox2frac = function(vox) {
|
|
13897
|
+
Niivue.prototype.vox2frac = function(vox, volIdx = 0) {
|
|
13870
13898
|
let frac = [
|
|
13871
|
-
(vox[0] + 0.5) / this.
|
|
13872
|
-
(vox[1] + 0.5) / this.
|
|
13873
|
-
(vox[2] + 0.5) / this.
|
|
13899
|
+
(vox[0] + 0.5) / this.volumes[volIdx].hdr.dims[1],
|
|
13900
|
+
(vox[1] + 0.5) / this.volumes[volIdx].hdr.dims[2],
|
|
13901
|
+
(vox[2] + 0.5) / this.volumes[volIdx].hdr.dims[3]
|
|
13874
13902
|
];
|
|
13875
13903
|
return frac;
|
|
13876
13904
|
};
|
|
13877
|
-
Niivue.prototype.frac2vox = function(frac) {
|
|
13905
|
+
Niivue.prototype.frac2vox = function(frac, volIdx = 0) {
|
|
13878
13906
|
let vox = [
|
|
13879
|
-
Math.round(frac[0] * this.
|
|
13880
|
-
Math.round(frac[1] * this.
|
|
13881
|
-
Math.round(frac[2] * this.
|
|
13907
|
+
Math.round(frac[0] * this.volumes[volIdx].hdr.dims[1] - 0.5),
|
|
13908
|
+
Math.round(frac[1] * this.volumes[volIdx].hdr.dims[2] - 0.5),
|
|
13909
|
+
Math.round(frac[2] * this.volumes[volIdx].hdr.dims[3] - 0.5)
|
|
13882
13910
|
];
|
|
13883
13911
|
return vox;
|
|
13884
13912
|
};
|
|
13885
|
-
Niivue.prototype.frac2mm = function(frac) {
|
|
13913
|
+
Niivue.prototype.frac2mm = function(frac, volIdx = 0) {
|
|
13886
13914
|
let pos = fromValues(frac[0], frac[1], frac[2], 1);
|
|
13887
|
-
let dim = fromValues(this.
|
|
13888
|
-
let sform = clone(this.
|
|
13915
|
+
let dim = fromValues(this.volumes[volIdx].hdr.dims[1], this.volumes[volIdx].hdr.dims[2], this.volumes[volIdx].hdr.dims[3], 1);
|
|
13916
|
+
let sform = clone(this.volumes[volIdx].matRAS);
|
|
13889
13917
|
transpose(sform, sform);
|
|
13890
13918
|
mul(pos, pos, dim);
|
|
13891
13919
|
let shim = fromValues(-0.5, -0.5, -0.5, 0);
|
|
13892
13920
|
add(pos, pos, shim);
|
|
13893
13921
|
transformMat4(pos, pos, sform);
|
|
13894
|
-
this.mm2frac(pos);
|
|
13895
13922
|
return pos;
|
|
13896
13923
|
};
|
|
13897
13924
|
Niivue.prototype.canvasPos2frac = function(canvasPos) {
|