NGL@1.0.0-beta.7 Home Manual Reference Source Gallery

src/parser/dsn6-parser.js

  1. /**
  2. * @file Dsn6 Parser
  3. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  4. * @private
  5. */
  6.  
  7. import { Matrix4 } from '../../lib/three.es6.js'
  8.  
  9. import { Debug, Log, ParserRegistry } from '../globals.js'
  10. import { ensureBuffer } from '../utils.js'
  11. import { degToRad } from '../math/math-utils.js'
  12. import VolumeParser from './volume-parser.js'
  13.  
  14. class Dsn6Parser extends VolumeParser {
  15. get type () { return 'dsn6' }
  16. get isBinary () { return true }
  17.  
  18. _parse () {
  19. // DSN6 http://www.uoxray.uoregon.edu/tnt/manual/node104.html
  20. // BRIX http://svn.cgl.ucsf.edu/svn/chimera/trunk/libs/VolumeData/dsn6/brix-1.html
  21.  
  22. if (Debug) Log.time('Dsn6Parser._parse ' + this.name)
  23.  
  24. const v = this.volume
  25. const header = {}
  26. let divisor, summand
  27.  
  28. const bin = ensureBuffer(this.streamer.data)
  29. const intView = new Int16Array(bin)
  30. const byteView = new Uint8Array(bin)
  31. const brixStr = String.fromCharCode.apply(null, byteView.subarray(0, 512))
  32.  
  33. if (brixStr.startsWith(':-)')) {
  34. header.xStart = parseInt(brixStr.substr(10, 5)) // NXSTART
  35. header.yStart = parseInt(brixStr.substr(15, 5))
  36. header.zStart = parseInt(brixStr.substr(20, 5))
  37.  
  38. header.xExtent = parseInt(brixStr.substr(32, 5)) // NX
  39. header.yExtent = parseInt(brixStr.substr(38, 5))
  40. header.zExtent = parseInt(brixStr.substr(42, 5))
  41.  
  42. header.xRate = parseInt(brixStr.substr(52, 5)) // MX
  43. header.yRate = parseInt(brixStr.substr(58, 5))
  44. header.zRate = parseInt(brixStr.substr(62, 5))
  45.  
  46. header.xlen = parseFloat(brixStr.substr(73, 10)) * this.voxelSize
  47. header.ylen = parseFloat(brixStr.substr(83, 10)) * this.voxelSize
  48. header.zlen = parseFloat(brixStr.substr(93, 10)) * this.voxelSize
  49.  
  50. header.alpha = parseFloat(brixStr.substr(103, 10))
  51. header.beta = parseFloat(brixStr.substr(113, 10))
  52. header.gamma = parseFloat(brixStr.substr(123, 10))
  53.  
  54. divisor = parseFloat(brixStr.substr(138, 12)) / 100
  55. summand = parseInt(brixStr.substr(155, 8))
  56.  
  57. header.sigma = parseFloat(brixStr.substr(170, 12)) * 100
  58. } else {
  59. // swap byte order when big endian
  60. if (intView[ 18 ] !== 100) {
  61. for (let i = 0, n = intView.length; i < n; ++i) {
  62. const val = intView[ i ]
  63. intView[ i ] = ((val & 0xff) << 8) | ((val >> 8) & 0xff)
  64. }
  65. }
  66.  
  67. header.xStart = intView[ 0 ] // NXSTART
  68. header.yStart = intView[ 1 ]
  69. header.zStart = intView[ 2 ]
  70.  
  71. header.xExtent = intView[ 3 ] // NX
  72. header.yExtent = intView[ 4 ]
  73. header.zExtent = intView[ 5 ]
  74.  
  75. header.xRate = intView[ 6 ] // MX
  76. header.yRate = intView[ 7 ]
  77. header.zRate = intView[ 8 ]
  78.  
  79. const factor = 1 / intView[ 17 ]
  80. const scalingFactor = factor * this.voxelSize
  81.  
  82. header.xlen = intView[ 9 ] * scalingFactor
  83. header.ylen = intView[ 10 ] * scalingFactor
  84. header.zlen = intView[ 11 ] * scalingFactor
  85.  
  86. header.alpha = intView[ 12 ] * factor
  87. header.beta = intView[ 13 ] * factor
  88. header.gamma = intView[ 14 ] * factor
  89.  
  90. divisor = intView[ 15 ] / 100
  91. summand = intView[ 16 ]
  92. header.gamma = intView[ 14 ] * factor
  93. }
  94.  
  95. v.header = header
  96.  
  97. if (Debug) Log.log(header, divisor, summand)
  98.  
  99. const data = new Float32Array(
  100. header.xExtent * header.yExtent * header.zExtent
  101. )
  102.  
  103. let offset = 512
  104. const xBlocks = Math.ceil(header.xExtent / 8)
  105. const yBlocks = Math.ceil(header.yExtent / 8)
  106. const zBlocks = Math.ceil(header.zExtent / 8)
  107.  
  108. // loop over blocks
  109. for (var zz = 0; zz < zBlocks; ++zz) {
  110. for (var yy = 0; yy < yBlocks; ++yy) {
  111. for (var xx = 0; xx < xBlocks; ++xx) {
  112. // loop inside block
  113. for (var k = 0; k < 8; ++k) {
  114. var z = 8 * zz + k
  115. for (var j = 0; j < 8; ++j) {
  116. var y = 8 * yy + j
  117. for (var i = 0; i < 8; ++i) {
  118. var x = 8 * xx + i
  119.  
  120. // check if remaining slice-part contains data
  121. if (x < header.xExtent && y < header.yExtent && z < header.zExtent) {
  122. var idx = ((((x * header.yExtent) + y) * header.zExtent) + z)
  123. data[ idx ] = (byteView[ offset ] - summand) / divisor
  124. ++offset
  125. } else {
  126. offset += 8 - i
  127. break
  128. }
  129. }
  130. }
  131. }
  132. }
  133. }
  134. }
  135.  
  136. v.setData(data, header.zExtent, header.yExtent, header.xExtent)
  137. if (header.sigma) {
  138. v.setStats(undefined, undefined, undefined, header.sigma)
  139. }
  140.  
  141. if (Debug) Log.timeEnd('Dsn6Parser._parse ' + this.name)
  142. }
  143.  
  144. getMatrix () {
  145. const h = this.volume.header
  146.  
  147. const basisX = [
  148. h.xlen,
  149. 0,
  150. 0
  151. ]
  152.  
  153. const basisY = [
  154. h.ylen * Math.cos(Math.PI / 180.0 * h.gamma),
  155. h.ylen * Math.sin(Math.PI / 180.0 * h.gamma),
  156. 0
  157. ]
  158.  
  159. const basisZ = [
  160. h.zlen * Math.cos(Math.PI / 180.0 * h.beta),
  161. h.zlen * (
  162. Math.cos(Math.PI / 180.0 * h.alpha) -
  163. Math.cos(Math.PI / 180.0 * h.gamma) *
  164. Math.cos(Math.PI / 180.0 * h.beta)
  165. ) / Math.sin(Math.PI / 180.0 * h.gamma),
  166. 0
  167. ]
  168. basisZ[ 2 ] = Math.sqrt(
  169. h.zlen * h.zlen * Math.sin(Math.PI / 180.0 * h.beta) *
  170. Math.sin(Math.PI / 180.0 * h.beta) - basisZ[ 1 ] * basisZ[ 1 ]
  171. )
  172.  
  173. const basis = [ 0, basisX, basisY, basisZ ]
  174. const nxyz = [ 0, h.xRate, h.yRate, h.zRate ]
  175. const mapcrs = [ 0, 1, 2, 3 ]
  176.  
  177. const matrix = new Matrix4()
  178.  
  179. matrix.set(
  180. basis[ mapcrs[1] ][0] / nxyz[ mapcrs[1] ],
  181. basis[ mapcrs[2] ][0] / nxyz[ mapcrs[2] ],
  182. basis[ mapcrs[3] ][0] / nxyz[ mapcrs[3] ],
  183. 0,
  184. basis[ mapcrs[1] ][1] / nxyz[ mapcrs[1] ],
  185. basis[ mapcrs[2] ][1] / nxyz[ mapcrs[2] ],
  186. basis[ mapcrs[3] ][1] / nxyz[ mapcrs[3] ],
  187. 0,
  188. basis[ mapcrs[1] ][2] / nxyz[ mapcrs[1] ],
  189. basis[ mapcrs[2] ][2] / nxyz[ mapcrs[2] ],
  190. basis[ mapcrs[3] ][2] / nxyz[ mapcrs[3] ],
  191. 0,
  192. 0, 0, 0, 1
  193. )
  194.  
  195. matrix.multiply(
  196. new Matrix4().makeRotationY(degToRad(90))
  197. )
  198.  
  199. matrix.multiply(new Matrix4().makeTranslation(
  200. -h.zStart, h.yStart, h.xStart
  201. ))
  202.  
  203. matrix.multiply(new Matrix4().makeScale(
  204. -1, 1, 1
  205. ))
  206.  
  207. return matrix
  208. }
  209. }
  210.  
  211. ParserRegistry.add('dsn6', Dsn6Parser)
  212. ParserRegistry.add('brix', Dsn6Parser)
  213.  
  214. export default Dsn6Parser