@niivue/niivue 0.44.2 → 0.45.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/src/nvdocument.ts CHANGED
@@ -96,6 +96,7 @@ export type NVConfigOptions = {
96
96
  multiplanarPadPixels: number
97
97
  // @deprecated
98
98
  multiplanarForceRender: boolean
99
+ multiplanarEqualSize: boolean
99
100
  multiplanarShowRender: SHOW_RENDER
100
101
  isRadiologicalConvention: boolean
101
102
  // string to allow infinity
@@ -177,6 +178,7 @@ export const DEFAULT_OPTIONS: NVConfigOptions = {
177
178
  multiplanarPadPixels: 0,
178
179
  // @deprecated
179
180
  multiplanarForceRender: false,
181
+ multiplanarEqualSize: false,
180
182
  multiplanarShowRender: SHOW_RENDER.AUTO, // auto is the same behaviour as multiplanarForceRender: false
181
183
  isRadiologicalConvention: false,
182
184
  meshThicknessOn2D: Infinity,
@@ -217,6 +219,7 @@ export const DEFAULT_OPTIONS: NVConfigOptions = {
217
219
  }
218
220
 
219
221
  type SceneData = {
222
+ gamma: number
220
223
  azimuth: number
221
224
  elevation: number
222
225
  crosshairPos: vec3
@@ -230,6 +233,7 @@ type SceneData = {
230
233
  }
231
234
 
232
235
  export const INITIAL_SCENE_DATA = {
236
+ gamma: 1.0,
233
237
  azimuth: 110,
234
238
  elevation: 10,
235
239
  crosshairPos: vec3.create(),
@@ -255,6 +259,7 @@ export type Scene = {
255
259
  pan2Dxyzmm: vec4
256
260
  _elevation?: number
257
261
  _azimuth?: number
262
+ gamma?: number
258
263
  }
259
264
 
260
265
  export type DocumentData = {
@@ -566,6 +571,12 @@ export class NVDocument {
566
571
  }
567
572
 
568
573
  data.labels = [...this.data.labels]
574
+
575
+ // remove any handlers
576
+ for (const label of data.labels) {
577
+ delete label.onClick
578
+ }
579
+
569
580
  data.customData = this.customData
570
581
 
571
582
  // volumes
@@ -1631,7 +1631,7 @@ export class NVImage {
1631
1631
  hdr.datatypeCode = NiiDataType.DT_FLOAT64
1632
1632
  break
1633
1633
  default:
1634
- throw new Error('Unsupported NRRD data type: ' + items[0])
1634
+ throw new Error('Unsupported MHA data type: ' + items[0])
1635
1635
  }
1636
1636
  }
1637
1637
  if (line.startsWith('ObjectType') && !items[0].includes('Image')) {
@@ -1653,6 +1653,9 @@ export class NVImage {
1653
1653
  [mat33[2], mat33[5], mat33[8], offset[2]],
1654
1654
  [0, 0, 0, 1]
1655
1655
  ]
1656
+ while (bytes[pos] === 10) {
1657
+ pos++
1658
+ }
1656
1659
  hdr.vox_offset = pos
1657
1660
  if (isDetached && pairedImgData) {
1658
1661
  if (isGz) {
package/src/nvlabel.ts CHANGED
@@ -10,6 +10,29 @@ export enum LabelLineTerminator {
10
10
  RING = 'ring'
11
11
  }
12
12
 
13
+ export enum LabelAnchorFlag {
14
+ NONE = 0,
15
+ LEFT = 1 << 0,
16
+ CENTER = 1 << 1,
17
+ RIGHT = 1 << 2,
18
+ TOP = 1 << 3,
19
+ MIDDLE = 1 << 4,
20
+ BOTTOM = 1 << 5
21
+ }
22
+
23
+ export enum LabelAnchorPoint {
24
+ NONE = LabelAnchorFlag.NONE,
25
+ TOPLEFT = LabelAnchorFlag.TOP | LabelAnchorFlag.LEFT,
26
+ TOPCENTER = LabelAnchorFlag.TOP | LabelAnchorFlag.CENTER,
27
+ TOPRIGHT = LabelAnchorFlag.TOP | LabelAnchorFlag.RIGHT,
28
+ MIDDLELEFT = LabelAnchorFlag.MIDDLE | LabelAnchorFlag.LEFT,
29
+ MIDDLECENTER = LabelAnchorFlag.MIDDLE | LabelAnchorFlag.CENTER,
30
+ MIDDLERIGHT = LabelAnchorFlag.MIDDLE | LabelAnchorFlag.RIGHT,
31
+ BOTTOMLEFT = LabelAnchorFlag.BOTTOM | LabelAnchorFlag.LEFT,
32
+ BOTTOMCENTER = LabelAnchorFlag.BOTTOM | LabelAnchorFlag.CENTER,
33
+ BOTTOMRIGHT = LabelAnchorFlag.BOTTOM | LabelAnchorFlag.RIGHT
34
+ }
35
+
13
36
  /**
14
37
  * Class representing label style.
15
38
  * @ignore
@@ -65,15 +88,25 @@ export class NVLabel3D {
65
88
  text: string
66
89
  style: NVLabel3DStyle
67
90
  points?: number[] | number[][]
91
+ anchor: LabelAnchorPoint
92
+ onClick?: (label: NVLabel3D) => void
68
93
 
69
94
  /**
70
95
  * @param text - The text of the label
71
96
  * @param style - The style of the label
72
97
  * @param points - An array of points label for label lines
73
98
  */
74
- constructor(text: string, style: NVLabel3DStyle, points?: number[] | number[][]) {
99
+ constructor(
100
+ text: string,
101
+ style: NVLabel3DStyle,
102
+ points?: number[] | number[][],
103
+ anchor?: LabelAnchorPoint,
104
+ onClick?: (label: NVLabel3D) => void
105
+ ) {
75
106
  this.text = text
76
107
  this.style = style
77
108
  this.points = points
109
+ this.anchor = anchor || LabelAnchorPoint.NONE
110
+ this.onClick = onClick
78
111
  }
79
112
  }
@@ -709,6 +709,12 @@ export class NVMeshLoaders {
709
709
  while (lines[pos].length < 1) {
710
710
  pos++
711
711
  } // skip blank lines
712
+ if (lines[pos].startsWith('METADATA')) {
713
+ while (lines[pos].length > 1) {
714
+ pos++
715
+ } // skip until blank line
716
+ pos++
717
+ }
712
718
  items = lines[pos].trim().split(/\s+/)
713
719
  pos++
714
720
  if (items[0].includes('LINES')) {
@@ -909,7 +915,7 @@ export class NVMeshLoaders {
909
915
  layer.values = obj
910
916
  }
911
917
  }
912
- } else if (ext === 'CRV' || ext === 'CURV') {
918
+ } else if (ext === 'CRV' || ext === 'CURV' || ext === 'THICKNESS' || ext === 'AREA') {
913
919
  layer.values = NVMeshLoaders.readCURV(buffer, n_vert)
914
920
  layer.isTransparentBelowCalMin = false
915
921
  } else if (ext === 'GII') {
@@ -935,6 +941,10 @@ export class NVMeshLoaders {
935
941
  layer.values = NVMeshLoaders.readSMP(buffer, n_vert)
936
942
  } else if (ext === 'STC') {
937
943
  layer.values = NVMeshLoaders.readSTC(buffer, n_vert)
944
+ } else if (NVMeshLoaders.isCurv(buffer)) {
945
+ // Unknown layer overlay format - hail mary assume FreeSurfer
946
+ layer.values = NVMeshLoaders.readCURV(buffer, n_vert)
947
+ layer.isTransparentBelowCalMin = false
938
948
  } else {
939
949
  log.warn('Unknown layer overlay format ' + name)
940
950
  return layer
@@ -1123,6 +1133,19 @@ export class NVMeshLoaders {
1123
1133
  return f32
1124
1134
  } // readSTC()
1125
1135
 
1136
+ static isCurv(buffer: ArrayBuffer): boolean {
1137
+ const view = new DataView(buffer) // ArrayBuffer to dataview
1138
+ // ALWAYS big endian
1139
+ const sig0 = view.getUint8(0)
1140
+ const sig1 = view.getUint8(1)
1141
+ const sig2 = view.getUint8(2)
1142
+ if (sig0 !== 255 || sig1 !== 255 || sig2 !== 255) {
1143
+ utiltiesLogger.debug('Unable to recognize file type: does not appear to be FreeSurfer format.')
1144
+ return false
1145
+ }
1146
+ return true
1147
+ }
1148
+
1126
1149
  // read freesurfer curv big-endian format
1127
1150
  // https://github.com/bonilhamusclab/MRIcroS/blob/master/%2BfileUtils/%2Bpial/readPial.m
1128
1151
  // http://www.grahamwideman.com/gw/brain/fs/surfacefileformats.htm