@niivue/niivue 0.67.1-dev.0 → 0.67.1-dev.1

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.
@@ -19,7 +19,7 @@ import { mat4 as mat418, vec2, vec3 as vec324, vec4 as vec417 } from "gl-matrix"
19
19
  // package.json
20
20
  var package_default = {
21
21
  name: "@niivue/niivue",
22
- version: "0.67.0",
22
+ version: "0.67.1-dev.0",
23
23
  description: "minimal webgl2 nifti image viewer",
24
24
  types: "./build/niivue/index.d.ts",
25
25
  main: "./build/niivue/index.js",
@@ -22535,9 +22535,11 @@ function createTypedVoxelArray(datatypeCode, size) {
22535
22535
  case 512 /* DT_UINT16 */:
22536
22536
  return new Uint16Array(size);
22537
22537
  case 4 /* DT_INT16 */:
22538
- case 8 /* DT_INT32 */:
22539
22538
  return new Int16Array(size);
22539
+ case 8 /* DT_INT32 */:
22540
+ return new Int32Array(size);
22540
22541
  case 768 /* DT_UINT32 */:
22542
+ return new Uint32Array(size);
22541
22543
  case 16 /* DT_FLOAT32 */:
22542
22544
  return new Float32Array(size);
22543
22545
  case 64 /* DT_FLOAT64 */:
@@ -22661,13 +22663,15 @@ var NVZarrHelper = class _NVZarrHelper {
22661
22663
  const level = Math.max(0, Math.min(options.level, helper.pyramidInfo.levels.length - 1));
22662
22664
  helper.pyramidLevel = level;
22663
22665
  helper.updateLevelInfo();
22664
- helper.centerX = helper.levelDims.width / 2;
22665
- helper.centerY = helper.levelDims.height / 2;
22666
- helper.centerZ = helper.levelDims.depth / 2;
22666
+ helper.centerX = helper.volumeDims.width / 2;
22667
+ helper.centerY = helper.volumeDims.height / 2;
22668
+ helper.centerZ = helper.volumeDims.depth / 2;
22667
22669
  helper.configureHostImage();
22668
- await helper.updateVolume();
22669
22670
  return helper;
22670
22671
  }
22672
+ async loadInitialChunks() {
22673
+ await this.updateVolume();
22674
+ }
22671
22675
  updateLevelInfo() {
22672
22676
  const levelInfo = this.pyramidInfo.levels[this.pyramidLevel];
22673
22677
  const shape = levelInfo.shape;
@@ -22739,12 +22743,12 @@ var NVZarrHelper = class _NVZarrHelper {
22739
22743
  img.img = createTypedVoxelArray(this.datatypeCode, width * height * depth);
22740
22744
  this.updateAffine();
22741
22745
  img.originalAffine = copyAffine(hdr.affine);
22742
- img.cal_min = NaN;
22743
- img.cal_max = NaN;
22744
- img.robust_min = NaN;
22745
- img.robust_max = NaN;
22746
- img.global_min = NaN;
22747
- img.global_max = NaN;
22746
+ img.cal_min = 0;
22747
+ img.cal_max = 0;
22748
+ img.robust_min = 0;
22749
+ img.robust_max = 0;
22750
+ img.global_min = 0;
22751
+ img.global_max = 0;
22748
22752
  }
22749
22753
  /** Get unit-converted voxel scales */
22750
22754
  getConvertedScales() {
@@ -22863,6 +22867,9 @@ var NVZarrHelper = class _NVZarrHelper {
22863
22867
  beginDrag() {
22864
22868
  this.centerAtDragStart = { x: this.centerX, y: this.centerY, z: this.centerZ };
22865
22869
  }
22870
+ endDrag() {
22871
+ this.centerAtDragStart = null;
22872
+ }
22866
22873
  async panBy(dx, dy, dz = 0) {
22867
22874
  this.centerX -= dx;
22868
22875
  this.centerY -= dy;
@@ -22872,12 +22879,18 @@ var NVZarrHelper = class _NVZarrHelper {
22872
22879
  await this.updateVolume();
22873
22880
  }
22874
22881
  async panTo(newCenterX, newCenterY, newCenterZ) {
22882
+ const prevX = this.centerX;
22883
+ const prevY = this.centerY;
22884
+ const prevZ = this.centerZ;
22875
22885
  this.centerX = newCenterX;
22876
22886
  this.centerY = newCenterY;
22877
22887
  if (newCenterZ !== void 0) {
22878
22888
  this.centerZ = newCenterZ;
22879
22889
  }
22880
22890
  this.clampCenter();
22891
+ if (Math.abs(this.centerX - prevX) < 1e-3 && Math.abs(this.centerY - prevY) < 1e-3 && Math.abs(this.centerZ - prevZ) < 1e-3) {
22892
+ return;
22893
+ }
22881
22894
  this.updateAffine();
22882
22895
  await this.updateVolume();
22883
22896
  }
@@ -22917,6 +22930,54 @@ var NVZarrHelper = class _NVZarrHelper {
22917
22930
  getVolumeDims() {
22918
22931
  return { ...this.volumeDims };
22919
22932
  }
22933
+ /**
22934
+ * Convert physical (mm) coordinates back to real zarr level pixel coordinates.
22935
+ * Inverts the affine: levelPixel = (mm - OME_translation) / scale
22936
+ */
22937
+ mmToLevelCoords(mmX, mmY, mmZ) {
22938
+ const { scaleW, scaleH, scaleD } = this.getConvertedScales();
22939
+ const axisNames = this.pyramidInfo.axisMapping.spatialAxisNames;
22940
+ const mmByAxis = { x: mmX, y: mmY, z: mmZ };
22941
+ let levelW = 0;
22942
+ let levelH = 0;
22943
+ let levelD = 0;
22944
+ if (axisNames.length >= 2) {
22945
+ const wAxisName = axisNames[axisNames.length - 1];
22946
+ const hAxisName = axisNames[axisNames.length - 2];
22947
+ const dAxisName = axisNames.length >= 3 ? axisNames[axisNames.length - 3] : "z";
22948
+ const mmW = mmByAxis[wAxisName] ?? mmX;
22949
+ const mmH = mmByAxis[hAxisName] ?? mmY;
22950
+ const mmD = mmByAxis[dAxisName] ?? mmZ;
22951
+ if (this.hasTranslations) {
22952
+ const { transW, transH, transD } = this.getConvertedTranslations();
22953
+ levelW = scaleW !== 0 ? (mmW - transW) / scaleW : 0;
22954
+ levelH = scaleH !== 0 ? (mmH - transH) / scaleH : 0;
22955
+ levelD = scaleD !== 0 ? (mmD - transD) / scaleD : 0;
22956
+ } else {
22957
+ levelW = scaleW !== 0 ? mmW / scaleW : 0;
22958
+ levelH = scaleH !== 0 ? mmH / scaleH : 0;
22959
+ levelD = scaleD !== 0 ? mmD / scaleD : 0;
22960
+ }
22961
+ } else {
22962
+ if (this.hasTranslations) {
22963
+ const { transW, transH, transD } = this.getConvertedTranslations();
22964
+ levelW = scaleW !== 0 ? (mmX - transW) / scaleW : 0;
22965
+ levelH = scaleH !== 0 ? (mmY - transH) / scaleH : 0;
22966
+ levelD = scaleD !== 0 ? (mmZ - transD) / scaleD : 0;
22967
+ } else {
22968
+ levelW = scaleW !== 0 ? mmX / scaleW : 0;
22969
+ levelH = scaleH !== 0 ? mmY / scaleH : 0;
22970
+ levelD = scaleD !== 0 ? mmZ / scaleD : 0;
22971
+ }
22972
+ }
22973
+ return {
22974
+ width: Math.round(levelW),
22975
+ height: Math.round(levelH),
22976
+ depth: Math.round(levelD),
22977
+ level: this.pyramidLevel,
22978
+ levelDims: { ...this.levelDims }
22979
+ };
22980
+ }
22920
22981
  clampCenter() {
22921
22982
  const halfW = this.volumeDims.width / 2;
22922
22983
  const halfH = this.volumeDims.height / 2;
@@ -34659,6 +34720,7 @@ var Niivue = class {
34659
34720
  crosshair: false
34660
34721
  });
34661
34722
  __publicField(this, "readyForSync", false);
34723
+ __publicField(this, "_skipDragInDraw", false);
34662
34724
  // UI Data
34663
34725
  __publicField(this, "uiData", {
34664
34726
  mousedown: false,
@@ -35755,6 +35817,9 @@ var Niivue = class {
35755
35817
  }
35756
35818
  if (this.uiData.isDragging) {
35757
35819
  this.uiData.isDragging = false;
35820
+ for (const vol of this.getZarrVolumes()) {
35821
+ vol.zarrHelper?.endDrag();
35822
+ }
35758
35823
  if (currentDragMode === 7 /* angle */) {
35759
35824
  if (this.uiData.angleState === "drawing_first_line") {
35760
35825
  this.uiData.angleFirstLine = [this.uiData.dragStart[0], this.uiData.dragStart[1], this.uiData.dragEnd[0], this.uiData.dragEnd[1]];
@@ -35900,6 +35965,9 @@ var Niivue = class {
35900
35965
  }
35901
35966
  if (this.uiData.isDragging) {
35902
35967
  this.uiData.isDragging = false;
35968
+ for (const vol of this.getZarrVolumes()) {
35969
+ vol.zarrHelper?.endDrag();
35970
+ }
35903
35971
  if (this.getCurrentDragMode() === 1 /* contrast */) {
35904
35972
  this.calculateNewRange();
35905
35973
  this.refreshLayers(this.volumes[0], 0);
@@ -35959,6 +36027,9 @@ var Niivue = class {
35959
36027
  if (this.uiData.isDragging || this.uiData.mousedown) {
35960
36028
  log.debug("Mouse left canvas during drag, resetting drag state.");
35961
36029
  this.uiData.isDragging = false;
36030
+ for (const vol of this.getZarrVolumes()) {
36031
+ vol.zarrHelper?.endDrag();
36032
+ }
35962
36033
  const resetState = createResetButtonState();
35963
36034
  this.uiData.mouseButtonLeftDown = resetState.mouseButtonLeftDown;
35964
36035
  this.uiData.mouseButtonCenterDown = resetState.mouseButtonCenterDown;
@@ -37111,8 +37182,11 @@ var Niivue = class {
37111
37182
  if (volume.zarrHelper) {
37112
37183
  volume.zarrHelper.onChunksUpdated = () => {
37113
37184
  this.updateGLVolume();
37185
+ this._skipDragInDraw = true;
37114
37186
  this.drawScene();
37187
+ this._skipDragInDraw = false;
37115
37188
  };
37189
+ volume.zarrHelper.loadInitialChunks().catch((err) => log.error("Failed to load initial zarr chunks", err));
37116
37190
  }
37117
37191
  log.debug("loaded volume", volume.name);
37118
37192
  log.debug(volume);
@@ -41239,7 +41313,9 @@ var Niivue = class {
41239
41313
  }
41240
41314
  if (panPromises.length > 0) {
41241
41315
  Promise.all(panPromises).then(() => {
41316
+ this._skipDragInDraw = true;
41242
41317
  this.drawScene();
41318
+ this._skipDragInDraw = false;
41243
41319
  }).catch((err) => {
41244
41320
  log.error("Failed to pan Zarr:", err);
41245
41321
  });
@@ -44516,7 +44592,7 @@ var Niivue = class {
44516
44592
  this.dragForSlicer3D([this.uiData.dragStart[0], this.uiData.dragStart[1], this.uiData.dragEnd[0], this.uiData.dragEnd[1]]);
44517
44593
  return;
44518
44594
  }
44519
- if (this.getCurrentDragMode() === 3 /* pan */) {
44595
+ if (this.getCurrentDragMode() === 3 /* pan */ && !this._skipDragInDraw) {
44520
44596
  this.dragForPanZoom([this.uiData.dragStart[0], this.uiData.dragStart[1], this.uiData.dragEnd[0], this.uiData.dragEnd[1]]);
44521
44597
  return;
44522
44598
  }