From ad88e1748a36460c658ef4524d844195e1d60ab6 Mon Sep 17 00:00:00 2001 From: Taylor Hanayik Date: Fri, 12 May 2023 16:21:14 +0100 Subject: [PATCH 1/3] update tests; combine all typescript changes --- __tests__/nifti-not-nifti.spec.ts | 23 + __tests__/nifti1-5D-big.spec.ts | 62 + __tests__/nifti1-5D-small.spec.ts | 56 + __tests__/nifti1-5D.spec.ts | 64 + __tests__/nifti1-extension.spec.ts | 123 + __tests__/nifti1-gz.spec.ts | 58 + __tests__/nifti1-little.spec.ts | 62 + __tests__/nifti1-pair.spec.ts | 86 + __tests__/nifti1.spec.ts | 68 + __tests__/nifti2-extension.spec.ts | 37 + __tests__/nifti2-gz.spec.ts | 75 + __tests__/nifti2-pair.spec.ts | 86 + {tests/data => data}/5D_small.nii | Bin {tests/data => data}/5D_zeros.nii.gz | Bin {tests/data => data}/air.hdr.gz | Bin {tests/data => data}/air.img.gz | Bin {tests/data => data}/air2.hdr.gz | Bin {tests/data => data}/air2.img.gz | Bin {tests/data => data}/avg152T1_LR_nifti.nii | Bin {tests/data => data}/avg152T1_LR_nifti.nii.gz | Bin .../data => data}/avg152T1_LR_nifti2.nii.gz | Bin {tests/data => data}/big.nii.gz | Bin {tests/data => data}/little.nii.gz | Bin {tests/data => data}/not-nifti.nii | Bin {tests/data => data}/with_extension.nii.gz | Bin dist/__tests__/nifti-not-nifti.spec.d.ts | 2 + dist/__tests__/nifti-not-nifti.spec.d.ts.map | 1 + dist/__tests__/nifti-not-nifti.spec.js | 45 + dist/__tests__/nifti-not-nifti.spec.js.map | 1 + dist/__tests__/nifti1-5D-big.spec.d.ts | 2 + dist/__tests__/nifti1-5D-big.spec.d.ts.map | 1 + dist/__tests__/nifti1-5D-big.spec.js | 75 + dist/__tests__/nifti1-5D-big.spec.js.map | 1 + dist/__tests__/nifti1-5D-small.spec.d.ts | 2 + dist/__tests__/nifti1-5D-small.spec.d.ts.map | 1 + dist/__tests__/nifti1-5D-small.spec.js | 71 + dist/__tests__/nifti1-5D-small.spec.js.map | 1 + dist/__tests__/nifti1-5D.spec.d.ts | 2 + dist/__tests__/nifti1-5D.spec.d.ts.map | 1 + dist/__tests__/nifti1-5D.spec.js | 77 + dist/__tests__/nifti1-5D.spec.js.map | 1 + dist/__tests__/nifti1-extension.spec.d.ts | 2 + dist/__tests__/nifti1-extension.spec.d.ts.map | 1 + dist/__tests__/nifti1-extension.spec.js | 128 + dist/__tests__/nifti1-extension.spec.js.map | 1 + dist/__tests__/nifti1-gz.spec.d.ts | 2 + dist/__tests__/nifti1-gz.spec.d.ts.map | 1 + dist/__tests__/nifti1-gz.spec.js | 72 + dist/__tests__/nifti1-gz.spec.js.map | 1 + dist/__tests__/nifti1-little.spec.d.ts | 2 + dist/__tests__/nifti1-little.spec.d.ts.map | 1 + dist/__tests__/nifti1-little.spec.js | 75 + dist/__tests__/nifti1-little.spec.js.map | 1 + dist/__tests__/nifti1-pair.spec.d.ts | 2 + dist/__tests__/nifti1-pair.spec.d.ts.map | 1 + dist/__tests__/nifti1-pair.spec.js | 92 + dist/__tests__/nifti1-pair.spec.js.map | 1 + dist/__tests__/nifti1.spec.d.ts | 2 + dist/__tests__/nifti1.spec.d.ts.map | 1 + dist/__tests__/nifti1.spec.js | 76 + dist/__tests__/nifti1.spec.js.map | 1 + dist/__tests__/nifti2-extension.spec.d.ts | 2 + dist/__tests__/nifti2-extension.spec.d.ts.map | 1 + dist/__tests__/nifti2-extension.spec.js | 58 + dist/__tests__/nifti2-extension.spec.js.map | 1 + dist/__tests__/nifti2-gz.spec.d.ts | 2 + dist/__tests__/nifti2-gz.spec.d.ts.map | 1 + dist/__tests__/nifti2-gz.spec.js | 81 + dist/__tests__/nifti2-gz.spec.js.map | 1 + dist/__tests__/nifti2-pair.spec.d.ts | 2 + dist/__tests__/nifti2-pair.spec.d.ts.map | 1 + dist/__tests__/nifti2-pair.spec.js | 90 + dist/__tests__/nifti2-pair.spec.js.map | 1 + dist/src/nifti-extension.d.ts | 23 + dist/src/nifti-extension.d.ts.map | 1 + dist/src/nifti-extension.js | 44 + dist/src/nifti-extension.js.map | 1 + dist/src/nifti.d.ts | 71 + dist/src/nifti.d.ts.map | 1 + dist/src/nifti.js | 208 + dist/src/nifti.js.map | 1 + dist/src/nifti1.d.ts | 223 + dist/src/nifti1.d.ts.map | 1 + dist/src/nifti1.js | 1110 +++++ dist/src/nifti1.js.map | 1 + dist/src/nifti2.d.ts | 179 + dist/src/nifti2.d.ts.map | 1 + dist/src/nifti2.js | 520 +++ dist/src/nifti2.js.map | 1 + dist/src/utilities.d.ts | 24 + dist/src/utilities.d.ts.map | 1 + dist/src/utilities.js | 134 + dist/src/utilities.js.map | 1 + package-lock.json | 3852 ++++++++++++++++- package.json | 18 +- release/current/nifti-reader-min.js | 108 +- release/current/nifti-reader.js | 2510 ++++++----- src/nifti-extension.js | 53 - src/nifti-extension.ts | 49 + src/nifti.js | 228 - src/nifti.ts | 221 + src/nifti1.js | 1114 ----- src/nifti1.ts | 1334 ++++++ src/nifti2.js | 559 --- src/nifti2.ts | 633 +++ src/utilities.js | 196 - src/utilities.ts | 208 + tests/driver-nifti1-5D-small.js | 4 +- tests/driver-nifti1-5D.js | 4 +- tests/driver-nifti1-big.js | 4 +- tests/driver-nifti1-extension.js | 4 +- tests/driver-nifti1-gz.js | 4 +- tests/driver-nifti1-little.js | 4 +- tests/driver-nifti1-pair.js | 10 +- tests/driver-nifti1.js | 8 +- tests/driver-nifti2-extension.js | 4 +- tests/driver-nifti2-gz.js | 8 +- tests/driver-nifti2-pair.js | 10 +- tests/driver-not-nifti.js | 4 +- tsconfig.json | 105 + 120 files changed, 12206 insertions(+), 3384 deletions(-) create mode 100644 __tests__/nifti-not-nifti.spec.ts create mode 100644 __tests__/nifti1-5D-big.spec.ts create mode 100644 __tests__/nifti1-5D-small.spec.ts create mode 100644 __tests__/nifti1-5D.spec.ts create mode 100644 __tests__/nifti1-extension.spec.ts create mode 100644 __tests__/nifti1-gz.spec.ts create mode 100644 __tests__/nifti1-little.spec.ts create mode 100644 __tests__/nifti1-pair.spec.ts create mode 100644 __tests__/nifti1.spec.ts create mode 100644 __tests__/nifti2-extension.spec.ts create mode 100644 __tests__/nifti2-gz.spec.ts create mode 100644 __tests__/nifti2-pair.spec.ts rename {tests/data => data}/5D_small.nii (100%) rename {tests/data => data}/5D_zeros.nii.gz (100%) rename {tests/data => data}/air.hdr.gz (100%) rename {tests/data => data}/air.img.gz (100%) rename {tests/data => data}/air2.hdr.gz (100%) rename {tests/data => data}/air2.img.gz (100%) rename {tests/data => data}/avg152T1_LR_nifti.nii (100%) rename {tests/data => data}/avg152T1_LR_nifti.nii.gz (100%) rename {tests/data => data}/avg152T1_LR_nifti2.nii.gz (100%) rename {tests/data => data}/big.nii.gz (100%) rename {tests/data => data}/little.nii.gz (100%) rename {tests/data => data}/not-nifti.nii (100%) rename {tests/data => data}/with_extension.nii.gz (100%) create mode 100644 dist/__tests__/nifti-not-nifti.spec.d.ts create mode 100644 dist/__tests__/nifti-not-nifti.spec.d.ts.map create mode 100644 dist/__tests__/nifti-not-nifti.spec.js create mode 100644 dist/__tests__/nifti-not-nifti.spec.js.map create mode 100644 dist/__tests__/nifti1-5D-big.spec.d.ts create mode 100644 dist/__tests__/nifti1-5D-big.spec.d.ts.map create mode 100644 dist/__tests__/nifti1-5D-big.spec.js create mode 100644 dist/__tests__/nifti1-5D-big.spec.js.map create mode 100644 dist/__tests__/nifti1-5D-small.spec.d.ts create mode 100644 dist/__tests__/nifti1-5D-small.spec.d.ts.map create mode 100644 dist/__tests__/nifti1-5D-small.spec.js create mode 100644 dist/__tests__/nifti1-5D-small.spec.js.map create mode 100644 dist/__tests__/nifti1-5D.spec.d.ts create mode 100644 dist/__tests__/nifti1-5D.spec.d.ts.map create mode 100644 dist/__tests__/nifti1-5D.spec.js create mode 100644 dist/__tests__/nifti1-5D.spec.js.map create mode 100644 dist/__tests__/nifti1-extension.spec.d.ts create mode 100644 dist/__tests__/nifti1-extension.spec.d.ts.map create mode 100644 dist/__tests__/nifti1-extension.spec.js create mode 100644 dist/__tests__/nifti1-extension.spec.js.map create mode 100644 dist/__tests__/nifti1-gz.spec.d.ts create mode 100644 dist/__tests__/nifti1-gz.spec.d.ts.map create mode 100644 dist/__tests__/nifti1-gz.spec.js create mode 100644 dist/__tests__/nifti1-gz.spec.js.map create mode 100644 dist/__tests__/nifti1-little.spec.d.ts create mode 100644 dist/__tests__/nifti1-little.spec.d.ts.map create mode 100644 dist/__tests__/nifti1-little.spec.js create mode 100644 dist/__tests__/nifti1-little.spec.js.map create mode 100644 dist/__tests__/nifti1-pair.spec.d.ts create mode 100644 dist/__tests__/nifti1-pair.spec.d.ts.map create mode 100644 dist/__tests__/nifti1-pair.spec.js create mode 100644 dist/__tests__/nifti1-pair.spec.js.map create mode 100644 dist/__tests__/nifti1.spec.d.ts create mode 100644 dist/__tests__/nifti1.spec.d.ts.map create mode 100644 dist/__tests__/nifti1.spec.js create mode 100644 dist/__tests__/nifti1.spec.js.map create mode 100644 dist/__tests__/nifti2-extension.spec.d.ts create mode 100644 dist/__tests__/nifti2-extension.spec.d.ts.map create mode 100644 dist/__tests__/nifti2-extension.spec.js create mode 100644 dist/__tests__/nifti2-extension.spec.js.map create mode 100644 dist/__tests__/nifti2-gz.spec.d.ts create mode 100644 dist/__tests__/nifti2-gz.spec.d.ts.map create mode 100644 dist/__tests__/nifti2-gz.spec.js create mode 100644 dist/__tests__/nifti2-gz.spec.js.map create mode 100644 dist/__tests__/nifti2-pair.spec.d.ts create mode 100644 dist/__tests__/nifti2-pair.spec.d.ts.map create mode 100644 dist/__tests__/nifti2-pair.spec.js create mode 100644 dist/__tests__/nifti2-pair.spec.js.map create mode 100644 dist/src/nifti-extension.d.ts create mode 100644 dist/src/nifti-extension.d.ts.map create mode 100644 dist/src/nifti-extension.js create mode 100644 dist/src/nifti-extension.js.map create mode 100644 dist/src/nifti.d.ts create mode 100644 dist/src/nifti.d.ts.map create mode 100644 dist/src/nifti.js create mode 100644 dist/src/nifti.js.map create mode 100644 dist/src/nifti1.d.ts create mode 100644 dist/src/nifti1.d.ts.map create mode 100644 dist/src/nifti1.js create mode 100644 dist/src/nifti1.js.map create mode 100644 dist/src/nifti2.d.ts create mode 100644 dist/src/nifti2.d.ts.map create mode 100644 dist/src/nifti2.js create mode 100644 dist/src/nifti2.js.map create mode 100644 dist/src/utilities.d.ts create mode 100644 dist/src/utilities.d.ts.map create mode 100644 dist/src/utilities.js create mode 100644 dist/src/utilities.js.map delete mode 100644 src/nifti-extension.js create mode 100644 src/nifti-extension.ts delete mode 100644 src/nifti.js create mode 100644 src/nifti.ts delete mode 100644 src/nifti1.js create mode 100644 src/nifti1.ts delete mode 100644 src/nifti2.js create mode 100644 src/nifti2.ts delete mode 100644 src/utilities.js create mode 100644 src/utilities.ts create mode 100644 tsconfig.json diff --git a/__tests__/nifti-not-nifti.spec.ts b/__tests__/nifti-not-nifti.spec.ts new file mode 100644 index 0000000..2ca2230 --- /dev/null +++ b/__tests__/nifti-not-nifti.spec.ts @@ -0,0 +1,23 @@ +import { isCompressed, readHeader, isNIFTI } from "../src/nifti"; +import { assert } from "chai"; +import * as fs from "fs"; +import { Utils } from "../src/utilities"; + +const buf = fs.readFileSync("./data/not-nifti.nii"); +let data = Utils.toArrayBuffer(buf); + +describe('NIFTI-Reader-JS', function () { + describe('not-nifti test', function () { + it('isCompressed() should return false', function () { + assert.equal(false, isCompressed(data)); + }); + + it('isNIFTI() should return false', function () { + assert.equal(false, isNIFTI(data)); + }); + + it('readHeader() should return null', function () { + assert.equal(null, readHeader(data)); + }); + }); +}); diff --git a/__tests__/nifti1-5D-big.spec.ts b/__tests__/nifti1-5D-big.spec.ts new file mode 100644 index 0000000..aa20223 --- /dev/null +++ b/__tests__/nifti1-5D-big.spec.ts @@ -0,0 +1,62 @@ +import { isCompressed, readHeader, readImage, decompress, isNIFTI1 } from "../src/nifti"; +import { NIFTI1 } from "../src/nifti1"; +import { assert } from "chai"; +import * as fs from "fs"; +import { Utils } from "../src/utilities"; +import { NIFTI2 } from "../src/nifti2"; + +const buf = fs.readFileSync("./data/big.nii.gz"); +let data = Utils.toArrayBuffer(buf); +let nifti1: NIFTI1 | NIFTI2 | null; + +describe('NIFTI-Reader-JS', function () { + describe('nifti-1 big endian test', function () { + it('isCompressed() should return true', function () { + assert.equal(true, isCompressed(data)); + }); + + it('should not throw error when decompressing', function (done) { + assert.doesNotThrow(function() { + data = decompress(data); + done(); + }); + }); + + it('isNIFTI1() should return true', function () { + assert.equal(true, isNIFTI1(data)); + }); + + it('should not throw error when reading header', function (done) { + assert.doesNotThrow(function() { + nifti1 = readHeader(data); + done(); + }); + }); + + it('numBitsPerVoxel should be 32', function () { + assert.equal(32, nifti1!.numBitsPerVoxel); + }); + + it('littleEndian should be false', function () { + assert.equal(false, nifti1!.littleEndian); + }); + + it('dims[1] should be 64', function () { + assert.equal(64, nifti1!.dims[1]); + }); + + it('dims[2] should be 64', function () { + assert.equal(64, nifti1!.dims[2]); + }); + + it('dims[3] should be 21', function () { + assert.equal(21, nifti1!.dims[3]); + }); + + it('image data checksum should equal 3243691439', function () { + var imageData = readImage(nifti1!, data); + var checksum = Utils.crc32(new DataView(imageData)); + assert.equal(checksum, 3243691439); + }); + }); +}); \ No newline at end of file diff --git a/__tests__/nifti1-5D-small.spec.ts b/__tests__/nifti1-5D-small.spec.ts new file mode 100644 index 0000000..6d70ab3 --- /dev/null +++ b/__tests__/nifti1-5D-small.spec.ts @@ -0,0 +1,56 @@ +import { isCompressed, readHeader, readImage } from "../src/nifti"; +import { NIFTI1 } from "../src/nifti1"; +import { assert } from "chai"; +import * as fs from "fs"; +import { Utils } from "../src/utilities"; +import { NIFTI2 } from "../src/nifti2"; + +const buf = fs.readFileSync("./data/5D_small.nii"); +const data = Utils.toArrayBuffer(buf); +let nifti1: NIFTI1 | NIFTI2 | null; +let imageData = null; + +describe("NIFTI-Reader-JS", () => { + describe("uncompressed 5D nifti-1 test", function () { + it("isCompressed() should return false", function () { + assert.equal(false, isCompressed(data)); + }); + it("should not throw error when reading header", function (done) { + assert.doesNotThrow(function () { + nifti1 = readHeader(data); + done(); + }); + }); + + it("dims[1] should be 1", function () { + assert.equal(1, nifti1!.dims[1]); + }); + + it("dims[2] should be 2", function () { + assert.equal(2, nifti1!.dims[2]); + }); + + it("dims[3] should be 3", function () { + assert.equal(3, nifti1!.dims[3]); + }); + + it("dims[4] should be 1", function () { + assert.equal(1, nifti1!.dims[4]); + }); + + it("dims[5] should be 3", function () { + assert.equal(3, nifti1!.dims[5]); + }); + + it("image size should equal 1 * 2 * 3 * 1 * 3", function () { + imageData = readImage(nifti1!, data); + assert.equal(18, imageData.byteLength); + }); + + it("image data checksum should equal 1033497386", function () { + var imageData = readImage(nifti1!, data); + var checksum = Utils.crc32(new DataView(imageData)); + assert.equal(checksum, 1168954819); + }); + }); +}); diff --git a/__tests__/nifti1-5D.spec.ts b/__tests__/nifti1-5D.spec.ts new file mode 100644 index 0000000..5343c1a --- /dev/null +++ b/__tests__/nifti1-5D.spec.ts @@ -0,0 +1,64 @@ +import { isCompressed, readHeader, readImage, decompress } from "../src/nifti"; +import { NIFTI1 } from "../src/nifti1"; +import { assert } from "chai"; +import * as fs from "fs"; +import { Utils } from "../src/utilities"; +import { NIFTI2 } from "../src/nifti2"; + +const buf = fs.readFileSync("./data/5D_zeros.nii.gz"); +let data = Utils.toArrayBuffer(buf); +let nifti1: NIFTI1 | NIFTI2 | null; +let imageData = null; + +describe('NIFTI-Reader-JS', function () { + describe('compressed 5D nifti-1 test', function () { + it('isCompressed() should return true', function () { + assert.equal(true, isCompressed(data)); + }); + + it('should not throw error when decompressing', function (done) { + assert.doesNotThrow(function() { + data = decompress(data); + done(); + }); + }); + + it('should not throw error when reading header', function (done) { + assert.doesNotThrow(function() { + nifti1 = readHeader(data); + done(); + }); + }); + + it('dims[1] should be 256', function () { + assert.equal(256, nifti1!.dims[1]); + }); + + it('dims[2] should be 256', function () { + assert.equal(256, nifti1!.dims[2]); + }); + + it('dims[3] should be 170', function () { + assert.equal(170, nifti1!.dims[3]); + }); + + it('dims[4] should be 1', function () { + assert.equal(1, nifti1!.dims[4]); + }); + + it('dims[5] should be 3', function () { + assert.equal(3, nifti1!.dims[5]); + }); + + it('image size should equal 33423360', function () { + imageData = readImage(nifti1!, data); + assert.equal(33423360, imageData.byteLength); + }); + + it('image data checksum should equal 1033497386', function () { + var imageData = readImage(nifti1!, data); + var checksum = Utils.crc32(new DataView(imageData)); + assert.equal(checksum, 2980574675); + }); + }); +}); \ No newline at end of file diff --git a/__tests__/nifti1-extension.spec.ts b/__tests__/nifti1-extension.spec.ts new file mode 100644 index 0000000..d659644 --- /dev/null +++ b/__tests__/nifti1-extension.spec.ts @@ -0,0 +1,123 @@ +import { readHeader, decompress, hasExtension, isNIFTI1, readExtensionData } from "../src/nifti"; +import { NIFTI1 } from "../src/nifti1"; +import { assert } from "chai"; +import * as fs from "fs"; +import { Utils } from "../src/utilities"; +import { NIFTI2 } from "../src/nifti2"; +import { NIFTIEXTENSION } from "../src/nifti"; + +var buf = fs.readFileSync('./data/with_extension.nii.gz'); +var data = Utils.toArrayBuffer(buf); +let nifti1: NIFTI1 | NIFTI2 | null = null; +let extension: NIFTIEXTENSION | null = null; +const EXPECTED_EXTENSION_LENGTH = 376; + +describe('NIFTI-Reader-JS', function () { + describe('nifti-1 extension test', function () { + it('should not throw error when decompressing', function (done) { + assert.doesNotThrow(function() { + data = decompress(data); + done(); + }); + }); + + it('isNIFTI1() should return true', function () { + assert.equal(true, isNIFTI1(data)); + }); + + it('should not throw error when reading header', function (done) { + assert.doesNotThrow(function() { + nifti1 = readHeader(data); + done(); + }); + }); + + it('hasExtension() should return true', function () { + assert.equal(true, hasExtension(nifti1!)); + }); + + it('extension length should be 376 (384 - 8)', function () { + assert.equal(EXPECTED_EXTENSION_LENGTH + 8, nifti1!.getExtensionSize(new DataView(data))); + + assert.equal(EXPECTED_EXTENSION_LENGTH, readExtensionData(nifti1!, data).byteLength); + }); + + it('should have one extension that is 376 bytes', function() { + extension = nifti1!.extensions[0]; + assert.equal(EXPECTED_EXTENSION_LENGTH, extension.edata.byteLength); + assert.equal(1, nifti1!.extensions.length); + }); + + it('removed extension changes the vox offset', function() { + extension = nifti1!.extensions[0]; + assert.equal(EXPECTED_EXTENSION_LENGTH, extension.edata.byteLength); + assert.equal(1, nifti1!.extensions.length); + }); + + it('removed extension updates the vox offset', function() { + let oldVoxOffset = nifti1!.vox_offset; + nifti1!.removeExtension(0); + assert.equal(0, nifti1!.extensions.length); + assert.equal(nifti1!.vox_offset + extension!.esize, oldVoxOffset); + }); + + it('added extension updates vox_offset', function() { + let oldVoxOffset = nifti1!.vox_offset; + nifti1!.addExtension(extension!); + assert.equal(1, nifti1!.extensions.length); + assert.equal(nifti1!.vox_offset, oldVoxOffset + extension!.esize); + }); + + it('toArrayBuffer properly allocates extension byte array', function() { + assert.equal(1, nifti1!.extensions.length); + let bytesWithHeader = nifti1!.toArrayBuffer(true); + let bytesWithoutHeader = nifti1!.toArrayBuffer(); + let headerBytesGreater = bytesWithHeader.byteLength > bytesWithoutHeader.byteLength; + + assert.equal(true, headerBytesGreater); + }); + + it('toArrayBuffer properly preserves extension bytes', function() { + let bytes = nifti1!.toArrayBuffer(true); + let copy = readHeader(bytes); + assert.equal(1, copy!.extensions.length); + assert.equal(EXPECTED_EXTENSION_LENGTH, copy!.extensions[0].edata.byteLength); + }); + + it('extensions can be added and serialized', function() { + let edata = new Int32Array(6); + edata.fill(8); + let newExtension = new NIFTIEXTENSION(32, 4, edata.buffer, true); + nifti1!.addExtension(newExtension); + assert.equal(2, nifti1!.extensions.length); + let bytes = nifti1!.toArrayBuffer(true); + let copy = readHeader(bytes); + assert.equal(2, copy!.extensions.length); + assert.equal(4, copy!.extensions[1].ecode); + assert.equal(24, copy!.extensions[1].edata.byteLength); + }); + + it('extensions can be removed by index', function() { + nifti1!.removeExtension(1); + assert.equal(1, nifti1!.extensions.length); + let bytes = nifti1!.toArrayBuffer(true); + let copy = readHeader(bytes); + assert.equal(1, copy!.extensions.length); + assert.equal(EXPECTED_EXTENSION_LENGTH, copy!.extensions[0].edata.byteLength); + }) + + it('extensions can be inserted and serialized', function() { + let newExtension = new NIFTIEXTENSION(32, 4, new Uint8Array(16), true); + nifti1!.addExtension(newExtension, 0); + assert.equal(2, nifti1!.extensions.length); + let bytes = nifti1!.toArrayBuffer(true); + let copy = readHeader(bytes); + assert.equal(2, copy!.extensions.length); + assert.equal(4, copy!.extensions[0].ecode); + assert.equal(32, copy!.extensions[0].esize); + assert.equal(24, copy!.extensions[0].edata.byteLength); + + }) + + }); +}); diff --git a/__tests__/nifti1-gz.spec.ts b/__tests__/nifti1-gz.spec.ts new file mode 100644 index 0000000..cb601b0 --- /dev/null +++ b/__tests__/nifti1-gz.spec.ts @@ -0,0 +1,58 @@ +import { isCompressed, readHeader, readImage, decompress, isNIFTI1, hasExtension } from "../src/nifti"; +import { NIFTI1 } from "../src/nifti1"; +import { assert } from "chai"; +import * as fs from "fs"; +import { Utils } from "../src/utilities"; +import { NIFTI2 } from "../src/nifti2"; + +const buf = fs.readFileSync("./data/avg152T1_LR_nifti.nii.gz"); +let data = Utils.toArrayBuffer(buf); +let nifti1: NIFTI1 | NIFTI2 | null; + +describe('NIFTI-Reader-JS', function () { + describe('compressed nifti-1 test', function () { + it('isCompressed() should return true', function () { + assert.equal(true, isCompressed(data)); + }); + + it('should not throw error when decompressing', function (done) { + assert.doesNotThrow(function() { + data = decompress(data); + done(); + }); + }); + + it('isNIFTI1() should return true', function () { + assert.equal(true, isNIFTI1(data)); + }); + + it('should not throw error when reading header', function (done) { + assert.doesNotThrow(function() { + nifti1 = readHeader(data); + done(); + }); + }); + + it('dims[1] should be 91', function () { + assert.equal(91, nifti1!.dims[1]); + }); + + it('dims[2] should be 109', function () { + assert.equal(109, nifti1!.dims[2]); + }); + + it('dims[3] should be 91', function () { + assert.equal(91, nifti1!.dims[3]); + }); + + it('hasExtension() should return false', function () { + assert.equal(false, hasExtension(nifti1!)); + }); + + it('image data checksum should equal 1033497386', function () { + var imageData = readImage(nifti1!, data); + var checksum = Utils.crc32(new DataView(imageData)); + assert.equal(checksum, 1033497386); + }); + }); +}); diff --git a/__tests__/nifti1-little.spec.ts b/__tests__/nifti1-little.spec.ts new file mode 100644 index 0000000..535e58f --- /dev/null +++ b/__tests__/nifti1-little.spec.ts @@ -0,0 +1,62 @@ +import { isCompressed, readHeader, readImage, decompress, isNIFTI1, hasExtension } from "../src/nifti"; +import { NIFTI1 } from "../src/nifti1"; +import { assert } from "chai"; +import * as fs from "fs"; +import { Utils } from "../src/utilities"; +import { NIFTI2 } from "../src/nifti2"; + +const buf = fs.readFileSync("./data/little.nii.gz"); +let data = Utils.toArrayBuffer(buf); +let nifti1: NIFTI1 | NIFTI2 | null; + +describe('NIFTI-Reader-JS', function () { + describe('nifti-1 little endian test', function () { + it('isCompressed() should return true', function () { + assert.equal(true, isCompressed(data)); + }); + + it('should not throw error when decompressing', function (done) { + assert.doesNotThrow(function() { + data = decompress(data); + done(); + }); + }); + + it('isNIFTI1() should return true', function () { + assert.equal(true, isNIFTI1(data)); + }); + + it('should not throw error when reading header', function (done) { + assert.doesNotThrow(function() { + nifti1 = readHeader(data); + done(); + }); + }); + + it('numBitsPerVoxel should be 32', function () { + assert.equal(32, nifti1!.numBitsPerVoxel); + }); + + it('littleEndian should be true', function () { + assert.equal(true, nifti1!.littleEndian); + }); + + it('dims[1] should be 64', function () { + assert.equal(64, nifti1!.dims[1]); + }); + + it('dims[2] should be 64', function () { + assert.equal(64, nifti1!.dims[2]); + }); + + it('dims[3] should be 21', function () { + assert.equal(21, nifti1!.dims[3]); + }); + + it('image data checksum should equal 4006845507', function () { + var imageData = readImage(nifti1!, data); + var checksum = Utils.crc32(new DataView(imageData)); + assert.equal(checksum, 4006845507); + }); + }); +}); diff --git a/__tests__/nifti1-pair.spec.ts b/__tests__/nifti1-pair.spec.ts new file mode 100644 index 0000000..ac55de5 --- /dev/null +++ b/__tests__/nifti1-pair.spec.ts @@ -0,0 +1,86 @@ +import { isCompressed, readHeader, readImage, decompress, isNIFTI1, isNIFTI } from "../src/nifti"; +import { NIFTI1 } from "../src/nifti1"; +import chai, { assert, expect } from "chai"; +import * as fs from "fs"; +import { Utils } from "../src/utilities"; +import { NIFTI2 } from "../src/nifti2"; + +// uncomment the line below to get verbose logging +// chai.config.truncateThreshold = 0; // disable truncating +const buf = fs.readFileSync("./data/air.hdr.gz"); +let data = Utils.toArrayBuffer(buf); +let nifti1: NIFTI1 | NIFTI2 | null; + + +const ibuf = fs.readFileSync('./data/air.img.gz'); +let idata = Utils.toArrayBuffer(ibuf); + +let bytes = null; +let clone = null; +describe('NIFTI-Reader-JS', function () { + describe('uncompressed nifti-1 hdr/img pair test', function () { + it('isCompressed() should return true', function () { + assert.equal(true, isCompressed(idata)); + }); + + + it('should not throw error when decompressing header', function (done) { + assert.doesNotThrow(function() { + data = decompress(data); + done(); + }); + }); + + it('should not throw error when decompressing image', function (done) { + assert.doesNotThrow(function() { + idata = decompress(idata); + done(); + }); + }); + + it('isNIFTI1() should return true', function () { + assert.equal(true, isNIFTI1(data, true)); + }); + + it('isNIFTI() should return true', function () { + assert.equal(true, isNIFTI(data, true)); + }); + + it('should not throw error when reading header', function (done) { + assert.doesNotThrow(function() { + nifti1 = readHeader(data, true); + done(); + }); + }); + + it('dims[1] should be 79', function () { + assert.equal(79, nifti1!.dims[1]); + }); + + it('dims[2] should be 67', function () { + assert.equal(67, nifti1!.dims[2]); + }); + + it('dims[3] should be 64', function () { + assert.equal(64, nifti1!.dims[3]); + }); + + it('image data checksum should equal 692149477', function () { + var imageData = readImage(nifti1!, idata); + var checksum = Utils.crc32(new DataView(imageData)); + assert.equal(checksum, 692149477); + }); + + it('data returned from toArrayBuffer preserves all nifti-1 properties', function() { + nifti1 = readHeader(data, true); + bytes = nifti1!.toArrayBuffer(); + clone = readHeader(bytes, true); + let niftiHeaderText = JSON.stringify(nifti1); + let cloneText = JSON.stringify(clone); + expect(cloneText).to.equal(niftiHeaderText); + + }); + + }); + +}); diff --git a/__tests__/nifti1.spec.ts b/__tests__/nifti1.spec.ts new file mode 100644 index 0000000..6ee7e79 --- /dev/null +++ b/__tests__/nifti1.spec.ts @@ -0,0 +1,68 @@ +import { + isCompressed, + readHeader, + readImage, + isNIFTI1, + isNIFTI, +} from "../src/nifti"; +import { NIFTI1 } from "../src/nifti1"; +import { assert, expect } from "chai"; +import * as fs from "fs"; +import { Utils } from "../src/utilities"; +import { NIFTI2 } from "../src/nifti2"; + +const buf = fs.readFileSync("./data/avg152T1_LR_nifti.nii"); +let data = Utils.toArrayBuffer(buf); +let nifti1: NIFTI1 | NIFTI2 | null; +let bytes = null; +let clone = null; + +describe("NIFTI-Reader-JS", function () { + describe("uncompressed nifti-1 test", function () { + it("isCompressed() should return false", function () { + assert.equal(false, isCompressed(data)); + }); + + it("isNIFTI1() should return true", function () { + assert.equal(true, isNIFTI1(data)); + }); + + it("isNIFTI() should return true", function () { + assert.equal(true, isNIFTI(data)); + }); + + it("should not throw error when reading header", function (done) { + assert.doesNotThrow(function () { + nifti1 = readHeader(data); + done(); + }); + }); + + it("dims[1] should be 91", function () { + assert.equal(91, nifti1!.dims[1]); + }); + + it("dims[2] should be 109", function () { + assert.equal(109, nifti1!.dims[2]); + }); + + it("dims[3] should be 91", function () { + assert.equal(91, nifti1!.dims[3]); + }); + + it("image data checksum should equal 1033497386", function () { + var imageData = readImage(nifti1!, data); + var checksum = Utils.crc32(new DataView(imageData)); + assert.equal(checksum, 1033497386); + }); + + it("data returned from toArrayBuffer preserves all nifti-1 properties", function () { + nifti1 = readHeader(data); + bytes = nifti1!.toArrayBuffer(); + clone = readHeader(bytes); + let niftiHeaderText = JSON.stringify(nifti1); + let cloneText = JSON.stringify(clone); + expect(cloneText).to.equal(niftiHeaderText); + }); + }); +}); diff --git a/__tests__/nifti2-extension.spec.ts b/__tests__/nifti2-extension.spec.ts new file mode 100644 index 0000000..ba2a917 --- /dev/null +++ b/__tests__/nifti2-extension.spec.ts @@ -0,0 +1,37 @@ +import { readHeader } from "../src/nifti"; +import { NIFTI1 } from "../src/nifti1"; +import { assert } from "chai"; +import * as fs from "fs"; +import { Utils } from "../src/utilities"; +import { NIFTI2 } from "../src/nifti2"; +import { NIFTIEXTENSION } from "../src/nifti"; + +var buf = fs.readFileSync('./data/avg152T1_LR_nifti2.nii.gz'); +var data = Utils.toArrayBuffer(buf); +let nifti2: NIFTI1 | NIFTI2 | null = null; +let extension: NIFTIEXTENSION | null = null; +const EXPECTED_EXTENSION_LENGTH = 376; + +describe("NIFTI-Reader-JS", function () { + describe("nifti-2 extension test", function () { + it("should not throw error when reading header", function (done) { + assert.doesNotThrow(function () { + nifti2 = readHeader(data); + done(); + }); + }); + + it("extensions can be added and serialized", function () { + let edata = new Int32Array(6); + edata.fill(8); + let newExtension = new NIFTIEXTENSION(32, 4, edata.buffer, true); + nifti2!.addExtension(newExtension); + assert.equal(1, nifti2!.extensions.length); + let bytes = nifti2!.toArrayBuffer(true); + let copy = readHeader(bytes); + assert.equal(1, copy!.extensions.length); + assert.equal(4, copy!.extensions[0].ecode); + assert.equal(24, copy!.extensions[0].edata.byteLength); + }); + }); +}); \ No newline at end of file diff --git a/__tests__/nifti2-gz.spec.ts b/__tests__/nifti2-gz.spec.ts new file mode 100644 index 0000000..add3899 --- /dev/null +++ b/__tests__/nifti2-gz.spec.ts @@ -0,0 +1,75 @@ +import { + isCompressed, + readHeader, + readImage, + decompress, + isNIFTI2, + isNIFTI1, +} from "../src/nifti"; +import { NIFTI1 } from "../src/nifti1"; +import { assert, expect } from "chai"; +import * as fs from "fs"; +import { Utils } from "../src/utilities"; +import { NIFTI2 } from "../src/nifti2"; + +const buf = fs.readFileSync("./data/avg152T1_LR_nifti2.nii.gz"); +let data = Utils.toArrayBuffer(buf); +let nifti2: NIFTI1 | NIFTI2 | null; +var bytes = null; +var clone = null; + +describe("NIFTI-Reader-JS", function () { + describe("compressed nifti-2 test", function () { + it("isCompressed() should return true", function () { + assert.equal(true, isCompressed(data)); + }); + + it("should not throw error when decompressing", function (done) { + assert.doesNotThrow(function () { + data = decompress(data); + done(); + }); + }); + + it("isNIFTI1() should return false", function () { + assert.equal(false, isNIFTI1(data)); + }); + + it("isNIFTI2() should return true", function () { + assert.equal(true, isNIFTI2(data)); + }); + + it("should not throw error when reading header", function (done) { + assert.doesNotThrow(function () { + nifti2 = readHeader(data); + done(); + }); + }); + + it("dims[1] should be 91", function () { + assert.equal(91, nifti2!.dims[1]); + }); + + it("dims[2] should be 109", function () { + assert.equal(109, nifti2!.dims[2]); + }); + + it("dims[3] should be 91", function () { + assert.equal(91, nifti2!.dims[3]); + }); + + it("image data checksum should equal 471047545", function () { + var imageData = readImage(nifti2!, data); + var checksum = Utils.crc32(new DataView(imageData)); + assert.equal(checksum, 471047545); + }); + + it("data returned from toArrayBuffer preserves all nifti-2 properties", function () { + bytes = nifti2!.toArrayBuffer(); + clone = readHeader(bytes); + let niftiHeaderText = JSON.stringify(nifti2); + let cloneText = JSON.stringify(clone); + expect(cloneText).to.equal(niftiHeaderText); + }); + }); +}); diff --git a/__tests__/nifti2-pair.spec.ts b/__tests__/nifti2-pair.spec.ts new file mode 100644 index 0000000..12b3aac --- /dev/null +++ b/__tests__/nifti2-pair.spec.ts @@ -0,0 +1,86 @@ +import { + isCompressed, + readHeader, + readImage, + decompress, + isNIFTI, + isNIFTI2, +} from "../src/nifti"; +import { NIFTI1 } from "../src/nifti1"; +import { assert, expect } from "chai"; +import * as fs from "fs"; +import { Utils } from "../src/utilities"; +import { NIFTI2 } from "../src/nifti2"; + +const buf = fs.readFileSync("./data/air2.hdr.gz"); +let data = Utils.toArrayBuffer(buf); +let nifti2: NIFTI1 | NIFTI2 | null; +const ibuf = fs.readFileSync("./data/air2.img.gz"); +let idata = Utils.toArrayBuffer(ibuf); + +let bytes = null; +let clone = null; + +describe("NIFTI-Reader-JS", function () { + describe("uncompressed nifti-2 hdr/img pair test", function () { + it("isCompressed() should return true", function () { + assert.equal(true, isCompressed(idata)); + }); + + it("should not throw error when decompressing header", function (done) { + assert.doesNotThrow(function () { + data = decompress(data); + done(); + }); + }); + + it("should not throw error when decompressing image", function (done) { + assert.doesNotThrow(function () { + idata = decompress(idata); + done(); + }); + }); + + it("isNIFTI2() should return true", function () { + assert.equal(true, isNIFTI2(data, true)); + }); + + it("isNIFTI() should return true", function () { + assert.equal(true, isNIFTI(data, true)); + }); + + it("should not throw error when reading header", function (done) { + assert.doesNotThrow(function () { + nifti2 = readHeader(data, true); + done(); + }); + }); + + it("dims[1] should be 79", function () { + assert.equal(79, nifti2!.dims[1]); + }); + + it("dims[2] should be 67", function () { + assert.equal(67, nifti2!.dims[2]); + }); + + it("dims[3] should be 64", function () { + assert.equal(64, nifti2!.dims[3]); + }); + + it("image data checksum should equal 692149477", function () { + var imageData = readImage(nifti2!, idata); + var checksum = Utils.crc32(new DataView(imageData)); + assert.equal(checksum, 692149477); + }); + + it("data returned from toArrayBuffer preserves all nifti-2 properties", function () { + nifti2 = readHeader(data, true); + bytes = nifti2!.toArrayBuffer(); + clone = readHeader(bytes, true); + let niftiHeaderText = JSON.stringify(nifti2); + let cloneText = JSON.stringify(clone); + expect(cloneText).to.equal(niftiHeaderText); + }); + }); +}); diff --git a/tests/data/5D_small.nii b/data/5D_small.nii similarity index 100% rename from tests/data/5D_small.nii rename to data/5D_small.nii diff --git a/tests/data/5D_zeros.nii.gz b/data/5D_zeros.nii.gz similarity index 100% rename from tests/data/5D_zeros.nii.gz rename to data/5D_zeros.nii.gz diff --git a/tests/data/air.hdr.gz b/data/air.hdr.gz similarity index 100% rename from tests/data/air.hdr.gz rename to data/air.hdr.gz diff --git a/tests/data/air.img.gz b/data/air.img.gz similarity index 100% rename from tests/data/air.img.gz rename to data/air.img.gz diff --git a/tests/data/air2.hdr.gz b/data/air2.hdr.gz similarity index 100% rename from tests/data/air2.hdr.gz rename to data/air2.hdr.gz diff --git a/tests/data/air2.img.gz b/data/air2.img.gz similarity index 100% rename from tests/data/air2.img.gz rename to data/air2.img.gz diff --git a/tests/data/avg152T1_LR_nifti.nii b/data/avg152T1_LR_nifti.nii similarity index 100% rename from tests/data/avg152T1_LR_nifti.nii rename to data/avg152T1_LR_nifti.nii diff --git a/tests/data/avg152T1_LR_nifti.nii.gz b/data/avg152T1_LR_nifti.nii.gz similarity index 100% rename from tests/data/avg152T1_LR_nifti.nii.gz rename to data/avg152T1_LR_nifti.nii.gz diff --git a/tests/data/avg152T1_LR_nifti2.nii.gz b/data/avg152T1_LR_nifti2.nii.gz similarity index 100% rename from tests/data/avg152T1_LR_nifti2.nii.gz rename to data/avg152T1_LR_nifti2.nii.gz diff --git a/tests/data/big.nii.gz b/data/big.nii.gz similarity index 100% rename from tests/data/big.nii.gz rename to data/big.nii.gz diff --git a/tests/data/little.nii.gz b/data/little.nii.gz similarity index 100% rename from tests/data/little.nii.gz rename to data/little.nii.gz diff --git a/tests/data/not-nifti.nii b/data/not-nifti.nii similarity index 100% rename from tests/data/not-nifti.nii rename to data/not-nifti.nii diff --git a/tests/data/with_extension.nii.gz b/data/with_extension.nii.gz similarity index 100% rename from tests/data/with_extension.nii.gz rename to data/with_extension.nii.gz diff --git a/dist/__tests__/nifti-not-nifti.spec.d.ts b/dist/__tests__/nifti-not-nifti.spec.d.ts new file mode 100644 index 0000000..e7a08db --- /dev/null +++ b/dist/__tests__/nifti-not-nifti.spec.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=nifti-not-nifti.spec.d.ts.map \ No newline at end of file diff --git a/dist/__tests__/nifti-not-nifti.spec.d.ts.map b/dist/__tests__/nifti-not-nifti.spec.d.ts.map new file mode 100644 index 0000000..72c5d92 --- /dev/null +++ b/dist/__tests__/nifti-not-nifti.spec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti-not-nifti.spec.d.ts","sourceRoot":"","sources":["../../__tests__/nifti-not-nifti.spec.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/__tests__/nifti-not-nifti.spec.js b/dist/__tests__/nifti-not-nifti.spec.js new file mode 100644 index 0000000..854724c --- /dev/null +++ b/dist/__tests__/nifti-not-nifti.spec.js @@ -0,0 +1,45 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const nifti_1 = require("../src/nifti"); +const chai_1 = require("chai"); +const fs = __importStar(require("fs")); +const utilities_1 = require("../src/utilities"); +const buf = fs.readFileSync("./data/not-nifti.nii"); +let data = utilities_1.Utils.toArrayBuffer(buf); +describe('NIFTI-Reader-JS', function () { + describe('not-nifti test', function () { + it('isCompressed() should return false', function () { + chai_1.assert.equal(false, (0, nifti_1.isCompressed)(data)); + }); + it('isNIFTI() should return false', function () { + chai_1.assert.equal(false, (0, nifti_1.isNIFTI)(data)); + }); + it('readHeader() should return null', function () { + chai_1.assert.equal(null, (0, nifti_1.readHeader)(data)); + }); + }); +}); +//# sourceMappingURL=nifti-not-nifti.spec.js.map \ No newline at end of file diff --git a/dist/__tests__/nifti-not-nifti.spec.js.map b/dist/__tests__/nifti-not-nifti.spec.js.map new file mode 100644 index 0000000..8af6534 --- /dev/null +++ b/dist/__tests__/nifti-not-nifti.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti-not-nifti.spec.js","sourceRoot":"","sources":["../../__tests__/nifti-not-nifti.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wCAAiE;AACjE,+BAA8B;AAC9B,uCAAyB;AACzB,gDAAyC;AAEzC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,sBAAsB,CAAC,CAAC;AACpD,IAAI,IAAI,GAAG,iBAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;AAEpC,QAAQ,CAAC,iBAAiB,EAAE;IAC1B,QAAQ,CAAC,gBAAgB,EAAE;QACvB,EAAE,CAAC,oCAAoC,EAAE;YACrC,aAAM,CAAC,KAAK,CAAC,KAAK,EAAE,IAAA,oBAAY,EAAC,IAAI,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE;YAChC,aAAM,CAAC,KAAK,CAAC,KAAK,EAAE,IAAA,eAAO,EAAC,IAAI,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE;YAClC,aAAM,CAAC,KAAK,CAAC,IAAI,EAAE,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/__tests__/nifti1-5D-big.spec.d.ts b/dist/__tests__/nifti1-5D-big.spec.d.ts new file mode 100644 index 0000000..2547bfc --- /dev/null +++ b/dist/__tests__/nifti1-5D-big.spec.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=nifti1-5D-big.spec.d.ts.map \ No newline at end of file diff --git a/dist/__tests__/nifti1-5D-big.spec.d.ts.map b/dist/__tests__/nifti1-5D-big.spec.d.ts.map new file mode 100644 index 0000000..d79779c --- /dev/null +++ b/dist/__tests__/nifti1-5D-big.spec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1-5D-big.spec.d.ts","sourceRoot":"","sources":["../../__tests__/nifti1-5D-big.spec.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/__tests__/nifti1-5D-big.spec.js b/dist/__tests__/nifti1-5D-big.spec.js new file mode 100644 index 0000000..a518aec --- /dev/null +++ b/dist/__tests__/nifti1-5D-big.spec.js @@ -0,0 +1,75 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const nifti_1 = require("../src/nifti"); +const chai_1 = require("chai"); +const fs = __importStar(require("fs")); +const utilities_1 = require("../src/utilities"); +const buf = fs.readFileSync("./data/big.nii.gz"); +let data = utilities_1.Utils.toArrayBuffer(buf); +let nifti1; +describe('NIFTI-Reader-JS', function () { + describe('nifti-1 big endian test', function () { + it('isCompressed() should return true', function () { + chai_1.assert.equal(true, (0, nifti_1.isCompressed)(data)); + }); + it('should not throw error when decompressing', function (done) { + chai_1.assert.doesNotThrow(function () { + data = (0, nifti_1.decompress)(data); + done(); + }); + }); + it('isNIFTI1() should return true', function () { + chai_1.assert.equal(true, (0, nifti_1.isNIFTI1)(data)); + }); + it('should not throw error when reading header', function (done) { + chai_1.assert.doesNotThrow(function () { + nifti1 = (0, nifti_1.readHeader)(data); + done(); + }); + }); + it('numBitsPerVoxel should be 32', function () { + chai_1.assert.equal(32, nifti1.numBitsPerVoxel); + }); + it('littleEndian should be false', function () { + chai_1.assert.equal(false, nifti1.littleEndian); + }); + it('dims[1] should be 64', function () { + chai_1.assert.equal(64, nifti1.dims[1]); + }); + it('dims[2] should be 64', function () { + chai_1.assert.equal(64, nifti1.dims[2]); + }); + it('dims[3] should be 21', function () { + chai_1.assert.equal(21, nifti1.dims[3]); + }); + it('image data checksum should equal 3243691439', function () { + var imageData = (0, nifti_1.readImage)(nifti1, data); + var checksum = utilities_1.Utils.crc32(new DataView(imageData)); + chai_1.assert.equal(checksum, 3243691439); + }); + }); +}); +//# sourceMappingURL=nifti1-5D-big.spec.js.map \ No newline at end of file diff --git a/dist/__tests__/nifti1-5D-big.spec.js.map b/dist/__tests__/nifti1-5D-big.spec.js.map new file mode 100644 index 0000000..02329de --- /dev/null +++ b/dist/__tests__/nifti1-5D-big.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1-5D-big.spec.js","sourceRoot":"","sources":["../../__tests__/nifti1-5D-big.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wCAAyF;AAEzF,+BAA8B;AAC9B,uCAAyB;AACzB,gDAAyC;AAGzC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC;AACjD,IAAI,IAAI,GAAG,iBAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;AACpC,IAAI,MAA8B,CAAC;AAEnC,QAAQ,CAAC,iBAAiB,EAAE;IAC1B,QAAQ,CAAC,yBAAyB,EAAE;QAChC,EAAE,CAAC,mCAAmC,EAAE;YACpC,aAAM,CAAC,KAAK,CAAC,IAAI,EAAE,IAAA,oBAAY,EAAC,IAAI,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,UAAU,IAAI;YAC1D,aAAM,CAAC,YAAY,CAAC;gBAChB,IAAI,GAAG,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC;gBACxB,IAAI,EAAE,CAAC;YACX,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE;YAChC,aAAM,CAAC,KAAK,CAAC,IAAI,EAAE,IAAA,gBAAQ,EAAC,IAAI,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,UAAU,IAAI;YAC3D,aAAM,CAAC,YAAY,CAAC;gBAChB,MAAM,GAAG,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC;gBAC1B,IAAI,EAAE,CAAC;YACX,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE;YAC/B,aAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAO,CAAC,eAAe,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE;YAC/B,aAAM,CAAC,KAAK,CAAC,KAAK,EAAE,MAAO,CAAC,YAAY,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE;YACvB,aAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE;YACvB,aAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE;YACvB,aAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE;YAC9C,IAAI,SAAS,GAAG,IAAA,iBAAS,EAAC,MAAO,EAAE,IAAI,CAAC,CAAC;YACzC,IAAI,QAAQ,GAAG,iBAAK,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;YACpD,aAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/__tests__/nifti1-5D-small.spec.d.ts b/dist/__tests__/nifti1-5D-small.spec.d.ts new file mode 100644 index 0000000..b728d79 --- /dev/null +++ b/dist/__tests__/nifti1-5D-small.spec.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=nifti1-5D-small.spec.d.ts.map \ No newline at end of file diff --git a/dist/__tests__/nifti1-5D-small.spec.d.ts.map b/dist/__tests__/nifti1-5D-small.spec.d.ts.map new file mode 100644 index 0000000..5aff78d --- /dev/null +++ b/dist/__tests__/nifti1-5D-small.spec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1-5D-small.spec.d.ts","sourceRoot":"","sources":["../../__tests__/nifti1-5D-small.spec.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/__tests__/nifti1-5D-small.spec.js b/dist/__tests__/nifti1-5D-small.spec.js new file mode 100644 index 0000000..a9c3745 --- /dev/null +++ b/dist/__tests__/nifti1-5D-small.spec.js @@ -0,0 +1,71 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const nifti_1 = require("../src/nifti"); +const chai_1 = require("chai"); +const fs = __importStar(require("fs")); +const utilities_1 = require("../src/utilities"); +const buf = fs.readFileSync("./data/5D_small.nii"); +const data = utilities_1.Utils.toArrayBuffer(buf); +let nifti1; +let imageData = null; +describe("NIFTI-Reader-JS", () => { + describe("uncompressed 5D nifti-1 test", function () { + it("isCompressed() should return false", function () { + chai_1.assert.equal(false, (0, nifti_1.isCompressed)(data)); + }); + it("should not throw error when reading header", function (done) { + chai_1.assert.doesNotThrow(function () { + nifti1 = (0, nifti_1.readHeader)(data); + done(); + }); + }); + it("dims[1] should be 1", function () { + chai_1.assert.equal(1, nifti1.dims[1]); + }); + it("dims[2] should be 2", function () { + chai_1.assert.equal(2, nifti1.dims[2]); + }); + it("dims[3] should be 3", function () { + chai_1.assert.equal(3, nifti1.dims[3]); + }); + it("dims[4] should be 1", function () { + chai_1.assert.equal(1, nifti1.dims[4]); + }); + it("dims[5] should be 3", function () { + chai_1.assert.equal(3, nifti1.dims[5]); + }); + it("image size should equal 1 * 2 * 3 * 1 * 3", function () { + imageData = (0, nifti_1.readImage)(nifti1, data); + chai_1.assert.equal(18, imageData.byteLength); + }); + it("image data checksum should equal 1033497386", function () { + var imageData = (0, nifti_1.readImage)(nifti1, data); + var checksum = utilities_1.Utils.crc32(new DataView(imageData)); + chai_1.assert.equal(checksum, 1168954819); + }); + }); +}); +//# sourceMappingURL=nifti1-5D-small.spec.js.map \ No newline at end of file diff --git a/dist/__tests__/nifti1-5D-small.spec.js.map b/dist/__tests__/nifti1-5D-small.spec.js.map new file mode 100644 index 0000000..9f14fdd --- /dev/null +++ b/dist/__tests__/nifti1-5D-small.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1-5D-small.spec.js","sourceRoot":"","sources":["../../__tests__/nifti1-5D-small.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wCAAmE;AAEnE,+BAA8B;AAC9B,uCAAyB;AACzB,gDAAyC;AAGzC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,qBAAqB,CAAC,CAAC;AACnD,MAAM,IAAI,GAAG,iBAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;AACtC,IAAI,MAA8B,CAAC;AACnC,IAAI,SAAS,GAAG,IAAI,CAAC;AAErB,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,QAAQ,CAAC,8BAA8B,EAAE;QACvC,EAAE,CAAC,oCAAoC,EAAE;YACvC,aAAM,CAAC,KAAK,CAAC,KAAK,EAAE,IAAA,oBAAY,EAAC,IAAI,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,4CAA4C,EAAE,UAAU,IAAI;YAC7D,aAAM,CAAC,YAAY,CAAC;gBAClB,MAAM,GAAG,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC;gBAC1B,IAAI,EAAE,CAAC;YACT,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qBAAqB,EAAE;YACxB,aAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qBAAqB,EAAE;YACxB,aAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qBAAqB,EAAE;YACxB,aAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qBAAqB,EAAE;YACxB,aAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qBAAqB,EAAE;YACxB,aAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE;YAC9C,SAAS,GAAG,IAAA,iBAAS,EAAC,MAAO,EAAE,IAAI,CAAC,CAAC;YACrC,aAAM,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE;YAChD,IAAI,SAAS,GAAG,IAAA,iBAAS,EAAC,MAAO,EAAE,IAAI,CAAC,CAAC;YACzC,IAAI,QAAQ,GAAG,iBAAK,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;YACpD,aAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/__tests__/nifti1-5D.spec.d.ts b/dist/__tests__/nifti1-5D.spec.d.ts new file mode 100644 index 0000000..e931bee --- /dev/null +++ b/dist/__tests__/nifti1-5D.spec.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=nifti1-5D.spec.d.ts.map \ No newline at end of file diff --git a/dist/__tests__/nifti1-5D.spec.d.ts.map b/dist/__tests__/nifti1-5D.spec.d.ts.map new file mode 100644 index 0000000..27671d1 --- /dev/null +++ b/dist/__tests__/nifti1-5D.spec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1-5D.spec.d.ts","sourceRoot":"","sources":["../../__tests__/nifti1-5D.spec.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/__tests__/nifti1-5D.spec.js b/dist/__tests__/nifti1-5D.spec.js new file mode 100644 index 0000000..01d2912 --- /dev/null +++ b/dist/__tests__/nifti1-5D.spec.js @@ -0,0 +1,77 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const nifti_1 = require("../src/nifti"); +const chai_1 = require("chai"); +const fs = __importStar(require("fs")); +const utilities_1 = require("../src/utilities"); +const buf = fs.readFileSync("./data/5D_zeros.nii.gz"); +let data = utilities_1.Utils.toArrayBuffer(buf); +let nifti1; +let imageData = null; +describe('NIFTI-Reader-JS', function () { + describe('compressed 5D nifti-1 test', function () { + it('isCompressed() should return true', function () { + chai_1.assert.equal(true, (0, nifti_1.isCompressed)(data)); + }); + it('should not throw error when decompressing', function (done) { + chai_1.assert.doesNotThrow(function () { + data = (0, nifti_1.decompress)(data); + done(); + }); + }); + it('should not throw error when reading header', function (done) { + chai_1.assert.doesNotThrow(function () { + nifti1 = (0, nifti_1.readHeader)(data); + done(); + }); + }); + it('dims[1] should be 256', function () { + chai_1.assert.equal(256, nifti1.dims[1]); + }); + it('dims[2] should be 256', function () { + chai_1.assert.equal(256, nifti1.dims[2]); + }); + it('dims[3] should be 170', function () { + chai_1.assert.equal(170, nifti1.dims[3]); + }); + it('dims[4] should be 1', function () { + chai_1.assert.equal(1, nifti1.dims[4]); + }); + it('dims[5] should be 3', function () { + chai_1.assert.equal(3, nifti1.dims[5]); + }); + it('image size should equal 33423360', function () { + imageData = (0, nifti_1.readImage)(nifti1, data); + chai_1.assert.equal(33423360, imageData.byteLength); + }); + it('image data checksum should equal 1033497386', function () { + var imageData = (0, nifti_1.readImage)(nifti1, data); + var checksum = utilities_1.Utils.crc32(new DataView(imageData)); + chai_1.assert.equal(checksum, 2980574675); + }); + }); +}); +//# sourceMappingURL=nifti1-5D.spec.js.map \ No newline at end of file diff --git a/dist/__tests__/nifti1-5D.spec.js.map b/dist/__tests__/nifti1-5D.spec.js.map new file mode 100644 index 0000000..171fef7 --- /dev/null +++ b/dist/__tests__/nifti1-5D.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1-5D.spec.js","sourceRoot":"","sources":["../../__tests__/nifti1-5D.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wCAA+E;AAE/E,+BAA8B;AAC9B,uCAAyB;AACzB,gDAAyC;AAGzC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,wBAAwB,CAAC,CAAC;AACtD,IAAI,IAAI,GAAG,iBAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;AACpC,IAAI,MAA8B,CAAC;AACnC,IAAI,SAAS,GAAG,IAAI,CAAC;AAErB,QAAQ,CAAC,iBAAiB,EAAE;IAC1B,QAAQ,CAAC,4BAA4B,EAAE;QACnC,EAAE,CAAC,mCAAmC,EAAE;YACpC,aAAM,CAAC,KAAK,CAAC,IAAI,EAAE,IAAA,oBAAY,EAAC,IAAI,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,UAAU,IAAI;YAC1D,aAAM,CAAC,YAAY,CAAC;gBAChB,IAAI,GAAG,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC;gBACxB,IAAI,EAAE,CAAC;YACX,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,UAAU,IAAI;YAC3D,aAAM,CAAC,YAAY,CAAC;gBAChB,MAAM,GAAG,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC;gBAC1B,IAAI,EAAE,CAAC;YACX,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uBAAuB,EAAE;YACxB,aAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uBAAuB,EAAE;YACxB,aAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uBAAuB,EAAE;YACxB,aAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qBAAqB,EAAE;YACtB,aAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qBAAqB,EAAE;YACtB,aAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kCAAkC,EAAE;YACnC,SAAS,GAAG,IAAA,iBAAS,EAAC,MAAO,EAAE,IAAI,CAAC,CAAC;YACrC,aAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE;YAC9C,IAAI,SAAS,GAAG,IAAA,iBAAS,EAAC,MAAO,EAAE,IAAI,CAAC,CAAC;YACzC,IAAI,QAAQ,GAAG,iBAAK,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;YACpD,aAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/__tests__/nifti1-extension.spec.d.ts b/dist/__tests__/nifti1-extension.spec.d.ts new file mode 100644 index 0000000..cb21f5a --- /dev/null +++ b/dist/__tests__/nifti1-extension.spec.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=nifti1-extension.spec.d.ts.map \ No newline at end of file diff --git a/dist/__tests__/nifti1-extension.spec.d.ts.map b/dist/__tests__/nifti1-extension.spec.d.ts.map new file mode 100644 index 0000000..d0046b8 --- /dev/null +++ b/dist/__tests__/nifti1-extension.spec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1-extension.spec.d.ts","sourceRoot":"","sources":["../../__tests__/nifti1-extension.spec.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/__tests__/nifti1-extension.spec.js b/dist/__tests__/nifti1-extension.spec.js new file mode 100644 index 0000000..79eb55a --- /dev/null +++ b/dist/__tests__/nifti1-extension.spec.js @@ -0,0 +1,128 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const nifti_1 = require("../src/nifti"); +const chai_1 = require("chai"); +const fs = __importStar(require("fs")); +const utilities_1 = require("../src/utilities"); +const nifti_2 = require("../src/nifti"); +var buf = fs.readFileSync('./data/with_extension.nii.gz'); +var data = utilities_1.Utils.toArrayBuffer(buf); +let nifti1 = null; +let extension = null; +const EXPECTED_EXTENSION_LENGTH = 376; +describe('NIFTI-Reader-JS', function () { + describe('nifti-1 extension test', function () { + it('should not throw error when decompressing', function (done) { + chai_1.assert.doesNotThrow(function () { + data = (0, nifti_1.decompress)(data); + done(); + }); + }); + it('isNIFTI1() should return true', function () { + chai_1.assert.equal(true, (0, nifti_1.isNIFTI1)(data)); + }); + it('should not throw error when reading header', function (done) { + chai_1.assert.doesNotThrow(function () { + nifti1 = (0, nifti_1.readHeader)(data); + done(); + }); + }); + it('hasExtension() should return true', function () { + chai_1.assert.equal(true, (0, nifti_1.hasExtension)(nifti1)); + }); + it('extension length should be 376 (384 - 8)', function () { + chai_1.assert.equal(EXPECTED_EXTENSION_LENGTH + 8, nifti1.getExtensionSize(new DataView(data))); + chai_1.assert.equal(EXPECTED_EXTENSION_LENGTH, (0, nifti_1.readExtensionData)(nifti1, data).byteLength); + }); + it('should have one extension that is 376 bytes', function () { + extension = nifti1.extensions[0]; + chai_1.assert.equal(EXPECTED_EXTENSION_LENGTH, extension.edata.byteLength); + chai_1.assert.equal(1, nifti1.extensions.length); + }); + it('removed extension changes the vox offset', function () { + extension = nifti1.extensions[0]; + chai_1.assert.equal(EXPECTED_EXTENSION_LENGTH, extension.edata.byteLength); + chai_1.assert.equal(1, nifti1.extensions.length); + }); + it('removed extension updates the vox offset', function () { + let oldVoxOffset = nifti1.vox_offset; + nifti1.removeExtension(0); + chai_1.assert.equal(0, nifti1.extensions.length); + chai_1.assert.equal(nifti1.vox_offset + extension.esize, oldVoxOffset); + }); + it('added extension updates vox_offset', function () { + let oldVoxOffset = nifti1.vox_offset; + nifti1.addExtension(extension); + chai_1.assert.equal(1, nifti1.extensions.length); + chai_1.assert.equal(nifti1.vox_offset, oldVoxOffset + extension.esize); + }); + it('toArrayBuffer properly allocates extension byte array', function () { + chai_1.assert.equal(1, nifti1.extensions.length); + let bytesWithHeader = nifti1.toArrayBuffer(true); + let bytesWithoutHeader = nifti1.toArrayBuffer(); + let headerBytesGreater = bytesWithHeader.byteLength > bytesWithoutHeader.byteLength; + chai_1.assert.equal(true, headerBytesGreater); + }); + it('toArrayBuffer properly preserves extension bytes', function () { + let bytes = nifti1.toArrayBuffer(true); + let copy = (0, nifti_1.readHeader)(bytes); + chai_1.assert.equal(1, copy.extensions.length); + chai_1.assert.equal(EXPECTED_EXTENSION_LENGTH, copy.extensions[0].edata.byteLength); + }); + it('extensions can be added and serialized', function () { + let edata = new Int32Array(6); + edata.fill(8); + let newExtension = new nifti_2.NIFTIEXTENSION(32, 4, edata.buffer, true); + nifti1.addExtension(newExtension); + chai_1.assert.equal(2, nifti1.extensions.length); + let bytes = nifti1.toArrayBuffer(true); + let copy = (0, nifti_1.readHeader)(bytes); + chai_1.assert.equal(2, copy.extensions.length); + chai_1.assert.equal(4, copy.extensions[1].ecode); + chai_1.assert.equal(24, copy.extensions[1].edata.byteLength); + }); + it('extensions can be removed by index', function () { + nifti1.removeExtension(1); + chai_1.assert.equal(1, nifti1.extensions.length); + let bytes = nifti1.toArrayBuffer(true); + let copy = (0, nifti_1.readHeader)(bytes); + chai_1.assert.equal(1, copy.extensions.length); + chai_1.assert.equal(EXPECTED_EXTENSION_LENGTH, copy.extensions[0].edata.byteLength); + }); + it('extensions can be inserted and serialized', function () { + let newExtension = new nifti_2.NIFTIEXTENSION(32, 4, new Uint8Array(16), true); + nifti1.addExtension(newExtension, 0); + chai_1.assert.equal(2, nifti1.extensions.length); + let bytes = nifti1.toArrayBuffer(true); + let copy = (0, nifti_1.readHeader)(bytes); + chai_1.assert.equal(2, copy.extensions.length); + chai_1.assert.equal(4, copy.extensions[0].ecode); + chai_1.assert.equal(32, copy.extensions[0].esize); + chai_1.assert.equal(24, copy.extensions[0].edata.byteLength); + }); + }); +}); +//# sourceMappingURL=nifti1-extension.spec.js.map \ No newline at end of file diff --git a/dist/__tests__/nifti1-extension.spec.js.map b/dist/__tests__/nifti1-extension.spec.js.map new file mode 100644 index 0000000..e92d274 --- /dev/null +++ b/dist/__tests__/nifti1-extension.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1-extension.spec.js","sourceRoot":"","sources":["../../__tests__/nifti1-extension.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/__tests__/nifti1-gz.spec.d.ts b/dist/__tests__/nifti1-gz.spec.d.ts new file mode 100644 index 0000000..b59d7e6 --- /dev/null +++ b/dist/__tests__/nifti1-gz.spec.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=nifti1-gz.spec.d.ts.map \ No newline at end of file diff --git a/dist/__tests__/nifti1-gz.spec.d.ts.map b/dist/__tests__/nifti1-gz.spec.d.ts.map new file mode 100644 index 0000000..adb50a3 --- /dev/null +++ b/dist/__tests__/nifti1-gz.spec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1-gz.spec.d.ts","sourceRoot":"","sources":["../../__tests__/nifti1-gz.spec.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/__tests__/nifti1-gz.spec.js b/dist/__tests__/nifti1-gz.spec.js new file mode 100644 index 0000000..89fbf4f --- /dev/null +++ b/dist/__tests__/nifti1-gz.spec.js @@ -0,0 +1,72 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const nifti_1 = require("../src/nifti"); +const chai_1 = require("chai"); +const fs = __importStar(require("fs")); +const utilities_1 = require("../src/utilities"); +const buf = fs.readFileSync("./data/avg152T1_LR_nifti.nii.gz"); +let data = utilities_1.Utils.toArrayBuffer(buf); +let nifti1; +describe('NIFTI-Reader-JS', function () { + describe('compressed nifti-1 test', function () { + it('isCompressed() should return true', function () { + chai_1.assert.equal(true, (0, nifti_1.isCompressed)(data)); + }); + it('should not throw error when decompressing', function (done) { + chai_1.assert.doesNotThrow(function () { + data = (0, nifti_1.decompress)(data); + done(); + }); + }); + it('isNIFTI1() should return true', function () { + chai_1.assert.equal(true, (0, nifti_1.isNIFTI1)(data)); + }); + it('should not throw error when reading header', function (done) { + chai_1.assert.doesNotThrow(function () { + nifti1 = (0, nifti_1.readHeader)(data); + done(); + }); + }); + it('dims[1] should be 91', function () { + chai_1.assert.equal(91, nifti1.dims[1]); + }); + it('dims[2] should be 109', function () { + chai_1.assert.equal(109, nifti1.dims[2]); + }); + it('dims[3] should be 91', function () { + chai_1.assert.equal(91, nifti1.dims[3]); + }); + it('hasExtension() should return false', function () { + chai_1.assert.equal(false, (0, nifti_1.hasExtension)(nifti1)); + }); + it('image data checksum should equal 1033497386', function () { + var imageData = (0, nifti_1.readImage)(nifti1, data); + var checksum = utilities_1.Utils.crc32(new DataView(imageData)); + chai_1.assert.equal(checksum, 1033497386); + }); + }); +}); +//# sourceMappingURL=nifti1-gz.spec.js.map \ No newline at end of file diff --git a/dist/__tests__/nifti1-gz.spec.js.map b/dist/__tests__/nifti1-gz.spec.js.map new file mode 100644 index 0000000..23c5ea0 --- /dev/null +++ b/dist/__tests__/nifti1-gz.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1-gz.spec.js","sourceRoot":"","sources":["../../__tests__/nifti1-gz.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wCAAuG;AAEvG,+BAA8B;AAC9B,uCAAyB;AACzB,gDAAyC;AAGzC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,iCAAiC,CAAC,CAAC;AAC/D,IAAI,IAAI,GAAG,iBAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;AACpC,IAAI,MAA8B,CAAC;AAEnC,QAAQ,CAAC,iBAAiB,EAAE;IAC1B,QAAQ,CAAC,yBAAyB,EAAE;QAChC,EAAE,CAAC,mCAAmC,EAAE;YACpC,aAAM,CAAC,KAAK,CAAC,IAAI,EAAE,IAAA,oBAAY,EAAC,IAAI,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,UAAU,IAAI;YAC1D,aAAM,CAAC,YAAY,CAAC;gBAChB,IAAI,GAAG,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC;gBACxB,IAAI,EAAE,CAAC;YACX,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE;YAChC,aAAM,CAAC,KAAK,CAAC,IAAI,EAAE,IAAA,gBAAQ,EAAC,IAAI,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,UAAU,IAAI;YAC3D,aAAM,CAAC,YAAY,CAAC;gBAChB,MAAM,GAAG,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC;gBAC1B,IAAI,EAAE,CAAC;YACX,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE;YACvB,aAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uBAAuB,EAAE;YACxB,aAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE;YACvB,aAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oCAAoC,EAAE;YACrC,aAAM,CAAC,KAAK,CAAC,KAAK,EAAE,IAAA,oBAAY,EAAC,MAAO,CAAC,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE;YAC9C,IAAI,SAAS,GAAG,IAAA,iBAAS,EAAC,MAAO,EAAE,IAAI,CAAC,CAAC;YACzC,IAAI,QAAQ,GAAG,iBAAK,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;YACpD,aAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/__tests__/nifti1-little.spec.d.ts b/dist/__tests__/nifti1-little.spec.d.ts new file mode 100644 index 0000000..32d0eed --- /dev/null +++ b/dist/__tests__/nifti1-little.spec.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=nifti1-little.spec.d.ts.map \ No newline at end of file diff --git a/dist/__tests__/nifti1-little.spec.d.ts.map b/dist/__tests__/nifti1-little.spec.d.ts.map new file mode 100644 index 0000000..82d8589 --- /dev/null +++ b/dist/__tests__/nifti1-little.spec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1-little.spec.d.ts","sourceRoot":"","sources":["../../__tests__/nifti1-little.spec.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/__tests__/nifti1-little.spec.js b/dist/__tests__/nifti1-little.spec.js new file mode 100644 index 0000000..32bf16d --- /dev/null +++ b/dist/__tests__/nifti1-little.spec.js @@ -0,0 +1,75 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const nifti_1 = require("../src/nifti"); +const chai_1 = require("chai"); +const fs = __importStar(require("fs")); +const utilities_1 = require("../src/utilities"); +const buf = fs.readFileSync("./data/little.nii.gz"); +let data = utilities_1.Utils.toArrayBuffer(buf); +let nifti1; +describe('NIFTI-Reader-JS', function () { + describe('nifti-1 little endian test', function () { + it('isCompressed() should return true', function () { + chai_1.assert.equal(true, (0, nifti_1.isCompressed)(data)); + }); + it('should not throw error when decompressing', function (done) { + chai_1.assert.doesNotThrow(function () { + data = (0, nifti_1.decompress)(data); + done(); + }); + }); + it('isNIFTI1() should return true', function () { + chai_1.assert.equal(true, (0, nifti_1.isNIFTI1)(data)); + }); + it('should not throw error when reading header', function (done) { + chai_1.assert.doesNotThrow(function () { + nifti1 = (0, nifti_1.readHeader)(data); + done(); + }); + }); + it('numBitsPerVoxel should be 32', function () { + chai_1.assert.equal(32, nifti1.numBitsPerVoxel); + }); + it('littleEndian should be true', function () { + chai_1.assert.equal(true, nifti1.littleEndian); + }); + it('dims[1] should be 64', function () { + chai_1.assert.equal(64, nifti1.dims[1]); + }); + it('dims[2] should be 64', function () { + chai_1.assert.equal(64, nifti1.dims[2]); + }); + it('dims[3] should be 21', function () { + chai_1.assert.equal(21, nifti1.dims[3]); + }); + it('image data checksum should equal 4006845507', function () { + var imageData = (0, nifti_1.readImage)(nifti1, data); + var checksum = utilities_1.Utils.crc32(new DataView(imageData)); + chai_1.assert.equal(checksum, 4006845507); + }); + }); +}); +//# sourceMappingURL=nifti1-little.spec.js.map \ No newline at end of file diff --git a/dist/__tests__/nifti1-little.spec.js.map b/dist/__tests__/nifti1-little.spec.js.map new file mode 100644 index 0000000..323881f --- /dev/null +++ b/dist/__tests__/nifti1-little.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1-little.spec.js","sourceRoot":"","sources":["../../__tests__/nifti1-little.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wCAAuG;AAEvG,+BAA8B;AAC9B,uCAAyB;AACzB,gDAAyC;AAGzC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,sBAAsB,CAAC,CAAC;AACpD,IAAI,IAAI,GAAG,iBAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;AACpC,IAAI,MAA8B,CAAC;AAEnC,QAAQ,CAAC,iBAAiB,EAAE;IAC1B,QAAQ,CAAC,4BAA4B,EAAE;QACnC,EAAE,CAAC,mCAAmC,EAAE;YACpC,aAAM,CAAC,KAAK,CAAC,IAAI,EAAE,IAAA,oBAAY,EAAC,IAAI,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,UAAU,IAAI;YAC1D,aAAM,CAAC,YAAY,CAAC;gBAChB,IAAI,GAAG,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC;gBACxB,IAAI,EAAE,CAAC;YACX,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE;YAChC,aAAM,CAAC,KAAK,CAAC,IAAI,EAAE,IAAA,gBAAQ,EAAC,IAAI,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,UAAU,IAAI;YAC3D,aAAM,CAAC,YAAY,CAAC;gBAChB,MAAM,GAAG,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC;gBAC1B,IAAI,EAAE,CAAC;YACX,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE;YAC/B,aAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAO,CAAC,eAAe,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE;YAC9B,aAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAO,CAAC,YAAY,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE;YACvB,aAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE;YACvB,aAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE;YACvB,aAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE;YAC9C,IAAI,SAAS,GAAG,IAAA,iBAAS,EAAC,MAAO,EAAE,IAAI,CAAC,CAAC;YACzC,IAAI,QAAQ,GAAG,iBAAK,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;YACpD,aAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/__tests__/nifti1-pair.spec.d.ts b/dist/__tests__/nifti1-pair.spec.d.ts new file mode 100644 index 0000000..672e91d --- /dev/null +++ b/dist/__tests__/nifti1-pair.spec.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=nifti1-pair.spec.d.ts.map \ No newline at end of file diff --git a/dist/__tests__/nifti1-pair.spec.d.ts.map b/dist/__tests__/nifti1-pair.spec.d.ts.map new file mode 100644 index 0000000..eb3a4e0 --- /dev/null +++ b/dist/__tests__/nifti1-pair.spec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1-pair.spec.d.ts","sourceRoot":"","sources":["../../__tests__/nifti1-pair.spec.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/__tests__/nifti1-pair.spec.js b/dist/__tests__/nifti1-pair.spec.js new file mode 100644 index 0000000..e6d48e7 --- /dev/null +++ b/dist/__tests__/nifti1-pair.spec.js @@ -0,0 +1,92 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const nifti_1 = require("../src/nifti"); +const chai_1 = require("chai"); +const fs = __importStar(require("fs")); +const utilities_1 = require("../src/utilities"); +// uncomment the line below to get verbose logging +// chai.config.truncateThreshold = 0; // disable truncating +const buf = fs.readFileSync("./data/air.hdr.gz"); +let data = utilities_1.Utils.toArrayBuffer(buf); +let nifti1; +const ibuf = fs.readFileSync('./data/air.img.gz'); +let idata = utilities_1.Utils.toArrayBuffer(ibuf); +let bytes = null; +let clone = null; +describe('NIFTI-Reader-JS', function () { + describe('uncompressed nifti-1 hdr/img pair test', function () { + it('isCompressed() should return true', function () { + chai_1.assert.equal(true, (0, nifti_1.isCompressed)(idata)); + }); + it('should not throw error when decompressing header', function (done) { + chai_1.assert.doesNotThrow(function () { + data = (0, nifti_1.decompress)(data); + done(); + }); + }); + it('should not throw error when decompressing image', function (done) { + chai_1.assert.doesNotThrow(function () { + idata = (0, nifti_1.decompress)(idata); + done(); + }); + }); + it('isNIFTI1() should return true', function () { + chai_1.assert.equal(true, (0, nifti_1.isNIFTI1)(data, true)); + }); + it('isNIFTI() should return true', function () { + chai_1.assert.equal(true, (0, nifti_1.isNIFTI)(data, true)); + }); + it('should not throw error when reading header', function (done) { + chai_1.assert.doesNotThrow(function () { + nifti1 = (0, nifti_1.readHeader)(data, true); + done(); + }); + }); + it('dims[1] should be 79', function () { + chai_1.assert.equal(79, nifti1.dims[1]); + }); + it('dims[2] should be 67', function () { + chai_1.assert.equal(67, nifti1.dims[2]); + }); + it('dims[3] should be 64', function () { + chai_1.assert.equal(64, nifti1.dims[3]); + }); + it('image data checksum should equal 692149477', function () { + var imageData = (0, nifti_1.readImage)(nifti1, idata); + var checksum = utilities_1.Utils.crc32(new DataView(imageData)); + chai_1.assert.equal(checksum, 692149477); + }); + it('data returned from toArrayBuffer preserves all nifti-1 properties', function () { + nifti1 = (0, nifti_1.readHeader)(data, true); + bytes = nifti1.toArrayBuffer(); + clone = (0, nifti_1.readHeader)(bytes, true); + let niftiHeaderText = JSON.stringify(nifti1); + let cloneText = JSON.stringify(clone); + (0, chai_1.expect)(cloneText).to.equal(niftiHeaderText); + }); + }); +}); +//# sourceMappingURL=nifti1-pair.spec.js.map \ No newline at end of file diff --git a/dist/__tests__/nifti1-pair.spec.js.map b/dist/__tests__/nifti1-pair.spec.js.map new file mode 100644 index 0000000..cc23034 --- /dev/null +++ b/dist/__tests__/nifti1-pair.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1-pair.spec.js","sourceRoot":"","sources":["../../__tests__/nifti1-pair.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/__tests__/nifti1.spec.d.ts b/dist/__tests__/nifti1.spec.d.ts new file mode 100644 index 0000000..243004a --- /dev/null +++ b/dist/__tests__/nifti1.spec.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=nifti1.spec.d.ts.map \ No newline at end of file diff --git a/dist/__tests__/nifti1.spec.d.ts.map b/dist/__tests__/nifti1.spec.d.ts.map new file mode 100644 index 0000000..4a355cf --- /dev/null +++ b/dist/__tests__/nifti1.spec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1.spec.d.ts","sourceRoot":"","sources":["../../__tests__/nifti1.spec.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/__tests__/nifti1.spec.js b/dist/__tests__/nifti1.spec.js new file mode 100644 index 0000000..c8eee69 --- /dev/null +++ b/dist/__tests__/nifti1.spec.js @@ -0,0 +1,76 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const nifti_1 = require("../src/nifti"); +const chai_1 = require("chai"); +const fs = __importStar(require("fs")); +const utilities_1 = require("../src/utilities"); +const buf = fs.readFileSync("./data/avg152T1_LR_nifti.nii"); +let data = utilities_1.Utils.toArrayBuffer(buf); +let nifti1; +let bytes = null; +let clone = null; +describe("NIFTI-Reader-JS", function () { + describe("uncompressed nifti-1 test", function () { + it("isCompressed() should return false", function () { + chai_1.assert.equal(false, (0, nifti_1.isCompressed)(data)); + }); + it("isNIFTI1() should return true", function () { + chai_1.assert.equal(true, (0, nifti_1.isNIFTI1)(data)); + }); + it("isNIFTI() should return true", function () { + chai_1.assert.equal(true, (0, nifti_1.isNIFTI)(data)); + }); + it("should not throw error when reading header", function (done) { + chai_1.assert.doesNotThrow(function () { + nifti1 = (0, nifti_1.readHeader)(data); + done(); + }); + }); + it("dims[1] should be 91", function () { + chai_1.assert.equal(91, nifti1.dims[1]); + }); + it("dims[2] should be 109", function () { + chai_1.assert.equal(109, nifti1.dims[2]); + }); + it("dims[3] should be 91", function () { + chai_1.assert.equal(91, nifti1.dims[3]); + }); + it("image data checksum should equal 1033497386", function () { + var imageData = (0, nifti_1.readImage)(nifti1, data); + var checksum = utilities_1.Utils.crc32(new DataView(imageData)); + chai_1.assert.equal(checksum, 1033497386); + }); + it("data returned from toArrayBuffer preserves all nifti-1 properties", function () { + nifti1 = (0, nifti_1.readHeader)(data); + bytes = nifti1.toArrayBuffer(); + clone = (0, nifti_1.readHeader)(bytes); + let niftiHeaderText = JSON.stringify(nifti1); + let cloneText = JSON.stringify(clone); + (0, chai_1.expect)(cloneText).to.equal(niftiHeaderText); + }); + }); +}); +//# sourceMappingURL=nifti1.spec.js.map \ No newline at end of file diff --git a/dist/__tests__/nifti1.spec.js.map b/dist/__tests__/nifti1.spec.js.map new file mode 100644 index 0000000..9851074 --- /dev/null +++ b/dist/__tests__/nifti1.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1.spec.js","sourceRoot":"","sources":["../../__tests__/nifti1.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wCAMsB;AAEtB,+BAAsC;AACtC,uCAAyB;AACzB,gDAAyC;AAGzC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,8BAA8B,CAAC,CAAC;AAC5D,IAAI,IAAI,GAAG,iBAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;AACpC,IAAI,MAA8B,CAAC;AACnC,IAAI,KAAK,GAAG,IAAI,CAAC;AACjB,IAAI,KAAK,GAAG,IAAI,CAAC;AAEjB,QAAQ,CAAC,iBAAiB,EAAE;IAC1B,QAAQ,CAAC,2BAA2B,EAAE;QACpC,EAAE,CAAC,oCAAoC,EAAE;YACvC,aAAM,CAAC,KAAK,CAAC,KAAK,EAAE,IAAA,oBAAY,EAAC,IAAI,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE;YAClC,aAAM,CAAC,KAAK,CAAC,IAAI,EAAE,IAAA,gBAAQ,EAAC,IAAI,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE;YACjC,aAAM,CAAC,KAAK,CAAC,IAAI,EAAE,IAAA,eAAO,EAAC,IAAI,CAAC,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,UAAU,IAAI;YAC7D,aAAM,CAAC,YAAY,CAAC;gBAClB,MAAM,GAAG,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC;gBAC1B,IAAI,EAAE,CAAC;YACT,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE;YACzB,aAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uBAAuB,EAAE;YAC1B,aAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE;YACzB,aAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE;YAChD,IAAI,SAAS,GAAG,IAAA,iBAAS,EAAC,MAAO,EAAE,IAAI,CAAC,CAAC;YACzC,IAAI,QAAQ,GAAG,iBAAK,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;YACpD,aAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mEAAmE,EAAE;YACtE,MAAM,GAAG,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC;YAC1B,KAAK,GAAG,MAAO,CAAC,aAAa,EAAE,CAAC;YAChC,KAAK,GAAG,IAAA,kBAAU,EAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YAC7C,IAAI,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACtC,IAAA,aAAM,EAAC,SAAS,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/__tests__/nifti2-extension.spec.d.ts b/dist/__tests__/nifti2-extension.spec.d.ts new file mode 100644 index 0000000..f166e82 --- /dev/null +++ b/dist/__tests__/nifti2-extension.spec.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=nifti2-extension.spec.d.ts.map \ No newline at end of file diff --git a/dist/__tests__/nifti2-extension.spec.d.ts.map b/dist/__tests__/nifti2-extension.spec.d.ts.map new file mode 100644 index 0000000..1a14010 --- /dev/null +++ b/dist/__tests__/nifti2-extension.spec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti2-extension.spec.d.ts","sourceRoot":"","sources":["../../__tests__/nifti2-extension.spec.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/__tests__/nifti2-extension.spec.js b/dist/__tests__/nifti2-extension.spec.js new file mode 100644 index 0000000..8245b65 --- /dev/null +++ b/dist/__tests__/nifti2-extension.spec.js @@ -0,0 +1,58 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const nifti_1 = require("../src/nifti"); +const chai_1 = require("chai"); +const fs = __importStar(require("fs")); +const utilities_1 = require("../src/utilities"); +const nifti_2 = require("../src/nifti"); +var buf = fs.readFileSync('./data/avg152T1_LR_nifti2.nii.gz'); +var data = utilities_1.Utils.toArrayBuffer(buf); +let nifti2 = null; +let extension = null; +const EXPECTED_EXTENSION_LENGTH = 376; +describe("NIFTI-Reader-JS", function () { + describe("nifti-2 extension test", function () { + it("should not throw error when reading header", function (done) { + chai_1.assert.doesNotThrow(function () { + nifti2 = (0, nifti_1.readHeader)(data); + done(); + }); + }); + it("extensions can be added and serialized", function () { + let edata = new Int32Array(6); + edata.fill(8); + let newExtension = new nifti_2.NIFTIEXTENSION(32, 4, edata.buffer, true); + nifti2.addExtension(newExtension); + chai_1.assert.equal(1, nifti2.extensions.length); + let bytes = nifti2.toArrayBuffer(true); + let copy = (0, nifti_1.readHeader)(bytes); + chai_1.assert.equal(1, copy.extensions.length); + chai_1.assert.equal(4, copy.extensions[0].ecode); + chai_1.assert.equal(24, copy.extensions[0].edata.byteLength); + }); + }); +}); +//# sourceMappingURL=nifti2-extension.spec.js.map \ No newline at end of file diff --git a/dist/__tests__/nifti2-extension.spec.js.map b/dist/__tests__/nifti2-extension.spec.js.map new file mode 100644 index 0000000..26d0c43 --- /dev/null +++ b/dist/__tests__/nifti2-extension.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti2-extension.spec.js","sourceRoot":"","sources":["../../__tests__/nifti2-extension.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wCAA0C;AAE1C,+BAA8B;AAC9B,uCAAyB;AACzB,gDAAyC;AAEzC,wCAA8C;AAE9C,IAAI,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,kCAAkC,CAAC,CAAC;AAC9D,IAAI,IAAI,GAAG,iBAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;AACpC,IAAI,MAAM,GAA2B,IAAI,CAAC;AAC1C,IAAI,SAAS,GAA0B,IAAI,CAAC;AAC5C,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAEtC,QAAQ,CAAC,iBAAiB,EAAE;IAC1B,QAAQ,CAAC,wBAAwB,EAAE;QACjC,EAAE,CAAC,4CAA4C,EAAE,UAAU,IAAI;YAC7D,aAAM,CAAC,YAAY,CAAC;gBAClB,MAAM,GAAG,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC;gBAC1B,IAAI,EAAE,CAAC;YACT,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE;YAC3C,IAAI,KAAK,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACd,IAAI,YAAY,GAAG,IAAI,sBAAc,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACjE,MAAO,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;YACnC,aAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAC3C,IAAI,KAAK,GAAG,MAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YACxC,IAAI,IAAI,GAAG,IAAA,kBAAU,EAAC,KAAK,CAAC,CAAC;YAC7B,aAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACzC,aAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAC3C,aAAM,CAAC,KAAK,CAAC,EAAE,EAAE,IAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/__tests__/nifti2-gz.spec.d.ts b/dist/__tests__/nifti2-gz.spec.d.ts new file mode 100644 index 0000000..3ec99ad --- /dev/null +++ b/dist/__tests__/nifti2-gz.spec.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=nifti2-gz.spec.d.ts.map \ No newline at end of file diff --git a/dist/__tests__/nifti2-gz.spec.d.ts.map b/dist/__tests__/nifti2-gz.spec.d.ts.map new file mode 100644 index 0000000..4373594 --- /dev/null +++ b/dist/__tests__/nifti2-gz.spec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti2-gz.spec.d.ts","sourceRoot":"","sources":["../../__tests__/nifti2-gz.spec.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/__tests__/nifti2-gz.spec.js b/dist/__tests__/nifti2-gz.spec.js new file mode 100644 index 0000000..5974e2d --- /dev/null +++ b/dist/__tests__/nifti2-gz.spec.js @@ -0,0 +1,81 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const nifti_1 = require("../src/nifti"); +const chai_1 = require("chai"); +const fs = __importStar(require("fs")); +const utilities_1 = require("../src/utilities"); +const buf = fs.readFileSync("./data/avg152T1_LR_nifti2.nii.gz"); +let data = utilities_1.Utils.toArrayBuffer(buf); +let nifti2; +var bytes = null; +var clone = null; +describe("NIFTI-Reader-JS", function () { + describe("compressed nifti-2 test", function () { + it("isCompressed() should return true", function () { + chai_1.assert.equal(true, (0, nifti_1.isCompressed)(data)); + }); + it("should not throw error when decompressing", function (done) { + chai_1.assert.doesNotThrow(function () { + data = (0, nifti_1.decompress)(data); + done(); + }); + }); + it("isNIFTI1() should return false", function () { + chai_1.assert.equal(false, (0, nifti_1.isNIFTI1)(data)); + }); + it("isNIFTI2() should return true", function () { + chai_1.assert.equal(true, (0, nifti_1.isNIFTI2)(data)); + }); + it("should not throw error when reading header", function (done) { + chai_1.assert.doesNotThrow(function () { + nifti2 = (0, nifti_1.readHeader)(data); + done(); + }); + }); + it("dims[1] should be 91", function () { + chai_1.assert.equal(91, nifti2.dims[1]); + }); + it("dims[2] should be 109", function () { + chai_1.assert.equal(109, nifti2.dims[2]); + }); + it("dims[3] should be 91", function () { + chai_1.assert.equal(91, nifti2.dims[3]); + }); + it("image data checksum should equal 471047545", function () { + var imageData = (0, nifti_1.readImage)(nifti2, data); + var checksum = utilities_1.Utils.crc32(new DataView(imageData)); + chai_1.assert.equal(checksum, 471047545); + }); + it("data returned from toArrayBuffer preserves all nifti-2 properties", function () { + bytes = nifti2.toArrayBuffer(); + clone = (0, nifti_1.readHeader)(bytes); + let niftiHeaderText = JSON.stringify(nifti2); + let cloneText = JSON.stringify(clone); + (0, chai_1.expect)(cloneText).to.equal(niftiHeaderText); + }); + }); +}); +//# sourceMappingURL=nifti2-gz.spec.js.map \ No newline at end of file diff --git a/dist/__tests__/nifti2-gz.spec.js.map b/dist/__tests__/nifti2-gz.spec.js.map new file mode 100644 index 0000000..c3249b2 --- /dev/null +++ b/dist/__tests__/nifti2-gz.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti2-gz.spec.js","sourceRoot":"","sources":["../../__tests__/nifti2-gz.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/__tests__/nifti2-pair.spec.d.ts b/dist/__tests__/nifti2-pair.spec.d.ts new file mode 100644 index 0000000..cb8707e --- /dev/null +++ b/dist/__tests__/nifti2-pair.spec.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=nifti2-pair.spec.d.ts.map \ No newline at end of file diff --git a/dist/__tests__/nifti2-pair.spec.d.ts.map b/dist/__tests__/nifti2-pair.spec.d.ts.map new file mode 100644 index 0000000..0d2aeeb --- /dev/null +++ b/dist/__tests__/nifti2-pair.spec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti2-pair.spec.d.ts","sourceRoot":"","sources":["../../__tests__/nifti2-pair.spec.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/__tests__/nifti2-pair.spec.js b/dist/__tests__/nifti2-pair.spec.js new file mode 100644 index 0000000..b386c5c --- /dev/null +++ b/dist/__tests__/nifti2-pair.spec.js @@ -0,0 +1,90 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const nifti_1 = require("../src/nifti"); +const chai_1 = require("chai"); +const fs = __importStar(require("fs")); +const utilities_1 = require("../src/utilities"); +const buf = fs.readFileSync("./data/air2.hdr.gz"); +let data = utilities_1.Utils.toArrayBuffer(buf); +let nifti2; +const ibuf = fs.readFileSync("./data/air2.img.gz"); +let idata = utilities_1.Utils.toArrayBuffer(ibuf); +let bytes = null; +let clone = null; +describe("NIFTI-Reader-JS", function () { + describe("uncompressed nifti-2 hdr/img pair test", function () { + it("isCompressed() should return true", function () { + chai_1.assert.equal(true, (0, nifti_1.isCompressed)(idata)); + }); + it("should not throw error when decompressing header", function (done) { + chai_1.assert.doesNotThrow(function () { + data = (0, nifti_1.decompress)(data); + done(); + }); + }); + it("should not throw error when decompressing image", function (done) { + chai_1.assert.doesNotThrow(function () { + idata = (0, nifti_1.decompress)(idata); + done(); + }); + }); + it("isNIFTI2() should return true", function () { + chai_1.assert.equal(true, (0, nifti_1.isNIFTI2)(data, true)); + }); + it("isNIFTI() should return true", function () { + chai_1.assert.equal(true, (0, nifti_1.isNIFTI)(data, true)); + }); + it("should not throw error when reading header", function (done) { + chai_1.assert.doesNotThrow(function () { + nifti2 = (0, nifti_1.readHeader)(data, true); + done(); + }); + }); + it("dims[1] should be 79", function () { + chai_1.assert.equal(79, nifti2.dims[1]); + }); + it("dims[2] should be 67", function () { + chai_1.assert.equal(67, nifti2.dims[2]); + }); + it("dims[3] should be 64", function () { + chai_1.assert.equal(64, nifti2.dims[3]); + }); + it("image data checksum should equal 692149477", function () { + var imageData = (0, nifti_1.readImage)(nifti2, idata); + var checksum = utilities_1.Utils.crc32(new DataView(imageData)); + chai_1.assert.equal(checksum, 692149477); + }); + it("data returned from toArrayBuffer preserves all nifti-2 properties", function () { + nifti2 = (0, nifti_1.readHeader)(data, true); + bytes = nifti2.toArrayBuffer(); + clone = (0, nifti_1.readHeader)(bytes, true); + let niftiHeaderText = JSON.stringify(nifti2); + let cloneText = JSON.stringify(clone); + (0, chai_1.expect)(cloneText).to.equal(niftiHeaderText); + }); + }); +}); +//# sourceMappingURL=nifti2-pair.spec.js.map \ No newline at end of file diff --git a/dist/__tests__/nifti2-pair.spec.js.map b/dist/__tests__/nifti2-pair.spec.js.map new file mode 100644 index 0000000..4d94811 --- /dev/null +++ b/dist/__tests__/nifti2-pair.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti2-pair.spec.js","sourceRoot":"","sources":["../../__tests__/nifti2-pair.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/src/nifti-extension.d.ts b/dist/src/nifti-extension.d.ts new file mode 100644 index 0000000..628d144 --- /dev/null +++ b/dist/src/nifti-extension.d.ts @@ -0,0 +1,23 @@ +/*** Constructor ***/ +/** + * The NIFTIEXTENSION constructor. + * @constructor + * @property {number} esize - number of bytes that form the extended header data + * @property {number} ecode - developer group id + * @property {ArrayBuffer} data - extension data + * @property {boolean} littleEndian - is little endian + * @type {Function} + */ +export declare class NIFTIEXTENSION { + esize: number; + ecode: number; + edata: ArrayBuffer; + littleEndian: boolean; + constructor(esize: number, ecode: number, edata: ArrayBuffer, littleEndian: boolean); + /** + * Returns extension as ArrayBuffer. + * @returns {ArrayBuffer} + */ + toArrayBuffer(): ArrayBufferLike; +} +//# sourceMappingURL=nifti-extension.d.ts.map \ No newline at end of file diff --git a/dist/src/nifti-extension.d.ts.map b/dist/src/nifti-extension.d.ts.map new file mode 100644 index 0000000..4905d91 --- /dev/null +++ b/dist/src/nifti-extension.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti-extension.d.ts","sourceRoot":"","sources":["../../src/nifti-extension.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB;;;;;;;;GAQG;AACH,qBAAa,cAAc;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,WAAW,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;gBAGpB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,WAAW,EAClB,YAAY,EAAE,OAAO;IAWvB;;;OAGG;IACH,aAAa;CAad"} \ No newline at end of file diff --git a/dist/src/nifti-extension.js b/dist/src/nifti-extension.js new file mode 100644 index 0000000..3ac0c32 --- /dev/null +++ b/dist/src/nifti-extension.js @@ -0,0 +1,44 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NIFTIEXTENSION = void 0; +/*** Constructor ***/ +/** + * The NIFTIEXTENSION constructor. + * @constructor + * @property {number} esize - number of bytes that form the extended header data + * @property {number} ecode - developer group id + * @property {ArrayBuffer} data - extension data + * @property {boolean} littleEndian - is little endian + * @type {Function} + */ +class NIFTIEXTENSION { + esize; + ecode; + edata; + littleEndian; + constructor(esize, ecode, edata, littleEndian) { + if (esize % 16 != 0) { + throw new Error("This does not appear to be a NIFTI extension"); + } + this.esize = esize; + this.ecode = ecode; + this.edata = edata; + this.littleEndian = littleEndian; + } + /** + * Returns extension as ArrayBuffer. + * @returns {ArrayBuffer} + */ + toArrayBuffer() { + let byteArray = new Uint8Array(this.esize); + let data = new Uint8Array(this.edata); + byteArray.set(data, 8); + let view = new DataView(byteArray.buffer); + // size of extension + view.setInt32(0, this.esize, this.littleEndian); + view.setInt32(4, this.ecode, this.littleEndian); + return byteArray.buffer; + } +} +exports.NIFTIEXTENSION = NIFTIEXTENSION; +//# sourceMappingURL=nifti-extension.js.map \ No newline at end of file diff --git a/dist/src/nifti-extension.js.map b/dist/src/nifti-extension.js.map new file mode 100644 index 0000000..cea5935 --- /dev/null +++ b/dist/src/nifti-extension.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti-extension.js","sourceRoot":"","sources":["../../src/nifti-extension.ts"],"names":[],"mappings":";;;AAAA,qBAAqB;AACrB;;;;;;;;GAQG;AACH,MAAa,cAAc;IACvB,KAAK,CAAS;IACd,KAAK,CAAS;IACd,KAAK,CAAc;IACnB,YAAY,CAAU;IAEtB,YACE,KAAa,EACb,KAAa,EACb,KAAkB,EAClB,YAAqB;QAErB,IAAI,KAAK,GAAG,EAAE,IAAI,CAAC,EAAE;YACnB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;SACjE;QACD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;IAED;;;OAGG;IACH,aAAa;QACX,IAAI,SAAS,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAEvB,IAAI,IAAI,GAAG,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAE1C,oBAAoB;QACpB,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAChD,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAEhD,OAAO,SAAS,CAAC,MAAM,CAAC;IAC1B,CAAC;CACF;AAtCH,wCAsCG"} \ No newline at end of file diff --git a/dist/src/nifti.d.ts b/dist/src/nifti.d.ts new file mode 100644 index 0000000..9a7b80f --- /dev/null +++ b/dist/src/nifti.d.ts @@ -0,0 +1,71 @@ +import { NIFTI1 } from "./nifti1"; +import { NIFTI2 } from "./nifti2"; +export { NIFTI1 } from "./nifti1"; +export { NIFTI2 } from "./nifti2"; +export { Utils } from "./utilities"; +export { NIFTIEXTENSION } from "./nifti-extension"; +/*** Static Methods ***/ +/** + * Returns true if this data represents a NIFTI-1 header. + * @param {ArrayBuffer} data + * @returns {boolean} + */ +export declare function isNIFTI1(data: ArrayBuffer, isHdrImgPairOK?: boolean): boolean; +/** + * Returns true if this data represents a NIFTI-2 header. + * @param {ArrayBuffer} data + * @returns {boolean} + */ +export declare function isNIFTI2(data: ArrayBuffer, isHdrImgPairOK?: boolean): boolean; +/** + * Returns true if this data represents a NIFTI header. + * @param {ArrayBuffer} data + * @returns {boolean} + */ +export declare function isNIFTI(data: ArrayBuffer, isHdrImgPairOK?: boolean): boolean; +/** + * Returns true if this data is GZIP compressed. + * @param {ArrayBuffer} data + * @returns {boolean} + */ +export declare function isCompressed(data: ArrayBuffer): boolean; +/** + * Returns decompressed data. + * @param {ArrayBuffer} data + * @returns {ArrayBuffer} + */ +export declare function decompress(data: ArrayBuffer): ArrayBufferLike; +/** + * Reads and returns the header object. + * @param {ArrayBuffer} data + * @returns {NIFTI1|NIFTI2|null} + */ +export declare function readHeader(data: ArrayBuffer, isHdrImgPairOK?: boolean): NIFTI1 | NIFTI2 | null; +/** + * Returns true if this header contains an extension. + * @param {NIFTI1|NIFTI2} header + * @returns {boolean} + */ +export declare function hasExtension(header: NIFTI1 | NIFTI2): boolean; +/** + * Returns the image data. + * @param {NIFTI1|NIFTI2} header + * @param {ArrayBuffer} data + * @returns {ArrayBuffer} + */ +export declare function readImage(header: NIFTI1 | NIFTI2, data: ArrayBuffer): ArrayBuffer; +/** + * Returns the extension data (including extension header). + * @param {NIFTI1|NIFTI2} header + * @param {ArrayBuffer} data + * @returns {ArrayBuffer} + */ +export declare function readExtension(header: NIFTI1 | NIFTI2, data: ArrayBuffer): ArrayBuffer; +/** + * Returns the extension data. + * @param {NIFTI1|NIFTI2} header + * @param {ArrayBuffer} data + * @returns {ArrayBuffer} + */ +export declare function readExtensionData(header: NIFTI1 | NIFTI2, data: ArrayBuffer): ArrayBuffer; +//# sourceMappingURL=nifti.d.ts.map \ No newline at end of file diff --git a/dist/src/nifti.d.ts.map b/dist/src/nifti.d.ts.map new file mode 100644 index 0000000..811ccff --- /dev/null +++ b/dist/src/nifti.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti.d.ts","sourceRoot":"","sources":["../../src/nifti.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEjD,wBAAwB;AACxB;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,cAAc,UAAQ,WA0BjE;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,cAAc,UAAQ,WAyBjE;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,cAAc,UAAQ,WAKhE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,WAmB7C;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,mBAE3C;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,cAAc,UAAQ,0BAoBnE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,WAEnD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,IAAI,EAAE,WAAW,eAsBlB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,IAAI,EAAE,WAAW,eAMlB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,IAAI,EAAE,WAAW,eAMlB"} \ No newline at end of file diff --git a/dist/src/nifti.js b/dist/src/nifti.js new file mode 100644 index 0000000..73d2a93 --- /dev/null +++ b/dist/src/nifti.js @@ -0,0 +1,208 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.readExtensionData = exports.readExtension = exports.readImage = exports.hasExtension = exports.readHeader = exports.decompress = exports.isCompressed = exports.isNIFTI = exports.isNIFTI2 = exports.isNIFTI1 = exports.NIFTIEXTENSION = exports.Utils = exports.NIFTI2 = exports.NIFTI1 = void 0; +const fflate = __importStar(require("fflate")); +const nifti1_1 = require("./nifti1"); +const nifti2_1 = require("./nifti2"); +const utilities_1 = require("./utilities"); +var nifti1_2 = require("./nifti1"); +Object.defineProperty(exports, "NIFTI1", { enumerable: true, get: function () { return nifti1_2.NIFTI1; } }); +var nifti2_2 = require("./nifti2"); +Object.defineProperty(exports, "NIFTI2", { enumerable: true, get: function () { return nifti2_2.NIFTI2; } }); +var utilities_2 = require("./utilities"); +Object.defineProperty(exports, "Utils", { enumerable: true, get: function () { return utilities_2.Utils; } }); +var nifti_extension_1 = require("./nifti-extension"); +Object.defineProperty(exports, "NIFTIEXTENSION", { enumerable: true, get: function () { return nifti_extension_1.NIFTIEXTENSION; } }); +/*** Static Methods ***/ +/** + * Returns true if this data represents a NIFTI-1 header. + * @param {ArrayBuffer} data + * @returns {boolean} + */ +function isNIFTI1(data, isHdrImgPairOK = false) { + var buf, mag1, mag2, mag3; + if (data.byteLength < nifti1_1.NIFTI1.STANDARD_HEADER_SIZE) { + return false; + } + buf = new DataView(data); + if (buf) + mag1 = buf.getUint8(nifti1_1.NIFTI1.MAGIC_NUMBER_LOCATION); + mag2 = buf.getUint8(nifti1_1.NIFTI1.MAGIC_NUMBER_LOCATION + 1); + mag3 = buf.getUint8(nifti1_1.NIFTI1.MAGIC_NUMBER_LOCATION + 2); + if (isHdrImgPairOK && + mag1 === nifti1_1.NIFTI1.MAGIC_NUMBER2[0] && + mag2 === nifti1_1.NIFTI1.MAGIC_NUMBER2[1] && + mag3 === nifti1_1.NIFTI1.MAGIC_NUMBER2[2]) + return true; // hdr/img pair + return !!(mag1 === nifti1_1.NIFTI1.MAGIC_NUMBER[0] && + mag2 === nifti1_1.NIFTI1.MAGIC_NUMBER[1] && + mag3 === nifti1_1.NIFTI1.MAGIC_NUMBER[2]); +} +exports.isNIFTI1 = isNIFTI1; +/** + * Returns true if this data represents a NIFTI-2 header. + * @param {ArrayBuffer} data + * @returns {boolean} + */ +function isNIFTI2(data, isHdrImgPairOK = false) { + var buf, mag1, mag2, mag3; + if (data.byteLength < nifti1_1.NIFTI1.STANDARD_HEADER_SIZE) { + return false; + } + buf = new DataView(data); + mag1 = buf.getUint8(nifti2_1.NIFTI2.MAGIC_NUMBER_LOCATION); + mag2 = buf.getUint8(nifti2_1.NIFTI2.MAGIC_NUMBER_LOCATION + 1); + mag3 = buf.getUint8(nifti2_1.NIFTI2.MAGIC_NUMBER_LOCATION + 2); + if (isHdrImgPairOK && + mag1 === nifti2_1.NIFTI2.MAGIC_NUMBER2[0] && + mag2 === nifti2_1.NIFTI2.MAGIC_NUMBER2[1] && + mag3 === nifti2_1.NIFTI2.MAGIC_NUMBER2[2]) + return true; // hdr/img pair + return !!(mag1 === nifti2_1.NIFTI2.MAGIC_NUMBER[0] && + mag2 === nifti2_1.NIFTI2.MAGIC_NUMBER[1] && + mag3 === nifti2_1.NIFTI2.MAGIC_NUMBER[2]); +} +exports.isNIFTI2 = isNIFTI2; +/** + * Returns true if this data represents a NIFTI header. + * @param {ArrayBuffer} data + * @returns {boolean} + */ +function isNIFTI(data, isHdrImgPairOK = false) { + return (isNIFTI1(data, isHdrImgPairOK) || + isNIFTI2(data, isHdrImgPairOK)); +} +exports.isNIFTI = isNIFTI; +/** + * Returns true if this data is GZIP compressed. + * @param {ArrayBuffer} data + * @returns {boolean} + */ +function isCompressed(data) { + var buf, magicCookie1, magicCookie2; + if (data) { + buf = new DataView(data); + magicCookie1 = buf.getUint8(0); + magicCookie2 = buf.getUint8(1); + if (magicCookie1 === utilities_1.Utils.GUNZIP_MAGIC_COOKIE1) { + return true; + } + if (magicCookie2 === utilities_1.Utils.GUNZIP_MAGIC_COOKIE2) { + return true; + } + } + return false; +} +exports.isCompressed = isCompressed; +/** + * Returns decompressed data. + * @param {ArrayBuffer} data + * @returns {ArrayBuffer} + */ +function decompress(data) { + return fflate.decompressSync(new Uint8Array(data)).buffer; +} +exports.decompress = decompress; +/** + * Reads and returns the header object. + * @param {ArrayBuffer} data + * @returns {NIFTI1|NIFTI2|null} + */ +function readHeader(data, isHdrImgPairOK = false) { + var header = null; + if (isCompressed(data)) { + data = decompress(data); + } + if (isNIFTI1(data, isHdrImgPairOK)) { + header = new nifti1_1.NIFTI1(); + } + else if (isNIFTI2(data, isHdrImgPairOK)) { + header = new nifti2_1.NIFTI2(); + } + if (header) { + header.readHeader(data); + } + else { + console.error("That file does not appear to be NIFTI!"); + } + return header; +} +exports.readHeader = readHeader; +/** + * Returns true if this header contains an extension. + * @param {NIFTI1|NIFTI2} header + * @returns {boolean} + */ +function hasExtension(header) { + return header.extensionFlag[0] != 0; +} +exports.hasExtension = hasExtension; +/** + * Returns the image data. + * @param {NIFTI1|NIFTI2} header + * @param {ArrayBuffer} data + * @returns {ArrayBuffer} + */ +function readImage(header, data) { + var imageOffset = header.vox_offset, timeDim = 1, statDim = 1; + if (header.dims[4]) { + timeDim = header.dims[4]; + } + if (header.dims[5]) { + statDim = header.dims[5]; + } + var imageSize = header.dims[1] * + header.dims[2] * + header.dims[3] * + timeDim * + statDim * + (header.numBitsPerVoxel / 8); + return data.slice(imageOffset, imageOffset + imageSize); +} +exports.readImage = readImage; +/** + * Returns the extension data (including extension header). + * @param {NIFTI1|NIFTI2} header + * @param {ArrayBuffer} data + * @returns {ArrayBuffer} + */ +function readExtension(header, data) { + var loc = header.getExtensionLocation(), size = header.extensionSize; + return data.slice(loc, loc + size); +} +exports.readExtension = readExtension; +/** + * Returns the extension data. + * @param {NIFTI1|NIFTI2} header + * @param {ArrayBuffer} data + * @returns {ArrayBuffer} + */ +function readExtensionData(header, data) { + var loc = header.getExtensionLocation(), size = header.extensionSize; + return data.slice(loc + 8, loc + size); // +8 for loc and -8 for esize and ecode +} +exports.readExtensionData = readExtensionData; +//# sourceMappingURL=nifti.js.map \ No newline at end of file diff --git a/dist/src/nifti.js.map b/dist/src/nifti.js.map new file mode 100644 index 0000000..2b5a883 --- /dev/null +++ b/dist/src/nifti.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti.js","sourceRoot":"","sources":["../../src/nifti.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/src/nifti1.d.ts b/dist/src/nifti1.d.ts new file mode 100644 index 0000000..84dc664 --- /dev/null +++ b/dist/src/nifti1.d.ts @@ -0,0 +1,223 @@ +import { NIFTIEXTENSION } from "./nifti-extension"; +/*** Constructor ***/ +/** + * The NIFTI1 constructor. + * @constructor + * @property {boolean} littleEndian + * @property {number} dim_info + * @property {number[]} dims - image dimensions + * @property {number} intent_p1 + * @property {number} intent_p2 + * @property {number} intent_p3 + * @property {number} intent_code + * @property {number} datatypeCode + * @property {number} numBitsPerVoxel + * @property {number} slice_start + * @property {number} slice_end + * @property {number} slice_code + * @property {number[]} pixDims - voxel dimensions + * @property {number} vox_offset + * @property {number} scl_slope + * @property {number} scl_inter + * @property {number} xyzt_units + * @property {number} cal_max + * @property {number} cal_min + * @property {number} slice_duration + * @property {number} toffset + * @property {string} description + * @property {string} aux_file + * @property {string} intent_name + * @property {number} qform_code + * @property {number} sform_code + * @property {number} quatern_b + * @property {number} quatern_c + * @property {number} quatern_d + * @property {number} quatern_x + * @property {number} quatern_y + * @property {number} quatern_z + * @property {Array.>} affine + * @property {string} magic + * @property {boolean} isHDR - if hdr/img format + * @property {number[]} extensionFlag + * @property {number} extensionSize + * @property {number} extensionCode + * @property {nifti.NIFTIEXTENSION[]} extensions + * @type {Function} + */ +export declare class NIFTI1 { + littleEndian: boolean; + dim_info: number; + dims: number[]; + intent_p1: number; + intent_p2: number; + intent_p3: number; + intent_code: number; + datatypeCode: number; + numBitsPerVoxel: number; + slice_start: number; + slice_end: number; + slice_code: number; + pixDims: number[]; + vox_offset: number; + scl_slope: number; + scl_inter: number; + xyzt_units: number; + cal_max: number; + cal_min: number; + slice_duration: number; + toffset: number; + description: string; + aux_file: string; + intent_name: string; + qform_code: number; + sform_code: number; + quatern_a: number; + quatern_b: number; + quatern_c: number; + quatern_d: number; + qoffset_x: number; + qoffset_y: number; + qoffset_z: number; + affine: number[][]; + qfac: number; + quatern_R: number[][] | undefined; + magic: string; + isHDR: boolean; + extensionFlag: number[]; + extensionSize: number; + extensionCode: number; + extensions: NIFTIEXTENSION[]; + /*** Static Pseudo-constants ***/ + static readonly TYPE_NONE = 0; + static readonly TYPE_BINARY = 1; + static readonly TYPE_UINT8 = 2; + static readonly TYPE_INT16 = 4; + static readonly TYPE_INT32 = 8; + static readonly TYPE_FLOAT32 = 16; + static readonly TYPE_COMPLEX64 = 32; + static readonly TYPE_FLOAT64 = 64; + static readonly TYPE_RGB24 = 128; + static readonly TYPE_INT8 = 256; + static readonly TYPE_UINT16 = 512; + static readonly TYPE_UINT32 = 768; + static readonly TYPE_INT64 = 1024; + static readonly TYPE_UINT64 = 1280; + static readonly TYPE_FLOAT128 = 1536; + static readonly TYPE_COMPLEX128 = 1792; + static readonly TYPE_COMPLEX256 = 2048; + static readonly XFORM_UNKNOWN = 0; + static readonly XFORM_SCANNER_ANAT = 1; + static readonly XFORM_ALIGNED_ANAT = 2; + static readonly XFORM_TALAIRACH = 3; + static readonly XFORM_MNI_152 = 4; + static readonly SPATIAL_UNITS_MASK = 7; + static readonly TEMPORAL_UNITS_MASK = 56; + static readonly UNITS_UNKNOWN = 0; + static readonly UNITS_METER = 1; + static readonly UNITS_MM = 2; + static readonly UNITS_MICRON = 3; + static readonly UNITS_SEC = 8; + static readonly UNITS_MSEC = 16; + static readonly UNITS_USEC = 24; + static readonly UNITS_HZ = 32; + static readonly UNITS_PPM = 40; + static readonly UNITS_RADS = 48; + static readonly MAGIC_COOKIE = 348; + static readonly STANDARD_HEADER_SIZE = 348; + static readonly MAGIC_NUMBER_LOCATION = 344; + static readonly MAGIC_NUMBER: number[]; + static readonly MAGIC_NUMBER2: number[]; + static readonly EXTENSION_HEADER_SIZE = 8; + /*** Prototype Methods ***/ + /** + * Reads the header data. + * @param {ArrayBuffer} data + */ + readHeader(data: ArrayBuffer): void; + /** + * Returns a formatted string of header fields. + * @returns {string} + */ + toFormattedString(): string; + /** + * Returns a human-readable string of datatype. + * @param {number} code + * @returns {string} + */ + getDatatypeCodeString: (code: number) => string; + /** + * Returns a human-readable string of transform type. + * @param {number} code + * @returns {string} + */ + getTransformCodeString: (code: number) => string; + /** + * Returns a human-readable string of spatial and temporal units. + * @param {number} code + * @returns {string} + */ + getUnitsCodeString: (code: number) => string; + /** + * Returns the qform matrix. + * @returns {Array.>} + */ + getQformMat(): Array>; + /** + * Converts qform to an affine. (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {number} qb + * @param {number} qc + * @param {number} qd + * @param {number} qx + * @param {number} qy + * @param {number} qz + * @param {number} dx + * @param {number} dy + * @param {number} dz + * @param {number} qfac + * @returns {Array.>} + */ + convertNiftiQFormToNiftiSForm(qb: number, qc: number, qd: number, qx: number, qy: number, qz: number, dx: number, dy: number, dz: number, qfac: number): Array>; + /** + * Converts sform to an orientation string (e.g., XYZ+--). (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {Array.>} R + * @returns {string} + */ + convertNiftiSFormToNEMA(R: Array>): string | null; + nifti_mat33_mul: (A: number[][], B: number[][]) => number[][]; + nifti_mat33_determ: (R: number[][]) => number; + /** + * Returns the byte index of the extension. + * @returns {number} + */ + getExtensionLocation(): number; + /** + * Returns the extension size. + * @param {DataView} data + * @returns {number} + */ + getExtensionSize(data: DataView): number; + /** + * Returns the extension code. + * @param {DataView} data + * @returns {number} + */ + getExtensionCode(data: DataView): number; + /** + * Adds an extension + * @param {NIFTIEXTENSION} extension + * @param {number} index + */ + addExtension(extension: NIFTIEXTENSION, index?: number): void; + /** + * Removes an extension + * @param {number} index + */ + removeExtension(index: number): void; + /** + * Returns header as ArrayBuffer. + * @param {boolean} includeExtensions - should extension bytes be included + * @returns {ArrayBuffer} + */ + toArrayBuffer(includeExtensions?: boolean): ArrayBufferLike; +} +//# sourceMappingURL=nifti1.d.ts.map \ No newline at end of file diff --git a/dist/src/nifti1.d.ts.map b/dist/src/nifti1.d.ts.map new file mode 100644 index 0000000..ed138f2 --- /dev/null +++ b/dist/src/nifti1.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1.d.ts","sourceRoot":"","sources":["../../src/nifti1.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/src/nifti1.js b/dist/src/nifti1.js new file mode 100644 index 0000000..cab128b --- /dev/null +++ b/dist/src/nifti1.js @@ -0,0 +1,1110 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NIFTI1 = void 0; +const utilities_1 = require("./utilities"); +/*** Constructor ***/ +/** + * The NIFTI1 constructor. + * @constructor + * @property {boolean} littleEndian + * @property {number} dim_info + * @property {number[]} dims - image dimensions + * @property {number} intent_p1 + * @property {number} intent_p2 + * @property {number} intent_p3 + * @property {number} intent_code + * @property {number} datatypeCode + * @property {number} numBitsPerVoxel + * @property {number} slice_start + * @property {number} slice_end + * @property {number} slice_code + * @property {number[]} pixDims - voxel dimensions + * @property {number} vox_offset + * @property {number} scl_slope + * @property {number} scl_inter + * @property {number} xyzt_units + * @property {number} cal_max + * @property {number} cal_min + * @property {number} slice_duration + * @property {number} toffset + * @property {string} description + * @property {string} aux_file + * @property {string} intent_name + * @property {number} qform_code + * @property {number} sform_code + * @property {number} quatern_b + * @property {number} quatern_c + * @property {number} quatern_d + * @property {number} quatern_x + * @property {number} quatern_y + * @property {number} quatern_z + * @property {Array.>} affine + * @property {string} magic + * @property {boolean} isHDR - if hdr/img format + * @property {number[]} extensionFlag + * @property {number} extensionSize + * @property {number} extensionCode + * @property {nifti.NIFTIEXTENSION[]} extensions + * @type {Function} + */ +class NIFTI1 { + littleEndian = false; + dim_info = 0; + dims = []; + intent_p1 = 0.0; + intent_p2 = 0.0; + intent_p3 = 0.0; + intent_code = 0; + datatypeCode = 0; + numBitsPerVoxel = 0; + slice_start = 0; + slice_end = 0; + slice_code = 0; + pixDims = []; + vox_offset = 0; + scl_slope = 1.0; + scl_inter = 0.0; + xyzt_units = 0; + cal_max = 0.0; + cal_min = 0.0; + slice_duration = 0.0; + toffset = 0.0; + description = ""; + aux_file = ""; + intent_name = ""; + qform_code = 0; + sform_code = 0; + quatern_a = 0.0; + quatern_b = 0.0; + quatern_c = 0.0; + quatern_d = 0.0; + qoffset_x = 0.0; + qoffset_y = 0.0; + qoffset_z = 0.0; + affine = [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1], + ]; + qfac = 1; + quatern_R; + magic = "0"; + isHDR = false; + extensionFlag = [0, 0, 0, 0]; + extensionSize = 0; + extensionCode = 0; + extensions = []; + /*** Static Pseudo-constants ***/ + // datatype codes + static TYPE_NONE = 0; + static TYPE_BINARY = 1; + static TYPE_UINT8 = 2; + static TYPE_INT16 = 4; + static TYPE_INT32 = 8; + static TYPE_FLOAT32 = 16; + static TYPE_COMPLEX64 = 32; + static TYPE_FLOAT64 = 64; + static TYPE_RGB24 = 128; + static TYPE_INT8 = 256; + static TYPE_UINT16 = 512; + static TYPE_UINT32 = 768; + static TYPE_INT64 = 1024; + static TYPE_UINT64 = 1280; + static TYPE_FLOAT128 = 1536; + static TYPE_COMPLEX128 = 1792; + static TYPE_COMPLEX256 = 2048; + // transform codes + static XFORM_UNKNOWN = 0; + static XFORM_SCANNER_ANAT = 1; + static XFORM_ALIGNED_ANAT = 2; + static XFORM_TALAIRACH = 3; + static XFORM_MNI_152 = 4; + // unit codes + static SPATIAL_UNITS_MASK = 0x07; + static TEMPORAL_UNITS_MASK = 0x38; + static UNITS_UNKNOWN = 0; + static UNITS_METER = 1; + static UNITS_MM = 2; + static UNITS_MICRON = 3; + static UNITS_SEC = 8; + static UNITS_MSEC = 16; + static UNITS_USEC = 24; + static UNITS_HZ = 32; + static UNITS_PPM = 40; + static UNITS_RADS = 48; + // nifti1 codes + static MAGIC_COOKIE = 348; + static STANDARD_HEADER_SIZE = 348; + static MAGIC_NUMBER_LOCATION = 344; + static MAGIC_NUMBER = [0x6e, 0x2b, 0x31]; // n+1 (.nii) + static MAGIC_NUMBER2 = [0x6e, 0x69, 0x31]; // ni1 (.hdr/.img) + static EXTENSION_HEADER_SIZE = 8; + /*** Prototype Methods ***/ + /** + * Reads the header data. + * @param {ArrayBuffer} data + */ + readHeader(data) { + var rawData = new DataView(data), magicCookieVal = utilities_1.Utils.getIntAt(rawData, 0, this.littleEndian), ctr, ctrOut, ctrIn, index; + if (magicCookieVal !== NIFTI1.MAGIC_COOKIE) { + // try as little endian + this.littleEndian = true; + magicCookieVal = utilities_1.Utils.getIntAt(rawData, 0, this.littleEndian); + } + if (magicCookieVal !== NIFTI1.MAGIC_COOKIE) { + throw new Error("This does not appear to be a NIFTI file!"); + } + this.dim_info = utilities_1.Utils.getByteAt(rawData, 39); + for (ctr = 0; ctr < 8; ctr += 1) { + index = 40 + ctr * 2; + this.dims[ctr] = utilities_1.Utils.getShortAt(rawData, index, this.littleEndian); + } + this.intent_p1 = utilities_1.Utils.getFloatAt(rawData, 56, this.littleEndian); + this.intent_p2 = utilities_1.Utils.getFloatAt(rawData, 60, this.littleEndian); + this.intent_p3 = utilities_1.Utils.getFloatAt(rawData, 64, this.littleEndian); + this.intent_code = utilities_1.Utils.getShortAt(rawData, 68, this.littleEndian); + this.datatypeCode = utilities_1.Utils.getShortAt(rawData, 70, this.littleEndian); + this.numBitsPerVoxel = utilities_1.Utils.getShortAt(rawData, 72, this.littleEndian); + this.slice_start = utilities_1.Utils.getShortAt(rawData, 74, this.littleEndian); + for (ctr = 0; ctr < 8; ctr += 1) { + index = 76 + ctr * 4; + this.pixDims[ctr] = utilities_1.Utils.getFloatAt(rawData, index, this.littleEndian); + } + this.vox_offset = utilities_1.Utils.getFloatAt(rawData, 108, this.littleEndian); + this.scl_slope = utilities_1.Utils.getFloatAt(rawData, 112, this.littleEndian); + this.scl_inter = utilities_1.Utils.getFloatAt(rawData, 116, this.littleEndian); + this.slice_end = utilities_1.Utils.getShortAt(rawData, 120, this.littleEndian); + this.slice_code = utilities_1.Utils.getByteAt(rawData, 122); + this.xyzt_units = utilities_1.Utils.getByteAt(rawData, 123); + this.cal_max = utilities_1.Utils.getFloatAt(rawData, 124, this.littleEndian); + this.cal_min = utilities_1.Utils.getFloatAt(rawData, 128, this.littleEndian); + this.slice_duration = utilities_1.Utils.getFloatAt(rawData, 132, this.littleEndian); + this.toffset = utilities_1.Utils.getFloatAt(rawData, 136, this.littleEndian); + this.description = utilities_1.Utils.getStringAt(rawData, 148, 228); + this.aux_file = utilities_1.Utils.getStringAt(rawData, 228, 252); + this.qform_code = utilities_1.Utils.getShortAt(rawData, 252, this.littleEndian); + this.sform_code = utilities_1.Utils.getShortAt(rawData, 254, this.littleEndian); + this.quatern_b = utilities_1.Utils.getFloatAt(rawData, 256, this.littleEndian); + this.quatern_c = utilities_1.Utils.getFloatAt(rawData, 260, this.littleEndian); + this.quatern_d = utilities_1.Utils.getFloatAt(rawData, 264, this.littleEndian); + // Added by znshje on 27/11/2021 + // + // quatern_a is a parameter in quaternion [a, b, c, d], which is required in affine calculation (METHOD 2) + // mentioned in the nifti1.h file + // It can be calculated by a = sqrt(1.0-(b*b+c*c+d*d)) + this.quatern_a = Math.sqrt(1.0 - + (Math.pow(this.quatern_b, 2) + + Math.pow(this.quatern_c, 2) + + Math.pow(this.quatern_d, 2))); + this.qoffset_x = utilities_1.Utils.getFloatAt(rawData, 268, this.littleEndian); + this.qoffset_y = utilities_1.Utils.getFloatAt(rawData, 272, this.littleEndian); + this.qoffset_z = utilities_1.Utils.getFloatAt(rawData, 276, this.littleEndian); + // Added by znshje on 27/11/2021 + // + /* See: https://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1.h */ + if (this.qform_code > 0) { + // METHOD 2 (used when qform_code > 0, which should be the "normal" case): + // --------------------------------------------------------------------- + // The (x,y,z) coordinates are given by the pixdim[] scales, a rotation + // matrix, and a shift. This method is intended to represent + // "scanner-anatomical" coordinates, which are often embedded in the + // image header (e.g., DICOM fields (0020,0032), (0020,0037), (0028,0030), + // and (0018,0050)), and represent the nominal orientation and location of + // the data. This method can also be used to represent "aligned" + // coordinates, which would typically result from some post-acquisition + // alignment of the volume to a standard orientation (e.g., the same + // subject on another day, or a rigid rotation to true anatomical + // orientation from the tilted position of the subject in the scanner). + // The formula for (x,y,z) in terms of header parameters and (i,j,k) is: + // + // [ x ] [ R11 R12 R13 ] [ pixdim[1] * i ] [ qoffset_x ] + // [ y ] = [ R21 R22 R23 ] [ pixdim[2] * j ] + [ qoffset_y ] + // [ z ] [ R31 R32 R33 ] [ qfac * pixdim[3] * k ] [ qoffset_z ] + // + // The qoffset_* shifts are in the NIFTI-1 header. Note that the center + // of the (i,j,k)=(0,0,0) voxel (first value in the dataset array) is + // just (x,y,z)=(qoffset_x,qoffset_y,qoffset_z). + // + // The rotation matrix R is calculated from the quatern_* parameters. + // This calculation is described below. + // + // The scaling factor qfac is either 1 or -1. The rotation matrix R + // defined by the quaternion parameters is "proper" (has determinant 1). + // This may not fit the needs of the data; for example, if the image + // grid is + // i increases from Left-to-Right + // j increases from Anterior-to-Posterior + // k increases from Inferior-to-Superior + // Then (i,j,k) is a left-handed triple. In this example, if qfac=1, + // the R matrix would have to be + // + // [ 1 0 0 ] + // [ 0 -1 0 ] which is "improper" (determinant = -1). + // [ 0 0 1 ] + // + // If we set qfac=-1, then the R matrix would be + // + // [ 1 0 0 ] + // [ 0 -1 0 ] which is proper. + // [ 0 0 -1 ] + // + // This R matrix is represented by quaternion [a,b,c,d] = [0,1,0,0] + // (which encodes a 180 degree rotation about the x-axis). + // Define a, b, c, d for coding covenience + const a = this.quatern_a; + const b = this.quatern_b; + const c = this.quatern_c; + const d = this.quatern_d; + this.qfac = this.pixDims[0] === 0 ? 1 : this.pixDims[0]; + this.quatern_R = [ + [ + a * a + b * b - c * c - d * d, + 2 * b * c - 2 * a * d, + 2 * b * d + 2 * a * c, + ], + [ + 2 * b * c + 2 * a * d, + a * a + c * c - b * b - d * d, + 2 * c * d - 2 * a * b, + ], + [ + 2 * b * d - 2 * a * c, + 2 * c * d + 2 * a * b, + a * a + d * d - c * c - b * b, + ], + ]; + for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { + for (ctrIn = 0; ctrIn < 3; ctrIn += 1) { + this.affine[ctrOut][ctrIn] = + this.quatern_R[ctrOut][ctrIn] * this.pixDims[ctrIn + 1]; + if (ctrIn === 2) { + this.affine[ctrOut][ctrIn] *= this.qfac; + } + } + } + // The last row of affine matrix is the offset vector + this.affine[0][3] = this.qoffset_x; + this.affine[1][3] = this.qoffset_y; + this.affine[2][3] = this.qoffset_z; + } + else if (this.sform_code > 0) { + // METHOD 3 (used when sform_code > 0): + // ----------------------------------- + // The (x,y,z) coordinates are given by a general affine transformation + // of the (i,j,k) indexes: + // + // x = srow_x[0] * i + srow_x[1] * j + srow_x[2] * k + srow_x[3] + // y = srow_y[0] * i + srow_y[1] * j + srow_y[2] * k + srow_y[3] + // z = srow_z[0] * i + srow_z[1] * j + srow_z[2] * k + srow_z[3] + // + // The srow_* vectors are in the NIFTI_1 header. Note that no use is + // made of pixdim[] in this method. + for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { + for (ctrIn = 0; ctrIn < 4; ctrIn += 1) { + index = 280 + (ctrOut * 4 + ctrIn) * 4; + this.affine[ctrOut][ctrIn] = utilities_1.Utils.getFloatAt(rawData, index, this.littleEndian); + } + } + } + this.affine[3][0] = 0; + this.affine[3][1] = 0; + this.affine[3][2] = 0; + this.affine[3][3] = 1; + this.intent_name = utilities_1.Utils.getStringAt(rawData, 328, 344); + this.magic = utilities_1.Utils.getStringAt(rawData, 344, 348); + this.isHDR = this.magic === String.fromCharCode.apply(null, NIFTI1.MAGIC_NUMBER2); + if (rawData.byteLength > NIFTI1.MAGIC_COOKIE) { + this.extensionFlag[0] = utilities_1.Utils.getByteAt(rawData, 348); + this.extensionFlag[1] = utilities_1.Utils.getByteAt(rawData, 348 + 1); + this.extensionFlag[2] = utilities_1.Utils.getByteAt(rawData, 348 + 2); + this.extensionFlag[3] = utilities_1.Utils.getByteAt(rawData, 348 + 3); + if (this.extensionFlag[0]) { + // read our extensions + this.extensions = utilities_1.Utils.getExtensionsAt(rawData, this.getExtensionLocation(), this.littleEndian, this.vox_offset); + // set the extensionSize and extensionCode from the first extension found + this.extensionSize = this.extensions[0].esize; + this.extensionCode = this.extensions[0].ecode; + } + } + } + /** + * Returns a formatted string of header fields. + * @returns {string} + */ + toFormattedString() { + var fmt = utilities_1.Utils.formatNumber, string = ""; + string += "Dim Info = " + this.dim_info + "\n"; + string += + "Image Dimensions (1-8): " + + this.dims[0] + + ", " + + this.dims[1] + + ", " + + this.dims[2] + + ", " + + this.dims[3] + + ", " + + this.dims[4] + + ", " + + this.dims[5] + + ", " + + this.dims[6] + + ", " + + this.dims[7] + + "\n"; + string += + "Intent Parameters (1-3): " + + this.intent_p1 + + ", " + + this.intent_p2 + + ", " + + this.intent_p3 + + "\n"; + string += "Intent Code = " + this.intent_code + "\n"; + string += + "Datatype = " + + this.datatypeCode + + " (" + + this.getDatatypeCodeString(this.datatypeCode) + + ")\n"; + string += "Bits Per Voxel = " + this.numBitsPerVoxel + "\n"; + string += "Slice Start = " + this.slice_start + "\n"; + string += + "Voxel Dimensions (1-8): " + + fmt(this.pixDims[0]) + + ", " + + fmt(this.pixDims[1]) + + ", " + + fmt(this.pixDims[2]) + + ", " + + fmt(this.pixDims[3]) + + ", " + + fmt(this.pixDims[4]) + + ", " + + fmt(this.pixDims[5]) + + ", " + + fmt(this.pixDims[6]) + + ", " + + fmt(this.pixDims[7]) + + "\n"; + string += "Image Offset = " + this.vox_offset + "\n"; + string += + "Data Scale: Slope = " + + fmt(this.scl_slope) + + " Intercept = " + + fmt(this.scl_inter) + + "\n"; + string += "Slice End = " + this.slice_end + "\n"; + string += "Slice Code = " + this.slice_code + "\n"; + string += + "Units Code = " + + this.xyzt_units + + " (" + + this.getUnitsCodeString(NIFTI1.SPATIAL_UNITS_MASK & this.xyzt_units) + + ", " + + this.getUnitsCodeString(NIFTI1.TEMPORAL_UNITS_MASK & this.xyzt_units) + + ")\n"; + string += + "Display Range: Max = " + + fmt(this.cal_max) + + " Min = " + + fmt(this.cal_min) + + "\n"; + string += "Slice Duration = " + this.slice_duration + "\n"; + string += "Time Axis Shift = " + this.toffset + "\n"; + string += 'Description: "' + this.description + '"\n'; + string += 'Auxiliary File: "' + this.aux_file + '"\n'; + string += + "Q-Form Code = " + + this.qform_code + + " (" + + this.getTransformCodeString(this.qform_code) + + ")\n"; + string += + "S-Form Code = " + + this.sform_code + + " (" + + this.getTransformCodeString(this.sform_code) + + ")\n"; + string += + "Quaternion Parameters: " + + "b = " + + fmt(this.quatern_b) + + " " + + "c = " + + fmt(this.quatern_c) + + " " + + "d = " + + fmt(this.quatern_d) + + "\n"; + string += + "Quaternion Offsets: " + + "x = " + + this.qoffset_x + + " " + + "y = " + + this.qoffset_y + + " " + + "z = " + + this.qoffset_z + + "\n"; + string += + "S-Form Parameters X: " + + fmt(this.affine[0][0]) + + ", " + + fmt(this.affine[0][1]) + + ", " + + fmt(this.affine[0][2]) + + ", " + + fmt(this.affine[0][3]) + + "\n"; + string += + "S-Form Parameters Y: " + + fmt(this.affine[1][0]) + + ", " + + fmt(this.affine[1][1]) + + ", " + + fmt(this.affine[1][2]) + + ", " + + fmt(this.affine[1][3]) + + "\n"; + string += + "S-Form Parameters Z: " + + fmt(this.affine[2][0]) + + ", " + + fmt(this.affine[2][1]) + + ", " + + fmt(this.affine[2][2]) + + ", " + + fmt(this.affine[2][3]) + + "\n"; + string += 'Intent Name: "' + this.intent_name + '"\n'; + if (this.extensionFlag[0]) { + string += + "Extension: Size = " + + this.extensionSize + + " Code = " + + this.extensionCode + + "\n"; + } + return string; + } + /** + * Returns a human-readable string of datatype. + * @param {number} code + * @returns {string} + */ + getDatatypeCodeString = function (code) { + if (code === NIFTI1.TYPE_UINT8) { + return "1-Byte Unsigned Integer"; + } + else if (code === NIFTI1.TYPE_INT16) { + return "2-Byte Signed Integer"; + } + else if (code === NIFTI1.TYPE_INT32) { + return "4-Byte Signed Integer"; + } + else if (code === NIFTI1.TYPE_FLOAT32) { + return "4-Byte Float"; + } + else if (code === NIFTI1.TYPE_FLOAT64) { + return "8-Byte Float"; + } + else if (code === NIFTI1.TYPE_RGB24) { + return "RGB"; + } + else if (code === NIFTI1.TYPE_INT8) { + return "1-Byte Signed Integer"; + } + else if (code === NIFTI1.TYPE_UINT16) { + return "2-Byte Unsigned Integer"; + } + else if (code === NIFTI1.TYPE_UINT32) { + return "4-Byte Unsigned Integer"; + } + else if (code === NIFTI1.TYPE_INT64) { + return "8-Byte Signed Integer"; + } + else if (code === NIFTI1.TYPE_UINT64) { + return "8-Byte Unsigned Integer"; + } + else { + return "Unknown"; + } + }; + /** + * Returns a human-readable string of transform type. + * @param {number} code + * @returns {string} + */ + getTransformCodeString = function (code) { + if (code === NIFTI1.XFORM_SCANNER_ANAT) { + return "Scanner"; + } + else if (code === NIFTI1.XFORM_ALIGNED_ANAT) { + return "Aligned"; + } + else if (code === NIFTI1.XFORM_TALAIRACH) { + return "Talairach"; + } + else if (code === NIFTI1.XFORM_MNI_152) { + return "MNI"; + } + else { + return "Unknown"; + } + }; + /** + * Returns a human-readable string of spatial and temporal units. + * @param {number} code + * @returns {string} + */ + getUnitsCodeString = function (code) { + if (code === NIFTI1.UNITS_METER) { + return "Meters"; + } + else if (code === NIFTI1.UNITS_MM) { + return "Millimeters"; + } + else if (code === NIFTI1.UNITS_MICRON) { + return "Microns"; + } + else if (code === NIFTI1.UNITS_SEC) { + return "Seconds"; + } + else if (code === NIFTI1.UNITS_MSEC) { + return "Milliseconds"; + } + else if (code === NIFTI1.UNITS_USEC) { + return "Microseconds"; + } + else if (code === NIFTI1.UNITS_HZ) { + return "Hz"; + } + else if (code === NIFTI1.UNITS_PPM) { + return "PPM"; + } + else if (code === NIFTI1.UNITS_RADS) { + return "Rads"; + } + else { + return "Unknown"; + } + }; + /** + * Returns the qform matrix. + * @returns {Array.>} + */ + getQformMat() { + return this.convertNiftiQFormToNiftiSForm(this.quatern_b, this.quatern_c, this.quatern_d, this.qoffset_x, this.qoffset_y, this.qoffset_z, this.pixDims[1], this.pixDims[2], this.pixDims[3], this.pixDims[0]); + } + /** + * Converts qform to an affine. (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {number} qb + * @param {number} qc + * @param {number} qd + * @param {number} qx + * @param {number} qy + * @param {number} qz + * @param {number} dx + * @param {number} dy + * @param {number} dz + * @param {number} qfac + * @returns {Array.>} + */ + convertNiftiQFormToNiftiSForm(qb, qc, qd, qx, qy, qz, dx, dy, dz, qfac) { + var R = [ + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + ], a, b = qb, c = qc, d = qd, xd, yd, zd; + // last row is always [ 0 0 0 1 ] + R[3][0] = R[3][1] = R[3][2] = 0.0; + R[3][3] = 1.0; + // compute a parameter from b,c,d + a = 1.0 - (b * b + c * c + d * d); + if (a < 0.0000001) { + /* special case */ + a = 1.0 / Math.sqrt(b * b + c * c + d * d); + b *= a; + c *= a; + d *= a; /* normalize (b,c,d) vector */ + a = 0.0; /* a = 0 ==> 180 degree rotation */ + } + else { + a = Math.sqrt(a); /* angle = 2*arccos(a) */ + } + // load rotation matrix, including scaling factors for voxel sizes + xd = dx > 0.0 ? dx : 1.0; /* make sure are positive */ + yd = dy > 0.0 ? dy : 1.0; + zd = dz > 0.0 ? dz : 1.0; + if (qfac < 0.0) { + zd = -zd; /* left handedness? */ + } + R[0][0] = (a * a + b * b - c * c - d * d) * xd; + R[0][1] = 2.0 * (b * c - a * d) * yd; + R[0][2] = 2.0 * (b * d + a * c) * zd; + R[1][0] = 2.0 * (b * c + a * d) * xd; + R[1][1] = (a * a + c * c - b * b - d * d) * yd; + R[1][2] = 2.0 * (c * d - a * b) * zd; + R[2][0] = 2.0 * (b * d - a * c) * xd; + R[2][1] = 2.0 * (c * d + a * b) * yd; + R[2][2] = (a * a + d * d - c * c - b * b) * zd; + // load offsets + R[0][3] = qx; + R[1][3] = qy; + R[2][3] = qz; + return R; + } + /** + * Converts sform to an orientation string (e.g., XYZ+--). (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {Array.>} R + * @returns {string} + */ + convertNiftiSFormToNEMA(R) { + var xi, xj, xk, yi, yj, yk, zi, zj, zk, val, detQ, detP, i, j, k, p, q, r, ibest, jbest, kbest, pbest, qbest, rbest, M, vbest, Q, P, iChar, jChar, kChar, iSense, jSense, kSense; + k = 0; + Q = [ + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ]; + P = [ + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ]; + //if( icod == NULL || jcod == NULL || kcod == NULL ) return ; /* bad */ + //*icod = *jcod = *kcod = 0 ; /* this.errorMessage returns, if sh*t happens */ + /* load column vectors for each (i,j,k) direction from matrix */ + /*-- i axis --*/ /*-- j axis --*/ /*-- k axis --*/ + xi = R[0][0]; + xj = R[0][1]; + xk = R[0][2]; + yi = R[1][0]; + yj = R[1][1]; + yk = R[1][2]; + zi = R[2][0]; + zj = R[2][1]; + zk = R[2][2]; + /* normalize column vectors to get unit vectors along each ijk-axis */ + /* normalize i axis */ + val = Math.sqrt(xi * xi + yi * yi + zi * zi); + if (val === 0.0) { + /* stupid input */ + return null; + } + xi /= val; + yi /= val; + zi /= val; + /* normalize j axis */ + val = Math.sqrt(xj * xj + yj * yj + zj * zj); + if (val === 0.0) { + /* stupid input */ + return null; + } + xj /= val; + yj /= val; + zj /= val; + /* orthogonalize j axis to i axis, if needed */ + val = xi * xj + yi * yj + zi * zj; /* dot product between i and j */ + if (Math.abs(val) > 1e-4) { + xj -= val * xi; + yj -= val * yi; + zj -= val * zi; + val = Math.sqrt(xj * xj + yj * yj + zj * zj); /* must renormalize */ + if (val === 0.0) { + /* j was parallel to i? */ + return null; + } + xj /= val; + yj /= val; + zj /= val; + } + /* normalize k axis; if it is zero, make it the cross product i x j */ + val = Math.sqrt(xk * xk + yk * yk + zk * zk); + if (val === 0.0) { + xk = yi * zj - zi * yj; + yk = zi * xj - zj * xi; + zk = xi * yj - yi * xj; + } + else { + xk /= val; + yk /= val; + zk /= val; + } + /* orthogonalize k to i */ + val = xi * xk + yi * yk + zi * zk; /* dot product between i and k */ + if (Math.abs(val) > 1e-4) { + xk -= val * xi; + yk -= val * yi; + zk -= val * zi; + val = Math.sqrt(xk * xk + yk * yk + zk * zk); + if (val === 0.0) { + /* bad */ + return null; + } + xk /= val; + yk /= val; + zk /= val; + } + /* orthogonalize k to j */ + val = xj * xk + yj * yk + zj * zk; /* dot product between j and k */ + if (Math.abs(val) > 1e-4) { + xk -= val * xj; + yk -= val * yj; + zk -= val * zj; + val = Math.sqrt(xk * xk + yk * yk + zk * zk); + if (val === 0.0) { + /* bad */ + return null; + } + xk /= val; + yk /= val; + zk /= val; + } + Q[0][0] = xi; + Q[0][1] = xj; + Q[0][2] = xk; + Q[1][0] = yi; + Q[1][1] = yj; + Q[1][2] = yk; + Q[2][0] = zi; + Q[2][1] = zj; + Q[2][2] = zk; + /* at this point, Q is the rotation matrix from the (i,j,k) to (x,y,z) axes */ + detQ = this.nifti_mat33_determ(Q); + if (detQ === 0.0) { + /* shouldn't happen unless user is a DUFIS */ + return null; + } + /* Build and test all possible +1/-1 coordinate permutation matrices P; + then find the P such that the rotation matrix M=PQ is closest to the + identity, in the sense of M having the smallest total rotation angle. */ + /* Despite the formidable looking 6 nested loops, there are + only 3*3*3*2*2*2 = 216 passes, which will run very quickly. */ + vbest = -666.0; + ibest = pbest = qbest = rbest = 1; + jbest = 2; + kbest = 3; + for (i = 1; i <= 3; i += 1) { + /* i = column number to use for row #1 */ + for (j = 1; j <= 3; j += 1) { + /* j = column number to use for row #2 */ + if (i !== j) { + for (k = 1; k <= 3; k += 1) { + /* k = column number to use for row #3 */ + if (!(i === k || j === k)) { + P[0][0] = + P[0][1] = + P[0][2] = + P[1][0] = + P[1][1] = + P[1][2] = + P[2][0] = + P[2][1] = + P[2][2] = + 0.0; + for (p = -1; p <= 1; p += 2) { + /* p,q,r are -1 or +1 */ + for (q = -1; q <= 1; q += 2) { + /* and go into rows #1,2,3 */ + for (r = -1; r <= 1; r += 2) { + P[0][i - 1] = p; + P[1][j - 1] = q; + P[2][k - 1] = r; + detP = + this.nifti_mat33_determ(P); /* sign of permutation */ + if (detP * detQ > 0.0) { + M = this.nifti_mat33_mul(P, Q); + /* angle of M rotation = 2.0*acos(0.5*sqrt(1.0+trace(M))) */ + /* we want largest trace(M) == smallest angle == M nearest to I */ + val = M[0][0] + M[1][1] + M[2][2]; /* trace */ + if (val > vbest) { + vbest = val; + ibest = i; + jbest = j; + kbest = k; + pbest = p; + qbest = q; + rbest = r; + } + } /* doesn't match sign of Q */ + } + } + } + } + } + } + } + } + /* At this point ibest is 1 or 2 or 3; pbest is -1 or +1; etc. + + The matrix P that corresponds is the best permutation approximation + to Q-inverse; that is, P (approximately) takes (x,y,z) coordinates + to the (i,j,k) axes. + + For example, the first row of P (which contains pbest in column ibest) + determines the way the i axis points relative to the anatomical + (x,y,z) axes. If ibest is 2, then the i axis is along the y axis, + which is direction P2A (if pbest > 0) or A2P (if pbest < 0). + + So, using ibest and pbest, we can assign the output code for + the i axis. Mutatis mutandis for the j and k axes, of course. */ + iChar = jChar = kChar = iSense = jSense = kSense = ""; + switch (ibest * pbest) { + case 1 /*i = NIFTI_L2R*/: + iChar = "X"; + iSense = "+"; + break; + case -1 /*i = NIFTI_R2L*/: + iChar = "X"; + iSense = "-"; + break; + case 2 /*i = NIFTI_P2A*/: + iChar = "Y"; + iSense = "+"; + break; + case -2 /*i = NIFTI_A2P*/: + iChar = "Y"; + iSense = "-"; + break; + case 3 /*i = NIFTI_I2S*/: + iChar = "Z"; + iSense = "+"; + break; + case -3 /*i = NIFTI_S2I*/: + iChar = "Z"; + iSense = "-"; + break; + } + switch (jbest * qbest) { + case 1 /*j = NIFTI_L2R*/: + jChar = "X"; + jSense = "+"; + break; + case -1 /*j = NIFTI_R2L*/: + jChar = "X"; + jSense = "-"; + break; + case 2 /*j = NIFTI_P2A*/: + jChar = "Y"; + jSense = "+"; + break; + case -2 /*j = NIFTI_A2P*/: + jChar = "Y"; + jSense = "-"; + break; + case 3 /*j = NIFTI_I2S*/: + jChar = "Z"; + jSense = "+"; + break; + case -3 /*j = NIFTI_S2I*/: + jChar = "Z"; + jSense = "-"; + break; + } + switch (kbest * rbest) { + case 1 /*k = NIFTI_L2R*/: + kChar = "X"; + kSense = "+"; + break; + case -1 /*k = NIFTI_R2L*/: + kChar = "X"; + kSense = "-"; + break; + case 2 /*k = NIFTI_P2A*/: + kChar = "Y"; + kSense = "+"; + break; + case -2 /*k = NIFTI_A2P*/: + kChar = "Y"; + kSense = "-"; + break; + case 3 /*k = NIFTI_I2S*/: + kChar = "Z"; + kSense = "+"; + break; + case -3 /*k = NIFTI_S2I*/: + kChar = "Z"; + kSense = "-"; + break; + } + return iChar + jChar + kChar + iSense + jSense + kSense; + } + nifti_mat33_mul = function (A, B) { + var C = [ + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], i, j; + for (i = 0; i < 3; i += 1) { + for (j = 0; j < 3; j += 1) { + C[i][j] = A[i][0] * B[0][j] + A[i][1] * B[1][j] + A[i][2] * B[2][j]; + } + } + return C; + }; + nifti_mat33_determ = function (R) { + var r11, r12, r13, r21, r22, r23, r31, r32, r33; + /* INPUT MATRIX: */ + r11 = R[0][0]; + r12 = R[0][1]; + r13 = R[0][2]; + r21 = R[1][0]; + r22 = R[1][1]; + r23 = R[1][2]; + r31 = R[2][0]; + r32 = R[2][1]; + r33 = R[2][2]; + return (r11 * r22 * r33 - + r11 * r32 * r23 - + r21 * r12 * r33 + + r21 * r32 * r13 + + r31 * r12 * r23 - + r31 * r22 * r13); + }; + /** + * Returns the byte index of the extension. + * @returns {number} + */ + getExtensionLocation() { + return NIFTI1.MAGIC_COOKIE + 4; + } + /** + * Returns the extension size. + * @param {DataView} data + * @returns {number} + */ + getExtensionSize(data) { + return utilities_1.Utils.getIntAt(data, this.getExtensionLocation(), this.littleEndian); + } + /** + * Returns the extension code. + * @param {DataView} data + * @returns {number} + */ + getExtensionCode(data) { + return utilities_1.Utils.getIntAt(data, this.getExtensionLocation() + 4, this.littleEndian); + } + /** + * Adds an extension + * @param {NIFTIEXTENSION} extension + * @param {number} index + */ + addExtension(extension, index = -1) { + if (index == -1) { + this.extensions.push(extension); + } + else { + this.extensions.splice(index, 0, extension); + } + this.vox_offset += extension.esize; + } + /** + * Removes an extension + * @param {number} index + */ + removeExtension(index) { + let extension = this.extensions[index]; + if (extension) { + this.vox_offset -= extension.esize; + } + this.extensions.splice(index, 1); + } + /** + * Returns header as ArrayBuffer. + * @param {boolean} includeExtensions - should extension bytes be included + * @returns {ArrayBuffer} + */ + toArrayBuffer(includeExtensions = false) { + const SHORT_SIZE = 2; + const FLOAT32_SIZE = 4; + let byteSize = 348 + 4; // + 4 for the extension bytes + // calculate necessary size + if (includeExtensions) { + for (let extension of this.extensions) { + byteSize += extension.esize; + } + } + let byteArray = new Uint8Array(byteSize); + let view = new DataView(byteArray.buffer); + // sizeof_hdr + view.setInt32(0, 348, this.littleEndian); + // data_type, db_name, extents, session_error, regular are not used + // dim_info + view.setUint8(39, this.dim_info); + // dims + for (let i = 0; i < 8; i++) { + view.setUint16(40 + SHORT_SIZE * i, this.dims[i], this.littleEndian); + } + // intent_p1, intent_p2, intent_p3 + view.setFloat32(56, this.intent_p1, this.littleEndian); + view.setFloat32(60, this.intent_p2, this.littleEndian); + view.setFloat32(64, this.intent_p3, this.littleEndian); + // intent_code, datatype, bitpix, slice_start + view.setInt16(68, this.intent_code, this.littleEndian); + view.setInt16(70, this.datatypeCode, this.littleEndian); + view.setInt16(72, this.numBitsPerVoxel, this.littleEndian); + view.setInt16(74, this.slice_start, this.littleEndian); + // pixdim[8], vox_offset, scl_slope, scl_inter + for (let i = 0; i < 8; i++) { + view.setFloat32(76 + FLOAT32_SIZE * i, this.pixDims[i], this.littleEndian); + } + view.setFloat32(108, this.vox_offset, this.littleEndian); + view.setFloat32(112, this.scl_slope, this.littleEndian); + view.setFloat32(116, this.scl_inter, this.littleEndian); + // slice_end + view.setInt16(120, this.slice_end, this.littleEndian); + // slice_code, xyzt_units + view.setUint8(122, this.slice_code); + view.setUint8(123, this.xyzt_units); + // cal_max, cal_min, slice_duration, toffset + view.setFloat32(124, this.cal_max, this.littleEndian); + view.setFloat32(128, this.cal_min, this.littleEndian); + view.setFloat32(132, this.slice_duration, this.littleEndian); + view.setFloat32(136, this.toffset, this.littleEndian); + // glmax, glmin are unused + // descrip and aux_file + byteArray.set(Buffer.from(this.description), 148); + byteArray.set(Buffer.from(this.aux_file), 228); + // qform_code, sform_code + view.setInt16(252, this.qform_code, this.littleEndian); + view.setInt16(254, this.sform_code, this.littleEndian); + // quatern_b, quatern_c, quatern_d, qoffset_x, qoffset_y, qoffset_z, srow_x[4], srow_y[4], and srow_z[4] + view.setFloat32(256, this.quatern_b, this.littleEndian); + view.setFloat32(260, this.quatern_c, this.littleEndian); + view.setFloat32(264, this.quatern_d, this.littleEndian); + view.setFloat32(268, this.qoffset_x, this.littleEndian); + view.setFloat32(272, this.qoffset_y, this.littleEndian); + view.setFloat32(276, this.qoffset_z, this.littleEndian); + const flattened = this.affine.flat(); + // we only want the first three rows + for (let i = 0; i < 12; i++) { + view.setFloat32(280 + FLOAT32_SIZE * i, flattened[i], this.littleEndian); + } + // intent_name and magic + byteArray.set(Buffer.from(this.intent_name), 328); + byteArray.set(Buffer.from(this.magic), 344); + // add our extension data + if (includeExtensions) { + byteArray.set(Uint8Array.from([1, 0, 0, 0]), 348); + let extensionByteIndex = this.getExtensionLocation(); + for (const extension of this.extensions) { + view.setInt32(extensionByteIndex, extension.esize, extension.littleEndian); + view.setInt32(extensionByteIndex + 4, extension.ecode, extension.littleEndian); + byteArray.set(new Uint8Array(extension.edata), extensionByteIndex + 8); + extensionByteIndex += extension.esize; + } + } + else { + // In a .nii file, these 4 bytes will always be present + byteArray.set(new Uint8Array(4).fill(0), 348); + } + return byteArray.buffer; + } +} +exports.NIFTI1 = NIFTI1; +//# sourceMappingURL=nifti1.js.map \ No newline at end of file diff --git a/dist/src/nifti1.js.map b/dist/src/nifti1.js.map new file mode 100644 index 0000000..4d91733 --- /dev/null +++ b/dist/src/nifti1.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti1.js","sourceRoot":"","sources":["../../src/nifti1.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/src/nifti2.d.ts b/dist/src/nifti2.d.ts new file mode 100644 index 0000000..f1ceb42 --- /dev/null +++ b/dist/src/nifti2.d.ts @@ -0,0 +1,179 @@ +import { NIFTIEXTENSION } from "./nifti-extension"; +/** + * The NIFTI2 constructor. + * @constructor + * @property {boolean} littleEndian + * @property {number} dim_info + * @property {number[]} dims - image dimensions + * @property {number} intent_p1 + * @property {number} intent_p2 + * @property {number} intent_p3 + * @property {number} intent_code + * @property {number} datatypeCode + * @property {number} numBitsPerVoxel + * @property {number} slice_start + * @property {number} slice_end + * @property {number} slice_code + * @property {number[]} pixDims - voxel dimensions + * @property {number} vox_offset + * @property {number} scl_slope + * @property {number} scl_inter + * @property {number} xyzt_units + * @property {number} cal_max + * @property {number} cal_min + * @property {number} slice_duration + * @property {number} toffset + * @property {string} description + * @property {string} aux_file + * @property {string} intent_name + * @property {number} qform_code + * @property {number} sform_code + * @property {number} quatern_b + * @property {number} quatern_c + * @property {number} quatern_d + * @property {number} quatern_x + * @property {number} quatern_y + * @property {number} quatern_z + * @property {Array.>} affine + * @property {string} magic + * @property {number[]} extensionFlag + * @property {NIFTIEXTENSION[]} extensions + * @type {Function} + */ +export declare class NIFTI2 { + littleEndian: boolean; + dim_info: number; + dims: number[]; + intent_p1: number; + intent_p2: number; + intent_p3: number; + intent_code: number; + datatypeCode: number; + numBitsPerVoxel: number; + slice_start: number; + slice_end: number; + slice_code: number; + pixDims: number[]; + vox_offset: number; + scl_slope: number; + scl_inter: number; + xyzt_units: number; + cal_max: number; + cal_min: number; + slice_duration: number; + toffset: number; + description: string; + aux_file: string; + intent_name: string; + qform_code: number; + sform_code: number; + quatern_b: number; + quatern_c: number; + quatern_d: number; + qoffset_x: number; + qoffset_y: number; + qoffset_z: number; + affine: number[][]; + magic: string; + extensionFlag: number[]; + extensions: NIFTIEXTENSION[]; + extensionSize: number; + extensionCode: number; + /*** Static Pseudo-constants ***/ + static readonly MAGIC_COOKIE = 540; + static readonly MAGIC_NUMBER_LOCATION = 4; + static readonly MAGIC_NUMBER: number[]; + static readonly MAGIC_NUMBER2: number[]; + /*** Prototype Methods ***/ + /** + * Reads the header data. + * @param {ArrayBuffer} data + */ + readHeader(data: ArrayBuffer): void; + /** + * Returns a formatted string of header fields. + * @returns {string} + */ + toFormattedString(): string; + /** + * Returns the byte index of the extension. + * @returns {number} + */ + getExtensionLocation: () => number; + /** + * Returns the extension size. + * @param {DataView} data + * @returns {number} + */ + getExtensionSize: (data: DataView) => number; + /** + * Returns the extension code. + * @param {DataView} data + * @returns {number} + */ + getExtensionCode: (data: DataView) => number; + /** + * Adds an extension + * @param {NIFTIEXTENSION} extension + * @param {number} index + */ + addExtension: (extension: NIFTIEXTENSION, index?: number) => void; + /** + * Removes an extension + * @param {number} index + */ + removeExtension: (index: number) => void; + /** + * Returns a human-readable string of datatype. + * @param {number} code + * @returns {string} + */ + getDatatypeCodeString: (code: number) => string; + /** + * Returns a human-readable string of transform type. + * @param {number} code + * @returns {string} + */ + getTransformCodeString: (code: number) => string; + /** + * Returns a human-readable string of spatial and temporal units. + * @param {number} code + * @returns {string} + */ + getUnitsCodeString: (code: number) => string; + /** + * Returns the qform matrix. + * @returns {Array.>} + */ + getQformMat: () => number[][]; + /** + * Converts qform to an affine. (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {number} qb + * @param {number} qc + * @param {number} qd + * @param {number} qx + * @param {number} qy + * @param {number} qz + * @param {number} dx + * @param {number} dy + * @param {number} dz + * @param {number} qfac + * @returns {Array.>} + */ + convertNiftiQFormToNiftiSForm: (qb: number, qc: number, qd: number, qx: number, qy: number, qz: number, dx: number, dy: number, dz: number, qfac: number) => number[][]; + /** + * Converts sform to an orientation string (e.g., XYZ+--). (See http://nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {Array.>} R + * @returns {string} + */ + convertNiftiSFormToNEMA: (R: number[][]) => string | null; + nifti_mat33_mul: (A: number[][], B: number[][]) => number[][]; + nifti_mat33_determ: (R: number[][]) => number; + /** + * Returns header as ArrayBuffer. + * @param {boolean} includeExtensions - should extension bytes be included + * @returns {ArrayBuffer} + */ + toArrayBuffer(includeExtensions?: boolean): ArrayBufferLike; +} +//# sourceMappingURL=nifti2.d.ts.map \ No newline at end of file diff --git a/dist/src/nifti2.d.ts.map b/dist/src/nifti2.d.ts.map new file mode 100644 index 0000000..16c79e3 --- /dev/null +++ b/dist/src/nifti2.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti2.d.ts","sourceRoot":"","sources":["../../src/nifti2.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAInD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,qBAAa,MAAM;IACjB,YAAY,UAAS;IACrB,QAAQ,SAAK;IACb,IAAI,EAAE,MAAM,EAAE,CAAM;IACpB,SAAS,SAAK;IACd,SAAS,SAAK;IACd,SAAS,SAAK;IACd,WAAW,SAAK;IAChB,YAAY,SAAK;IACjB,eAAe,SAAK;IACpB,WAAW,SAAK;IAChB,SAAS,SAAK;IACd,UAAU,SAAK;IACf,OAAO,EAAE,MAAM,EAAE,CAAM;IACvB,UAAU,SAAK;IACf,SAAS,SAAK;IACd,SAAS,SAAK;IACd,UAAU,SAAK;IACf,OAAO,SAAK;IACZ,OAAO,SAAK;IACZ,cAAc,SAAK;IACnB,OAAO,SAAK;IACZ,WAAW,SAAM;IACjB,QAAQ,SAAM;IACd,WAAW,SAAM;IACjB,UAAU,SAAK;IACf,UAAU,SAAK;IACf,SAAS,SAAK;IACd,SAAS,SAAK;IACd,SAAS,SAAK;IACd,SAAS,SAAK;IACd,SAAS,SAAK;IACd,SAAS,SAAK;IACd,MAAM,aAKJ;IACF,KAAK,SAAO;IACZ,aAAa,WAAgB;IAC7B,UAAU,EAAE,cAAc,EAAE,CAAM;IAClC,aAAa,SAAK;IAClB,aAAa,SAAK;IAElB,iCAAiC;IAEjC,gBAAuB,YAAY,OAAO;IAC1C,gBAAuB,qBAAqB,KAAK;IACjD,gBAAuB,YAAY,WAEjC;IACF,gBAAuB,aAAa,WAElC;IAEF,2BAA2B;IAE3B;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,WAAW;IA6G5B;;;OAGG;IACH,iBAAiB;IAoKjB;;;OAGG;IACH,oBAAoB,eAElB;IAEF;;;;OAIG;IACH,gBAAgB,6BAAqC;IAErD;;;;OAIG;IACH,gBAAgB,6BAAqC;IAErD;;;;OAIG;IACH,YAAY,sDAAiC;IAE7C;;;OAGG;IACH,eAAe,0BAAoC;IAEnD;;;;OAIG;IACH,qBAAqB,2BAA0C;IAE/D;;;;OAIG;IACH,sBAAsB,2BAA2C;IAEjE;;;;OAIG;IACH,kBAAkB,2BAAuC;IAEzD;;;OAGG;IACH,WAAW,mBAAgC;IAE3C;;;;;;;;;;;;;OAaG;IACH,6BAA6B,2IACoB;IAEjD;;;;OAIG;IACH,uBAAuB,mCAA4C;IAEnE,eAAe,+CAAoC;IAEnD,kBAAkB,4BAAuC;IAEzD;;;;OAIG;IACH,aAAa,CAAC,iBAAiB,UAAQ;CAyJxC"} \ No newline at end of file diff --git a/dist/src/nifti2.js b/dist/src/nifti2.js new file mode 100644 index 0000000..ac34b8a --- /dev/null +++ b/dist/src/nifti2.js @@ -0,0 +1,520 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NIFTI2 = void 0; +const nifti1_1 = require("./nifti1"); +const utilities_1 = require("./utilities"); +/** + * The NIFTI2 constructor. + * @constructor + * @property {boolean} littleEndian + * @property {number} dim_info + * @property {number[]} dims - image dimensions + * @property {number} intent_p1 + * @property {number} intent_p2 + * @property {number} intent_p3 + * @property {number} intent_code + * @property {number} datatypeCode + * @property {number} numBitsPerVoxel + * @property {number} slice_start + * @property {number} slice_end + * @property {number} slice_code + * @property {number[]} pixDims - voxel dimensions + * @property {number} vox_offset + * @property {number} scl_slope + * @property {number} scl_inter + * @property {number} xyzt_units + * @property {number} cal_max + * @property {number} cal_min + * @property {number} slice_duration + * @property {number} toffset + * @property {string} description + * @property {string} aux_file + * @property {string} intent_name + * @property {number} qform_code + * @property {number} sform_code + * @property {number} quatern_b + * @property {number} quatern_c + * @property {number} quatern_d + * @property {number} quatern_x + * @property {number} quatern_y + * @property {number} quatern_z + * @property {Array.>} affine + * @property {string} magic + * @property {number[]} extensionFlag + * @property {NIFTIEXTENSION[]} extensions + * @type {Function} + */ +class NIFTI2 { + littleEndian = false; + dim_info = 0; + dims = []; + intent_p1 = 0; + intent_p2 = 0; + intent_p3 = 0; + intent_code = 0; + datatypeCode = 0; + numBitsPerVoxel = 0; + slice_start = 0; + slice_end = 0; + slice_code = 0; + pixDims = []; + vox_offset = 0; + scl_slope = 1; + scl_inter = 0; + xyzt_units = 0; + cal_max = 0; + cal_min = 0; + slice_duration = 0; + toffset = 0; + description = ""; + aux_file = ""; + intent_name = ""; + qform_code = 0; + sform_code = 0; + quatern_b = 0; + quatern_c = 0; + quatern_d = 0; + qoffset_x = 0; + qoffset_y = 0; + qoffset_z = 0; + affine = [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1], + ]; + magic = "0"; + extensionFlag = [0, 0, 0, 0]; + extensions = []; + extensionSize = 0; + extensionCode = 0; + /*** Static Pseudo-constants ***/ + static MAGIC_COOKIE = 540; + static MAGIC_NUMBER_LOCATION = 4; + static MAGIC_NUMBER = [ + 0x6e, 0x2b, 0x32, 0, 0x0d, 0x0a, 0x1a, 0x0a, + ]; // n+2\0 + static MAGIC_NUMBER2 = [ + 0x6e, 0x69, 0x32, 0, 0x0d, 0x0a, 0x1a, 0x0a, + ]; // ni2\0 + /*** Prototype Methods ***/ + /** + * Reads the header data. + * @param {ArrayBuffer} data + */ + readHeader(data) { + var rawData = new DataView(data), magicCookieVal = utilities_1.Utils.getIntAt(rawData, 0, this.littleEndian), ctr, ctrOut, ctrIn, index, array; + if (magicCookieVal !== NIFTI2.MAGIC_COOKIE) { + // try as little endian + this.littleEndian = true; + magicCookieVal = utilities_1.Utils.getIntAt(rawData, 0, this.littleEndian); + } + if (magicCookieVal !== NIFTI2.MAGIC_COOKIE) { + throw new Error("This does not appear to be a NIFTI file!"); + } + this.magic = utilities_1.Utils.getStringAt(rawData, 4, 12); + this.datatypeCode = utilities_1.Utils.getShortAt(rawData, 12, this.littleEndian); + this.numBitsPerVoxel = utilities_1.Utils.getShortAt(rawData, 14, this.littleEndian); + for (ctr = 0; ctr < 8; ctr += 1) { + index = 16 + ctr * 8; + this.dims[ctr] = utilities_1.Utils.getLongAt(rawData, index, this.littleEndian); + } + this.intent_p1 = utilities_1.Utils.getDoubleAt(rawData, 80, this.littleEndian); + this.intent_p2 = utilities_1.Utils.getDoubleAt(rawData, 88, this.littleEndian); + this.intent_p3 = utilities_1.Utils.getDoubleAt(rawData, 96, this.littleEndian); + for (ctr = 0; ctr < 8; ctr += 1) { + index = 104 + ctr * 8; + this.pixDims[ctr] = utilities_1.Utils.getDoubleAt(rawData, index, this.littleEndian); + } + this.vox_offset = utilities_1.Utils.getLongAt(rawData, 168, this.littleEndian); + this.scl_slope = utilities_1.Utils.getDoubleAt(rawData, 176, this.littleEndian); + this.scl_inter = utilities_1.Utils.getDoubleAt(rawData, 184, this.littleEndian); + this.cal_max = utilities_1.Utils.getDoubleAt(rawData, 192, this.littleEndian); + this.cal_min = utilities_1.Utils.getDoubleAt(rawData, 200, this.littleEndian); + this.slice_duration = utilities_1.Utils.getDoubleAt(rawData, 208, this.littleEndian); + this.toffset = utilities_1.Utils.getDoubleAt(rawData, 216, this.littleEndian); + this.slice_start = utilities_1.Utils.getLongAt(rawData, 224, this.littleEndian); + this.slice_end = utilities_1.Utils.getLongAt(rawData, 232, this.littleEndian); + this.description = utilities_1.Utils.getStringAt(rawData, 240, 240 + 80); + this.aux_file = utilities_1.Utils.getStringAt(rawData, 320, 320 + 24); + this.qform_code = utilities_1.Utils.getIntAt(rawData, 344, this.littleEndian); + this.sform_code = utilities_1.Utils.getIntAt(rawData, 348, this.littleEndian); + this.quatern_b = utilities_1.Utils.getDoubleAt(rawData, 352, this.littleEndian); + this.quatern_c = utilities_1.Utils.getDoubleAt(rawData, 360, this.littleEndian); + this.quatern_d = utilities_1.Utils.getDoubleAt(rawData, 368, this.littleEndian); + this.qoffset_x = utilities_1.Utils.getDoubleAt(rawData, 376, this.littleEndian); + this.qoffset_y = utilities_1.Utils.getDoubleAt(rawData, 384, this.littleEndian); + this.qoffset_z = utilities_1.Utils.getDoubleAt(rawData, 392, this.littleEndian); + for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { + for (ctrIn = 0; ctrIn < 4; ctrIn += 1) { + index = 400 + (ctrOut * 4 + ctrIn) * 8; + this.affine[ctrOut][ctrIn] = utilities_1.Utils.getDoubleAt(rawData, index, this.littleEndian); + } + } + this.affine[3][0] = 0; + this.affine[3][1] = 0; + this.affine[3][2] = 0; + this.affine[3][3] = 1; + this.slice_code = utilities_1.Utils.getIntAt(rawData, 496, this.littleEndian); + this.xyzt_units = utilities_1.Utils.getIntAt(rawData, 500, this.littleEndian); + this.intent_code = utilities_1.Utils.getIntAt(rawData, 504, this.littleEndian); + this.intent_name = utilities_1.Utils.getStringAt(rawData, 508, 508 + 16); + this.dim_info = utilities_1.Utils.getByteAt(rawData, 524); + if (rawData.byteLength > NIFTI2.MAGIC_COOKIE) { + this.extensionFlag[0] = utilities_1.Utils.getByteAt(rawData, 540); + this.extensionFlag[1] = utilities_1.Utils.getByteAt(rawData, 540 + 1); + this.extensionFlag[2] = utilities_1.Utils.getByteAt(rawData, 540 + 2); + this.extensionFlag[3] = utilities_1.Utils.getByteAt(rawData, 540 + 3); + if (this.extensionFlag[0]) { + // read our extensions + this.extensions = utilities_1.Utils.getExtensionsAt(rawData, this.getExtensionLocation(), this.littleEndian, this.vox_offset); + // set the extensionSize and extensionCode from the first extension found + this.extensionSize = this.extensions[0].esize; + this.extensionCode = this.extensions[0].ecode; + } + } + } + /** + * Returns a formatted string of header fields. + * @returns {string} + */ + toFormattedString() { + var fmt = utilities_1.Utils.formatNumber, string = ""; + string += + "Datatype = " + + +this.datatypeCode + + " (" + + this.getDatatypeCodeString(this.datatypeCode) + + ")\n"; + string += "Bits Per Voxel = " + " = " + this.numBitsPerVoxel + "\n"; + string += + "Image Dimensions" + + " (1-8): " + + this.dims[0] + + ", " + + this.dims[1] + + ", " + + this.dims[2] + + ", " + + this.dims[3] + + ", " + + this.dims[4] + + ", " + + this.dims[5] + + ", " + + this.dims[6] + + ", " + + this.dims[7] + + "\n"; + string += + "Intent Parameters (1-3): " + + this.intent_p1 + + ", " + + this.intent_p2 + + ", " + + this.intent_p3 + + "\n"; + string += + "Voxel Dimensions (1-8): " + + fmt(this.pixDims[0]) + + ", " + + fmt(this.pixDims[1]) + + ", " + + fmt(this.pixDims[2]) + + ", " + + fmt(this.pixDims[3]) + + ", " + + fmt(this.pixDims[4]) + + ", " + + fmt(this.pixDims[5]) + + ", " + + fmt(this.pixDims[6]) + + ", " + + fmt(this.pixDims[7]) + + "\n"; + string += "Image Offset = " + this.vox_offset + "\n"; + string += + "Data Scale: Slope = " + + fmt(this.scl_slope) + + " Intercept = " + + fmt(this.scl_inter) + + "\n"; + string += + "Display Range: Max = " + + fmt(this.cal_max) + + " Min = " + + fmt(this.cal_min) + + "\n"; + string += "Slice Duration = " + this.slice_duration + "\n"; + string += "Time Axis Shift = " + this.toffset + "\n"; + string += "Slice Start = " + this.slice_start + "\n"; + string += "Slice End = " + this.slice_end + "\n"; + string += 'Description: "' + this.description + '"\n'; + string += 'Auxiliary File: "' + this.aux_file + '"\n'; + string += + "Q-Form Code = " + + this.qform_code + + " (" + + this.getTransformCodeString(this.qform_code) + + ")\n"; + string += + "S-Form Code = " + + this.sform_code + + " (" + + this.getTransformCodeString(this.sform_code) + + ")\n"; + string += + "Quaternion Parameters: " + + "b = " + + fmt(this.quatern_b) + + " " + + "c = " + + fmt(this.quatern_c) + + " " + + "d = " + + fmt(this.quatern_d) + + "\n"; + string += + "Quaternion Offsets: " + + "x = " + + this.qoffset_x + + " " + + "y = " + + this.qoffset_y + + " " + + "z = " + + this.qoffset_z + + "\n"; + string += + "S-Form Parameters X: " + + fmt(this.affine[0][0]) + + ", " + + fmt(this.affine[0][1]) + + ", " + + fmt(this.affine[0][2]) + + ", " + + fmt(this.affine[0][3]) + + "\n"; + string += + "S-Form Parameters Y: " + + fmt(this.affine[1][0]) + + ", " + + fmt(this.affine[1][1]) + + ", " + + fmt(this.affine[1][2]) + + ", " + + fmt(this.affine[1][3]) + + "\n"; + string += + "S-Form Parameters Z: " + + fmt(this.affine[2][0]) + + ", " + + fmt(this.affine[2][1]) + + ", " + + fmt(this.affine[2][2]) + + ", " + + fmt(this.affine[2][3]) + + "\n"; + string += "Slice Code = " + this.slice_code + "\n"; + string += + "Units Code = " + + this.xyzt_units + + " (" + + this.getUnitsCodeString(nifti1_1.NIFTI1.SPATIAL_UNITS_MASK & this.xyzt_units) + + ", " + + this.getUnitsCodeString(nifti1_1.NIFTI1.TEMPORAL_UNITS_MASK & this.xyzt_units) + + ")\n"; + string += "Intent Code = " + this.intent_code + "\n"; + string += 'Intent Name: "' + this.intent_name + '"\n'; + string += "Dim Info = " + this.dim_info + "\n"; + return string; + } + /** + * Returns the byte index of the extension. + * @returns {number} + */ + getExtensionLocation = function () { + return NIFTI2.MAGIC_COOKIE + 4; + }; + /** + * Returns the extension size. + * @param {DataView} data + * @returns {number} + */ + getExtensionSize = nifti1_1.NIFTI1.prototype.getExtensionSize; + /** + * Returns the extension code. + * @param {DataView} data + * @returns {number} + */ + getExtensionCode = nifti1_1.NIFTI1.prototype.getExtensionCode; + /** + * Adds an extension + * @param {NIFTIEXTENSION} extension + * @param {number} index + */ + addExtension = nifti1_1.NIFTI1.prototype.addExtension; + /** + * Removes an extension + * @param {number} index + */ + removeExtension = nifti1_1.NIFTI1.prototype.removeExtension; + /** + * Returns a human-readable string of datatype. + * @param {number} code + * @returns {string} + */ + getDatatypeCodeString = nifti1_1.NIFTI1.prototype.getDatatypeCodeString; + /** + * Returns a human-readable string of transform type. + * @param {number} code + * @returns {string} + */ + getTransformCodeString = nifti1_1.NIFTI1.prototype.getTransformCodeString; + /** + * Returns a human-readable string of spatial and temporal units. + * @param {number} code + * @returns {string} + */ + getUnitsCodeString = nifti1_1.NIFTI1.prototype.getUnitsCodeString; + /** + * Returns the qform matrix. + * @returns {Array.>} + */ + getQformMat = nifti1_1.NIFTI1.prototype.getQformMat; + /** + * Converts qform to an affine. (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {number} qb + * @param {number} qc + * @param {number} qd + * @param {number} qx + * @param {number} qy + * @param {number} qz + * @param {number} dx + * @param {number} dy + * @param {number} dz + * @param {number} qfac + * @returns {Array.>} + */ + convertNiftiQFormToNiftiSForm = nifti1_1.NIFTI1.prototype.convertNiftiQFormToNiftiSForm; + /** + * Converts sform to an orientation string (e.g., XYZ+--). (See http://nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {Array.>} R + * @returns {string} + */ + convertNiftiSFormToNEMA = nifti1_1.NIFTI1.prototype.convertNiftiSFormToNEMA; + nifti_mat33_mul = nifti1_1.NIFTI1.prototype.nifti_mat33_mul; + nifti_mat33_determ = nifti1_1.NIFTI1.prototype.nifti_mat33_determ; + /** + * Returns header as ArrayBuffer. + * @param {boolean} includeExtensions - should extension bytes be included + * @returns {ArrayBuffer} + */ + toArrayBuffer(includeExtensions = false) { + const INT64_SIZE = 8; + const DOUBLE_SIZE = 8; + let byteSize = 540 + 4; // +4 for extension bytes + // calculate necessary size + if (includeExtensions) { + for (let extension of this.extensions) { + byteSize += extension.esize; + } + } + let byteArray = new Uint8Array(byteSize); + let view = new DataView(byteArray.buffer); + // sizeof_hdr + view.setInt32(0, 540, this.littleEndian); + // magic + byteArray.set(Buffer.from(this.magic), 4); + // datatype + view.setInt16(12, this.datatypeCode, this.littleEndian); + // bitpix + view.setInt16(14, this.numBitsPerVoxel, this.littleEndian); + // dim[8] + for (let i = 0; i < 8; i++) { + view.setBigInt64(16 + INT64_SIZE * i, BigInt(this.dims[i]), this.littleEndian); + } + // intent_p1 + view.setFloat64(80, this.intent_p1, this.littleEndian); + // intent_p2 + view.setFloat64(88, this.intent_p2, this.littleEndian); + // intent_p3 + view.setFloat64(96, this.intent_p3, this.littleEndian); + // pixdim + for (let i = 0; i < 8; i++) { + view.setFloat64(104 + DOUBLE_SIZE * i, this.pixDims[i], this.littleEndian); + } + // vox_offset + view.setBigInt64(168, BigInt(this.vox_offset), this.littleEndian); + // scl_slope + view.setFloat64(176, this.scl_slope, this.littleEndian); + // scl_inter + view.setFloat64(184, this.scl_inter, this.littleEndian); + // cal_max + view.setFloat64(192, this.cal_max, this.littleEndian); + // cal_min + view.setFloat64(200, this.cal_min, this.littleEndian); + // slice_duration + view.setFloat64(208, this.slice_duration, this.littleEndian); + // toffset + view.setFloat64(216, this.toffset, this.littleEndian); + // slice_start + view.setBigInt64(224, BigInt(this.slice_start), this.littleEndian); + // slice end + view.setBigInt64(232, BigInt(this.slice_end), this.littleEndian); + // descrip + byteArray.set(Buffer.from(this.description), 240); + // aux_file + byteArray.set(Buffer.from(this.aux_file), 320); + // qform_code + view.setInt32(344, this.qform_code, this.littleEndian); + // sform_code + view.setInt32(348, this.sform_code, this.littleEndian); + // quatern_b + view.setFloat64(352, this.quatern_b, this.littleEndian); + // quatern_c + view.setFloat64(360, this.quatern_c, this.littleEndian); + // quatern_d + view.setFloat64(368, this.quatern_d, this.littleEndian); + // qoffset_x + view.setFloat64(376, this.qoffset_x, this.littleEndian); + // qoffset_y + view.setFloat64(384, this.qoffset_y, this.littleEndian); + // qoffset_z + view.setFloat64(392, this.qoffset_z, this.littleEndian); + // srow_x[4], srow_y[4], and srow_z[4] + const flattened = this.affine.flat(); + // we only want the first three rows + for (let i = 0; i < 12; i++) { + view.setFloat64(400 + DOUBLE_SIZE * i, flattened[i], this.littleEndian); + } + // slice_code + view.setInt32(496, this.slice_code, this.littleEndian); + // xyzt_units + view.setInt32(500, this.xyzt_units, this.littleEndian); + // intent_code + view.setInt32(504, this.intent_code, this.littleEndian); + // intent_name + byteArray.set(Buffer.from(this.intent_name), 508); + // dim_info + view.setUint8(524, this.dim_info); + // add our extension data + if (includeExtensions) { + byteArray.set(Uint8Array.from([1, 0, 0, 0]), 540); + let extensionByteIndex = this.getExtensionLocation(); + for (const extension of this.extensions) { + view.setInt32(extensionByteIndex, extension.esize, extension.littleEndian); + view.setInt32(extensionByteIndex + 4, extension.ecode, extension.littleEndian); + byteArray.set(new Uint8Array(extension.edata), extensionByteIndex + 8); + extensionByteIndex += extension.esize; + } + } + else { + // In a .nii file, these 4 bytes will always be present + byteArray.set(new Uint8Array(4).fill(0), 540); + } + return byteArray.buffer; + } +} +exports.NIFTI2 = NIFTI2; +//# sourceMappingURL=nifti2.js.map \ No newline at end of file diff --git a/dist/src/nifti2.js.map b/dist/src/nifti2.js.map new file mode 100644 index 0000000..acbf60a --- /dev/null +++ b/dist/src/nifti2.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nifti2.js","sourceRoot":"","sources":["../../src/nifti2.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/src/utilities.d.ts b/dist/src/utilities.d.ts new file mode 100644 index 0000000..d59c0d8 --- /dev/null +++ b/dist/src/utilities.d.ts @@ -0,0 +1,24 @@ +import { NIFTIEXTENSION } from "./nifti-extension"; +type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array; +export declare class Utils { + /*** Static Pseudo-constants ***/ + static crcTable: number[] | null; + static readonly GUNZIP_MAGIC_COOKIE1 = 31; + static readonly GUNZIP_MAGIC_COOKIE2 = 139; + /*** Static methods ***/ + static getStringAt(data: DataView, start: number, end: number): string; + static getByteAt: (data: DataView, start: number) => number; + static getShortAt: (data: DataView, start: number, littleEndian: boolean) => number; + static getIntAt(data: DataView, start: number, littleEndian: boolean): number; + static getFloatAt(data: DataView, start: number, littleEndian: boolean): number; + static getDoubleAt(data: DataView, start: number, littleEndian: boolean): number; + static getLongAt(data: DataView, start: number, littleEndian: boolean): number; + static getExtensionsAt(data: DataView, start: number, littleEndian: boolean, voxOffset: number): NIFTIEXTENSION[]; + static toArrayBuffer(buffer: TypedArray): ArrayBuffer; + static isString(obj: Object): boolean; + static formatNumber(num: any, shortFormat?: boolean | undefined): number; + static makeCRCTable(): number[]; + static crc32(dataView: DataView): number; +} +export {}; +//# sourceMappingURL=utilities.d.ts.map \ No newline at end of file diff --git a/dist/src/utilities.d.ts.map b/dist/src/utilities.d.ts.map new file mode 100644 index 0000000..eb8b2ab --- /dev/null +++ b/dist/src/utilities.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../../src/utilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,KAAK,UAAU,GACX,SAAS,GACT,UAAU,GACV,iBAAiB,GACjB,UAAU,GACV,WAAW,GACX,UAAU,GACV,WAAW,GACX,YAAY,GACZ,YAAY,CAAC;AAEjB,qBAAa,KAAK;IAChB,iCAAiC;IAEjC,OAAc,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAQ;IAC/C,gBAAuB,oBAAoB,MAAM;IACjD,gBAAuB,oBAAoB,OAAO;IAElD,wBAAwB;IAExB,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IAgBtE,MAAM,CAAC,SAAS,SAAmB,QAAQ,SAAS,MAAM,KAAG,MAAM,CAEjE;IAEF,MAAM,CAAC,UAAU,SACT,QAAQ,SACP,MAAM,gBACC,OAAO,YAGrB;IAEF,MAAM,CAAC,QAAQ,CACb,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,OAAO,GACpB,MAAM;IAIT,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO;IAItE,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO;IAIvE,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO;IAgBrE,MAAM,CAAC,eAAe,CACpB,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,OAAO,EACrB,SAAS,EAAE,MAAM;IA0DnB,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW;IAWrD,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIrC,MAAM,CAAC,YAAY,CACjB,GAAG,EAAE,GAAG,EACR,WAAW,GAAE,OAAO,GAAG,SAAqB,GAC3C,MAAM;IAmBT,MAAM,CAAC,YAAY,IAAI,MAAM,EAAE;IAa/B,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM;CAazC"} \ No newline at end of file diff --git a/dist/src/utilities.js b/dist/src/utilities.js new file mode 100644 index 0000000..f95da4e --- /dev/null +++ b/dist/src/utilities.js @@ -0,0 +1,134 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Utils = void 0; +const nifti_extension_1 = require("./nifti-extension"); +class Utils { + /*** Static Pseudo-constants ***/ + static crcTable = null; + static GUNZIP_MAGIC_COOKIE1 = 31; + static GUNZIP_MAGIC_COOKIE2 = 139; + /*** Static methods ***/ + static getStringAt(data, start, end) { + var str = "", ctr, ch; + for (ctr = start; ctr < end; ctr += 1) { + ch = data.getUint8(ctr); + if (ch !== 0) { + str += String.fromCharCode(ch); + } + } + return str; + } + static getByteAt = function (data, start) { + return data.getInt8(start); + }; + static getShortAt = function (data, start, littleEndian) { + return data.getInt16(start, littleEndian); + }; + static getIntAt(data, start, littleEndian) { + return data.getInt32(start, littleEndian); + } + static getFloatAt(data, start, littleEndian) { + return data.getFloat32(start, littleEndian); + } + static getDoubleAt(data, start, littleEndian) { + return data.getFloat64(start, littleEndian); + } + static getLongAt(data, start, littleEndian) { + var ctr, array = [], value = 0; + for (ctr = 0; ctr < 8; ctr += 1) { + array[ctr] = Utils.getByteAt(data, start + ctr); + } + for (ctr = array.length - 1; ctr >= 0; ctr--) { + value = value * 256 + array[ctr]; + } + return value; + } + static getExtensionsAt(data, start, littleEndian, voxOffset) { + let extensions = []; + let extensionByteIndex = start; + // Multiple extended header sections are allowed + while (extensionByteIndex < voxOffset) { + // assume same endianess as header until proven otherwise + let extensionLittleEndian = littleEndian; + let esize = Utils.getIntAt(data, extensionByteIndex, littleEndian); + if (!esize) { + break; // no more extensions + } + // check if this takes us past vox_offset + if (esize + extensionByteIndex > voxOffset) { + // check if reversing byte order gets a proper size + extensionLittleEndian = !extensionLittleEndian; + esize = Utils.getIntAt(data, extensionByteIndex, extensionLittleEndian); + if (esize + extensionByteIndex > voxOffset) { + throw new Error("This does not appear to be a valid NIFTI extension"); + } + } + // esize must be a positive integral multiple of 16 + if (esize % 16 != 0) { + throw new Error("This does not appear to be a NIFTI extension"); + } + let ecode = Utils.getIntAt(data, extensionByteIndex + 4, extensionLittleEndian); + let edata = data.buffer.slice(extensionByteIndex + 8, extensionByteIndex + esize); + console.log("extensionByteIndex: " + (extensionByteIndex + 8) + " esize: " + esize); + console.log(edata); + let extension = new nifti_extension_1.NIFTIEXTENSION(esize, ecode, edata, extensionLittleEndian); + extensions.push(extension); + extensionByteIndex += esize; + } + return extensions; + } + static toArrayBuffer(buffer) { + var ab, view, i; + ab = new ArrayBuffer(buffer.length); + view = new Uint8Array(ab); + for (i = 0; i < buffer.length; i += 1) { + view[i] = buffer[i]; + } + return ab; + } + static isString(obj) { + return typeof obj === "string" || obj instanceof String; + } + static formatNumber(num, shortFormat = undefined) { + let val; + if (Utils.isString(num)) { + val = Number(num); + } + else { + val = num; + } + if (shortFormat) { + val = val.toPrecision(5); + } + else { + val = val.toPrecision(7); + } + return parseFloat(val); + } + // http://stackoverflow.com/questions/18638900/javascript-crc32 + static makeCRCTable() { + let c; + let crcTable = []; + for (var n = 0; n < 256; n++) { + c = n; + for (var k = 0; k < 8; k++) { + c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1; + } + crcTable[n] = c; + } + return crcTable; + } + static crc32(dataView) { + if (!Utils.crcTable) { + Utils.crcTable = Utils.makeCRCTable(); + } + const crcTable = Utils.crcTable; + let crc = 0 ^ -1; + for (var i = 0; i < dataView.byteLength; i++) { + crc = (crc >>> 8) ^ crcTable[(crc ^ dataView.getUint8(i)) & 0xff]; + } + return (crc ^ -1) >>> 0; + } +} +exports.Utils = Utils; +//# sourceMappingURL=utilities.js.map \ No newline at end of file diff --git a/dist/src/utilities.js.map b/dist/src/utilities.js.map new file mode 100644 index 0000000..dc7bf03 --- /dev/null +++ b/dist/src/utilities.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utilities.js","sourceRoot":"","sources":["../../src/utilities.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b34722f..560ab05 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,9 +12,15 @@ "fflate": "*" }, "devDependencies": { + "@types/chai": "^4.3.5", + "@types/mocha": "^10.0.1", + "chai": "^4.3.7", "esbuild": "*", "jsdoc-to-markdown": "*", - "mocha": "*" + "mocha": "*", + "ts-node": "^10.9.1", + "tsify": "^5.0.4", + "typescript": "^5.0.4" } }, "node_modules/@babel/parser": { @@ -29,6 +35,18 @@ "node": ">=6.0.0" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/android-arm": { "version": "0.17.15", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.15.tgz", @@ -381,12 +399,115 @@ "node": ">=12" } }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@types/chai": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", + "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", + "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.3.tgz", + "integrity": "sha512-NP2yfZpgmf2eDRPmgGq+fjGjSwFgYbihA8/gK+ey23qT9RkxsgNTZvGOEpXgzIGqesTYkElELLgtKoMQTys5vA==", + "dev": true, + "peer": true + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "peer": true, + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -441,6 +562,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, "node_modules/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -454,6 +581,12 @@ "node": ">= 8" } }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -472,12 +605,103 @@ "node": ">=12.17" } }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + }, + "node_modules/assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "peer": true, + "dependencies": { + "object-assign": "^4.1.1", + "util": "0.10.3" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", + "dev": true, + "peer": true + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "2.0.1" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -493,6 +717,13 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true, + "peer": true + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -515,12 +746,236 @@ "node": ">=8" } }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true, + "peer": true + }, + "node_modules/browser-pack": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "dev": true, + "peer": true, + "dependencies": { + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "JSONStream": "^1.0.3", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + }, + "bin": { + "browser-pack": "bin/cmd.js" + } + }, + "node_modules/browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "dev": true, + "peer": true, + "dependencies": { + "resolve": "^1.17.0" + } + }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "node_modules/browserify": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", + "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", + "dev": true, + "peer": true, + "dependencies": { + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "~0.2.0", + "buffer": "~5.2.1", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.1", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^3.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.2.1", + "JSONStream": "^1.0.3", + "labeled-stream-splicer": "^2.0.0", + "mkdirp-classic": "^0.5.2", + "module-deps": "^6.2.3", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "^1.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum-object": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^3.0.0", + "stream-http": "^3.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.12.0", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + }, + "bin": { + "browserify": "bin/cmd.js" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "peer": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "peer": true, + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "peer": true, + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "peer": true, + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "dev": true, + "peer": true, + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "peer": true + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true, + "peer": true + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true, + "peer": true + }, "node_modules/cache-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz", @@ -544,6 +999,27 @@ "node": ">=8" } }, + "node_modules/cached-path-relative": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.1.0.tgz", + "integrity": "sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==", + "dev": true, + "peer": true + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "peer": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/camelcase": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz", @@ -568,6 +1044,24 @@ "node": ">= 10" } }, + "node_modules/chai": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^4.1.2", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -596,6 +1090,15 @@ "node": ">=8" } }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/chokidar": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", @@ -617,6 +1120,17 @@ "fsevents": "~2.3.2" } }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -659,6 +1173,19 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha512-UlxQ9Vw0b/Bt/KYwCFqdEwsQ1eL8d1gibiFb7lxQJFdvTgc2hIZi6ugsg+kyhzhPV+QEpUiEIwInIAIrgoEkrg==", + "dev": true, + "peer": true, + "dependencies": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + } + }, "node_modules/command-line-args": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.0.tgz", @@ -762,6 +1289,22 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "peer": true, + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "node_modules/config-master": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", @@ -780,6 +1323,115 @@ "node": ">=0.10.0" } }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true, + "peer": true + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true, + "peer": true + }, + "node_modules/convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "peer": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "peer": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "peer": true, + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dash-ast": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", + "dev": true, + "peer": true + }, "node_modules/debug": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", @@ -815,6 +1467,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -824,15 +1488,89 @@ "node": ">=4.0.0" } }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "node_modules/defined": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", + "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", + "dev": true, + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deps-sort": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz", + "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==", + "dev": true, + "peer": true, + "dependencies": { + "JSONStream": "^1.0.3", + "shasum-object": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + }, + "bin": { + "deps-sort": "bin/cmd.js" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "dev": true, + "peer": true, + "dependencies": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + }, + "bin": { + "detective": "bin/detective.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, "engines": { "node": ">=0.3.1" } }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + }, "node_modules/dmd": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/dmd/-/dmd-6.0.0.tgz", @@ -874,6 +1612,50 @@ "node": ">=8" } }, + "node_modules/domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "peer": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -886,6 +1668,15 @@ "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", "dev": true }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/esbuild": { "version": "0.17.15", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.15.tgz", @@ -941,6 +1732,34 @@ "node": ">=8" } }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "peer": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "peer": true + }, "node_modules/fflate": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.3.tgz", @@ -1026,6 +1845,16 @@ "flat": "cli.js" } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "peer": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/fs-then-native": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", @@ -1055,6 +1884,20 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true, + "peer": true + }, + "node_modules/get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", + "dev": true, + "peer": true + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -1064,6 +1907,30 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, + "peer": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -1096,6 +1963,19 @@ "node": ">= 6" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "peer": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", @@ -1141,6 +2021,19 @@ "node": ">=0.10.0" } }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "peer": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -1150,6 +2043,76 @@ "node": ">=8" } }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "peer": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -1159,6 +2122,56 @@ "he": "bin/he" } }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "peer": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha512-eVcrzgbR4tim7c7soKQKtxa/kQM4TzjnlU83rcZ9bHU6t31ehfV7SktN6McWgwPWg+JYMA/O3qpGxBvFq1z2Jg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "dev": true, + "peer": true + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1175,6 +2188,61 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha512-0mVWSSbNDvedDWIN4wxLsdPM4a7cIPcpyMxj3QZ406QRwQ6ePGB1YIHxVPjqpcUGbWQ5C+nHTwGNWAGvt7ggVA==", + "dev": true, + "peer": true, + "dependencies": { + "source-map": "~0.5.3" + } + }, + "node_modules/insert-module-globals": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", + "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", + "dev": true, + "peer": true, + "dependencies": { + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "JSONStream": "^1.0.3", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + }, + "bin": { + "insert-module-globals": "bin/cmd.js" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -1187,6 +2255,39 @@ "node": ">=8" } }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "peer": true + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", + "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", + "dev": true, + "peer": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1205,6 +2306,22 @@ "node": ">=8" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "peer": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -1235,6 +2352,26 @@ "node": ">=8" } }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "peer": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -1247,6 +2384,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", + "dev": true + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1366,6 +2515,33 @@ "node": ">=12.17" } }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "peer": true + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "peer": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/klaw": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", @@ -1375,6 +2551,17 @@ "graceful-fs": "^4.1.9" } }, + "node_modules/labeled-stream-splicer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", + "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.1", + "stream-splicer": "^2.0.0" + } + }, "node_modules/linkify-it": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", @@ -1411,6 +2598,13 @@ "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", "dev": true }, + "node_modules/lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==", + "dev": true, + "peer": true + }, "node_modules/lodash.omit": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", @@ -1445,6 +2639,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.0" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "node_modules/markdown-it": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", @@ -1482,14 +2691,61 @@ "node": ">= 10" } }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "peer": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "node_modules/mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", "dev": true }, - "node_modules/minimatch": { - "version": "3.0.4", + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true, + "peer": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true, + "peer": true + }, + "node_modules/minimatch": { + "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, @@ -1501,10 +2757,13 @@ } }, "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/mkdirp": { "version": "1.0.4", @@ -1518,6 +2777,13 @@ "node": ">=10" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, + "peer": true + }, "node_modules/mkdirp2": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.5.tgz", @@ -1599,6 +2865,36 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/module-deps": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", + "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==", + "dev": true, + "peer": true, + "dependencies": { + "browser-resolve": "^2.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.2.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "JSONStream": "^1.0.3", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + }, + "bin": { + "module-deps": "bin/cmd.js" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -1632,6 +2928,15 @@ "node": ">=0.10.0" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-get": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", @@ -1656,6 +2961,13 @@ "wrappy": "1" } }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true, + "peer": true + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -1686,6 +2998,56 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "peer": true + }, + "node_modules/parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha512-mXKF3xkoUt5td2DoxpLmtOmZvko9VfFpwRwkKDHSNvgmpLAeBo18YDhcPbBzJq+QLCHMbGOfzia2cX4U+0v9Mg==", + "dev": true, + "peer": true, + "dependencies": { + "path-platform": "~0.11.15" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "peer": true, + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", + "dev": true, + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "peer": true + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -1704,6 +3066,49 @@ "node": ">=0.10.0" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "peer": true + }, + "node_modules/path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "peer": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", @@ -1716,6 +3121,72 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "peer": true, + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "peer": true + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -1725,6 +3196,57 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "peer": true, + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha512-3ALe0bjBVZtkdWKIcThYpQCLbBMd/+Tbh2CDSrAIDO3UsZ4Xs+tnyjv2MjCOMMgBG+AsUOeuP1cgtY1INISc8w==", + "dev": true, + "peer": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/readable-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -1847,6 +3369,35 @@ "lodash": "^4.17.14" } }, + "node_modules/resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "dev": true, + "peer": true, + "dependencies": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "peer": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1867,6 +3418,22 @@ } ] }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "peer": true + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", @@ -1876,6 +3443,61 @@ "randombytes": "^2.1.0" } }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shasum-object": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz", + "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==", + "dev": true, + "peer": true, + "dependencies": { + "fast-safe-stringify": "^2.0.7" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, "node_modules/sort-array": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.4.tgz", @@ -1907,12 +3529,59 @@ "node": ">=10" } }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-browserify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", + "dev": true, + "peer": true, + "dependencies": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, "node_modules/stream-connect": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", @@ -1937,6 +3606,45 @@ "node": ">=0.12.0" } }, + "node_modules/stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "dev": true, + "peer": true, + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, + "node_modules/stream-http/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-splicer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", + "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, "node_modules/stream-via": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", @@ -1946,6 +3654,16 @@ "node": ">=0.10.0" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -1972,6 +3690,18 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "dev": true, + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -1984,6 +3714,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha512-RIrIdRY0X1xojthNcVtgT9sjpOGagEUKpZdgBUi054OEPFo282yg+zE+t1Rj3+RqKq2xStL7uUHhY+AjbC4BXg==", + "dev": true, + "peer": true, + "dependencies": { + "minimist": "^1.1.0" + } + }, "node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -1999,6 +3739,29 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "peer": true, + "dependencies": { + "acorn-node": "^1.2.0" + } + }, "node_modules/table-layout": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", @@ -2064,6 +3827,36 @@ "node": ">=4" } }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "peer": true + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha512-PIxwAupJZiYU4JmVZYwXp9FKsHMXb5h0ZEFyuXTAn8WLHOlcij+FEcbrvDsom1o5dr1YggEtFbECvGCW2sT53Q==", + "dev": true, + "peer": true, + "dependencies": { + "process": "~0.11.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2076,7 +3869,158 @@ "node": ">=8.0" } }, - "node_modules/typical": { + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ts-node/node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tsconfig": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-5.0.3.tgz", + "integrity": "sha512-Cq65A3kVp6BbsUgg9DRHafaGmbMb9EhAc7fjWvudNWKjkbWrt43FnrtZt6awshH1R0ocfF2Z0uxock3lVqEgOg==", + "dev": true, + "dependencies": { + "any-promise": "^1.3.0", + "parse-json": "^2.2.0", + "strip-bom": "^2.0.0", + "strip-json-comments": "^2.0.0" + } + }, + "node_modules/tsconfig/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tsify": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/tsify/-/tsify-5.0.4.tgz", + "integrity": "sha512-XAZtQ5OMPsJFclkZ9xMZWkSNyMhMxEPsz3D2zu79yoKorH9j/DT4xCloJeXk5+cDhosEibu4bseMVjyPOAyLJA==", + "dev": true, + "dependencies": { + "convert-source-map": "^1.1.0", + "fs.realpath": "^1.0.0", + "object-assign": "^4.1.0", + "semver": "^6.1.0", + "through2": "^2.0.0", + "tsconfig": "^5.0.3" + }, + "engines": { + "node": ">=0.12" + }, + "peerDependencies": { + "browserify": ">= 10.x", + "typescript": ">= 2.8" + } + }, + "node_modules/tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true, + "peer": true + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true, + "peer": true + }, + "node_modules/typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/typical": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", @@ -2101,12 +4045,90 @@ "node": ">=0.8.0" } }, + "node_modules/umd": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", + "dev": true, + "peer": true, + "bin": { + "umd": "bin/cli.js" + } + }, + "node_modules/undeclared-identifiers": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", + "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", + "dev": true, + "peer": true, + "dependencies": { + "acorn-node": "^1.3.0", + "dash-ast": "^1.0.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + }, + "bin": { + "undeclared-identifiers": "bin.js" + } + }, "node_modules/underscore": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", "dev": true }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", + "dev": true, + "peer": true, + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "dev": true, + "peer": true + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true, + "peer": true + }, "node_modules/walk-back": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", @@ -2131,6 +4153,27 @@ "node": ">= 8" } }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "peer": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -2185,6 +4228,15 @@ "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", "dev": true }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -2236,6 +4288,15 @@ "node": ">=10" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -2256,6 +4317,15 @@ "integrity": "sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng==", "dev": true }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + } + }, "@esbuild/android-arm": { "version": "0.17.15", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.15.tgz", @@ -2410,12 +4480,103 @@ "dev": true, "optional": true }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "@types/chai": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", + "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", + "dev": true + }, + "@types/mocha": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", + "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", + "dev": true + }, + "@types/node": { + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.3.tgz", + "integrity": "sha512-NP2yfZpgmf2eDRPmgGq+fjGjSwFgYbihA8/gK+ey23qT9RkxsgNTZvGOEpXgzIGqesTYkElELLgtKoMQTys5vA==", + "dev": true, + "peer": true + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "peer": true + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "peer": true, + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "peer": true + }, "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -2454,6 +4615,12 @@ "color-convert": "^2.0.1" } }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -2464,6 +4631,12 @@ "picomatch": "^2.0.4" } }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -2479,12 +4652,84 @@ "integrity": "sha512-mixVv03GOOn/ubHE4STQ+uevX42ETdk0JoMVEjNkSOCT7WgERh7C8/+NyhWYNpE3BN69pxFyJIBcF7CxWz/+4A==", "dev": true }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "peer": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "peer": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", + "dev": true, + "peer": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", + "dev": true, + "peer": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "peer": true + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "peer": true + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -2497,6 +4742,13 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, + "bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true, + "peer": true + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2516,12 +4768,226 @@ "fill-range": "^7.0.1" } }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true, + "peer": true + }, + "browser-pack": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "dev": true, + "peer": true, + "requires": { + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "JSONStream": "^1.0.3", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + } + }, + "browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "dev": true, + "peer": true, + "requires": { + "resolve": "^1.17.0" + } + }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "browserify": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", + "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", + "dev": true, + "peer": true, + "requires": { + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "~0.2.0", + "buffer": "~5.2.1", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.1", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^3.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.2.1", + "JSONStream": "^1.0.3", + "labeled-stream-splicer": "^2.0.0", + "mkdirp-classic": "^0.5.2", + "module-deps": "^6.2.3", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "^1.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum-object": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^3.0.0", + "stream-http": "^3.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.12.0", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "peer": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "peer": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "peer": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "peer": true, + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "peer": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "peer": true, + "requires": { + "pako": "~1.0.5" + } + }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "dev": true, + "peer": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "peer": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true, + "peer": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true, + "peer": true + }, "cache-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz", @@ -2541,6 +5007,24 @@ } } }, + "cached-path-relative": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.1.0.tgz", + "integrity": "sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==", + "dev": true, + "peer": true + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "peer": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "camelcase": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz", @@ -2556,6 +5040,21 @@ "lodash": "^4.17.15" } }, + "chai": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^4.1.2", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + } + }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2577,6 +5076,12 @@ } } }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true + }, "chokidar": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", @@ -2593,6 +5098,17 @@ "readdirp": "~3.6.0" } }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -2629,6 +5145,19 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha512-UlxQ9Vw0b/Bt/KYwCFqdEwsQ1eL8d1gibiFb7lxQJFdvTgc2hIZi6ugsg+kyhzhPV+QEpUiEIwInIAIrgoEkrg==", + "dev": true, + "peer": true, + "requires": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + } + }, "command-line-args": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.0.tgz", @@ -2714,6 +5243,19 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "peer": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "config-master": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", @@ -2731,6 +5273,114 @@ } } }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true, + "peer": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true, + "peer": true + }, + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg==", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "peer": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "peer": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "peer": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "peer": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "dash-ast": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", + "dev": true, + "peer": true + }, "debug": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", @@ -2754,18 +5404,91 @@ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true }, + "deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true }, + "defined": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", + "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", + "dev": true, + "peer": true + }, + "deps-sort": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz", + "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==", + "dev": true, + "peer": true, + "requires": { + "JSONStream": "^1.0.3", + "shasum-object": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + } + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "dev": true, + "peer": true, + "requires": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + } + }, "diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "peer": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + } + } + }, "dmd": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/dmd/-/dmd-6.0.0.tgz", @@ -2800,6 +5523,48 @@ } } }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true, + "peer": true + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "peer": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "peer": true, + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + } + } + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2812,6 +5577,15 @@ "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", "dev": true }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, "esbuild": { "version": "0.17.15", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.15.tgz", @@ -2854,6 +5628,31 @@ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "peer": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "peer": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "peer": true + }, "fflate": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.3.tgz", @@ -2919,6 +5718,16 @@ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "peer": true, + "requires": { + "is-callable": "^1.1.3" + } + }, "fs-then-native": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", @@ -2938,12 +5747,44 @@ "dev": true, "optional": true }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true, + "peer": true + }, + "get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", + "dev": true, + "peer": true + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, + "peer": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, "glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -2967,6 +5808,16 @@ "is-glob": "^4.0.1" } }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "peer": true, + "requires": { + "get-intrinsic": "^1.1.3" + } + }, "graceful-fs": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", @@ -3000,18 +5851,115 @@ } } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "peer": true, + "requires": { + "function-bind": "^1.1.1" + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "peer": true + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "peer": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "peer": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha512-eVcrzgbR4tim7c7soKQKtxa/kQM4TzjnlU83rcZ9bHU6t31ehfV7SktN6McWgwPWg+JYMA/O3qpGxBvFq1z2Jg==", + "dev": true, + "peer": true + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "dev": true, + "peer": true + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "peer": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3028,6 +5976,52 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha512-0mVWSSbNDvedDWIN4wxLsdPM4a7cIPcpyMxj3QZ406QRwQ6ePGB1YIHxVPjqpcUGbWQ5C+nHTwGNWAGvt7ggVA==", + "dev": true, + "peer": true, + "requires": { + "source-map": "~0.5.3" + } + }, + "insert-module-globals": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", + "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", + "dev": true, + "peer": true, + "requires": { + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "JSONStream": "^1.0.3", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + } + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "peer": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -3037,6 +6031,30 @@ "binary-extensions": "^2.0.0" } }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "peer": true + }, + "is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "peer": true + }, + "is-core-module": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", + "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", + "dev": true, + "peer": true, + "requires": { + "has": "^1.0.3" + } + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3049,6 +6067,16 @@ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "peer": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -3070,12 +6098,38 @@ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, + "is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "peer": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, "is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3176,6 +6230,24 @@ "walk-back": "^5.1.0" } }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "peer": true + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "peer": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, "klaw": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", @@ -3185,6 +6257,17 @@ "graceful-fs": "^4.1.9" } }, + "labeled-stream-splicer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", + "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.1", + "stream-splicer": "^2.0.0" + } + }, "linkify-it": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", @@ -3215,6 +6298,13 @@ "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", "dev": true }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==", + "dev": true, + "peer": true + }, "lodash.omit": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", @@ -3243,6 +6333,21 @@ "is-unicode-supported": "^0.1.0" } }, + "loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, + "requires": { + "get-func-name": "^2.0.0" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "markdown-it": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", @@ -3269,11 +6374,57 @@ "integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==", "dev": true }, - "mdurl": { + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "peer": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "peer": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true, + "peer": true + }, + "minimalistic-crypto-utils": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true, + "peer": true }, "minimatch": { "version": "3.0.4", @@ -3285,9 +6436,9 @@ } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true }, "mkdirp": { @@ -3296,6 +6447,13 @@ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, + "peer": true + }, "mkdirp2": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.5.tgz", @@ -3356,6 +6514,30 @@ } } }, + "module-deps": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", + "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==", + "dev": true, + "peer": true, + "requires": { + "browser-resolve": "^2.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.2.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "JSONStream": "^1.0.3", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + } + }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3380,6 +6562,12 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true + }, "object-get": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", @@ -3401,6 +6589,13 @@ "wrappy": "1" } }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true, + "peer": true + }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -3419,6 +6614,53 @@ "p-limit": "^3.0.2" } }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "peer": true + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha512-mXKF3xkoUt5td2DoxpLmtOmZvko9VfFpwRwkKDHSNvgmpLAeBo18YDhcPbBzJq+QLCHMbGOfzia2cX4U+0v9Mg==", + "dev": true, + "peer": true, + "requires": { + "path-platform": "~0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "peer": true, + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "peer": true + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3431,12 +6673,104 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "peer": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg==", + "dev": true, + "peer": true + }, + "pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true + }, + "pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "peer": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "peer": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "peer": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true, + "peer": true + } + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "peer": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "dev": true, + "peer": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "dev": true, + "peer": true + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -3446,6 +6780,59 @@ "safe-buffer": "^5.1.0" } }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "peer": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha512-3ALe0bjBVZtkdWKIcThYpQCLbBMd/+Tbh2CDSrAIDO3UsZ4Xs+tnyjv2MjCOMMgBG+AsUOeuP1cgtY1INISc8w==", + "dev": true, + "peer": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3542,12 +6929,48 @@ "lodash": "^4.17.14" } }, + "resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "dev": true, + "peer": true, + "requires": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "peer": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "peer": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, "serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", @@ -3557,6 +6980,41 @@ "randombytes": "^2.1.0" } }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shasum-object": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz", + "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==", + "dev": true, + "peer": true, + "requires": { + "fast-safe-stringify": "^2.0.7" + } + }, + "shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "peer": true + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "peer": true + }, "sort-array": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.4.tgz", @@ -3581,12 +7039,55 @@ } } }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "peer": true + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "peer": true, + "requires": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", + "dev": true, + "peer": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, "stream-connect": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", @@ -3607,12 +7108,60 @@ } } }, + "stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "dev": true, + "peer": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "stream-splicer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", + "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, "stream-via": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", "dev": true }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "peer": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -3633,12 +7182,31 @@ "ansi-regex": "^5.0.1" } }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha512-RIrIdRY0X1xojthNcVtgT9sjpOGagEUKpZdgBUi054OEPFo282yg+zE+t1Rj3+RqKq2xStL7uUHhY+AjbC4BXg==", + "dev": true, + "peer": true, + "requires": { + "minimist": "^1.1.0" + } + }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -3648,6 +7216,23 @@ "has-flag": "^4.0.0" } }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "peer": true + }, + "syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "peer": true, + "requires": { + "acorn-node": "^1.2.0" + } + }, "table-layout": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", @@ -3705,6 +7290,33 @@ } } }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "peer": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha512-PIxwAupJZiYU4JmVZYwXp9FKsHMXb5h0ZEFyuXTAn8WLHOlcij+FEcbrvDsom1o5dr1YggEtFbECvGCW2sT53Q==", + "dev": true, + "peer": true, + "requires": { + "process": "~0.11.0" + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3714,6 +7326,107 @@ "is-number": "^7.0.0" } }, + "ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "dependencies": { + "acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + } + } + }, + "tsconfig": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-5.0.3.tgz", + "integrity": "sha512-Cq65A3kVp6BbsUgg9DRHafaGmbMb9EhAc7fjWvudNWKjkbWrt43FnrtZt6awshH1R0ocfF2Z0uxock3lVqEgOg==", + "dev": true, + "requires": { + "any-promise": "^1.3.0", + "parse-json": "^2.2.0", + "strip-bom": "^2.0.0", + "strip-json-comments": "^2.0.0" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true + } + } + }, + "tsify": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/tsify/-/tsify-5.0.4.tgz", + "integrity": "sha512-XAZtQ5OMPsJFclkZ9xMZWkSNyMhMxEPsz3D2zu79yoKorH9j/DT4xCloJeXk5+cDhosEibu4bseMVjyPOAyLJA==", + "dev": true, + "requires": { + "convert-source-map": "^1.1.0", + "fs.realpath": "^1.0.0", + "object-assign": "^4.1.0", + "semver": "^6.1.0", + "through2": "^2.0.0", + "tsconfig": "^5.0.3" + } + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true, + "peer": true + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true, + "peer": true + }, + "typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "dev": true + }, "typical": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", @@ -3733,12 +7446,86 @@ "dev": true, "optional": true }, + "umd": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", + "dev": true, + "peer": true + }, + "undeclared-identifiers": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", + "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", + "dev": true, + "peer": true, + "requires": { + "acorn-node": "^1.3.0", + "dash-ast": "^1.0.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + } + }, "underscore": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", "dev": true }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", + "dev": true, + "peer": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "dev": true, + "peer": true + } + } + }, + "util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true, + "peer": true + }, "walk-back": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", @@ -3754,6 +7541,21 @@ "isexe": "^2.0.0" } }, + "which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "peer": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + } + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -3799,6 +7601,12 @@ "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", "dev": true }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -3838,6 +7646,12 @@ "is-plain-obj": "^2.1.0" } }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 411cc5f..b6ec571 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,8 @@ "name": "nifti-reader-js", "version": "0.6.4", "description": "A JavaScript NIfTI file format reader.", - "main": "src/nifti.js", + "main": "dist/src/nifti.js", + "types": "dist/src/nifti.d.ts", "directories": { "test": "tests" }, @@ -10,15 +11,22 @@ "fflate": "*" }, "devDependencies": { + "@types/chai": "^4.3.5", + "@types/mocha": "^10.0.1", + "chai": "^4.3.7", "esbuild": "*", "jsdoc-to-markdown": "*", - "mocha": "*" + "mocha": "*", + "ts-node": "^10.9.1", + "tsify": "^5.0.4", + "typescript": "^5.0.4" }, "scripts": { - "test": "mocha --timeout 0 tests", - "build": "rm -rf build; mkdir build; esbuild src/nifti.js --bundle --outfile=build/nifti-reader.js; esbuild src/nifti.js --bundle --minify --outfile=build/nifti-reader-min.js", + "test": "mocha -r ts-node/register __tests__/**/*.spec.ts", + "test-js": "npm run build; npm run release; mocha --timeout 0 tests", + "build": "rm -rf build; mkdir build; tsc; esbuild dist/src/nifti.js --bundle --outfile=build/nifti-reader.js; esbuild dist/src/nifti.js --bundle --minify --outfile=build/nifti-reader-min.js", "release": "rm release/current/*.js; cp build/*.js release/current/.", - "doc": "rm -rf build; mkdir build; ./node_modules/.bin/jsdoc2md src/*.js > build/docs.md" + "doc": "rm -rf build; mkdir build; ./node_modules/.bin/jsdoc2md dist/src/*.js > build/docs.md" }, "repository": { "type": "git", diff --git a/release/current/nifti-reader-min.js b/release/current/nifti-reader-min.js index 7f2b26a..0db9eeb 100644 --- a/release/current/nifti-reader-min.js +++ b/release/current/nifti-reader-min.js @@ -1,54 +1,54 @@ -"use strict";(()=>{var H=(i=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(i,{get:(t,e)=>(typeof require<"u"?require:t)[e]}):i)(function(i){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+i+'" is not supported')});var vt=(i,t)=>()=>(t||i((t={exports:{}}).exports,t),t.exports);var Tt=vt((He,bt)=>{"use strict";var zt=zt||{};zt.NIFTIEXTENSION=zt.NIFTIEXTENSION||function(i,t,e,n){if(i%16!=0)throw new Error("This does not appear to be a NIFTI extension");this.esize=i,this.ecode=t,this.edata=e,this.littleEndian=n};zt.NIFTIEXTENSION.prototype.toArrayBuffer=function(){let i=new Uint8Array(this.esize);i.set(this.data.buffer,8);let t=new DataView(i.buffer);return t.setInt32(0,this.esize,this.littleEndian),t.setInt32(4,this.ecode,this.littleEndian),i.buffer};var _e=typeof bt;_e!=="undefined"&&bt.exports&&(bt.exports=zt.NIFTIEXTENSION)});var kt=vt((Qe,Zt)=>{"use strict";var P=P||{};P.Utils=P.Utils||{};P.NIFTIEXTENSION=P.NIFTIEXTENSION||(typeof H<"u"?Tt():null);P.Utils.crcTable=null;P.Utils.GUNZIP_MAGIC_COOKIE1=31;P.Utils.GUNZIP_MAGIC_COOKIE2=139;P.Utils.getStringAt=function(i,t,e){var n="",r,s;for(r=t;r=0;n--)s=s*256+r[n];return s};P.Utils.getExtensionsAt=function(i,t,e,n){let r=[],s=t;for(;sn&&(l=!l,a=P.Utils.getIntAt(i,s,l),a+s>n))throw new Error("This does not appear to be a valid NIFTI extension");if(a%16!=0)throw new Error("This does not appear to be a NIFTI extension");let h=P.Utils.getIntAt(i,s+4,l),f=i.buffer.slice(s+8,s+a);console.log("extensionByteIndex: "+(s+8)+" esize: "+a),console.log(f);let o=new P.NIFTIEXTENSION(a,h,f,l);r.push(o),s+=a}return r};P.Utils.toArrayBuffer=function(i){var t,e,n;for(t=new ArrayBuffer(i.length),e=new Uint8Array(t),n=0;n>>1:i>>>1;t[e]=i}return t};P.Utils.crc32=function(i){for(var t=P.Utils.crcTable||(P.Utils.crcTable=P.Utils.makeCRCTable()),e=-1,n=0;n>>8^t[(e^i.getUint8(n))&255];return(e^-1)>>>0};var Fe=typeof Zt;Fe!=="undefined"&&Zt.exports&&(Zt.exports=P.Utils)});var li=vt((We,Yt)=>{"use strict";var $e=Tt(),u=u||{};u.Utils=u.Utils||(typeof H<"u"?kt():null);u.NIFTIEXTENSION=u.NIFTIEXTENSION||(typeof H<"u"?Tt():null);u.NIFTI1=u.NIFTI1||function(){this.littleEndian=!1,this.dim_info=0,this.dims=[],this.intent_p1=0,this.intent_p2=0,this.intent_p3=0,this.intent_code=0,this.datatypeCode=0,this.numBitsPerVoxel=0,this.slice_start=0,this.slice_end=0,this.slice_code=0,this.pixDims=[],this.vox_offset=0,this.scl_slope=1,this.scl_inter=0,this.xyzt_units=0,this.cal_max=0,this.cal_min=0,this.slice_duration=0,this.toffset=0,this.description="",this.aux_file="",this.intent_name="",this.qform_code=0,this.sform_code=0,this.quatern_b=0,this.quatern_c=0,this.quatern_d=0,this.qoffset_x=0,this.qoffset_y=0,this.qoffset_z=0,this.affine=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],this.magic=0,this.isHDR=!1,this.extensionFlag=[0,0,0,0],this.extensionSize=0,this.extensionCode=0,this.extensions=[]};u.NIFTI1.TYPE_NONE=0;u.NIFTI1.TYPE_BINARY=1;u.NIFTI1.TYPE_UINT8=2;u.NIFTI1.TYPE_INT16=4;u.NIFTI1.TYPE_INT32=8;u.NIFTI1.TYPE_FLOAT32=16;u.NIFTI1.TYPE_COMPLEX64=32;u.NIFTI1.TYPE_FLOAT64=64;u.NIFTI1.TYPE_RGB24=128;u.NIFTI1.TYPE_INT8=256;u.NIFTI1.TYPE_UINT16=512;u.NIFTI1.TYPE_UINT32=768;u.NIFTI1.TYPE_INT64=1024;u.NIFTI1.TYPE_UINT64=1280;u.NIFTI1.TYPE_FLOAT128=1536;u.NIFTI1.TYPE_COMPLEX128=1792;u.NIFTI1.TYPE_COMPLEX256=2048;u.NIFTI1.XFORM_UNKNOWN=0;u.NIFTI1.XFORM_SCANNER_ANAT=1;u.NIFTI1.XFORM_ALIGNED_ANAT=2;u.NIFTI1.XFORM_TALAIRACH=3;u.NIFTI1.XFORM_MNI_152=4;u.NIFTI1.SPATIAL_UNITS_MASK=7;u.NIFTI1.TEMPORAL_UNITS_MASK=56;u.NIFTI1.UNITS_UNKNOWN=0;u.NIFTI1.UNITS_METER=1;u.NIFTI1.UNITS_MM=2;u.NIFTI1.UNITS_MICRON=3;u.NIFTI1.UNITS_SEC=8;u.NIFTI1.UNITS_MSEC=16;u.NIFTI1.UNITS_USEC=24;u.NIFTI1.UNITS_HZ=32;u.NIFTI1.UNITS_PPM=40;u.NIFTI1.UNITS_RADS=48;u.NIFTI1.MAGIC_COOKIE=348;u.NIFTI1.STANDARD_HEADER_SIZE=348;u.NIFTI1.MAGIC_NUMBER_LOCATION=344;u.NIFTI1.MAGIC_NUMBER=[110,43,49];u.NIFTI1.MAGIC_NUMBER2=[110,105,49];u.NIFTI1.EXTENSION_HEADER_SIZE=8;u.NIFTI1.prototype.readHeader=function(i){var t=new DataView(i),e=u.Utils.getIntAt(t,0,this.littleEndian),n,r,s,l;if(e!==u.NIFTI1.MAGIC_COOKIE&&(this.littleEndian=!0,e=u.Utils.getIntAt(t,0,this.littleEndian)),e!==u.NIFTI1.MAGIC_COOKIE)throw new Error("This does not appear to be a NIFTI file!");for(this.dim_info=u.Utils.getByteAt(t,39),n=0;n<8;n+=1)l=40+n*2,this.dims[n]=u.Utils.getShortAt(t,l,this.littleEndian);for(this.intent_p1=u.Utils.getFloatAt(t,56,this.littleEndian),this.intent_p2=u.Utils.getFloatAt(t,60,this.littleEndian),this.intent_p3=u.Utils.getFloatAt(t,64,this.littleEndian),this.intent_code=u.Utils.getShortAt(t,68,this.littleEndian),this.datatypeCode=u.Utils.getShortAt(t,70,this.littleEndian),this.numBitsPerVoxel=u.Utils.getShortAt(t,72,this.littleEndian),this.slice_start=u.Utils.getShortAt(t,74,this.littleEndian),n=0;n<8;n+=1)l=76+n*4,this.pixDims[n]=u.Utils.getFloatAt(t,l,this.littleEndian);if(this.vox_offset=u.Utils.getFloatAt(t,108,this.littleEndian),this.scl_slope=u.Utils.getFloatAt(t,112,this.littleEndian),this.scl_inter=u.Utils.getFloatAt(t,116,this.littleEndian),this.slice_end=u.Utils.getShortAt(t,120,this.littleEndian),this.slice_code=u.Utils.getByteAt(t,122),this.xyzt_units=u.Utils.getByteAt(t,123),this.cal_max=u.Utils.getFloatAt(t,124,this.littleEndian),this.cal_min=u.Utils.getFloatAt(t,128,this.littleEndian),this.slice_duration=u.Utils.getFloatAt(t,132,this.littleEndian),this.toffset=u.Utils.getFloatAt(t,136,this.littleEndian),this.description=u.Utils.getStringAt(t,148,228),this.aux_file=u.Utils.getStringAt(t,228,252),this.qform_code=u.Utils.getShortAt(t,252,this.littleEndian),this.sform_code=u.Utils.getShortAt(t,254,this.littleEndian),this.quatern_b=u.Utils.getFloatAt(t,256,this.littleEndian),this.quatern_c=u.Utils.getFloatAt(t,260,this.littleEndian),this.quatern_d=u.Utils.getFloatAt(t,264,this.littleEndian),this.quatern_a=Math.sqrt(1-(Math.pow(this.quatern_b,2)+Math.pow(this.quatern_c,2)+Math.pow(this.quatern_d,2))),this.qoffset_x=u.Utils.getFloatAt(t,268,this.littleEndian),this.qoffset_y=u.Utils.getFloatAt(t,272,this.littleEndian),this.qoffset_z=u.Utils.getFloatAt(t,276,this.littleEndian),this.qform_code<1&&this.sform_code<1&&(this.affine[0][0]=this.pixDims[1],this.affine[1][1]=this.pixDims[2],this.affine[2][2]=this.pixDims[3]),this.qform_code>0&&this.sform_code0)for(r=0;r<3;r+=1)for(s=0;s<4;s+=1)l=280+(r*4+s)*4,this.affine[r][s]=u.Utils.getFloatAt(t,l,this.littleEndian);this.affine[3][0]=0,this.affine[3][1]=0,this.affine[3][2]=0,this.affine[3][3]=1,this.intent_name=u.Utils.getStringAt(t,328,344),this.magic=u.Utils.getStringAt(t,344,348),this.isHDR=this.magic===u.NIFTI1.MAGIC_NUMBER2,t.byteLength>u.NIFTI1.MAGIC_COOKIE&&(this.extensionFlag[0]=u.Utils.getByteAt(t,348),this.extensionFlag[1]=u.Utils.getByteAt(t,348+1),this.extensionFlag[2]=u.Utils.getByteAt(t,348+2),this.extensionFlag[3]=u.Utils.getByteAt(t,348+3),this.extensionFlag[0]&&(this.extensions=u.Utils.getExtensionsAt(t,this.getExtensionLocation(),this.littleEndian,this.vox_offset),this.extensionSize=this.extensions[0].esize,this.extensionCode=this.extensions[0].ecode))};u.NIFTI1.prototype.toFormattedString=function(){var i=u.Utils.formatNumber,t="";return t+="Dim Info = "+this.dim_info+` -`,t+="Image Dimensions (1-8): "+this.dims[0]+", "+this.dims[1]+", "+this.dims[2]+", "+this.dims[3]+", "+this.dims[4]+", "+this.dims[5]+", "+this.dims[6]+", "+this.dims[7]+` -`,t+="Intent Parameters (1-3): "+this.intent_p1+", "+this.intent_p2+", "+this.intent_p3+` -`,t+="Intent Code = "+this.intent_code+` -`,t+="Datatype = "+this.datatypeCode+" ("+this.getDatatypeCodeString(this.datatypeCode)+`) -`,t+="Bits Per Voxel = "+this.numBitsPerVoxel+` -`,t+="Slice Start = "+this.slice_start+` -`,t+="Voxel Dimensions (1-8): "+i(this.pixDims[0])+", "+i(this.pixDims[1])+", "+i(this.pixDims[2])+", "+i(this.pixDims[3])+", "+i(this.pixDims[4])+", "+i(this.pixDims[5])+", "+i(this.pixDims[6])+", "+i(this.pixDims[7])+` -`,t+="Image Offset = "+this.vox_offset+` -`,t+="Data Scale: Slope = "+i(this.scl_slope)+" Intercept = "+i(this.scl_inter)+` -`,t+="Slice End = "+this.slice_end+` -`,t+="Slice Code = "+this.slice_code+` -`,t+="Units Code = "+this.xyzt_units+" ("+this.getUnitsCodeString(u.NIFTI1.SPATIAL_UNITS_MASK&this.xyzt_units)+", "+this.getUnitsCodeString(u.NIFTI1.TEMPORAL_UNITS_MASK&this.xyzt_units)+`) -`,t+="Display Range: Max = "+i(this.cal_max)+" Min = "+i(this.cal_min)+` -`,t+="Slice Duration = "+this.slice_duration+` -`,t+="Time Axis Shift = "+this.toffset+` -`,t+='Description: "'+this.description+`" -`,t+='Auxiliary File: "'+this.aux_file+`" -`,t+="Q-Form Code = "+this.qform_code+" ("+this.getTransformCodeString(this.qform_code)+`) -`,t+="S-Form Code = "+this.sform_code+" ("+this.getTransformCodeString(this.sform_code)+`) -`,t+="Quaternion Parameters: b = "+i(this.quatern_b)+" c = "+i(this.quatern_c)+" d = "+i(this.quatern_d)+` -`,t+="Quaternion Offsets: x = "+this.qoffset_x+" y = "+this.qoffset_y+" z = "+this.qoffset_z+` -`,t+="S-Form Parameters X: "+i(this.affine[0][0])+", "+i(this.affine[0][1])+", "+i(this.affine[0][2])+", "+i(this.affine[0][3])+` -`,t+="S-Form Parameters Y: "+i(this.affine[1][0])+", "+i(this.affine[1][1])+", "+i(this.affine[1][2])+", "+i(this.affine[1][3])+` -`,t+="S-Form Parameters Z: "+i(this.affine[2][0])+", "+i(this.affine[2][1])+", "+i(this.affine[2][2])+", "+i(this.affine[2][3])+` -`,t+='Intent Name: "'+this.intent_name+`" -`,this.extensionFlag[0]&&(t+="Extension: Size = "+this.extensionSize+" Code = "+this.extensionCode+` -`),t};u.NIFTI1.prototype.getDatatypeCodeString=function(i){return i===u.NIFTI1.TYPE_UINT8?"1-Byte Unsigned Integer":i===u.NIFTI1.TYPE_INT16?"2-Byte Signed Integer":i===u.NIFTI1.TYPE_INT32?"4-Byte Signed Integer":i===u.NIFTI1.TYPE_FLOAT32?"4-Byte Float":i===u.NIFTI1.TYPE_FLOAT64?"8-Byte Float":i===u.NIFTI1.TYPE_RGB24?"RGB":i===u.NIFTI1.TYPE_INT8?"1-Byte Signed Integer":i===u.NIFTI1.TYPE_UINT16?"2-Byte Unsigned Integer":i===u.NIFTI1.TYPE_UINT32?"4-Byte Unsigned Integer":i===u.NIFTI1.TYPE_INT64?"8-Byte Signed Integer":i===u.NIFTI1.TYPE_UINT64?"8-Byte Unsigned Integer":"Unknown"};u.NIFTI1.prototype.getTransformCodeString=function(i){return i===u.NIFTI1.XFORM_SCANNER_ANAT?"Scanner":i===u.NIFTI1.XFORM_ALIGNED_ANAT?"Aligned":i===u.NIFTI1.XFORM_TALAIRACH?"Talairach":i===u.NIFTI1.XFORM_MNI_152?"MNI":"Unknown"};u.NIFTI1.prototype.getUnitsCodeString=function(i){return i===u.NIFTI1.UNITS_METER?"Meters":i===u.NIFTI1.UNITS_MM?"Millimeters":i===u.NIFTI1.UNITS_MICRON?"Microns":i===u.NIFTI1.UNITS_SEC?"Seconds":i===u.NIFTI1.UNITS_MSEC?"Milliseconds":i===u.NIFTI1.UNITS_USEC?"Microseconds":i===u.NIFTI1.UNITS_HZ?"Hz":i===u.NIFTI1.UNITS_PPM?"PPM":i===u.NIFTI1.UNITS_RADS?"Rads":"Unknown"};u.NIFTI1.prototype.getQformMat=function(){return this.convertNiftiQFormToNiftiSForm(this.quatern_b,this.quatern_c,this.quatern_d,this.qoffset_x,this.qoffset_y,this.qoffset_z,this.pixDims[1],this.pixDims[2],this.pixDims[3],this.pixDims[0])};u.NIFTI1.prototype.convertNiftiQFormToNiftiSForm=function(i,t,e,n,r,s,l,a,h,f){var o=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],c,p=i,m=t,g=e,d,v,E;return o[3][0]=o[3][1]=o[3][2]=0,o[3][3]=1,c=1-(p*p+m*m+g*g),c<1e-7?(c=1/Math.sqrt(p*p+m*m+g*g),p*=c,m*=c,g*=c,c=0):c=Math.sqrt(c),d=l>0?l:1,v=a>0?a:1,E=h>0?h:1,f<0&&(E=-E),o[0][0]=(c*c+p*p-m*m-g*g)*d,o[0][1]=2*(p*m-c*g)*v,o[0][2]=2*(p*g+c*m)*E,o[1][0]=2*(p*m+c*g)*d,o[1][1]=(c*c+m*m-p*p-g*g)*v,o[1][2]=2*(m*g-c*p)*E,o[2][0]=2*(p*g-c*m)*d,o[2][1]=2*(m*g+c*p)*v,o[2][2]=(c*c+g*g-m*m-p*p)*E,o[0][3]=n,o[1][3]=r,o[2][3]=s,o};u.NIFTI1.prototype.convertNiftiSFormToNEMA=function(i){var t,e,n,r,s,l,a,h,f,o,c,p,m,g,d,v,E,A,x,y,L,z,U,T,Z,C,b,S,q,w,O,D,B,k;if(d=0,b=[[0,0,0],[0,0,0],[0,0,0]],S=[[0,0,0],[0,0,0],[0,0,0]],t=i[0][0],e=i[0][1],n=i[0][2],r=i[1][0],s=i[1][1],l=i[1][2],a=i[2][0],h=i[2][1],f=i[2][2],o=Math.sqrt(t*t+r*r+a*a),o===0||(t/=o,r/=o,a/=o,o=Math.sqrt(e*e+s*s+h*h),o===0))return null;if(e/=o,s/=o,h/=o,o=t*e+r*s+a*h,Math.abs(o)>1e-4){if(e-=o*t,s-=o*r,h-=o*a,o=Math.sqrt(e*e+s*s+h*h),o===0)return null;e/=o,s/=o,h/=o}if(o=Math.sqrt(n*n+l*l+f*f),o===0?(n=r*h-a*s,l=a*e-h*t,f=t*s-r*e):(n/=o,l/=o,f/=o),o=t*n+r*l+a*f,Math.abs(o)>1e-4){if(n-=o*t,l-=o*r,f-=o*a,o=Math.sqrt(n*n+l*l+f*f),o===0)return null;n/=o,l/=o,f/=o}if(o=e*n+s*l+h*f,Math.abs(o)>1e-4){if(n-=o*e,l-=o*s,f-=o*h,o=Math.sqrt(n*n+l*l+f*f),o===0)return null;n/=o,l/=o,f/=o}if(b[0][0]=t,b[0][1]=e,b[0][2]=n,b[1][0]=r,b[1][1]=s,b[1][2]=l,b[2][0]=a,b[2][1]=h,b[2][2]=f,c=this.nifti_mat33_determ(b),c===0)return null;for(C=-666,x=z=U=T=1,y=2,L=3,m=1;m<=3;m+=1)for(g=1;g<=3;g+=1)if(m!==g){for(d=1;d<=3;d+=1)if(!(m===d||g===d))for(S[0][0]=S[0][1]=S[0][2]=S[1][0]=S[1][1]=S[1][2]=S[2][0]=S[2][1]=S[2][2]=0,v=-1;v<=1;v+=2)for(E=-1;E<=1;E+=2)for(A=-1;A<=1;A+=2)S[0][m-1]=v,S[1][g-1]=E,S[2][d-1]=A,p=this.nifti_mat33_determ(S),p*c>0&&(Z=this.nifti_mat33_mul(S,b),o=Z[0][0]+Z[1][1]+Z[2][2],o>C&&(C=o,x=m,y=g,L=d,z=v,U=E,T=A))}switch(q=w=O=D=B=k=0,x*z){case 1:q="X",D="+";break;case-1:q="X",D="-";break;case 2:q="Y",D="+";break;case-2:q="Y",D="-";break;case 3:q="Z",D="+";break;case-3:q="Z",D="-";break}switch(y*U){case 1:w="X",B="+";break;case-1:w="X",B="-";break;case 2:w="Y",B="+";break;case-2:w="Y",B="-";break;case 3:w="Z",B="+";break;case-3:w="Z",B="-";break}switch(L*T){case 1:O="X",k="+";break;case-1:O="X",k="-";break;case 2:O="Y",k="+";break;case-2:O="Y",k="-";break;case 3:O="Z",k="+";break;case-3:O="Z",k="-";break}return q+w+O+D+B+k};u.NIFTI1.prototype.nifti_mat33_mul=function(i,t){var e=[[0,0,0],[0,0,0],[0,0,0]],n,r;for(n=0;n<3;n+=1)for(r=0;r<3;r+=1)e[n][r]=i[n][0]*t[0][r]+i[n][1]*t[1][r]+i[n][2]*t[2][r];return e};u.NIFTI1.prototype.nifti_mat33_determ=function(i){var t,e,n,r,s,l,a,h,f;return t=i[0][0],e=i[0][1],n=i[0][2],r=i[1][0],s=i[1][1],l=i[1][2],a=i[2][0],h=i[2][1],f=i[2][2],t*s*f-t*h*l-r*e*f+r*h*n+a*e*l-a*s*n};u.NIFTI1.prototype.getExtensionLocation=function(){return u.NIFTI1.MAGIC_COOKIE+4};u.NIFTI1.prototype.getExtensionSize=function(i){return u.Utils.getIntAt(i,this.getExtensionLocation(),this.littleEndian)};u.NIFTI1.prototype.getExtensionCode=function(i){return u.Utils.getIntAt(i,this.getExtensionLocation()+4,this.littleEndian)};u.NIFTI1.prototype.addExtension=function(i,t=-1){t==-1?this.extensions.push(i):this.extensions.splice(t,0,i),this.vox_offset+=i.esize};u.NIFTI1.prototype.removeExtension=function(i){let t=this.extensions[i];t&&(this.vox_offset-=t.esize),this.extensions.splice(i,1)};u.NIFTI1.prototype.toArrayBuffer=function(i=!1){let n=352;if(i)for(let a of this.extensions)n+=a.esize;let r=new Uint8Array(n),s=new DataView(r.buffer);s.setInt32(0,348,this.littleEndian),s.setUint8(39,this.dim_info);for(let a=0;a<8;a++)s.setUint16(40+2*a,this.dims[a],this.littleEndian);s.setFloat32(56,this.intent_p1,this.littleEndian),s.setFloat32(60,this.intent_p2,this.littleEndian),s.setFloat32(64,this.intent_p3,this.littleEndian),s.setInt16(68,this.intent_code,this.littleEndian),s.setInt16(70,this.datatypeCode,this.littleEndian),s.setInt16(72,this.numBitsPerVoxel,this.littleEndian),s.setInt16(74,this.slice_start,this.littleEndian);for(let a=0;a<8;a++)s.setFloat32(76+4*a,this.pixDims[a],this.littleEndian);s.setFloat32(108,this.vox_offset,this.littleEndian),s.setFloat32(112,this.scl_slope,this.littleEndian),s.setFloat32(116,this.scl_inter,this.littleEndian),s.setInt16(120,this.slice_end,this.littleEndian),s.setUint8(122,this.slice_code),s.setUint8(123,this.xyzt_units),s.setFloat32(124,this.cal_max,this.littleEndian),s.setFloat32(128,this.cal_min,this.littleEndian),s.setFloat32(132,this.slice_duration,this.littleEndian),s.setFloat32(136,this.toffset,this.littleEndian),r.set(Buffer.from(this.description),148),r.set(Buffer.from(this.aux_file),228),s.setInt16(252,this.qform_code,this.littleEndian),s.setInt16(254,this.sform_code,this.littleEndian),s.setFloat32(256,this.quatern_b,this.littleEndian),s.setFloat32(260,this.quatern_c,this.littleEndian),s.setFloat32(264,this.quatern_d,this.littleEndian),s.setFloat32(268,this.qoffset_x,this.littleEndian),s.setFloat32(272,this.qoffset_y,this.littleEndian),s.setFloat32(276,this.qoffset_z,this.littleEndian);let l=this.affine.flat();for(let a=0;a<12;a++)s.setFloat32(280+4*a,l[a],this.littleEndian);if(r.set(Buffer.from(this.intent_name),328),r.set(Buffer.from(this.magic),344),i){r.set(Uint8Array.from([1,0,0,0]),348);let a=this.getExtensionLocation();for(let h of this.extensions)s.setInt32(a,h.esize,h.littleEndian),s.setInt32(a+4,h.ecode,h.littleEndian),r.set(new Uint8Array(h.edata),a+8),a+=h.esize}else r.set(new Uint8Array(4).fill(0),348);return r.buffer};var ye=typeof Yt;ye!=="undefined"&&Yt.exports&&(Yt.exports=u.NIFTI1)});var zi=vt((tn,Xt)=>{"use strict";var I=I||{};I.Utils=I.Utils||(typeof H<"u"?kt():null);I.NIFTI1=I.NIFTI1||(typeof H<"u"?li():null);I.NIFTIEXTENSION=I.NIFTIEXTENSION||(typeof H<"u"?Tt():null);I.NIFTI2=I.NIFTI2||function(){this.littleEndian=!1,this.dim_info=0,this.dims=[],this.intent_p1=0,this.intent_p2=0,this.intent_p3=0,this.intent_code=0,this.datatypeCode=0,this.numBitsPerVoxel=0,this.slice_start=0,this.slice_end=0,this.slice_code=0,this.pixDims=[],this.vox_offset=0,this.scl_slope=1,this.scl_inter=0,this.xyzt_units=0,this.cal_max=0,this.cal_min=0,this.slice_duration=0,this.toffset=0,this.description="",this.aux_file="",this.intent_name="",this.qform_code=0,this.sform_code=0,this.quatern_b=0,this.quatern_c=0,this.quatern_d=0,this.qoffset_x=0,this.qoffset_y=0,this.qoffset_z=0,this.affine=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],this.magic=0,this.extensionFlag=[0,0,0,0],this.extensions=[]};I.NIFTI2.MAGIC_COOKIE=540;I.NIFTI2.MAGIC_NUMBER_LOCATION=4;I.NIFTI2.MAGIC_NUMBER=[110,43,50,0,13,10,26,10];I.NIFTI2.MAGIC_NUMBER2=[110,105,50,0,13,10,26,10];I.NIFTI2.prototype.readHeader=function(i){var t=new DataView(i),e=I.Utils.getIntAt(t,0,this.littleEndian),n,r,s,l,a;if(e!==I.NIFTI2.MAGIC_COOKIE&&(this.littleEndian=!0,e=I.Utils.getIntAt(t,0,this.littleEndian)),e!==I.NIFTI2.MAGIC_COOKIE)throw new Error("This does not appear to be a NIFTI file!");for(this.magic=I.Utils.getStringAt(t,4,12),this.datatypeCode=I.Utils.getShortAt(t,12,this.littleEndian),this.numBitsPerVoxel=I.Utils.getShortAt(t,14,this.littleEndian),n=0;n<8;n+=1)l=16+n*8,this.dims[n]=I.Utils.getLongAt(t,l,this.littleEndian);for(this.intent_p1=I.Utils.getDoubleAt(t,80,this.littleEndian),this.intent_p2=I.Utils.getDoubleAt(t,88,this.littleEndian),this.intent_p3=I.Utils.getDoubleAt(t,96,this.littleEndian),n=0;n<8;n+=1)l=104+n*8,this.pixDims[n]=I.Utils.getDoubleAt(t,l,this.littleEndian);for(this.vox_offset=I.Utils.getLongAt(t,168,this.littleEndian),this.scl_slope=I.Utils.getDoubleAt(t,176,this.littleEndian),this.scl_inter=I.Utils.getDoubleAt(t,184,this.littleEndian),this.cal_max=I.Utils.getDoubleAt(t,192,this.littleEndian),this.cal_min=I.Utils.getDoubleAt(t,200,this.littleEndian),this.slice_duration=I.Utils.getDoubleAt(t,208,this.littleEndian),this.toffset=I.Utils.getDoubleAt(t,216,this.littleEndian),this.slice_start=I.Utils.getLongAt(t,224,this.littleEndian),this.slice_end=I.Utils.getLongAt(t,232,this.littleEndian),this.description=I.Utils.getStringAt(t,240,240+80),this.aux_file=I.Utils.getStringAt(t,320,320+24),this.qform_code=I.Utils.getIntAt(t,344,this.littleEndian),this.sform_code=I.Utils.getIntAt(t,348,this.littleEndian),this.quatern_b=I.Utils.getDoubleAt(t,352,this.littleEndian),this.quatern_c=I.Utils.getDoubleAt(t,360,this.littleEndian),this.quatern_d=I.Utils.getDoubleAt(t,368,this.littleEndian),this.qoffset_x=I.Utils.getDoubleAt(t,376,this.littleEndian),this.qoffset_y=I.Utils.getDoubleAt(t,384,this.littleEndian),this.qoffset_z=I.Utils.getDoubleAt(t,392,this.littleEndian),r=0;r<3;r+=1)for(s=0;s<4;s+=1)l=400+(r*4+s)*8,this.affine[r][s]=I.Utils.getDoubleAt(t,l,this.littleEndian);this.affine[3][0]=0,this.affine[3][1]=0,this.affine[3][2]=0,this.affine[3][3]=1,this.slice_code=I.Utils.getIntAt(t,496,this.littleEndian),this.xyzt_units=I.Utils.getIntAt(t,500,this.littleEndian),this.intent_code=I.Utils.getIntAt(t,504,this.littleEndian),this.intent_name=I.Utils.getStringAt(t,508,508+16),this.dim_info=I.Utils.getByteAt(t,524),t.byteLength>I.NIFTI2.MAGIC_COOKIE&&(this.extensionFlag[0]=I.Utils.getByteAt(t,540),this.extensionFlag[1]=I.Utils.getByteAt(t,540+1),this.extensionFlag[2]=I.Utils.getByteAt(t,540+2),this.extensionFlag[3]=I.Utils.getByteAt(t,540+3),this.extensionFlag[0]&&(this.extensions=I.Utils.getExtensionsAt(t,this.getExtensionLocation(),this.littleEndian,this.vox_offset),this.extensionSize=this.extensions[0].esize,this.extensionCode=this.extensions[0].ecode))};I.NIFTI2.prototype.toFormattedString=function(){var i=I.Utils.formatNumber,t="";return t+="Datatype = "+ +this.datatypeCode+" ("+this.getDatatypeCodeString(this.datatypeCode)+`) -`,t+="Bits Per Voxel = = "+this.numBitsPerVoxel+` -`,t+="Image Dimensions (1-8): "+this.dims[0]+", "+this.dims[1]+", "+this.dims[2]+", "+this.dims[3]+", "+this.dims[4]+", "+this.dims[5]+", "+this.dims[6]+", "+this.dims[7]+` -`,t+="Intent Parameters (1-3): "+this.intent_p1+", "+this.intent_p2+", "+this.intent_p3+` -`,t+="Voxel Dimensions (1-8): "+i(this.pixDims[0])+", "+i(this.pixDims[1])+", "+i(this.pixDims[2])+", "+i(this.pixDims[3])+", "+i(this.pixDims[4])+", "+i(this.pixDims[5])+", "+i(this.pixDims[6])+", "+i(this.pixDims[7])+` -`,t+="Image Offset = "+this.vox_offset+` -`,t+="Data Scale: Slope = "+i(this.scl_slope)+" Intercept = "+i(this.scl_inter)+` -`,t+="Display Range: Max = "+i(this.cal_max)+" Min = "+i(this.cal_min)+` -`,t+="Slice Duration = "+this.slice_duration+` -`,t+="Time Axis Shift = "+this.toffset+` -`,t+="Slice Start = "+this.slice_start+` -`,t+="Slice End = "+this.slice_end+` -`,t+='Description: "'+this.description+`" -`,t+='Auxiliary File: "'+this.aux_file+`" -`,t+="Q-Form Code = "+this.qform_code+" ("+this.getTransformCodeString(this.qform_code)+`) -`,t+="S-Form Code = "+this.sform_code+" ("+this.getTransformCodeString(this.sform_code)+`) -`,t+="Quaternion Parameters: b = "+i(this.quatern_b)+" c = "+i(this.quatern_c)+" d = "+i(this.quatern_d)+` -`,t+="Quaternion Offsets: x = "+this.qoffset_x+" y = "+this.qoffset_y+" z = "+this.qoffset_z+` -`,t+="S-Form Parameters X: "+i(this.affine[0][0])+", "+i(this.affine[0][1])+", "+i(this.affine[0][2])+", "+i(this.affine[0][3])+` -`,t+="S-Form Parameters Y: "+i(this.affine[1][0])+", "+i(this.affine[1][1])+", "+i(this.affine[1][2])+", "+i(this.affine[1][3])+` -`,t+="S-Form Parameters Z: "+i(this.affine[2][0])+", "+i(this.affine[2][1])+", "+i(this.affine[2][2])+", "+i(this.affine[2][3])+` -`,t+="Slice Code = "+this.slice_code+` -`,t+="Units Code = "+this.xyzt_units+" ("+this.getUnitsCodeString(I.NIFTI1.SPATIAL_UNITS_MASK&this.xyzt_units)+", "+this.getUnitsCodeString(I.NIFTI1.TEMPORAL_UNITS_MASK&this.xyzt_units)+`) -`,t+="Intent Code = "+this.intent_code+` -`,t+='Intent Name: "'+this.intent_name+`" -`,t+="Dim Info = "+this.dim_info+` -`,t};I.NIFTI2.prototype.getExtensionLocation=function(){return I.NIFTI2.MAGIC_COOKIE+4};I.NIFTI2.prototype.getExtensionSize=I.NIFTI1.prototype.getExtensionSize;I.NIFTI2.prototype.getExtensionCode=I.NIFTI1.prototype.getExtensionCode;I.NIFTI2.prototype.addExtension=I.NIFTI1.prototype.addExtension;I.NIFTI2.prototype.removeExtension=I.NIFTI1.prototype.removeExtension;I.NIFTI2.prototype.getDatatypeCodeString=I.NIFTI1.prototype.getDatatypeCodeString;I.NIFTI2.prototype.getTransformCodeString=I.NIFTI1.prototype.getTransformCodeString;I.NIFTI2.prototype.getUnitsCodeString=I.NIFTI1.prototype.getUnitsCodeString;I.NIFTI2.prototype.getQformMat=I.NIFTI1.prototype.getQformMat;I.NIFTI2.prototype.convertNiftiQFormToNiftiSForm=I.NIFTI1.prototype.convertNiftiQFormToNiftiSForm;I.NIFTI2.prototype.convertNiftiSFormToNEMA=I.NIFTI1.prototype.convertNiftiSFormToNEMA;I.NIFTI2.prototype.nifti_mat33_mul=I.NIFTI1.prototype.nifti_mat33_mul;I.NIFTI2.prototype.nifti_mat33_determ=I.NIFTI1.prototype.nifti_mat33_determ;I.NIFTI2.prototype.toArrayBuffer=function(i=!1){let n=544;if(i)for(let a of this.extensions)n+=a.esize;let r=new Uint8Array(n),s=new DataView(r.buffer);s.setInt32(0,540,this.littleEndian),r.set(Buffer.from(this.magic),4),s.setInt16(12,this.datatypeCode,this.littleEndian),s.setInt16(14,this.numBitsPerVoxel,this.littleEndian);for(let a=0;a<8;a++)s.setBigInt64(16+8*a,BigInt(this.dims[a]),this.littleEndian);s.setFloat64(80,this.intent_p1,this.littleEndian),s.setFloat64(88,this.intent_p2,this.littleEndian),s.setFloat64(96,this.intent_p3,this.littleEndian);for(let a=0;a<8;a++)s.setFloat64(104+8*a,this.pixDims[a],this.littleEndian);s.setBigInt64(168,BigInt(this.vox_offset),this.littleEndian),s.setFloat64(176,this.scl_slope,this.littleEndian),s.setFloat64(184,this.scl_inter,this.littleEndian),s.setFloat64(192,this.cal_max,this.littleEndian),s.setFloat64(200,this.cal_min,this.littleEndian),s.setFloat64(208,this.slice_duration,this.littleEndian),s.setFloat64(216,this.toffset,this.littleEndian),s.setBigInt64(224,BigInt(this.slice_start),this.littleEndian),s.setBigInt64(232,BigInt(this.slice_end),this.littleEndian),r.set(Buffer.from(this.description),240),r.set(Buffer.from(this.aux_file),320),s.setInt32(344,this.qform_code,this.littleEndian),s.setInt32(348,this.sform_code,this.littleEndian),s.setFloat64(352,this.quatern_b,this.littleEndian),s.setFloat64(360,this.quatern_c,this.littleEndian),s.setFloat64(368,this.quatern_d,this.littleEndian),s.setFloat64(376,this.qoffset_x,this.littleEndian),s.setFloat64(384,this.qoffset_y,this.littleEndian),s.setFloat64(392,this.qoffset_z,this.littleEndian);let l=this.affine.flat();for(let a=0;a<12;a++)s.setFloat64(400+8*a,l[a],this.littleEndian);if(s.setInt32(496,this.slice_code,this.littleEndian),s.setInt32(500,this.xyzt_units,this.littleEndian),s.setInt32(504,this.intent_code,this.littleEndian),r.set(Buffer.from(this.intent_name),508),s.setUint8(524,this.dim_info),i){r.set(Uint8Array.from([1,0,0,0]),540);let a=this.getExtensionLocation();for(let h of this.extensions)s.setInt32(a,h.esize,h.littleEndian),s.setInt32(a+4,h.ecode,h.littleEndian),r.set(new Uint8Array(h.edata),a+8),a+=h.esize}else r.set(new Uint8Array(4).fill(0),540);return r.buffer};var Ae=typeof Xt;Ae!=="undefined"&&Xt.exports&&(Xt.exports=I.NIFTI2)});var Bi=vt(qi=>{"use strict";var Di={};qi.default=function(i,t,e,n,r){var s=new Worker(Di[t]||(Di[t]=URL.createObjectURL(new Blob([i+';addEventListener("error",function(e){e=e.error;postMessage({$e$:[e.message,e.code,e.stack]})})'],{type:"text/javascript"}))));return s.onmessage=function(l){var a=l.data,h=a.$e$;if(h){var f=new Error(h[0]);f.code=h[1],f.stack=h[2],r(f,null)}else r(null,a)},s.postMessage(e,n),s}});var de=vt(_=>{"use strict";var Ue=Bi(),M=Uint8Array,V=Uint16Array,_t=Uint32Array,Ft=new M([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),yt=new M([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),Dt=new M([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Gi=function(i,t){for(var e=new V(31),n=0;n<31;++n)e[n]=t+=1<>>1|(G&21845)<<1,lt=(lt&52428)>>>2|(lt&13107)<<2,lt=(lt&61680)>>>4|(lt&3855)<<4,qt[G]=((lt&65280)>>>8|(lt&255)<<8)>>>1;var lt,G,it=function(i,t,e){for(var n=i.length,r=0,s=new V(t);r>>h]=f}else for(a=new V(n),r=0;r>>15-i[r]);return a},ht=new M(288);for(G=0;G<144;++G)ht[G]=8;var G;for(G=144;G<256;++G)ht[G]=9;var G;for(G=256;G<280;++G)ht[G]=7;var G;for(G=280;G<288;++G)ht[G]=8;var G,Nt=new M(32);for(G=0;G<32;++G)Nt[G]=5;var G,Zi=it(ht,9,0),ki=it(ht,9,1),Yi=it(Nt,5,0),Xi=it(Nt,5,1),Kt=function(i){for(var t=i[0],e=1;et&&(t=i[e]);return t},tt=function(i,t,e){var n=t/8|0;return(i[n]|i[n+1]<<8)>>(t&7)&e},Ht=function(i,t){var e=t/8|0;return(i[e]|i[e+1]<<8|i[e+2]<<16)>>(t&7)},Ot=function(i){return(i+7)/8|0},et=function(i,t,e){(t==null||t<0)&&(t=0),(e==null||e>i.length)&&(e=i.length);var n=new(i.BYTES_PER_ELEMENT==2?V:i.BYTES_PER_ELEMENT==4?_t:M)(e-t);return n.set(i.subarray(t,e)),n};_.FlateErrorCode={UnexpectedEOF:0,InvalidBlockType:1,InvalidLengthLiteral:2,InvalidDistance:3,StreamFinished:4,NoStreamHandler:5,InvalidHeader:6,NoCallback:7,InvalidUTF8:8,ExtraFieldTooLong:9,InvalidDate:10,FilenameTooLong:11,StreamFinishing:12,InvalidZipData:13,UnknownCompressionMethod:14};var Vi=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],N=function(i,t,e){var n=new Error(t||Vi[i]);if(n.code=i,Error.captureStackTrace&&Error.captureStackTrace(n,N),!e)throw n;return n},Pt=function(i,t,e){var n=i.length;if(!n||e&&e.f&&!e.l)return t||new M(0);var r=!t||e,s=!e||e.i;e||(e={}),t||(t=new M(n*3));var l=function(Rt){var Mt=t.length;if(Rt>Mt){var gt=new M(Math.max(Mt*2,Rt));gt.set(t),t=gt}},a=e.f||0,h=e.p||0,f=e.b||0,o=e.l,c=e.d,p=e.m,m=e.n,g=n*8;do{if(!o){a=tt(i,h,1);var d=tt(i,h+1,3);if(h+=3,d)if(d==1)o=ki,c=Xi,p=9,m=5;else if(d==2){var x=tt(i,h,31)+257,y=tt(i,h+10,15)+4,L=x+tt(i,h+5,31)+1;h+=14;for(var z=new M(L),U=new M(19),T=0;T>>4;if(v<16)z[T++]=v;else{var q=0,w=0;for(v==16?(w=3+tt(i,h,3),h+=2,q=z[T-1]):v==17?(w=3+tt(i,h,7),h+=3):v==18&&(w=11+tt(i,h,127),h+=7);w--;)z[T++]=q}}var O=z.subarray(0,x),D=z.subarray(x);p=Kt(O),m=Kt(D),o=it(O,p,1),c=it(D,m,1)}else N(1);else{var v=Ot(h)+4,E=i[v-4]|i[v-3]<<8,A=v+E;if(A>n){s&&N(0);break}r&&l(f+E),t.set(i.subarray(v,A),f),e.b=f+=E,e.p=h=A*8,e.f=a;continue}if(h>g){s&&N(0);break}}r&&l(f+131072);for(var B=(1<>>4;if(h+=q&15,h>g){s&&N(0);break}if(q||N(2),J<256)t[f++]=J;else if(J==256){j=h,o=null;break}else{var K=J-254;if(J>264){var T=J-257,st=Ft[T];K=tt(i,h,(1<>>4;rt||N(3),h+=rt&15;var D=bi[$];if($>3){var st=yt[$];D+=Ht(i,h)&(1<g){s&&N(0);break}r&&l(f+131072);for(var X=f+K;f>>8},mt=function(i,t,e){e<<=t&7;var n=t/8|0;i[n]|=e,i[n+1]|=e>>>8,i[n+2]|=e>>>16},Qt=function(i,t){for(var e=[],n=0;np&&(p=s[n].s);var m=new V(p+1),g=$t(e[o-1],m,0);if(g>t){var n=0,d=0,v=g-t,E=1<t)d+=E-(1<>>=v;d>0;){var x=s[n].s;m[x]=0&&d;--n){var y=s[n].s;m[y]==t&&(--m[y],++d)}g=t}return[new M(m),g]},$t=function(i,t,e){return i.s==-1?Math.max($t(i.l,t,e+1),$t(i.r,t,e+1)):t[i.s]=e},ui=function(i){for(var t=i.length;t&&!i[--t];);for(var e=new V(++t),n=0,r=i[0],s=1,l=function(h){e[n++]=h},a=1;a<=t;++a)if(i[a]==r&&a!=t)++s;else{if(!r&&s>2){for(;s>138;s-=138)l(32754);s>2&&(l(s>10?s-11<<5|28690:s-3<<5|12305),s=0)}else if(s>3){for(l(r),--s;s>6;s-=6)l(8304);s>2&&(l(s-3<<5|8208),s=0)}for(;s--;)l(r);s=1,r=i[a]}return[e.subarray(0,n),t]},dt=function(i,t){for(var e=0,n=0;n>>8,i[r+2]=i[r]^255,i[r+3]=i[r+1]^255;for(var s=0;s4&&!C[Dt[S-1]];--S);var q=f+5<<3,w=dt(r,ht)+dt(s,Nt)+l,O=dt(r,p)+dt(s,d)+l+14+3*S+dt(U,C)+(2*U[16]+3*U[17]+7*U[18]);if(q<=w&&q<=O)return Wt(t,o,i.subarray(h,h+f));var D,B,k,j;if(at(t,o,1+(O15&&(at(t,o,rt[T]>>>5&127),o+=rt[T]>>>12)}}else D=Zi,B=ht,k=Yi,j=Nt;for(var T=0;T255){var $=n[T]>>>18&31;mt(t,o,D[$+257]),o+=B[$+257],$>7&&(at(t,o,n[T]>>>23&31),o+=Ft[$]);var X=n[T]&31;mt(t,o,k[X]),o+=j[X],X>3&&(mt(t,o,n[T]>>>5&8191),o+=yt[X])}else mt(t,o,D[n[T]]),o+=B[n[T]];return mt(t,o,D[256]),o+B[256]},Ki=new _t([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),ft=new M(0),Hi=function(i,t,e,n,r,s){var l=i.length,a=new M(n+l+5*(1+Math.ceil(l/7e3))+r),h=a.subarray(n,a.length-r),f=0;if(!t||l<8)for(var o=0;o<=l;o+=65535){var c=o+65535;c>=l&&(h[f>>3]=s),f=Wt(h,f+1,i.subarray(o,c))}else{for(var p=Ki[t-1],m=p>>>13,g=p&8191,d=(1<7e3||C>24576)&&D>423){f=ci(i,h,0,L,z,U,Z,C,S,o-S,f),C=T=Z=0,S=o;for(var B=0;B<286;++B)z[B]=0;for(var B=0;B<30;++B)U[B]=0}var k=2,j=0,J=g,K=w-O&32767;if(D>2&&q==y(o-K))for(var st=Math.min(m,D)-1,rt=Math.min(32767,o),$=Math.min(258,D);K<=rt&&--J&&w!=O;){if(i[o+k]==i[o+k-K]){for(var X=0;X<$&&i[o+X]==i[o+X-K];++X);if(X>k){if(k=X,j=K,X>st)break;for(var Rt=Math.min(K,X-2),Mt=0,B=0;BMt&&(Mt=wi,O=gt)}}}w=O,O=v[w],K+=w-O+32768&32767}if(j){L[C++]=268435456|jt[k]<<18|hi[j];var Ci=jt[k]&31,Mi=hi[j]&31;Z+=Ft[Ci]+yt[Mi],++z[257+Ci],++U[Mi],b=o+k,++T}else L[C++]=i[o],++z[i[o]]}}f=ci(i,h,s,L,z,U,Z,C,S,o-S,f),!s&&f&7&&(f=Wt(h,f+1,ft))}return et(a,0,n+Ot(f)+r)},Qi=function(){for(var i=new Int32Array(256),t=0;t<256;++t){for(var e=t,n=9;--n;)e=(e&1&&-306674912)^e>>>1;i[t]=e}return i}(),At=function(){var i=-1;return{p:function(t){for(var e=i,n=0;n>>8;i=e},d:function(){return~i}}},Ti=function(){var i=1,t=0;return{p:function(e){for(var n=i,r=t,s=e.length|0,l=0;l!=s;){for(var a=Math.min(l+2655,s);l>16),r=(r&65535)+15*(r>>16)}i=n,t=r},d:function(){return i%=65521,t%=65521,(i&255)<<24|i>>>8<<16|(t&255)<<8|t>>>8}}},pt=function(i,t,e,n,r){return Hi(i,t.level==null?6:t.level,t.mem==null?Math.ceil(Math.max(8,Math.min(13,Math.log(i.length)))*1.5):12+t.mem,e,n,!r)},Gt=function(i,t){var e={};for(var n in i)e[n]=i[n];for(var n in t)e[n]=t[n];return e},Oi=function(i,t,e){for(var n=i(),r=i.toString(),s=r.slice(r.indexOf("[")+1,r.lastIndexOf("]")).replace(/\s+/g,"").split(","),l=0;l>>0},fi=function(i,t){return Y(i,t)+Y(i,t+4)*4294967296},R=function(i,t,e){for(;e;++t)i[t]=e,e>>>=8},di=function(i,t){var e=t.filename;if(i[0]=31,i[1]=139,i[2]=8,i[8]=t.level<2?4:t.level==9?2:0,i[9]=3,t.mtime!=0&&R(i,4,Math.floor(new Date(t.mtime||Date.now())/1e3)),e){i[3]=8;for(var n=0;n<=e.length;++n)i[n+10]=e.charCodeAt(n)}},Ni=function(i){(i[0]!=31||i[1]!=139||i[2]!=8)&&N(6,"invalid gzip data");var t=i[3],e=10;t&4&&(e+=i[10]|(i[11]<<8)+2);for(var n=(t>>3&1)+(t>>4&1);n>0;n-=!i[e++]);return e+(t&2)},ie=function(i){var t=i.length;return(i[t-4]|i[t-3]<<8|i[t-2]<<16|i[t-1]<<24)>>>0},Ei=function(i){return 10+(i.filename&&i.filename.length+1||0)},_i=function(i,t){var e=t.level,n=e==0?0:e<6?1:e==9?3:2;i[0]=120,i[1]=n<<6|(n?32-2*n:1)},ee=function(i){((i[0]&15)!=8||i[0]>>>4>7||(i[0]<<8|i[1])%31)&&N(6,"invalid zlib data"),i[1]&32&&N(6,"invalid zlib data: preset dictionaries not supported")};function Fi(i,t){return!t&&typeof i=="function"&&(t=i,i={}),this.ondata=t,i}var ot=function(){function i(t,e){!e&&typeof t=="function"&&(e=t,t={}),this.ondata=e,this.o=t||{}}return i.prototype.p=function(t,e){this.ondata(pt(t,this.o,0,0,!e),e)},i.prototype.push=function(t,e){this.ondata||N(5),this.d&&N(4),this.d=e,this.p(t,e||!1)},i}();_.Deflate=ot;var ne=function(){function i(t,e){wt([xt,function(){return[nt,ot]}],this,Fi.call(this,t,e),function(n){var r=new ot(n.data);onmessage=nt(r)},6)}return i}();_.AsyncDeflate=ne;function se(i,t,e){return e||(e=t,t={}),typeof e!="function"&&N(7),St(i,t,[xt],function(n){return It(Lt(n.data[0],n.data[1]))},0,e)}_.deflate=se;function Lt(i,t){return pt(i,t||{},0,0)}_.deflateSync=Lt;var W=function(){function i(t){this.s={},this.p=new M(0),this.ondata=t}return i.prototype.e=function(t){this.ondata||N(5),this.d&&N(4);var e=this.p.length,n=new M(e+t.length);n.set(this.p),n.set(t,e),this.p=n},i.prototype.c=function(t){this.d=this.s.i=t||!1;var e=this.s.b,n=Pt(this.p,this.o,this.s);this.ondata(et(n,e,this.s.b),this.d),this.o=et(n,this.s.b-32768),this.s.b=this.o.length,this.p=et(this.p,this.s.p/8|0),this.s.p&=7},i.prototype.push=function(t,e){this.e(t),this.c(e)},i}();_.Inflate=W;var yi=function(){function i(t){this.ondata=t,wt([Ut,function(){return[nt,W]}],this,0,function(){var e=new W;onmessage=nt(e)},7)}return i}();_.AsyncInflate=yi;function Ai(i,t,e){return e||(e=t,t={}),typeof e!="function"&&N(7),St(i,t,[Ut],function(n){return It(Ct(n.data[0],mi(n.data[1])))},1,e)}_.inflate=Ai;function Ct(i,t){return Pt(i,t)}_.inflateSync=Ct;var Jt=function(){function i(t,e){this.c=At(),this.l=0,this.v=1,ot.call(this,t,e)}return i.prototype.push=function(t,e){ot.prototype.push.call(this,t,e)},i.prototype.p=function(t,e){this.c.p(t),this.l+=t.length;var n=pt(t,this.o,this.v&&Ei(this.o),e&&8,!e);this.v&&(di(n,this.o),this.v=0),e&&(R(n,n.length-8,this.c.d()),R(n,n.length-4,this.l)),this.ondata(n,e)},i}();_.Gzip=Jt;_.Compress=Jt;var re=function(){function i(t,e){wt([xt,$i,function(){return[nt,ot,Jt]}],this,Fi.call(this,t,e),function(n){var r=new Jt(n.data);onmessage=nt(r)},8)}return i}();_.AsyncGzip=re;_.AsyncCompress=re;function ae(i,t,e){return e||(e=t,t={}),typeof e!="function"&&N(7),St(i,t,[xt,$i,function(){return[ti]}],function(n){return It(ti(n.data[0],n.data[1]))},2,e)}_.gzip=ae;_.compress=ae;function ti(i,t){t||(t={});var e=At(),n=i.length;e.p(i);var r=pt(i,t,Ei(t),8),s=r.length;return di(r,t),R(r,s-8,e.d()),R(r,s-4,n),r}_.gzipSync=ti;_.compressSync=ti;var ii=function(){function i(t){this.v=1,W.call(this,t)}return i.prototype.push=function(t,e){if(W.prototype.e.call(this,t),this.v){var n=this.p.length>3?Ni(this.p):4;if(n>=this.p.length&&!e)return;this.p=this.p.subarray(n),this.v=0}e&&(this.p.length<8&&N(6,"invalid gzip data"),this.p=this.p.subarray(0,-8)),W.prototype.c.call(this,e)},i}();_.Gunzip=ii;var oe=function(){function i(t){this.ondata=t,wt([Ut,Wi,function(){return[nt,W,ii]}],this,0,function(){var e=new ii;onmessage=nt(e)},9)}return i}();_.AsyncGunzip=oe;function le(i,t,e){return e||(e=t,t={}),typeof e!="function"&&N(7),St(i,t,[Ut,Wi,function(){return[ei]}],function(n){return It(ei(n.data[0]))},3,e)}_.gunzip=le;function ei(i,t){return Pt(i.subarray(Ni(i),-8),t||new M(ie(i)))}_.gunzipSync=ei;var Ii=function(){function i(t,e){this.c=Ti(),this.v=1,ot.call(this,t,e)}return i.prototype.push=function(t,e){ot.prototype.push.call(this,t,e)},i.prototype.p=function(t,e){this.c.p(t);var n=pt(t,this.o,this.v&&2,e&&4,!e);this.v&&(_i(n,this.o),this.v=0),e&&R(n,n.length-4,this.c.d()),this.ondata(n,e)},i}();_.Zlib=Ii;var Se=function(){function i(t,e){wt([xt,Ji,function(){return[nt,ot,Ii]}],this,Fi.call(this,t,e),function(n){var r=new Ii(n.data);onmessage=nt(r)},10)}return i}();_.AsyncZlib=Se;function we(i,t,e){return e||(e=t,t={}),typeof e!="function"&&N(7),St(i,t,[xt,Ji,function(){return[vi]}],function(n){return It(vi(n.data[0],n.data[1]))},4,e)}_.zlib=we;function vi(i,t){t||(t={});var e=Ti();e.p(i);var n=pt(i,t,2,4);return _i(n,t),R(n,n.length-4,e.d()),n}_.zlibSync=vi;var ni=function(){function i(t){this.v=1,W.call(this,t)}return i.prototype.push=function(t,e){if(W.prototype.e.call(this,t),this.v){if(this.p.length<2&&!e)return;this.p=this.p.subarray(2),this.v=0}e&&(this.p.length<4&&N(6,"invalid zlib data"),this.p=this.p.subarray(0,-4)),W.prototype.c.call(this,e)},i}();_.Unzlib=ni;var fe=function(){function i(t){this.ondata=t,wt([Ut,te,function(){return[nt,W,ni]}],this,0,function(){var e=new ni;onmessage=nt(e)},11)}return i}();_.AsyncUnzlib=fe;function he(i,t,e){return e||(e=t,t={}),typeof e!="function"&&N(7),St(i,t,[Ut,te,function(){return[si]}],function(n){return It(si(n.data[0],mi(n.data[1])))},5,e)}_.unzlib=he;function si(i,t){return Pt((ee(i),i.subarray(2,-4)),t)}_.unzlibSync=si;var ue=function(){function i(t){this.G=ii,this.I=W,this.Z=ni,this.ondata=t}return i.prototype.push=function(t,e){if(this.ondata||N(5),this.s)this.s.push(t,e);else{if(this.p&&this.p.length){var n=new M(this.p.length+t.length);n.set(this.p),n.set(t,this.p.length)}else this.p=t;if(this.p.length>2){var r=this,s=function(){r.ondata.apply(r,arguments)};this.s=this.p[0]==31&&this.p[1]==139&&this.p[2]==8?new this.G(s):(this.p[0]&15)!=8||this.p[0]>>4>7||(this.p[0]<<8|this.p[1])%31?new this.I(s):new this.Z(s),this.s.push(this.p,e),this.p=null}}},i}();_.Decompress=ue;var Ce=function(){function i(t){this.G=oe,this.I=yi,this.Z=fe,this.ondata=t}return i.prototype.push=function(t,e){ue.prototype.push.call(this,t,e)},i}();_.AsyncDecompress=Ce;function Me(i,t,e){return e||(e=t,t={}),typeof e!="function"&&N(7),i[0]==31&&i[1]==139&&i[2]==8?le(i,t,e):(i[0]&15)!=8||i[0]>>4>7||(i[0]<<8|i[1])%31?Ai(i,t,e):he(i,t,e)}_.decompress=Me;function ze(i,t){return i[0]==31&&i[1]==139&&i[2]==8?ei(i,t):(i[0]&15)!=8||i[0]>>4>7||(i[0]<<8|i[1])%31?Ct(i,t):si(i,t)}_.decompressSync=ze;var Ui=function(i,t,e,n){for(var r in i){var s=i[r],l=t+r,a=n;Array.isArray(s)&&(a=Gt(n,s[1]),s=s[0]),s instanceof M?e[l]=[s,a]:(e[l+="/"]=[new M(0),a],Ui(s,l,e,n))}},Pi=typeof TextEncoder<"u"&&new TextEncoder,pi=typeof TextDecoder<"u"&&new TextDecoder,ce=0;try{pi.decode(ft,{stream:!0}),ce=1}catch{}var Ie=function(i){for(var t="",e=0;;){var n=i[e++],r=(n>127)+(n>223)+(n>239);if(e+r>i.length)return[t,et(i,e-1)];r?r==3?(n=((n&15)<<18|(i[e++]&63)<<12|(i[e++]&63)<<6|i[e++]&63)-65536,t+=String.fromCharCode(55296|n>>10,56320|n&1023)):r&1?t+=String.fromCharCode((n&31)<<6|i[e++]&63):t+=String.fromCharCode((n&15)<<12|(i[e++]&63)<<6|i[e++]&63):t+=String.fromCharCode(n)}},De=function(){function i(t){this.ondata=t,ce?this.t=new TextDecoder:this.p=ft}return i.prototype.push=function(t,e){if(this.ondata||N(5),e=!!e,this.t){this.ondata(this.t.decode(t,{stream:!0}),e),e&&(this.t.decode().length&&N(8),this.t=null);return}this.p||N(4);var n=new M(this.p.length+t.length);n.set(this.p),n.set(t,this.p.length);var r=Ie(n),s=r[0],l=r[1];e?(l.length&&N(8),this.p=null):this.p=l,this.ondata(s,e)},i}();_.DecodeUTF8=De;var qe=function(){function i(t){this.ondata=t}return i.prototype.push=function(t,e){this.ondata||N(5),this.d&&N(4),this.ondata(ct(t),this.d=e||!1)},i}();_.EncodeUTF8=qe;function ct(i,t){if(t){for(var e=new M(i.length),n=0;n>1)),l=0,a=function(o){s[l++]=o},n=0;ns.length){var h=new M(l+8+(r-n<<1));h.set(s),s=h}var f=i.charCodeAt(n);f<128||t?a(f):f<2048?(a(192|f>>6),a(128|f&63)):f>55295&&f<57344?(f=65536+(f&1023<<10)|i.charCodeAt(++n)&1023,a(240|f>>18),a(128|f>>12&63),a(128|f>>6&63),a(128|f&63)):(a(224|f>>12),a(128|f>>6&63),a(128|f&63))}return et(s,0,l)}_.strToU8=ct;function xi(i,t){if(t){for(var e="",n=0;n65535&&N(9),t+=n+4}return t},Et=function(i,t,e,n,r,s,l,a){var h=n.length,f=e.extra,o=a&&a.length,c=ut(f);R(i,t,l!=null?33639248:67324752),t+=4,l!=null&&(i[t++]=20,i[t++]=e.os),i[t]=20,t+=2,i[t++]=e.flag<<1|(s==null&&8),i[t++]=r&&8,i[t++]=e.compression&255,i[t++]=e.compression>>8;var p=new Date(e.mtime==null?Date.now():e.mtime),m=p.getFullYear()-1980;if((m<0||m>119)&&N(10),R(i,t,m<<25|p.getMonth()+1<<21|p.getDate()<<16|p.getHours()<<11|p.getMinutes()<<5|p.getSeconds()>>>1),t+=4,s!=null&&(R(i,t,e.crc),R(i,t+4,s),R(i,t+8,e.size)),R(i,t+12,h),R(i,t+14,c),t+=16,l!=null&&(R(i,t,o),R(i,t+6,e.attrs),R(i,t+10,l),t+=14),i.set(n,t),t+=h,c)for(var g in f){var d=f[g],v=d.length;R(i,t,+g),R(i,t+2,v),i.set(d,t+4),t+=4+v}return o&&(i.set(a,t),t+=o),t},Si=function(i,t,e,n,r){R(i,t,101010256),R(i,t+8,e),R(i,t+10,e),R(i,t+12,n),R(i,t+16,r)},Bt=function(){function i(t){this.filename=t,this.c=At(),this.size=0,this.compression=0}return i.prototype.process=function(t,e){this.ondata(null,t,e)},i.prototype.push=function(t,e){this.ondata||N(5),this.c.p(t),this.size+=t.length,e&&(this.crc=this.c.d()),this.process(t,e||!1)},i}();_.ZipPassThrough=Bt;var Be=function(){function i(t,e){var n=this;e||(e={}),Bt.call(this,t),this.d=new ot(e,function(r,s){n.ondata(null,r,s)}),this.compression=8,this.flag=ve(e.level)}return i.prototype.process=function(t,e){try{this.d.push(t,e)}catch(n){this.ondata(n,null,e)}},i.prototype.push=function(t,e){Bt.prototype.push.call(this,t,e)},i}();_.ZipDeflate=Be;var Oe=function(){function i(t,e){var n=this;e||(e={}),Bt.call(this,t),this.d=new ne(e,function(r,s,l){n.ondata(r,s,l)}),this.compression=8,this.flag=ve(e.level),this.terminate=this.d.terminate}return i.prototype.process=function(t,e){this.d.push(t,e)},i.prototype.push=function(t,e){Bt.prototype.push.call(this,t,e)},i}();_.AsyncZipDeflate=Oe;var Pe=function(){function i(t){this.ondata=t,this.u=[],this.d=1}return i.prototype.add=function(t){var e=this;if(this.ondata||N(5),this.d&2)this.ondata(N(4+(this.d&1)*8,0,1),null,!1);else{var n=ct(t.filename),r=n.length,s=t.comment,l=s&&ct(s),a=r!=t.filename.length||l&&s.length!=l.length,h=r+ut(t.extra)+30;r>65535&&this.ondata(N(11,0,1),null,!1);var f=new M(h);Et(f,0,t,n,a);var o=[f],c=function(){for(var v=0,E=o;v65535&&w(N(11,0,1),null),!q)w(null,x);else if(z<16e4)try{w(null,Lt(x,y))}catch(O){w(O,null)}else o.push(se(x,y,w))},d=0;d65535&&N(11);var E=o?Lt(h,f):h,A=E.length,x=At();x.p(h),n.push(Gt(f,{size:h.length,crc:x.d(),c:E,f:c,m:g,u:p!=l.length||g&&m.length!=d,o:r,compression:o})),r+=30+p+v+A,s+=76+2*(p+v)+(d||0)+A}for(var y=new M(s+22),L=r,z=s-r,U=0;U0){var r=Math.min(this.c,t.length),s=t.subarray(0,r);if(this.c-=r,this.d?this.d.push(s,!this.c):this.k[0].push(s),t=t.subarray(r),t.length)return this.push(t,e)}else{var l=0,a=0,h=void 0,f=void 0;this.p.length?t.length?(f=new M(this.p.length+t.length),f.set(this.p),f.set(t,this.p.length)):f=this.p:f=t;for(var o=f.length,c=this.c,p=c&&this.d,m=function(){var E,A=Y(f,a);if(A==67324752){l=1,h=a,g.d=null,g.c=0;var x=Q(f,a+6),y=Q(f,a+8),L=x&2048,z=x&8,U=Q(f,a+26),T=Q(f,a+28);if(o>a+30+U+T){var Z=[];g.k.unshift(Z),l=2;var C=Y(f,a+18),b=Y(f,a+22),S=xi(f.subarray(a+30,a+=30+U),!L);C==4294967295?(E=z?[-2]:Te(f,a),C=E[0],b=E[1]):z&&(C=-1),a+=T,g.c=C;var q,w={name:S,compression:y,start:function(){if(w.ondata||N(5),!C)w.ondata(null,ft,!0);else{var O=n.o[y];O||w.ondata(N(14,"unknown compression type "+y,1),null,!1),q=C<0?new O(S):new O(S,C,b),q.ondata=function(j,J,K){w.ondata(j,J,K)};for(var D=0,B=Z;D=0&&(w.size=C,w.originalSize=b),g.onfile(w)}return"break"}else if(c){if(A==134695760)return h=a+=12+(c==-2&&8),l=3,g.c=0,"break";if(A==33639248)return h=a-=4,l=3,g.c=0,"break"}},g=this;a65558)return l(N(13,0,1),null),r;var h=Q(i,a+8);if(h){var f=h,o=Y(i,a+16),c=o==4294967295;if(c){if(a=Y(i,a-12),Y(i,a)!=101075792)return l(N(13,0,1),null),r;f=h=Y(i,a+32),o=Y(i,a+48)}for(var p=t&&t.filter,m=function(d){var v=ge(i,o,c),E=v[0],A=v[1],x=v[2],y=v[3],L=v[4],z=v[5],U=pe(i,z);o=L;var T=function(C,b){C?(r(),l(C,null)):(b&&(s[y]=b),--h||l(null,s))};if(!p||p({name:y,size:A,originalSize:x,compression:E}))if(!E)T(null,et(i,U,U+A));else if(E==8){var Z=i.subarray(U,U+A);if(A<32e4)try{T(null,Ct(Z,new M(x)))}catch(C){T(C,null)}else n.push(Ai(Z,{size:x},T))}else T(N(14,"unknown compression type "+E,1),null);else T(null,null)},g=0;g65558)&&N(13);var r=Q(i,n+8);if(!r)return{};var s=Y(i,n+16),l=s==4294967295;l&&(n=Y(i,n-12),Y(i,n)!=101075792&&N(13),r=Y(i,n+32),s=Y(i,n+48));for(var a=t&&t.filter,h=0;h{var F=F||{};F.NIFTI1=F.NIFTI1||(typeof H<"u"?li():null);F.NIFTI2=F.NIFTI2||(typeof H<"u"?zi():null);F.NIFTIEXTENSION=F.NIFTIEXTENSION||(typeof H<"u"?Tt():null);F.Utils=F.Utils||(typeof H<"u"?kt():null);var Ne=Ne||(typeof H<"u"?de():null);F.isNIFTI1=function(i,t=!1){var e,n,r,s;return i.byteLength{var Di=Object.defineProperty;var Oi=(i,t,e)=>t in i?Di(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var It=(i,t)=>()=>(t||i((t={exports:{}}).exports,t),t.exports);var E=(i,t,e)=>(Oi(i,typeof t!="symbol"?t+"":t,e),e);var ke=It(Ye=>{"use strict";var Ze={};Ye.default=function(i,t,e,n,r){var a=new Worker(Ze[t]||(Ze[t]=URL.createObjectURL(new Blob([i+';addEventListener("error",function(e){e=e.error;postMessage({$e$:[e.message,e.code,e.stack]})})'],{type:"text/javascript"}))));return a.onmessage=function(s){var l=s.data,o=l.$e$;if(o){var f=new Error(o[0]);f.code=o[1],f.stack=o[2],r(f,null)}else r(null,l)},a.postMessage(e,n),a}});var wi=It(I=>{"use strict";var qi=ke(),D=Uint8Array,K=Uint16Array,wt=Uint32Array,Ct=new D([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),Nt=new D([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),Gt=new D([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Ve=function(i,t){for(var e=new K(31),n=0;n<31;++n)e[n]=t+=1<>>1|(L&21845)<<1,vt=(vt&52428)>>>2|(vt&13107)<<2,vt=(vt&61680)>>>4|(vt&3855)<<4,Lt[L]=((vt&65280)>>>8|(vt&255)<<8)>>>1;var vt,L,nt=function(i,t,e){for(var n=i.length,r=0,a=new K(t);r>>o]=f}else for(l=new K(n),r=0;r>>15-i[r]);return l},pt=new D(288);for(L=0;L<144;++L)pt[L]=8;var L;for(L=144;L<256;++L)pt[L]=9;var L;for(L=256;L<280;++L)pt[L]=7;var L;for(L=280;L<288;++L)pt[L]=8;var L,Tt=new D(32);for(L=0;L<32;++L)Tt[L]=5;var L,$e=nt(pt,9,0),We=nt(pt,9,1),Je=nt(Tt,5,0),ti=nt(Tt,5,1),Kt=function(i){for(var t=i[0],e=1;et&&(t=i[e]);return t},it=function(i,t,e){var n=t/8|0;return(i[n]|i[n+1]<<8)>>(t&7)&e},Qt=function(i,t){var e=t/8|0;return(i[e]|i[e+1]<<8|i[e+2]<<16)>>(t&7)},Zt=function(i){return(i+7)/8|0},rt=function(i,t,e){(t==null||t<0)&&(t=0),(e==null||e>i.length)&&(e=i.length);var n=new(i.BYTES_PER_ELEMENT==2?K:i.BYTES_PER_ELEMENT==4?wt:D)(e-t);return n.set(i.subarray(t,e)),n};I.FlateErrorCode={UnexpectedEOF:0,InvalidBlockType:1,InvalidLengthLiteral:2,InvalidDistance:3,StreamFinished:4,NoStreamHandler:5,InvalidHeader:6,NoCallback:7,InvalidUTF8:8,ExtraFieldTooLong:9,InvalidDate:10,FilenameTooLong:11,StreamFinishing:12,InvalidZipData:13,UnknownCompressionMethod:14};var ei=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],_=function(i,t,e){var n=new Error(t||ei[i]);if(n.code=i,Error.captureStackTrace&&Error.captureStackTrace(n,_),!e)throw n;return n},Yt=function(i,t,e){var n=i.length;if(!n||e&&e.f&&!e.l)return t||new D(0);var r=!t||e,a=!e||e.i;e||(e={}),t||(t=new D(n*3));var s=function(Vt){var bt=t.length;if(Vt>bt){var xt=new D(Math.max(bt*2,Vt));xt.set(t),t=xt}},l=e.f||0,o=e.p||0,f=e.b||0,u=e.l,h=e.d,v=e.m,m=e.n,g=n*8;do{if(!u){l=it(i,o,1);var p=it(i,o+1,3);if(o+=3,p)if(p==1)u=We,h=ti,v=9,m=5;else if(p==2){var T=it(i,o,31)+257,x=it(i,o+10,15)+4,R=T+it(i,o+5,31)+1;o+=14;for(var q=new D(R),M=new D(19),d=0;d>>4;if(c<16)q[d++]=c;else{var w=0,F=0;for(c==16?(F=3+it(i,o,3),o+=2,w=q[d-1]):c==17?(F=3+it(i,o,7),o+=3):c==18&&(F=11+it(i,o,127),o+=7);F--;)q[d++]=w}}var G=q.subarray(0,T),B=q.subarray(T);v=Kt(G),m=Kt(B),u=nt(G,v,1),h=nt(B,m,1)}else _(1);else{var c=Zt(o)+4,y=i[c-4]|i[c-3]<<8,A=c+y;if(A>n){a&&_(0);break}r&&s(f+y),t.set(i.subarray(c,A),f),e.b=f+=y,e.p=o=A*8,e.f=l;continue}if(o>g){a&&_(0);break}}r&&s(f+131072);for(var P=(1<>>4;if(o+=w&15,o>g){a&&_(0);break}if(w||_(2),et<256)t[f++]=et;else if(et==256){X=o,u=null;break}else{var Q=et-254;if(et>264){var d=et-257,ot=Ct[d];Q=it(i,o,(1<>>4;ft||_(3),o+=ft&15;var B=Qe[W];if(W>3){var ot=Nt[W];B+=Qt(i,o)&(1<g){a&&_(0);break}r&&s(f+131072);for(var H=f+Q;f>>8},Ut=function(i,t,e){e<<=t&7;var n=t/8|0;i[n]|=e,i[n+1]|=e>>>8,i[n+2]|=e>>>16},$t=function(i,t){for(var e=[],n=0;nv&&(v=a[n].s);var m=new K(v+1),g=Jt(e[u-1],m,0);if(g>t){var n=0,p=0,c=g-t,y=1<t)p+=y-(1<>>=c;p>0;){var T=a[n].s;m[T]=0&&p;--n){var x=a[n].s;m[x]==t&&(--m[x],++p)}g=t}return[new D(m),g]},Jt=function(i,t,e){return i.s==-1?Math.max(Jt(i.l,t,e+1),Jt(i.r,t,e+1)):t[i.s]=e},de=function(i){for(var t=i.length;t&&!i[--t];);for(var e=new K(++t),n=0,r=i[0],a=1,s=function(o){e[n++]=o},l=1;l<=t;++l)if(i[l]==r&&l!=t)++a;else{if(!r&&a>2){for(;a>138;a-=138)s(32754);a>2&&(s(a>10?a-11<<5|28690:a-3<<5|12305),a=0)}else if(a>3){for(s(r),--a;a>6;a-=6)s(8304);a>2&&(s(a-3<<5|8208),a=0)}for(;a--;)s(r);a=1,r=i[l]}return[e.subarray(0,n),t]},St=function(i,t){for(var e=0,n=0;n>>8,i[r+2]=i[r]^255,i[r+3]=i[r+1]^255;for(var a=0;a4&&!N[Gt[z-1]];--z);var w=f+5<<3,F=St(r,pt)+St(a,Tt)+s,G=St(r,v)+St(a,p)+s+14+3*z+St(M,N)+(2*M[16]+3*M[17]+7*M[18]);if(w<=F&&w<=G)return te(t,u,i.subarray(o,o+f));var B,P,k,X;if(ht(t,u,1+(G15&&(ht(t,u,ft[d]>>>5&127),u+=ft[d]>>>12)}}else B=$e,P=pt,k=Je,X=Tt;for(var d=0;d255){var W=n[d]>>>18&31;Ut(t,u,B[W+257]),u+=P[W+257],W>7&&(ht(t,u,n[d]>>>23&31),u+=Ct[W]);var H=n[d]&31;Ut(t,u,k[H]),u+=X[H],H>3&&(Ut(t,u,n[d]>>>5&8191),u+=Nt[H])}else Ut(t,u,B[n[d]]),u+=P[n[d]];return Ut(t,u,B[256]),u+P[256]},ii=new wt([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),gt=new D(0),ni=function(i,t,e,n,r,a){var s=i.length,l=new D(n+s+5*(1+Math.ceil(s/7e3))+r),o=l.subarray(n,l.length-r),f=0;if(!t||s<8)for(var u=0;u<=s;u+=65535){var h=u+65535;h>=s&&(o[f>>3]=a),f=te(o,f+1,i.subarray(u,h))}else{for(var v=ii[t-1],m=v>>>13,g=v&8191,p=(1<7e3||N>24576)&&B>423){f=me(i,o,0,R,q,M,Y,N,z,u-z,f),N=d=Y=0,z=u;for(var P=0;P<286;++P)q[P]=0;for(var P=0;P<30;++P)M[P]=0}var k=2,X=0,et=g,Q=F-G&32767;if(B>2&&w==x(u-Q))for(var ot=Math.min(m,B)-1,ft=Math.min(32767,u),W=Math.min(258,B);Q<=ft&&--et&&F!=G;){if(i[u+k]==i[u+k-Q]){for(var H=0;Hk){if(k=H,X=Q,H>ot)break;for(var Vt=Math.min(Q,H-2),bt=0,P=0;Pbt&&(bt=Ge,G=xt)}}}F=G,G=c[F],Q+=F-G+32768&32767}if(X){R[N++]=268435456|Wt[k]<<18|pe[X];var Le=Wt[k]&31,Re=pe[X]&31;Y+=Ct[Le]+Nt[Re],++q[257+Le],++M[Re],V=u+k,++d}else R[N++]=i[u],++q[i[u]]}}f=me(i,o,a,R,q,M,Y,N,z,u-z,f),!a&&f&7&&(f=te(o,f+1,gt))}return rt(l,0,n+Zt(f)+r)},ri=function(){for(var i=new Int32Array(256),t=0;t<256;++t){for(var e=t,n=9;--n;)e=(e&1&&-306674912)^e>>>1;i[t]=e}return i}(),Ft=function(){var i=-1;return{p:function(t){for(var e=i,n=0;n>>8;i=e},d:function(){return~i}}},Ae=function(){var i=1,t=0;return{p:function(e){for(var n=i,r=t,a=e.length|0,s=0;s!=a;){for(var l=Math.min(s+2655,a);s>16),r=(r&65535)+15*(r>>16)}i=n,t=r},d:function(){return i%=65521,t%=65521,(i&255)<<24|i>>>8<<16|(t&255)<<8|t>>>8}}},yt=function(i,t,e,n,r){return ni(i,t.level==null?6:t.level,t.mem==null?Math.ceil(Math.max(8,Math.min(13,Math.log(i.length)))*1.5):12+t.mem,e,n,!r)},kt=function(i,t){var e={};for(var n in i)e[n]=i[n];for(var n in t)e[n]=t[n];return e},Xe=function(i,t,e){for(var n=i(),r=i.toString(),a=r.slice(r.indexOf("[")+1,r.lastIndexOf("]")).replace(/\s+/g,"").split(","),s=0;s>>0},ge=function(i,t){return j(i,t)+j(i,t+4)*4294967296},Z=function(i,t,e){for(;e;++t)i[t]=e,e>>>=8},Ue=function(i,t){var e=t.filename;if(i[0]=31,i[1]=139,i[2]=8,i[8]=t.level<2?4:t.level==9?2:0,i[9]=3,t.mtime!=0&&Z(i,4,Math.floor(new Date(t.mtime||Date.now())/1e3)),e){i[3]=8;for(var n=0;n<=e.length;++n)i[n+10]=e.charCodeAt(n)}},Se=function(i){(i[0]!=31||i[1]!=139||i[2]!=8)&&_(6,"invalid gzip data");var t=i[3],e=10;t&4&&(e+=i[10]|(i[11]<<8)+2);for(var n=(t>>3&1)+(t>>4&1);n>0;n-=!i[e++]);return e+(t&2)},hi=function(i){var t=i.length;return(i[t-4]|i[t-3]<<8|i[t-2]<<16|i[t-1]<<24)>>>0},Te=function(i){return 10+(i.filename&&i.filename.length+1||0)},Me=function(i,t){var e=t.level,n=e==0?0:e<6?1:e==9?3:2;i[0]=120,i[1]=n<<6|(n?32-2*n:1)},ui=function(i){((i[0]&15)!=8||i[0]>>>4>7||(i[0]<<8|i[1])%31)&&_(6,"invalid zlib data"),i[1]&32&&_(6,"invalid zlib data: preset dictionaries not supported")};function we(i,t){return!t&&typeof i=="function"&&(t=i,i={}),this.ondata=t,i}var ut=function(){function i(t,e){!e&&typeof t=="function"&&(e=t,t={}),this.ondata=e,this.o=t||{}}return i.prototype.p=function(t,e){this.ondata(yt(t,this.o,0,0,!e),e)},i.prototype.push=function(t,e){this.ondata||_(5),this.d&&_(4),this.d=e,this.p(t,e||!1)},i}();I.Deflate=ut;var ci=function(){function i(t,e){qt([Dt,function(){return[st,ut]}],this,we.call(this,t,e),function(n){var r=new ut(n.data);onmessage=st(r)},6)}return i}();I.AsyncDeflate=ci;function vi(i,t,e){return e||(e=t,t={}),typeof e!="function"&&_(7),Ot(i,t,[Dt],function(n){return _t(Xt(n.data[0],n.data[1]))},0,e)}I.deflate=vi;function Xt(i,t){return yt(i,t||{},0,0)}I.deflateSync=Xt;var J=function(){function i(t){this.s={},this.p=new D(0),this.ondata=t}return i.prototype.e=function(t){this.ondata||_(5),this.d&&_(4);var e=this.p.length,n=new D(e+t.length);n.set(this.p),n.set(t,e),this.p=n},i.prototype.c=function(t){this.d=this.s.i=t||!1;var e=this.s.b,n=Yt(this.p,this.o,this.s);this.ondata(rt(n,e,this.s.b),this.d),this.o=rt(n,this.s.b-32768),this.s.b=this.o.length,this.p=rt(this.p,this.s.p/8|0),this.s.p&=7},i.prototype.push=function(t,e){this.e(t),this.c(e)},i}();I.Inflate=J;var Ce=function(){function i(t){this.ondata=t,qt([zt,function(){return[st,J]}],this,0,function(){var e=new J;onmessage=st(e)},7)}return i}();I.AsyncInflate=Ce;function Ne(i,t,e){return e||(e=t,t={}),typeof e!="function"&&_(7),Ot(i,t,[zt],function(n){return _t(Bt(n.data[0],xe(n.data[1])))},1,e)}I.inflate=Ne;function Bt(i,t){return Yt(i,t)}I.inflateSync=Bt;var ee=function(){function i(t,e){this.c=Ft(),this.l=0,this.v=1,ut.call(this,t,e)}return i.prototype.push=function(t,e){ut.prototype.push.call(this,t,e)},i.prototype.p=function(t,e){this.c.p(t),this.l+=t.length;var n=yt(t,this.o,this.v&&Te(this.o),e&&8,!e);this.v&&(Ue(n,this.o),this.v=0),e&&(Z(n,n.length-8,this.c.d()),Z(n,n.length-4,this.l)),this.ondata(n,e)},i}();I.Gzip=ee;I.Compress=ee;var gi=function(){function i(t,e){qt([Dt,ai,function(){return[st,ut,ee]}],this,we.call(this,t,e),function(n){var r=new ee(n.data);onmessage=st(r)},8)}return i}();I.AsyncGzip=gi;I.AsyncCompress=gi;function pi(i,t,e){return e||(e=t,t={}),typeof e!="function"&&_(7),Ot(i,t,[Dt,ai,function(){return[ie]}],function(n){return _t(ie(n.data[0],n.data[1]))},2,e)}I.gzip=pi;I.compress=pi;function ie(i,t){t||(t={});var e=Ft(),n=i.length;e.p(i);var r=yt(i,t,Te(t),8),a=r.length;return Ue(r,t),Z(r,a-8,e.d()),Z(r,a-4,n),r}I.gzipSync=ie;I.compressSync=ie;var ne=function(){function i(t){this.v=1,J.call(this,t)}return i.prototype.push=function(t,e){if(J.prototype.e.call(this,t),this.v){var n=this.p.length>3?Se(this.p):4;if(n>=this.p.length&&!e)return;this.p=this.p.subarray(n),this.v=0}e&&(this.p.length<8&&_(6,"invalid gzip data"),this.p=this.p.subarray(0,-8)),J.prototype.c.call(this,e)},i}();I.Gunzip=ne;var di=function(){function i(t){this.ondata=t,qt([zt,oi,function(){return[st,J,ne]}],this,0,function(){var e=new ne;onmessage=st(e)},9)}return i}();I.AsyncGunzip=di;function mi(i,t,e){return e||(e=t,t={}),typeof e!="function"&&_(7),Ot(i,t,[zt,oi,function(){return[re]}],function(n){return _t(re(n.data[0]))},3,e)}I.gunzip=mi;function re(i,t){return Yt(i.subarray(Se(i),-8),t||new D(hi(i)))}I.gunzipSync=re;var _e=function(){function i(t,e){this.c=Ae(),this.v=1,ut.call(this,t,e)}return i.prototype.push=function(t,e){ut.prototype.push.call(this,t,e)},i.prototype.p=function(t,e){this.c.p(t);var n=yt(t,this.o,this.v&&2,e&&4,!e);this.v&&(Me(n,this.o),this.v=0),e&&Z(n,n.length-4,this.c.d()),this.ondata(n,e)},i}();I.Zlib=_e;var Pi=function(){function i(t,e){qt([Dt,li,function(){return[st,ut,_e]}],this,we.call(this,t,e),function(n){var r=new _e(n.data);onmessage=st(r)},10)}return i}();I.AsyncZlib=Pi;function bi(i,t,e){return e||(e=t,t={}),typeof e!="function"&&_(7),Ot(i,t,[Dt,li,function(){return[Ee]}],function(n){return _t(Ee(n.data[0],n.data[1]))},4,e)}I.zlib=bi;function Ee(i,t){t||(t={});var e=Ae();e.p(i);var n=yt(i,t,2,4);return Me(n,t),Z(n,n.length-4,e.d()),n}I.zlibSync=Ee;var se=function(){function i(t){this.v=1,J.call(this,t)}return i.prototype.push=function(t,e){if(J.prototype.e.call(this,t),this.v){if(this.p.length<2&&!e)return;this.p=this.p.subarray(2),this.v=0}e&&(this.p.length<4&&_(6,"invalid zlib data"),this.p=this.p.subarray(0,-4)),J.prototype.c.call(this,e)},i}();I.Unzlib=se;var _i=function(){function i(t){this.ondata=t,qt([zt,fi,function(){return[st,J,se]}],this,0,function(){var e=new se;onmessage=st(e)},11)}return i}();I.AsyncUnzlib=_i;function Ei(i,t,e){return e||(e=t,t={}),typeof e!="function"&&_(7),Ot(i,t,[zt,fi,function(){return[ae]}],function(n){return _t(ae(n.data[0],xe(n.data[1])))},5,e)}I.unzlib=Ei;function ae(i,t){return Yt((ui(i),i.subarray(2,-4)),t)}I.unzlibSync=ae;var Ii=function(){function i(t){this.G=ne,this.I=J,this.Z=se,this.ondata=t}return i.prototype.push=function(t,e){if(this.ondata||_(5),this.s)this.s.push(t,e);else{if(this.p&&this.p.length){var n=new D(this.p.length+t.length);n.set(this.p),n.set(t,this.p.length)}else this.p=t;if(this.p.length>2){var r=this,a=function(){r.ondata.apply(r,arguments)};this.s=this.p[0]==31&&this.p[1]==139&&this.p[2]==8?new this.G(a):(this.p[0]&15)!=8||this.p[0]>>4>7||(this.p[0]<<8|this.p[1])%31?new this.I(a):new this.Z(a),this.s.push(this.p,e),this.p=null}}},i}();I.Decompress=Ii;var Gi=function(){function i(t){this.G=di,this.I=Ce,this.Z=_i,this.ondata=t}return i.prototype.push=function(t,e){Ii.prototype.push.call(this,t,e)},i}();I.AsyncDecompress=Gi;function Li(i,t,e){return e||(e=t,t={}),typeof e!="function"&&_(7),i[0]==31&&i[1]==139&&i[2]==8?mi(i,t,e):(i[0]&15)!=8||i[0]>>4>7||(i[0]<<8|i[1])%31?Ne(i,t,e):Ei(i,t,e)}I.decompress=Li;function Ri(i,t){return i[0]==31&&i[1]==139&&i[2]==8?re(i,t):(i[0]&15)!=8||i[0]>>4>7||(i[0]<<8|i[1])%31?Bt(i,t):ae(i,t)}I.decompressSync=Ri;var Fe=function(i,t,e,n){for(var r in i){var a=i[r],s=t+r,l=n;Array.isArray(a)&&(l=kt(n,a[1]),a=a[0]),a instanceof D?e[s]=[a,l]:(e[s+="/"]=[new D(0),l],Fe(a,s,e,n))}},je=typeof TextEncoder<"u"&&new TextEncoder,Ie=typeof TextDecoder<"u"&&new TextDecoder,yi=0;try{Ie.decode(gt,{stream:!0}),yi=1}catch{}var Ai=function(i){for(var t="",e=0;;){var n=i[e++],r=(n>127)+(n>223)+(n>239);if(e+r>i.length)return[t,rt(i,e-1)];r?r==3?(n=((n&15)<<18|(i[e++]&63)<<12|(i[e++]&63)<<6|i[e++]&63)-65536,t+=String.fromCharCode(55296|n>>10,56320|n&1023)):r&1?t+=String.fromCharCode((n&31)<<6|i[e++]&63):t+=String.fromCharCode((n&15)<<12|(i[e++]&63)<<6|i[e++]&63):t+=String.fromCharCode(n)}},Zi=function(){function i(t){this.ondata=t,yi?this.t=new TextDecoder:this.p=gt}return i.prototype.push=function(t,e){if(this.ondata||_(5),e=!!e,this.t){this.ondata(this.t.decode(t,{stream:!0}),e),e&&(this.t.decode().length&&_(8),this.t=null);return}this.p||_(4);var n=new D(this.p.length+t.length);n.set(this.p),n.set(t,this.p.length);var r=Ai(n),a=r[0],s=r[1];e?(s.length&&_(8),this.p=null):this.p=s,this.ondata(a,e)},i}();I.DecodeUTF8=Zi;var Yi=function(){function i(t){this.ondata=t}return i.prototype.push=function(t,e){this.ondata||_(5),this.d&&_(4),this.ondata(mt(t),this.d=e||!1)},i}();I.EncodeUTF8=Yi;function mt(i,t){if(t){for(var e=new D(i.length),n=0;n>1)),s=0,l=function(u){a[s++]=u},n=0;na.length){var o=new D(s+8+(r-n<<1));o.set(a),a=o}var f=i.charCodeAt(n);f<128||t?l(f):f<2048?(l(192|f>>6),l(128|f&63)):f>55295&&f<57344?(f=65536+(f&1023<<10)|i.charCodeAt(++n)&1023,l(240|f>>18),l(128|f>>12&63),l(128|f>>6&63),l(128|f&63)):(l(224|f>>12),l(128|f>>6&63),l(128|f&63))}return rt(a,0,s)}I.strToU8=mt;function ze(i,t){if(t){for(var e="",n=0;n65535&&_(9),t+=n+4}return t},Mt=function(i,t,e,n,r,a,s,l){var o=n.length,f=e.extra,u=l&&l.length,h=dt(f);Z(i,t,s!=null?33639248:67324752),t+=4,s!=null&&(i[t++]=20,i[t++]=e.os),i[t]=20,t+=2,i[t++]=e.flag<<1|(a==null&&8),i[t++]=r&&8,i[t++]=e.compression&255,i[t++]=e.compression>>8;var v=new Date(e.mtime==null?Date.now():e.mtime),m=v.getFullYear()-1980;if((m<0||m>119)&&_(10),Z(i,t,m<<25|v.getMonth()+1<<21|v.getDate()<<16|v.getHours()<<11|v.getMinutes()<<5|v.getSeconds()>>>1),t+=4,a!=null&&(Z(i,t,e.crc),Z(i,t+4,a),Z(i,t+8,e.size)),Z(i,t+12,o),Z(i,t+14,h),t+=16,s!=null&&(Z(i,t,u),Z(i,t+6,e.attrs),Z(i,t+10,s),t+=14),i.set(n,t),t+=o,h)for(var g in f){var p=f[g],c=p.length;Z(i,t,+g),Z(i,t+2,c),i.set(p,t+4),t+=4+c}return u&&(i.set(l,t),t+=u),t},De=function(i,t,e,n,r){Z(i,t,101010256),Z(i,t+8,e),Z(i,t+10,e),Z(i,t+12,n),Z(i,t+16,r)},Rt=function(){function i(t){this.filename=t,this.c=Ft(),this.size=0,this.compression=0}return i.prototype.process=function(t,e){this.ondata(null,t,e)},i.prototype.push=function(t,e){this.ondata||_(5),this.c.p(t),this.size+=t.length,e&&(this.crc=this.c.d()),this.process(t,e||!1)},i}();I.ZipPassThrough=Rt;var ki=function(){function i(t,e){var n=this;e||(e={}),Rt.call(this,t),this.d=new ut(e,function(r,a){n.ondata(null,r,a)}),this.compression=8,this.flag=xi(e.level)}return i.prototype.process=function(t,e){try{this.d.push(t,e)}catch(n){this.ondata(n,null,e)}},i.prototype.push=function(t,e){Rt.prototype.push.call(this,t,e)},i}();I.ZipDeflate=ki;var Xi=function(){function i(t,e){var n=this;e||(e={}),Rt.call(this,t),this.d=new ci(e,function(r,a,s){n.ondata(r,a,s)}),this.compression=8,this.flag=xi(e.level),this.terminate=this.d.terminate}return i.prototype.process=function(t,e){this.d.push(t,e)},i.prototype.push=function(t,e){Rt.prototype.push.call(this,t,e)},i}();I.AsyncZipDeflate=Xi;var ji=function(){function i(t){this.ondata=t,this.u=[],this.d=1}return i.prototype.add=function(t){var e=this;if(this.ondata||_(5),this.d&2)this.ondata(_(4+(this.d&1)*8,0,1),null,!1);else{var n=mt(t.filename),r=n.length,a=t.comment,s=a&&mt(a),l=r!=t.filename.length||s&&a.length!=s.length,o=r+dt(t.extra)+30;r>65535&&this.ondata(_(11,0,1),null,!1);var f=new D(o);Mt(f,0,t,n,l);var u=[f],h=function(){for(var c=0,y=u;c65535&&F(_(11,0,1),null),!w)F(null,T);else if(q<16e4)try{F(null,Xt(T,x))}catch(G){F(G,null)}else u.push(vi(T,x,F))},p=0;p65535&&_(11);var y=u?Xt(o,f):o,A=y.length,T=Ft();T.p(o),n.push(kt(f,{size:o.length,crc:T.d(),c:y,f:h,m:g,u:v!=s.length||g&&m.length!=p,o:r,compression:u})),r+=30+v+c+A,a+=76+2*(v+c)+(p||0)+A}for(var x=new D(a+22),R=r,q=a-r,M=0;M0){var r=Math.min(this.c,t.length),a=t.subarray(0,r);if(this.c-=r,this.d?this.d.push(a,!this.c):this.k[0].push(a),t=t.subarray(r),t.length)return this.push(t,e)}else{var s=0,l=0,o=void 0,f=void 0;this.p.length?t.length?(f=new D(this.p.length+t.length),f.set(this.p),f.set(t,this.p.length)):f=this.p:f=t;for(var u=f.length,h=this.c,v=h&&this.d,m=function(){var y,A=j(f,l);if(A==67324752){s=1,o=l,g.d=null,g.c=0;var T=$(f,l+6),x=$(f,l+8),R=T&2048,q=T&8,M=$(f,l+26),d=$(f,l+28);if(u>l+30+M+d){var Y=[];g.k.unshift(Y),s=2;var N=j(f,l+18),V=j(f,l+22),z=ze(f.subarray(l+30,l+=30+M),!R);N==4294967295?(y=q?[-2]:Ti(f,l),N=y[0],V=y[1]):q&&(N=-1),l+=d,g.c=N;var w,F={name:z,compression:x,start:function(){if(F.ondata||_(5),!N)F.ondata(null,gt,!0);else{var G=n.o[x];G||F.ondata(_(14,"unknown compression type "+x,1),null,!1),w=N<0?new G(z):new G(z,N,V),w.ondata=function(X,et,Q){F.ondata(X,et,Q)};for(var B=0,P=Y;B=0&&(F.size=N,F.originalSize=V),g.onfile(F)}return"break"}else if(h){if(A==134695760)return o=l+=12+(h==-2&&8),s=3,g.c=0,"break";if(A==33639248)return o=l-=4,s=3,g.c=0,"break"}},g=this;l65558)return s(_(13,0,1),null),r;var o=$(i,l+8);if(o){var f=o,u=j(i,l+16),h=u==4294967295;if(h){if(l=j(i,l-12),j(i,l)!=101075792)return s(_(13,0,1),null),r;f=o=j(i,l+32),u=j(i,l+48)}for(var v=t&&t.filter,m=function(p){var c=Si(i,u,h),y=c[0],A=c[1],T=c[2],x=c[3],R=c[4],q=c[5],M=Ui(i,q);u=R;var d=function(N,V){N?(r(),s(N,null)):(V&&(a[x]=V),--o||s(null,a))};if(!v||v({name:x,size:A,originalSize:T,compression:y}))if(!y)d(null,rt(i,M,M+A));else if(y==8){var Y=i.subarray(M,M+A);if(A<32e4)try{d(null,Bt(Y,new D(T)))}catch(N){d(N,null)}else n.push(Ne(Y,{size:T},d))}else d(_(14,"unknown compression type "+y,1),null);else d(null,null)},g=0;g65558)&&_(13);var r=$(i,n+8);if(!r)return{};var a=j(i,n+16),s=a==4294967295;s&&(n=j(i,n-12),j(i,n)!=101075792&&_(13),r=j(i,n+32),a=j(i,n+48));for(var l=t&&t.filter,o=0;o{"use strict";Object.defineProperty(le,"__esModule",{value:!0});le.NIFTIEXTENSION=void 0;var Oe=class{esize;ecode;edata;littleEndian;constructor(t,e,n,r){if(t%16!=0)throw new Error("This does not appear to be a NIFTI extension");this.esize=t,this.ecode=e,this.edata=n,this.littleEndian=r}toArrayBuffer(){let t=new Uint8Array(this.esize),e=new Uint8Array(this.edata);t.set(e,8);let n=new DataView(t.buffer);return n.setInt32(0,this.esize,this.littleEndian),n.setInt32(4,this.ecode,this.littleEndian),t.buffer}};le.NIFTIEXTENSION=Oe});var jt=It(fe=>{"use strict";Object.defineProperty(fe,"__esModule",{value:!0});fe.Utils=void 0;var tn=qe(),lt=class{static getStringAt(t,e,n){var r="",a,s;for(a=e;a=0;r--)s=s*256+a[r];return s}static getExtensionsAt(t,e,n,r){let a=[],s=e;for(;sr&&(l=!l,o=lt.getIntAt(t,s,l),o+s>r))throw new Error("This does not appear to be a valid NIFTI extension");if(o%16!=0)throw new Error("This does not appear to be a NIFTI extension");let f=lt.getIntAt(t,s+4,l),u=t.buffer.slice(s+8,s+o);console.log("extensionByteIndex: "+(s+8)+" esize: "+o),console.log(u);let h=new tn.NIFTIEXTENSION(o,f,u,l);a.push(h),s+=o}return a}static toArrayBuffer(t){var e,n,r;for(e=new ArrayBuffer(t.length),n=new Uint8Array(e),r=0;r>>1:t>>>1;e[n]=t}return e}static crc32(t){lt.crcTable||(lt.crcTable=lt.makeCRCTable());let e=lt.crcTable,n=-1;for(var r=0;r>>8^e[(n^t.getUint8(r))&255];return(n^-1)>>>0}},Et=lt;E(Et,"crcTable",null),E(Et,"GUNZIP_MAGIC_COOKIE1",31),E(Et,"GUNZIP_MAGIC_COOKIE2",139),E(Et,"getByteAt",function(t,e){return t.getInt8(e)}),E(Et,"getShortAt",function(t,e,n){return t.getInt16(e,n)});fe.Utils=Et});var ue=It(he=>{"use strict";Object.defineProperty(he,"__esModule",{value:!0});he.NIFTI1=void 0;var U=jt(),b=class{littleEndian=!1;dim_info=0;dims=[];intent_p1=0;intent_p2=0;intent_p3=0;intent_code=0;datatypeCode=0;numBitsPerVoxel=0;slice_start=0;slice_end=0;slice_code=0;pixDims=[];vox_offset=0;scl_slope=1;scl_inter=0;xyzt_units=0;cal_max=0;cal_min=0;slice_duration=0;toffset=0;description="";aux_file="";intent_name="";qform_code=0;sform_code=0;quatern_a=0;quatern_b=0;quatern_c=0;quatern_d=0;qoffset_x=0;qoffset_y=0;qoffset_z=0;affine=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];qfac=1;quatern_R;magic="0";isHDR=!1;extensionFlag=[0,0,0,0];extensionSize=0;extensionCode=0;extensions=[];readHeader(t){var e=new DataView(t),n=U.Utils.getIntAt(e,0,this.littleEndian),r,a,s,l;if(n!==b.MAGIC_COOKIE&&(this.littleEndian=!0,n=U.Utils.getIntAt(e,0,this.littleEndian)),n!==b.MAGIC_COOKIE)throw new Error("This does not appear to be a NIFTI file!");for(this.dim_info=U.Utils.getByteAt(e,39),r=0;r<8;r+=1)l=40+r*2,this.dims[r]=U.Utils.getShortAt(e,l,this.littleEndian);for(this.intent_p1=U.Utils.getFloatAt(e,56,this.littleEndian),this.intent_p2=U.Utils.getFloatAt(e,60,this.littleEndian),this.intent_p3=U.Utils.getFloatAt(e,64,this.littleEndian),this.intent_code=U.Utils.getShortAt(e,68,this.littleEndian),this.datatypeCode=U.Utils.getShortAt(e,70,this.littleEndian),this.numBitsPerVoxel=U.Utils.getShortAt(e,72,this.littleEndian),this.slice_start=U.Utils.getShortAt(e,74,this.littleEndian),r=0;r<8;r+=1)l=76+r*4,this.pixDims[r]=U.Utils.getFloatAt(e,l,this.littleEndian);if(this.vox_offset=U.Utils.getFloatAt(e,108,this.littleEndian),this.scl_slope=U.Utils.getFloatAt(e,112,this.littleEndian),this.scl_inter=U.Utils.getFloatAt(e,116,this.littleEndian),this.slice_end=U.Utils.getShortAt(e,120,this.littleEndian),this.slice_code=U.Utils.getByteAt(e,122),this.xyzt_units=U.Utils.getByteAt(e,123),this.cal_max=U.Utils.getFloatAt(e,124,this.littleEndian),this.cal_min=U.Utils.getFloatAt(e,128,this.littleEndian),this.slice_duration=U.Utils.getFloatAt(e,132,this.littleEndian),this.toffset=U.Utils.getFloatAt(e,136,this.littleEndian),this.description=U.Utils.getStringAt(e,148,228),this.aux_file=U.Utils.getStringAt(e,228,252),this.qform_code=U.Utils.getShortAt(e,252,this.littleEndian),this.sform_code=U.Utils.getShortAt(e,254,this.littleEndian),this.quatern_b=U.Utils.getFloatAt(e,256,this.littleEndian),this.quatern_c=U.Utils.getFloatAt(e,260,this.littleEndian),this.quatern_d=U.Utils.getFloatAt(e,264,this.littleEndian),this.quatern_a=Math.sqrt(1-(Math.pow(this.quatern_b,2)+Math.pow(this.quatern_c,2)+Math.pow(this.quatern_d,2))),this.qoffset_x=U.Utils.getFloatAt(e,268,this.littleEndian),this.qoffset_y=U.Utils.getFloatAt(e,272,this.littleEndian),this.qoffset_z=U.Utils.getFloatAt(e,276,this.littleEndian),this.qform_code>0){let o=this.quatern_a,f=this.quatern_b,u=this.quatern_c,h=this.quatern_d;for(this.qfac=this.pixDims[0]===0?1:this.pixDims[0],this.quatern_R=[[o*o+f*f-u*u-h*h,2*f*u-2*o*h,2*f*h+2*o*u],[2*f*u+2*o*h,o*o+u*u-f*f-h*h,2*u*h-2*o*f],[2*f*h-2*o*u,2*u*h+2*o*f,o*o+h*h-u*u-f*f]],a=0;a<3;a+=1)for(s=0;s<3;s+=1)this.affine[a][s]=this.quatern_R[a][s]*this.pixDims[s+1],s===2&&(this.affine[a][s]*=this.qfac);this.affine[0][3]=this.qoffset_x,this.affine[1][3]=this.qoffset_y,this.affine[2][3]=this.qoffset_z}else if(this.sform_code>0)for(a=0;a<3;a+=1)for(s=0;s<4;s+=1)l=280+(a*4+s)*4,this.affine[a][s]=U.Utils.getFloatAt(e,l,this.littleEndian);this.affine[3][0]=0,this.affine[3][1]=0,this.affine[3][2]=0,this.affine[3][3]=1,this.intent_name=U.Utils.getStringAt(e,328,344),this.magic=U.Utils.getStringAt(e,344,348),this.isHDR=this.magic===String.fromCharCode.apply(null,b.MAGIC_NUMBER2),e.byteLength>b.MAGIC_COOKIE&&(this.extensionFlag[0]=U.Utils.getByteAt(e,348),this.extensionFlag[1]=U.Utils.getByteAt(e,348+1),this.extensionFlag[2]=U.Utils.getByteAt(e,348+2),this.extensionFlag[3]=U.Utils.getByteAt(e,348+3),this.extensionFlag[0]&&(this.extensions=U.Utils.getExtensionsAt(e,this.getExtensionLocation(),this.littleEndian,this.vox_offset),this.extensionSize=this.extensions[0].esize,this.extensionCode=this.extensions[0].ecode))}toFormattedString(){var t=U.Utils.formatNumber,e="";return e+="Dim Info = "+this.dim_info+` +`,e+="Image Dimensions (1-8): "+this.dims[0]+", "+this.dims[1]+", "+this.dims[2]+", "+this.dims[3]+", "+this.dims[4]+", "+this.dims[5]+", "+this.dims[6]+", "+this.dims[7]+` +`,e+="Intent Parameters (1-3): "+this.intent_p1+", "+this.intent_p2+", "+this.intent_p3+` +`,e+="Intent Code = "+this.intent_code+` +`,e+="Datatype = "+this.datatypeCode+" ("+this.getDatatypeCodeString(this.datatypeCode)+`) +`,e+="Bits Per Voxel = "+this.numBitsPerVoxel+` +`,e+="Slice Start = "+this.slice_start+` +`,e+="Voxel Dimensions (1-8): "+t(this.pixDims[0])+", "+t(this.pixDims[1])+", "+t(this.pixDims[2])+", "+t(this.pixDims[3])+", "+t(this.pixDims[4])+", "+t(this.pixDims[5])+", "+t(this.pixDims[6])+", "+t(this.pixDims[7])+` +`,e+="Image Offset = "+this.vox_offset+` +`,e+="Data Scale: Slope = "+t(this.scl_slope)+" Intercept = "+t(this.scl_inter)+` +`,e+="Slice End = "+this.slice_end+` +`,e+="Slice Code = "+this.slice_code+` +`,e+="Units Code = "+this.xyzt_units+" ("+this.getUnitsCodeString(b.SPATIAL_UNITS_MASK&this.xyzt_units)+", "+this.getUnitsCodeString(b.TEMPORAL_UNITS_MASK&this.xyzt_units)+`) +`,e+="Display Range: Max = "+t(this.cal_max)+" Min = "+t(this.cal_min)+` +`,e+="Slice Duration = "+this.slice_duration+` +`,e+="Time Axis Shift = "+this.toffset+` +`,e+='Description: "'+this.description+`" +`,e+='Auxiliary File: "'+this.aux_file+`" +`,e+="Q-Form Code = "+this.qform_code+" ("+this.getTransformCodeString(this.qform_code)+`) +`,e+="S-Form Code = "+this.sform_code+" ("+this.getTransformCodeString(this.sform_code)+`) +`,e+="Quaternion Parameters: b = "+t(this.quatern_b)+" c = "+t(this.quatern_c)+" d = "+t(this.quatern_d)+` +`,e+="Quaternion Offsets: x = "+this.qoffset_x+" y = "+this.qoffset_y+" z = "+this.qoffset_z+` +`,e+="S-Form Parameters X: "+t(this.affine[0][0])+", "+t(this.affine[0][1])+", "+t(this.affine[0][2])+", "+t(this.affine[0][3])+` +`,e+="S-Form Parameters Y: "+t(this.affine[1][0])+", "+t(this.affine[1][1])+", "+t(this.affine[1][2])+", "+t(this.affine[1][3])+` +`,e+="S-Form Parameters Z: "+t(this.affine[2][0])+", "+t(this.affine[2][1])+", "+t(this.affine[2][2])+", "+t(this.affine[2][3])+` +`,e+='Intent Name: "'+this.intent_name+`" +`,this.extensionFlag[0]&&(e+="Extension: Size = "+this.extensionSize+" Code = "+this.extensionCode+` +`),e}getDatatypeCodeString=function(t){return t===b.TYPE_UINT8?"1-Byte Unsigned Integer":t===b.TYPE_INT16?"2-Byte Signed Integer":t===b.TYPE_INT32?"4-Byte Signed Integer":t===b.TYPE_FLOAT32?"4-Byte Float":t===b.TYPE_FLOAT64?"8-Byte Float":t===b.TYPE_RGB24?"RGB":t===b.TYPE_INT8?"1-Byte Signed Integer":t===b.TYPE_UINT16?"2-Byte Unsigned Integer":t===b.TYPE_UINT32?"4-Byte Unsigned Integer":t===b.TYPE_INT64?"8-Byte Signed Integer":t===b.TYPE_UINT64?"8-Byte Unsigned Integer":"Unknown"};getTransformCodeString=function(t){return t===b.XFORM_SCANNER_ANAT?"Scanner":t===b.XFORM_ALIGNED_ANAT?"Aligned":t===b.XFORM_TALAIRACH?"Talairach":t===b.XFORM_MNI_152?"MNI":"Unknown"};getUnitsCodeString=function(t){return t===b.UNITS_METER?"Meters":t===b.UNITS_MM?"Millimeters":t===b.UNITS_MICRON?"Microns":t===b.UNITS_SEC?"Seconds":t===b.UNITS_MSEC?"Milliseconds":t===b.UNITS_USEC?"Microseconds":t===b.UNITS_HZ?"Hz":t===b.UNITS_PPM?"PPM":t===b.UNITS_RADS?"Rads":"Unknown"};getQformMat(){return this.convertNiftiQFormToNiftiSForm(this.quatern_b,this.quatern_c,this.quatern_d,this.qoffset_x,this.qoffset_y,this.qoffset_z,this.pixDims[1],this.pixDims[2],this.pixDims[3],this.pixDims[0])}convertNiftiQFormToNiftiSForm(t,e,n,r,a,s,l,o,f,u){var h=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],v,m=t,g=e,p=n,c,y,A;return h[3][0]=h[3][1]=h[3][2]=0,h[3][3]=1,v=1-(m*m+g*g+p*p),v<1e-7?(v=1/Math.sqrt(m*m+g*g+p*p),m*=v,g*=v,p*=v,v=0):v=Math.sqrt(v),c=l>0?l:1,y=o>0?o:1,A=f>0?f:1,u<0&&(A=-A),h[0][0]=(v*v+m*m-g*g-p*p)*c,h[0][1]=2*(m*g-v*p)*y,h[0][2]=2*(m*p+v*g)*A,h[1][0]=2*(m*g+v*p)*c,h[1][1]=(v*v+g*g-m*m-p*p)*y,h[1][2]=2*(g*p-v*m)*A,h[2][0]=2*(m*p-v*g)*c,h[2][1]=2*(g*p+v*m)*y,h[2][2]=(v*v+p*p-g*g-m*m)*A,h[0][3]=r,h[1][3]=a,h[2][3]=s,h}convertNiftiSFormToNEMA(t){var e,n,r,a,s,l,o,f,u,h,v,m,g,p,c,y,A,T,x,R,q,M,d,Y,N,V,z,w,F,G,B,P,k,X;if(c=0,z=[[0,0,0],[0,0,0],[0,0,0]],w=[[0,0,0],[0,0,0],[0,0,0]],e=t[0][0],n=t[0][1],r=t[0][2],a=t[1][0],s=t[1][1],l=t[1][2],o=t[2][0],f=t[2][1],u=t[2][2],h=Math.sqrt(e*e+a*a+o*o),h===0||(e/=h,a/=h,o/=h,h=Math.sqrt(n*n+s*s+f*f),h===0))return null;if(n/=h,s/=h,f/=h,h=e*n+a*s+o*f,Math.abs(h)>1e-4){if(n-=h*e,s-=h*a,f-=h*o,h=Math.sqrt(n*n+s*s+f*f),h===0)return null;n/=h,s/=h,f/=h}if(h=Math.sqrt(r*r+l*l+u*u),h===0?(r=a*f-o*s,l=o*n-f*e,u=e*s-a*n):(r/=h,l/=h,u/=h),h=e*r+a*l+o*u,Math.abs(h)>1e-4){if(r-=h*e,l-=h*a,u-=h*o,h=Math.sqrt(r*r+l*l+u*u),h===0)return null;r/=h,l/=h,u/=h}if(h=n*r+s*l+f*u,Math.abs(h)>1e-4){if(r-=h*n,l-=h*s,u-=h*f,h=Math.sqrt(r*r+l*l+u*u),h===0)return null;r/=h,l/=h,u/=h}if(z[0][0]=e,z[0][1]=n,z[0][2]=r,z[1][0]=a,z[1][1]=s,z[1][2]=l,z[2][0]=o,z[2][1]=f,z[2][2]=u,v=this.nifti_mat33_determ(z),v===0)return null;for(V=-666,x=M=d=Y=1,R=2,q=3,g=1;g<=3;g+=1)for(p=1;p<=3;p+=1)if(g!==p){for(c=1;c<=3;c+=1)if(!(g===c||p===c))for(w[0][0]=w[0][1]=w[0][2]=w[1][0]=w[1][1]=w[1][2]=w[2][0]=w[2][1]=w[2][2]=0,y=-1;y<=1;y+=2)for(A=-1;A<=1;A+=2)for(T=-1;T<=1;T+=2)w[0][g-1]=y,w[1][p-1]=A,w[2][c-1]=T,m=this.nifti_mat33_determ(w),m*v>0&&(N=this.nifti_mat33_mul(w,z),h=N[0][0]+N[1][1]+N[2][2],h>V&&(V=h,x=g,R=p,q=c,M=y,d=A,Y=T))}switch(F=G=B=P=k=X="",x*M){case 1:F="X",P="+";break;case-1:F="X",P="-";break;case 2:F="Y",P="+";break;case-2:F="Y",P="-";break;case 3:F="Z",P="+";break;case-3:F="Z",P="-";break}switch(R*d){case 1:G="X",k="+";break;case-1:G="X",k="-";break;case 2:G="Y",k="+";break;case-2:G="Y",k="-";break;case 3:G="Z",k="+";break;case-3:G="Z",k="-";break}switch(q*Y){case 1:B="X",X="+";break;case-1:B="X",X="-";break;case 2:B="Y",X="+";break;case-2:B="Y",X="-";break;case 3:B="Z",X="+";break;case-3:B="Z",X="-";break}return F+G+B+P+k+X}nifti_mat33_mul=function(t,e){var n=[[0,0,0],[0,0,0],[0,0,0]],r,a;for(r=0;r<3;r+=1)for(a=0;a<3;a+=1)n[r][a]=t[r][0]*e[0][a]+t[r][1]*e[1][a]+t[r][2]*e[2][a];return n};nifti_mat33_determ=function(t){var e,n,r,a,s,l,o,f,u;return e=t[0][0],n=t[0][1],r=t[0][2],a=t[1][0],s=t[1][1],l=t[1][2],o=t[2][0],f=t[2][1],u=t[2][2],e*s*u-e*f*l-a*n*u+a*f*r+o*n*l-o*s*r};getExtensionLocation(){return b.MAGIC_COOKIE+4}getExtensionSize(t){return U.Utils.getIntAt(t,this.getExtensionLocation(),this.littleEndian)}getExtensionCode(t){return U.Utils.getIntAt(t,this.getExtensionLocation()+4,this.littleEndian)}addExtension(t,e=-1){e==-1?this.extensions.push(t):this.extensions.splice(e,0,t),this.vox_offset+=t.esize}removeExtension(t){let e=this.extensions[t];e&&(this.vox_offset-=e.esize),this.extensions.splice(t,1)}toArrayBuffer(t=!1){let r=352;if(t)for(let o of this.extensions)r+=o.esize;let a=new Uint8Array(r),s=new DataView(a.buffer);s.setInt32(0,348,this.littleEndian),s.setUint8(39,this.dim_info);for(let o=0;o<8;o++)s.setUint16(40+2*o,this.dims[o],this.littleEndian);s.setFloat32(56,this.intent_p1,this.littleEndian),s.setFloat32(60,this.intent_p2,this.littleEndian),s.setFloat32(64,this.intent_p3,this.littleEndian),s.setInt16(68,this.intent_code,this.littleEndian),s.setInt16(70,this.datatypeCode,this.littleEndian),s.setInt16(72,this.numBitsPerVoxel,this.littleEndian),s.setInt16(74,this.slice_start,this.littleEndian);for(let o=0;o<8;o++)s.setFloat32(76+4*o,this.pixDims[o],this.littleEndian);s.setFloat32(108,this.vox_offset,this.littleEndian),s.setFloat32(112,this.scl_slope,this.littleEndian),s.setFloat32(116,this.scl_inter,this.littleEndian),s.setInt16(120,this.slice_end,this.littleEndian),s.setUint8(122,this.slice_code),s.setUint8(123,this.xyzt_units),s.setFloat32(124,this.cal_max,this.littleEndian),s.setFloat32(128,this.cal_min,this.littleEndian),s.setFloat32(132,this.slice_duration,this.littleEndian),s.setFloat32(136,this.toffset,this.littleEndian),a.set(Buffer.from(this.description),148),a.set(Buffer.from(this.aux_file),228),s.setInt16(252,this.qform_code,this.littleEndian),s.setInt16(254,this.sform_code,this.littleEndian),s.setFloat32(256,this.quatern_b,this.littleEndian),s.setFloat32(260,this.quatern_c,this.littleEndian),s.setFloat32(264,this.quatern_d,this.littleEndian),s.setFloat32(268,this.qoffset_x,this.littleEndian),s.setFloat32(272,this.qoffset_y,this.littleEndian),s.setFloat32(276,this.qoffset_z,this.littleEndian);let l=this.affine.flat();for(let o=0;o<12;o++)s.setFloat32(280+4*o,l[o],this.littleEndian);if(a.set(Buffer.from(this.intent_name),328),a.set(Buffer.from(this.magic),344),t){a.set(Uint8Array.from([1,0,0,0]),348);let o=this.getExtensionLocation();for(let f of this.extensions)s.setInt32(o,f.esize,f.littleEndian),s.setInt32(o+4,f.ecode,f.littleEndian),a.set(new Uint8Array(f.edata),o+8),o+=f.esize}else a.set(new Uint8Array(4).fill(0),348);return a.buffer}},S=b;E(S,"TYPE_NONE",0),E(S,"TYPE_BINARY",1),E(S,"TYPE_UINT8",2),E(S,"TYPE_INT16",4),E(S,"TYPE_INT32",8),E(S,"TYPE_FLOAT32",16),E(S,"TYPE_COMPLEX64",32),E(S,"TYPE_FLOAT64",64),E(S,"TYPE_RGB24",128),E(S,"TYPE_INT8",256),E(S,"TYPE_UINT16",512),E(S,"TYPE_UINT32",768),E(S,"TYPE_INT64",1024),E(S,"TYPE_UINT64",1280),E(S,"TYPE_FLOAT128",1536),E(S,"TYPE_COMPLEX128",1792),E(S,"TYPE_COMPLEX256",2048),E(S,"XFORM_UNKNOWN",0),E(S,"XFORM_SCANNER_ANAT",1),E(S,"XFORM_ALIGNED_ANAT",2),E(S,"XFORM_TALAIRACH",3),E(S,"XFORM_MNI_152",4),E(S,"SPATIAL_UNITS_MASK",7),E(S,"TEMPORAL_UNITS_MASK",56),E(S,"UNITS_UNKNOWN",0),E(S,"UNITS_METER",1),E(S,"UNITS_MM",2),E(S,"UNITS_MICRON",3),E(S,"UNITS_SEC",8),E(S,"UNITS_MSEC",16),E(S,"UNITS_USEC",24),E(S,"UNITS_HZ",32),E(S,"UNITS_PPM",40),E(S,"UNITS_RADS",48),E(S,"MAGIC_COOKIE",348),E(S,"STANDARD_HEADER_SIZE",348),E(S,"MAGIC_NUMBER_LOCATION",344),E(S,"MAGIC_NUMBER",[110,43,49]),E(S,"MAGIC_NUMBER2",[110,105,49]),E(S,"EXTENSION_HEADER_SIZE",8);he.NIFTI1=S});var Be=It(ce=>{"use strict";Object.defineProperty(ce,"__esModule",{value:!0});ce.NIFTI2=void 0;var tt=ue(),C=jt(),Pt=class{littleEndian=!1;dim_info=0;dims=[];intent_p1=0;intent_p2=0;intent_p3=0;intent_code=0;datatypeCode=0;numBitsPerVoxel=0;slice_start=0;slice_end=0;slice_code=0;pixDims=[];vox_offset=0;scl_slope=1;scl_inter=0;xyzt_units=0;cal_max=0;cal_min=0;slice_duration=0;toffset=0;description="";aux_file="";intent_name="";qform_code=0;sform_code=0;quatern_b=0;quatern_c=0;quatern_d=0;qoffset_x=0;qoffset_y=0;qoffset_z=0;affine=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];magic="0";extensionFlag=[0,0,0,0];extensions=[];extensionSize=0;extensionCode=0;readHeader(t){var e=new DataView(t),n=C.Utils.getIntAt(e,0,this.littleEndian),r,a,s,l,o;if(n!==Pt.MAGIC_COOKIE&&(this.littleEndian=!0,n=C.Utils.getIntAt(e,0,this.littleEndian)),n!==Pt.MAGIC_COOKIE)throw new Error("This does not appear to be a NIFTI file!");for(this.magic=C.Utils.getStringAt(e,4,12),this.datatypeCode=C.Utils.getShortAt(e,12,this.littleEndian),this.numBitsPerVoxel=C.Utils.getShortAt(e,14,this.littleEndian),r=0;r<8;r+=1)l=16+r*8,this.dims[r]=C.Utils.getLongAt(e,l,this.littleEndian);for(this.intent_p1=C.Utils.getDoubleAt(e,80,this.littleEndian),this.intent_p2=C.Utils.getDoubleAt(e,88,this.littleEndian),this.intent_p3=C.Utils.getDoubleAt(e,96,this.littleEndian),r=0;r<8;r+=1)l=104+r*8,this.pixDims[r]=C.Utils.getDoubleAt(e,l,this.littleEndian);for(this.vox_offset=C.Utils.getLongAt(e,168,this.littleEndian),this.scl_slope=C.Utils.getDoubleAt(e,176,this.littleEndian),this.scl_inter=C.Utils.getDoubleAt(e,184,this.littleEndian),this.cal_max=C.Utils.getDoubleAt(e,192,this.littleEndian),this.cal_min=C.Utils.getDoubleAt(e,200,this.littleEndian),this.slice_duration=C.Utils.getDoubleAt(e,208,this.littleEndian),this.toffset=C.Utils.getDoubleAt(e,216,this.littleEndian),this.slice_start=C.Utils.getLongAt(e,224,this.littleEndian),this.slice_end=C.Utils.getLongAt(e,232,this.littleEndian),this.description=C.Utils.getStringAt(e,240,240+80),this.aux_file=C.Utils.getStringAt(e,320,320+24),this.qform_code=C.Utils.getIntAt(e,344,this.littleEndian),this.sform_code=C.Utils.getIntAt(e,348,this.littleEndian),this.quatern_b=C.Utils.getDoubleAt(e,352,this.littleEndian),this.quatern_c=C.Utils.getDoubleAt(e,360,this.littleEndian),this.quatern_d=C.Utils.getDoubleAt(e,368,this.littleEndian),this.qoffset_x=C.Utils.getDoubleAt(e,376,this.littleEndian),this.qoffset_y=C.Utils.getDoubleAt(e,384,this.littleEndian),this.qoffset_z=C.Utils.getDoubleAt(e,392,this.littleEndian),a=0;a<3;a+=1)for(s=0;s<4;s+=1)l=400+(a*4+s)*8,this.affine[a][s]=C.Utils.getDoubleAt(e,l,this.littleEndian);this.affine[3][0]=0,this.affine[3][1]=0,this.affine[3][2]=0,this.affine[3][3]=1,this.slice_code=C.Utils.getIntAt(e,496,this.littleEndian),this.xyzt_units=C.Utils.getIntAt(e,500,this.littleEndian),this.intent_code=C.Utils.getIntAt(e,504,this.littleEndian),this.intent_name=C.Utils.getStringAt(e,508,508+16),this.dim_info=C.Utils.getByteAt(e,524),e.byteLength>Pt.MAGIC_COOKIE&&(this.extensionFlag[0]=C.Utils.getByteAt(e,540),this.extensionFlag[1]=C.Utils.getByteAt(e,540+1),this.extensionFlag[2]=C.Utils.getByteAt(e,540+2),this.extensionFlag[3]=C.Utils.getByteAt(e,540+3),this.extensionFlag[0]&&(this.extensions=C.Utils.getExtensionsAt(e,this.getExtensionLocation(),this.littleEndian,this.vox_offset),this.extensionSize=this.extensions[0].esize,this.extensionCode=this.extensions[0].ecode))}toFormattedString(){var t=C.Utils.formatNumber,e="";return e+="Datatype = "+ +this.datatypeCode+" ("+this.getDatatypeCodeString(this.datatypeCode)+`) +`,e+="Bits Per Voxel = = "+this.numBitsPerVoxel+` +`,e+="Image Dimensions (1-8): "+this.dims[0]+", "+this.dims[1]+", "+this.dims[2]+", "+this.dims[3]+", "+this.dims[4]+", "+this.dims[5]+", "+this.dims[6]+", "+this.dims[7]+` +`,e+="Intent Parameters (1-3): "+this.intent_p1+", "+this.intent_p2+", "+this.intent_p3+` +`,e+="Voxel Dimensions (1-8): "+t(this.pixDims[0])+", "+t(this.pixDims[1])+", "+t(this.pixDims[2])+", "+t(this.pixDims[3])+", "+t(this.pixDims[4])+", "+t(this.pixDims[5])+", "+t(this.pixDims[6])+", "+t(this.pixDims[7])+` +`,e+="Image Offset = "+this.vox_offset+` +`,e+="Data Scale: Slope = "+t(this.scl_slope)+" Intercept = "+t(this.scl_inter)+` +`,e+="Display Range: Max = "+t(this.cal_max)+" Min = "+t(this.cal_min)+` +`,e+="Slice Duration = "+this.slice_duration+` +`,e+="Time Axis Shift = "+this.toffset+` +`,e+="Slice Start = "+this.slice_start+` +`,e+="Slice End = "+this.slice_end+` +`,e+='Description: "'+this.description+`" +`,e+='Auxiliary File: "'+this.aux_file+`" +`,e+="Q-Form Code = "+this.qform_code+" ("+this.getTransformCodeString(this.qform_code)+`) +`,e+="S-Form Code = "+this.sform_code+" ("+this.getTransformCodeString(this.sform_code)+`) +`,e+="Quaternion Parameters: b = "+t(this.quatern_b)+" c = "+t(this.quatern_c)+" d = "+t(this.quatern_d)+` +`,e+="Quaternion Offsets: x = "+this.qoffset_x+" y = "+this.qoffset_y+" z = "+this.qoffset_z+` +`,e+="S-Form Parameters X: "+t(this.affine[0][0])+", "+t(this.affine[0][1])+", "+t(this.affine[0][2])+", "+t(this.affine[0][3])+` +`,e+="S-Form Parameters Y: "+t(this.affine[1][0])+", "+t(this.affine[1][1])+", "+t(this.affine[1][2])+", "+t(this.affine[1][3])+` +`,e+="S-Form Parameters Z: "+t(this.affine[2][0])+", "+t(this.affine[2][1])+", "+t(this.affine[2][2])+", "+t(this.affine[2][3])+` +`,e+="Slice Code = "+this.slice_code+` +`,e+="Units Code = "+this.xyzt_units+" ("+this.getUnitsCodeString(tt.NIFTI1.SPATIAL_UNITS_MASK&this.xyzt_units)+", "+this.getUnitsCodeString(tt.NIFTI1.TEMPORAL_UNITS_MASK&this.xyzt_units)+`) +`,e+="Intent Code = "+this.intent_code+` +`,e+='Intent Name: "'+this.intent_name+`" +`,e+="Dim Info = "+this.dim_info+` +`,e}getExtensionLocation=function(){return Pt.MAGIC_COOKIE+4};getExtensionSize=tt.NIFTI1.prototype.getExtensionSize;getExtensionCode=tt.NIFTI1.prototype.getExtensionCode;addExtension=tt.NIFTI1.prototype.addExtension;removeExtension=tt.NIFTI1.prototype.removeExtension;getDatatypeCodeString=tt.NIFTI1.prototype.getDatatypeCodeString;getTransformCodeString=tt.NIFTI1.prototype.getTransformCodeString;getUnitsCodeString=tt.NIFTI1.prototype.getUnitsCodeString;getQformMat=tt.NIFTI1.prototype.getQformMat;convertNiftiQFormToNiftiSForm=tt.NIFTI1.prototype.convertNiftiQFormToNiftiSForm;convertNiftiSFormToNEMA=tt.NIFTI1.prototype.convertNiftiSFormToNEMA;nifti_mat33_mul=tt.NIFTI1.prototype.nifti_mat33_mul;nifti_mat33_determ=tt.NIFTI1.prototype.nifti_mat33_determ;toArrayBuffer(t=!1){let r=544;if(t)for(let o of this.extensions)r+=o.esize;let a=new Uint8Array(r),s=new DataView(a.buffer);s.setInt32(0,540,this.littleEndian),a.set(Buffer.from(this.magic),4),s.setInt16(12,this.datatypeCode,this.littleEndian),s.setInt16(14,this.numBitsPerVoxel,this.littleEndian);for(let o=0;o<8;o++)s.setBigInt64(16+8*o,BigInt(this.dims[o]),this.littleEndian);s.setFloat64(80,this.intent_p1,this.littleEndian),s.setFloat64(88,this.intent_p2,this.littleEndian),s.setFloat64(96,this.intent_p3,this.littleEndian);for(let o=0;o<8;o++)s.setFloat64(104+8*o,this.pixDims[o],this.littleEndian);s.setBigInt64(168,BigInt(this.vox_offset),this.littleEndian),s.setFloat64(176,this.scl_slope,this.littleEndian),s.setFloat64(184,this.scl_inter,this.littleEndian),s.setFloat64(192,this.cal_max,this.littleEndian),s.setFloat64(200,this.cal_min,this.littleEndian),s.setFloat64(208,this.slice_duration,this.littleEndian),s.setFloat64(216,this.toffset,this.littleEndian),s.setBigInt64(224,BigInt(this.slice_start),this.littleEndian),s.setBigInt64(232,BigInt(this.slice_end),this.littleEndian),a.set(Buffer.from(this.description),240),a.set(Buffer.from(this.aux_file),320),s.setInt32(344,this.qform_code,this.littleEndian),s.setInt32(348,this.sform_code,this.littleEndian),s.setFloat64(352,this.quatern_b,this.littleEndian),s.setFloat64(360,this.quatern_c,this.littleEndian),s.setFloat64(368,this.quatern_d,this.littleEndian),s.setFloat64(376,this.qoffset_x,this.littleEndian),s.setFloat64(384,this.qoffset_y,this.littleEndian),s.setFloat64(392,this.qoffset_z,this.littleEndian);let l=this.affine.flat();for(let o=0;o<12;o++)s.setFloat64(400+8*o,l[o],this.littleEndian);if(s.setInt32(496,this.slice_code,this.littleEndian),s.setInt32(500,this.xyzt_units,this.littleEndian),s.setInt32(504,this.intent_code,this.littleEndian),a.set(Buffer.from(this.intent_name),508),s.setUint8(524,this.dim_info),t){a.set(Uint8Array.from([1,0,0,0]),540);let o=this.getExtensionLocation();for(let f of this.extensions)s.setInt32(o,f.esize,f.littleEndian),s.setInt32(o+4,f.ecode,f.littleEndian),a.set(new Uint8Array(f.edata),o+8),o+=f.esize}else a.set(new Uint8Array(4).fill(0),540);return a.buffer}},At=Pt;E(At,"MAGIC_COOKIE",540),E(At,"MAGIC_NUMBER_LOCATION",4),E(At,"MAGIC_NUMBER",[110,43,50,0,13,10,26,10]),E(At,"MAGIC_NUMBER2",[110,105,50,0,13,10,26,10]);ce.NIFTI2=At});var dn=It(O=>{var en=O&&O.__createBinding||(Object.create?function(i,t,e,n){n===void 0&&(n=e);var r=Object.getOwnPropertyDescriptor(t,e);(!r||("get"in r?!t.__esModule:r.writable||r.configurable))&&(r={enumerable:!0,get:function(){return t[e]}}),Object.defineProperty(i,n,r)}:function(i,t,e,n){n===void 0&&(n=e),i[n]=t[e]}),nn=O&&O.__setModuleDefault||(Object.create?function(i,t){Object.defineProperty(i,"default",{enumerable:!0,value:t})}:function(i,t){i.default=t}),rn=O&&O.__importStar||function(i){if(i&&i.__esModule)return i;var t={};if(i!=null)for(var e in i)e!=="default"&&Object.prototype.hasOwnProperty.call(i,e)&&en(t,i,e);return nn(t,i),t};Object.defineProperty(O,"__esModule",{value:!0});O.readExtensionData=O.readExtension=O.readImage=O.hasExtension=O.readHeader=O.decompress=O.isCompressed=O.isNIFTI=O.isNIFTI2=O.isNIFTI1=O.NIFTIEXTENSION=O.Utils=O.NIFTI2=O.NIFTI1=void 0;var sn=rn(wi()),at=ue(),ct=Be(),Ci=jt(),an=ue();Object.defineProperty(O,"NIFTI1",{enumerable:!0,get:function(){return an.NIFTI1}});var on=Be();Object.defineProperty(O,"NIFTI2",{enumerable:!0,get:function(){return on.NIFTI2}});var ln=jt();Object.defineProperty(O,"Utils",{enumerable:!0,get:function(){return ln.Utils}});var fn=qe();Object.defineProperty(O,"NIFTIEXTENSION",{enumerable:!0,get:function(){return fn.NIFTIEXTENSION}});function Pe(i,t=!1){var e,n,r,a;return i.byteLength { + var __defProp = Object.defineProperty; var __getOwnPropNames = Object.getOwnPropertyNames; - var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { - get: (a, b) => (typeof require !== "undefined" ? require : a)[b] - }) : x)(function(x) { - if (typeof require !== "undefined") - return require.apply(this, arguments); - throw new Error('Dynamic require of "' + x + '" is not supported'); - }); - var __commonJS = (cb, mod) => function __require2() { + var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; + var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; - - // src/nifti-extension.js - var require_nifti_extension = __commonJS({ - "src/nifti-extension.js"(exports, module) { - "use strict"; - var nifti = nifti || {}; - nifti.NIFTIEXTENSION = nifti.NIFTIEXTENSION || function(esize, ecode, edata, littleEndian) { - if (esize % 16 != 0) { - throw new Error("This does not appear to be a NIFTI extension"); - } - this.esize = esize; - this.ecode = ecode; - this.edata = edata; - this.littleEndian = littleEndian; - }; - nifti.NIFTIEXTENSION.prototype.toArrayBuffer = function() { - let byteArray = new Uint8Array(this.esize); - byteArray.set(this.data.buffer, 8); - let view = new DataView(byteArray.buffer); - view.setInt32(0, this.esize, this.littleEndian); - view.setInt32(4, this.ecode, this.littleEndian); - return byteArray.buffer; - }; - var moduleType = typeof module; - if (moduleType !== "undefined" && module.exports) { - module.exports = nifti.NIFTIEXTENSION; - } - } - }); - - // src/utilities.js - var require_utilities = __commonJS({ - "src/utilities.js"(exports, module) { - "use strict"; - var nifti = nifti || {}; - nifti.Utils = nifti.Utils || {}; - nifti.NIFTIEXTENSION = nifti.NIFTIEXTENSION || (typeof __require !== "undefined" ? require_nifti_extension() : null); - nifti.Utils.crcTable = null; - nifti.Utils.GUNZIP_MAGIC_COOKIE1 = 31; - nifti.Utils.GUNZIP_MAGIC_COOKIE2 = 139; - nifti.Utils.getStringAt = function(data, start, end) { - var str = "", ctr, ch; - for (ctr = start; ctr < end; ctr += 1) { - ch = data.getUint8(ctr); - if (ch !== 0) { - str += String.fromCharCode(ch); - } - } - return str; - }; - nifti.Utils.getByteAt = function(data, start) { - return data.getInt8(start); - }; - nifti.Utils.getShortAt = function(data, start, littleEndian) { - return data.getInt16(start, littleEndian); - }; - nifti.Utils.getIntAt = function(data, start, littleEndian) { - return data.getInt32(start, littleEndian); - }; - nifti.Utils.getFloatAt = function(data, start, littleEndian) { - return data.getFloat32(start, littleEndian); - }; - nifti.Utils.getDoubleAt = function(data, start, littleEndian) { - return data.getFloat64(start, littleEndian); - }; - nifti.Utils.getLongAt = function(data, start, littleEndian) { - var ctr, array = [], value = 0; - for (ctr = 0; ctr < 8; ctr += 1) { - array[ctr] = nifti.Utils.getByteAt(data, start + ctr, littleEndian); - } - for (ctr = array.length - 1; ctr >= 0; ctr--) { - value = value * 256 + array[ctr]; - } - return value; - }; - nifti.Utils.getExtensionsAt = function(data, start, littleEndian, voxOffset) { - let extensions = []; - let extensionByteIndex = start; - while (extensionByteIndex < voxOffset) { - let extensionLittleEndian = littleEndian; - let esize = nifti.Utils.getIntAt(data, extensionByteIndex, littleEndian); - if (!esize) { - break; - } - if (esize + extensionByteIndex > voxOffset) { - extensionLittleEndian = !extensionLittleEndian; - esize = nifti.Utils.getIntAt(data, extensionByteIndex, extensionLittleEndian); - if (esize + extensionByteIndex > voxOffset) { - throw new Error("This does not appear to be a valid NIFTI extension"); - } - } - if (esize % 16 != 0) { - throw new Error("This does not appear to be a NIFTI extension"); - } - let ecode = nifti.Utils.getIntAt(data, extensionByteIndex + 4, extensionLittleEndian); - let edata = data.buffer.slice(extensionByteIndex + 8, extensionByteIndex + esize); - console.log("extensionByteIndex: " + (extensionByteIndex + 8) + " esize: " + esize); - console.log(edata); - let extension = new nifti.NIFTIEXTENSION(esize, ecode, edata, extensionLittleEndian); - extensions.push(extension); - extensionByteIndex += esize; - } - return extensions; - }; - nifti.Utils.toArrayBuffer = function(buffer) { - var ab, view, i; - ab = new ArrayBuffer(buffer.length); - view = new Uint8Array(ab); - for (i = 0; i < buffer.length; i += 1) { - view[i] = buffer[i]; - } - return ab; - }; - nifti.Utils.isString = function(obj) { - return typeof obj === "string" || obj instanceof String; - }; - nifti.Utils.formatNumber = function(num, shortFormat) { - var val = 0; - if (nifti.Utils.isString(num)) { - val = Number(num); - } else { - val = num; - } - if (shortFormat) { - val = val.toPrecision(5); - } else { - val = val.toPrecision(7); - } - return parseFloat(val); - }; - nifti.Utils.makeCRCTable = function() { - var c; - var crcTable = []; - for (var n = 0; n < 256; n++) { - c = n; - for (var k = 0; k < 8; k++) { - c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1; - } - crcTable[n] = c; - } - return crcTable; - }; - nifti.Utils.crc32 = function(dataView) { - var crcTable = nifti.Utils.crcTable || (nifti.Utils.crcTable = nifti.Utils.makeCRCTable()); - var crc = 0 ^ -1; - for (var i = 0; i < dataView.byteLength; i++) { - crc = crc >>> 8 ^ crcTable[(crc ^ dataView.getUint8(i)) & 255]; - } - return (crc ^ -1) >>> 0; - }; - var moduleType = typeof module; - if (moduleType !== "undefined" && module.exports) { - module.exports = nifti.Utils; - } - } - }); - - // src/nifti1.js - var require_nifti1 = __commonJS({ - "src/nifti1.js"(exports, module) { - "use strict"; - var NIFTIEXTENSION = require_nifti_extension(); - var nifti = nifti || {}; - nifti.Utils = nifti.Utils || (typeof __require !== "undefined" ? require_utilities() : null); - nifti.NIFTIEXTENSION = nifti.NIFTIEXTENSION || (typeof __require !== "undefined" ? require_nifti_extension() : null); - nifti.NIFTI1 = nifti.NIFTI1 || function() { - this.littleEndian = false; - this.dim_info = 0; - this.dims = []; - this.intent_p1 = 0; - this.intent_p2 = 0; - this.intent_p3 = 0; - this.intent_code = 0; - this.datatypeCode = 0; - this.numBitsPerVoxel = 0; - this.slice_start = 0; - this.slice_end = 0; - this.slice_code = 0; - this.pixDims = []; - this.vox_offset = 0; - this.scl_slope = 1; - this.scl_inter = 0; - this.xyzt_units = 0; - this.cal_max = 0; - this.cal_min = 0; - this.slice_duration = 0; - this.toffset = 0; - this.description = ""; - this.aux_file = ""; - this.intent_name = ""; - this.qform_code = 0; - this.sform_code = 0; - this.quatern_b = 0; - this.quatern_c = 0; - this.quatern_d = 0; - this.qoffset_x = 0; - this.qoffset_y = 0; - this.qoffset_z = 0; - this.affine = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]; - this.magic = 0; - this.isHDR = false; - this.extensionFlag = [0, 0, 0, 0]; - this.extensionSize = 0; - this.extensionCode = 0; - this.extensions = []; - }; - nifti.NIFTI1.TYPE_NONE = 0; - nifti.NIFTI1.TYPE_BINARY = 1; - nifti.NIFTI1.TYPE_UINT8 = 2; - nifti.NIFTI1.TYPE_INT16 = 4; - nifti.NIFTI1.TYPE_INT32 = 8; - nifti.NIFTI1.TYPE_FLOAT32 = 16; - nifti.NIFTI1.TYPE_COMPLEX64 = 32; - nifti.NIFTI1.TYPE_FLOAT64 = 64; - nifti.NIFTI1.TYPE_RGB24 = 128; - nifti.NIFTI1.TYPE_INT8 = 256; - nifti.NIFTI1.TYPE_UINT16 = 512; - nifti.NIFTI1.TYPE_UINT32 = 768; - nifti.NIFTI1.TYPE_INT64 = 1024; - nifti.NIFTI1.TYPE_UINT64 = 1280; - nifti.NIFTI1.TYPE_FLOAT128 = 1536; - nifti.NIFTI1.TYPE_COMPLEX128 = 1792; - nifti.NIFTI1.TYPE_COMPLEX256 = 2048; - nifti.NIFTI1.XFORM_UNKNOWN = 0; - nifti.NIFTI1.XFORM_SCANNER_ANAT = 1; - nifti.NIFTI1.XFORM_ALIGNED_ANAT = 2; - nifti.NIFTI1.XFORM_TALAIRACH = 3; - nifti.NIFTI1.XFORM_MNI_152 = 4; - nifti.NIFTI1.SPATIAL_UNITS_MASK = 7; - nifti.NIFTI1.TEMPORAL_UNITS_MASK = 56; - nifti.NIFTI1.UNITS_UNKNOWN = 0; - nifti.NIFTI1.UNITS_METER = 1; - nifti.NIFTI1.UNITS_MM = 2; - nifti.NIFTI1.UNITS_MICRON = 3; - nifti.NIFTI1.UNITS_SEC = 8; - nifti.NIFTI1.UNITS_MSEC = 16; - nifti.NIFTI1.UNITS_USEC = 24; - nifti.NIFTI1.UNITS_HZ = 32; - nifti.NIFTI1.UNITS_PPM = 40; - nifti.NIFTI1.UNITS_RADS = 48; - nifti.NIFTI1.MAGIC_COOKIE = 348; - nifti.NIFTI1.STANDARD_HEADER_SIZE = 348; - nifti.NIFTI1.MAGIC_NUMBER_LOCATION = 344; - nifti.NIFTI1.MAGIC_NUMBER = [110, 43, 49]; - nifti.NIFTI1.MAGIC_NUMBER2 = [110, 105, 49]; - nifti.NIFTI1.EXTENSION_HEADER_SIZE = 8; - nifti.NIFTI1.prototype.readHeader = function(data) { - var rawData = new DataView(data), magicCookieVal = nifti.Utils.getIntAt(rawData, 0, this.littleEndian), ctr, ctrOut, ctrIn, index; - if (magicCookieVal !== nifti.NIFTI1.MAGIC_COOKIE) { - this.littleEndian = true; - magicCookieVal = nifti.Utils.getIntAt(rawData, 0, this.littleEndian); - } - if (magicCookieVal !== nifti.NIFTI1.MAGIC_COOKIE) { - throw new Error("This does not appear to be a NIFTI file!"); - } - this.dim_info = nifti.Utils.getByteAt(rawData, 39); - for (ctr = 0; ctr < 8; ctr += 1) { - index = 40 + ctr * 2; - this.dims[ctr] = nifti.Utils.getShortAt(rawData, index, this.littleEndian); - } - this.intent_p1 = nifti.Utils.getFloatAt(rawData, 56, this.littleEndian); - this.intent_p2 = nifti.Utils.getFloatAt(rawData, 60, this.littleEndian); - this.intent_p3 = nifti.Utils.getFloatAt(rawData, 64, this.littleEndian); - this.intent_code = nifti.Utils.getShortAt(rawData, 68, this.littleEndian); - this.datatypeCode = nifti.Utils.getShortAt(rawData, 70, this.littleEndian); - this.numBitsPerVoxel = nifti.Utils.getShortAt(rawData, 72, this.littleEndian); - this.slice_start = nifti.Utils.getShortAt(rawData, 74, this.littleEndian); - for (ctr = 0; ctr < 8; ctr += 1) { - index = 76 + ctr * 4; - this.pixDims[ctr] = nifti.Utils.getFloatAt(rawData, index, this.littleEndian); - } - this.vox_offset = nifti.Utils.getFloatAt(rawData, 108, this.littleEndian); - this.scl_slope = nifti.Utils.getFloatAt(rawData, 112, this.littleEndian); - this.scl_inter = nifti.Utils.getFloatAt(rawData, 116, this.littleEndian); - this.slice_end = nifti.Utils.getShortAt(rawData, 120, this.littleEndian); - this.slice_code = nifti.Utils.getByteAt(rawData, 122); - this.xyzt_units = nifti.Utils.getByteAt(rawData, 123); - this.cal_max = nifti.Utils.getFloatAt(rawData, 124, this.littleEndian); - this.cal_min = nifti.Utils.getFloatAt(rawData, 128, this.littleEndian); - this.slice_duration = nifti.Utils.getFloatAt(rawData, 132, this.littleEndian); - this.toffset = nifti.Utils.getFloatAt(rawData, 136, this.littleEndian); - this.description = nifti.Utils.getStringAt(rawData, 148, 228); - this.aux_file = nifti.Utils.getStringAt(rawData, 228, 252); - this.qform_code = nifti.Utils.getShortAt(rawData, 252, this.littleEndian); - this.sform_code = nifti.Utils.getShortAt(rawData, 254, this.littleEndian); - this.quatern_b = nifti.Utils.getFloatAt(rawData, 256, this.littleEndian); - this.quatern_c = nifti.Utils.getFloatAt(rawData, 260, this.littleEndian); - this.quatern_d = nifti.Utils.getFloatAt(rawData, 264, this.littleEndian); - this.quatern_a = Math.sqrt(1 - (Math.pow(this.quatern_b, 2) + Math.pow(this.quatern_c, 2) + Math.pow(this.quatern_d, 2))); - this.qoffset_x = nifti.Utils.getFloatAt(rawData, 268, this.littleEndian); - this.qoffset_y = nifti.Utils.getFloatAt(rawData, 272, this.littleEndian); - this.qoffset_z = nifti.Utils.getFloatAt(rawData, 276, this.littleEndian); - if (this.qform_code < 1 && this.sform_code < 1) { - this.affine[0][0] = this.pixDims[1]; - this.affine[1][1] = this.pixDims[2]; - this.affine[2][2] = this.pixDims[3]; - } - if (this.qform_code > 0 && this.sform_code < this.qform_code) { - const a = this.quatern_a; - const b = this.quatern_b; - const c = this.quatern_c; - const d = this.quatern_d; - this.qfac = this.pixDims[0] === 0 ? 1 : this.pixDims[0]; - this.quatern_R = [ - [a * a + b * b - c * c - d * d, 2 * b * c - 2 * a * d, 2 * b * d + 2 * a * c], - [2 * b * c + 2 * a * d, a * a + c * c - b * b - d * d, 2 * c * d - 2 * a * b], - [2 * b * d - 2 * a * c, 2 * c * d + 2 * a * b, a * a + d * d - c * c - b * b] - ]; - for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { - for (ctrIn = 0; ctrIn < 3; ctrIn += 1) { - this.affine[ctrOut][ctrIn] = this.quatern_R[ctrOut][ctrIn] * this.pixDims[ctrIn + 1]; - if (ctrIn === 2) { - this.affine[ctrOut][ctrIn] *= this.qfac; - } - } - } - this.affine[0][3] = this.qoffset_x; - this.affine[1][3] = this.qoffset_y; - this.affine[2][3] = this.qoffset_z; - } else if (this.sform_code > 0) { - for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { - for (ctrIn = 0; ctrIn < 4; ctrIn += 1) { - index = 280 + (ctrOut * 4 + ctrIn) * 4; - this.affine[ctrOut][ctrIn] = nifti.Utils.getFloatAt(rawData, index, this.littleEndian); - } - } - } - this.affine[3][0] = 0; - this.affine[3][1] = 0; - this.affine[3][2] = 0; - this.affine[3][3] = 1; - this.intent_name = nifti.Utils.getStringAt(rawData, 328, 344); - this.magic = nifti.Utils.getStringAt(rawData, 344, 348); - this.isHDR = this.magic === nifti.NIFTI1.MAGIC_NUMBER2; - if (rawData.byteLength > nifti.NIFTI1.MAGIC_COOKIE) { - this.extensionFlag[0] = nifti.Utils.getByteAt(rawData, 348); - this.extensionFlag[1] = nifti.Utils.getByteAt(rawData, 348 + 1); - this.extensionFlag[2] = nifti.Utils.getByteAt(rawData, 348 + 2); - this.extensionFlag[3] = nifti.Utils.getByteAt(rawData, 348 + 3); - if (this.extensionFlag[0]) { - this.extensions = nifti.Utils.getExtensionsAt( - rawData, - this.getExtensionLocation(), - this.littleEndian, - this.vox_offset - ); - this.extensionSize = this.extensions[0].esize; - this.extensionCode = this.extensions[0].ecode; - } - } - }; - nifti.NIFTI1.prototype.toFormattedString = function() { - var fmt = nifti.Utils.formatNumber, string = ""; - string += "Dim Info = " + this.dim_info + "\n"; - string += "Image Dimensions (1-8): " + this.dims[0] + ", " + this.dims[1] + ", " + this.dims[2] + ", " + this.dims[3] + ", " + this.dims[4] + ", " + this.dims[5] + ", " + this.dims[6] + ", " + this.dims[7] + "\n"; - string += "Intent Parameters (1-3): " + this.intent_p1 + ", " + this.intent_p2 + ", " + this.intent_p3 + "\n"; - string += "Intent Code = " + this.intent_code + "\n"; - string += "Datatype = " + this.datatypeCode + " (" + this.getDatatypeCodeString(this.datatypeCode) + ")\n"; - string += "Bits Per Voxel = " + this.numBitsPerVoxel + "\n"; - string += "Slice Start = " + this.slice_start + "\n"; - string += "Voxel Dimensions (1-8): " + fmt(this.pixDims[0]) + ", " + fmt(this.pixDims[1]) + ", " + fmt(this.pixDims[2]) + ", " + fmt(this.pixDims[3]) + ", " + fmt(this.pixDims[4]) + ", " + fmt(this.pixDims[5]) + ", " + fmt(this.pixDims[6]) + ", " + fmt(this.pixDims[7]) + "\n"; - string += "Image Offset = " + this.vox_offset + "\n"; - string += "Data Scale: Slope = " + fmt(this.scl_slope) + " Intercept = " + fmt(this.scl_inter) + "\n"; - string += "Slice End = " + this.slice_end + "\n"; - string += "Slice Code = " + this.slice_code + "\n"; - string += "Units Code = " + this.xyzt_units + " (" + this.getUnitsCodeString(nifti.NIFTI1.SPATIAL_UNITS_MASK & this.xyzt_units) + ", " + this.getUnitsCodeString(nifti.NIFTI1.TEMPORAL_UNITS_MASK & this.xyzt_units) + ")\n"; - string += "Display Range: Max = " + fmt(this.cal_max) + " Min = " + fmt(this.cal_min) + "\n"; - string += "Slice Duration = " + this.slice_duration + "\n"; - string += "Time Axis Shift = " + this.toffset + "\n"; - string += 'Description: "' + this.description + '"\n'; - string += 'Auxiliary File: "' + this.aux_file + '"\n'; - string += "Q-Form Code = " + this.qform_code + " (" + this.getTransformCodeString(this.qform_code) + ")\n"; - string += "S-Form Code = " + this.sform_code + " (" + this.getTransformCodeString(this.sform_code) + ")\n"; - string += "Quaternion Parameters: b = " + fmt(this.quatern_b) + " c = " + fmt(this.quatern_c) + " d = " + fmt(this.quatern_d) + "\n"; - string += "Quaternion Offsets: x = " + this.qoffset_x + " y = " + this.qoffset_y + " z = " + this.qoffset_z + "\n"; - string += "S-Form Parameters X: " + fmt(this.affine[0][0]) + ", " + fmt(this.affine[0][1]) + ", " + fmt(this.affine[0][2]) + ", " + fmt(this.affine[0][3]) + "\n"; - string += "S-Form Parameters Y: " + fmt(this.affine[1][0]) + ", " + fmt(this.affine[1][1]) + ", " + fmt(this.affine[1][2]) + ", " + fmt(this.affine[1][3]) + "\n"; - string += "S-Form Parameters Z: " + fmt(this.affine[2][0]) + ", " + fmt(this.affine[2][1]) + ", " + fmt(this.affine[2][2]) + ", " + fmt(this.affine[2][3]) + "\n"; - string += 'Intent Name: "' + this.intent_name + '"\n'; - if (this.extensionFlag[0]) { - string += "Extension: Size = " + this.extensionSize + " Code = " + this.extensionCode + "\n"; - } - return string; - }; - nifti.NIFTI1.prototype.getDatatypeCodeString = function(code) { - if (code === nifti.NIFTI1.TYPE_UINT8) { - return "1-Byte Unsigned Integer"; - } else if (code === nifti.NIFTI1.TYPE_INT16) { - return "2-Byte Signed Integer"; - } else if (code === nifti.NIFTI1.TYPE_INT32) { - return "4-Byte Signed Integer"; - } else if (code === nifti.NIFTI1.TYPE_FLOAT32) { - return "4-Byte Float"; - } else if (code === nifti.NIFTI1.TYPE_FLOAT64) { - return "8-Byte Float"; - } else if (code === nifti.NIFTI1.TYPE_RGB24) { - return "RGB"; - } else if (code === nifti.NIFTI1.TYPE_INT8) { - return "1-Byte Signed Integer"; - } else if (code === nifti.NIFTI1.TYPE_UINT16) { - return "2-Byte Unsigned Integer"; - } else if (code === nifti.NIFTI1.TYPE_UINT32) { - return "4-Byte Unsigned Integer"; - } else if (code === nifti.NIFTI1.TYPE_INT64) { - return "8-Byte Signed Integer"; - } else if (code === nifti.NIFTI1.TYPE_UINT64) { - return "8-Byte Unsigned Integer"; - } else { - return "Unknown"; - } - }; - nifti.NIFTI1.prototype.getTransformCodeString = function(code) { - if (code === nifti.NIFTI1.XFORM_SCANNER_ANAT) { - return "Scanner"; - } else if (code === nifti.NIFTI1.XFORM_ALIGNED_ANAT) { - return "Aligned"; - } else if (code === nifti.NIFTI1.XFORM_TALAIRACH) { - return "Talairach"; - } else if (code === nifti.NIFTI1.XFORM_MNI_152) { - return "MNI"; - } else { - return "Unknown"; - } - }; - nifti.NIFTI1.prototype.getUnitsCodeString = function(code) { - if (code === nifti.NIFTI1.UNITS_METER) { - return "Meters"; - } else if (code === nifti.NIFTI1.UNITS_MM) { - return "Millimeters"; - } else if (code === nifti.NIFTI1.UNITS_MICRON) { - return "Microns"; - } else if (code === nifti.NIFTI1.UNITS_SEC) { - return "Seconds"; - } else if (code === nifti.NIFTI1.UNITS_MSEC) { - return "Milliseconds"; - } else if (code === nifti.NIFTI1.UNITS_USEC) { - return "Microseconds"; - } else if (code === nifti.NIFTI1.UNITS_HZ) { - return "Hz"; - } else if (code === nifti.NIFTI1.UNITS_PPM) { - return "PPM"; - } else if (code === nifti.NIFTI1.UNITS_RADS) { - return "Rads"; - } else { - return "Unknown"; - } - }; - nifti.NIFTI1.prototype.getQformMat = function() { - return this.convertNiftiQFormToNiftiSForm( - this.quatern_b, - this.quatern_c, - this.quatern_d, - this.qoffset_x, - this.qoffset_y, - this.qoffset_z, - this.pixDims[1], - this.pixDims[2], - this.pixDims[3], - this.pixDims[0] - ); - }; - nifti.NIFTI1.prototype.convertNiftiQFormToNiftiSForm = function(qb, qc, qd, qx, qy, qz, dx, dy, dz, qfac) { - var R = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], a, b = qb, c = qc, d = qd, xd, yd, zd; - R[3][0] = R[3][1] = R[3][2] = 0; - R[3][3] = 1; - a = 1 - (b * b + c * c + d * d); - if (a < 1e-7) { - a = 1 / Math.sqrt(b * b + c * c + d * d); - b *= a; - c *= a; - d *= a; - a = 0; - } else { - a = Math.sqrt(a); - } - xd = dx > 0 ? dx : 1; - yd = dy > 0 ? dy : 1; - zd = dz > 0 ? dz : 1; - if (qfac < 0) { - zd = -zd; - } - R[0][0] = (a * a + b * b - c * c - d * d) * xd; - R[0][1] = 2 * (b * c - a * d) * yd; - R[0][2] = 2 * (b * d + a * c) * zd; - R[1][0] = 2 * (b * c + a * d) * xd; - R[1][1] = (a * a + c * c - b * b - d * d) * yd; - R[1][2] = 2 * (c * d - a * b) * zd; - R[2][0] = 2 * (b * d - a * c) * xd; - R[2][1] = 2 * (c * d + a * b) * yd; - R[2][2] = (a * a + d * d - c * c - b * b) * zd; - R[0][3] = qx; - R[1][3] = qy; - R[2][3] = qz; - return R; - }; - nifti.NIFTI1.prototype.convertNiftiSFormToNEMA = function(R) { - var xi, xj, xk, yi, yj, yk, zi, zj, zk, val, detQ, detP, i, j, k, p, q, r, ibest, jbest, kbest, pbest, qbest, rbest, M, vbest, Q, P, iChar, jChar, kChar, iSense, jSense, kSense; - k = 0; - Q = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]; - P = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]; - xi = R[0][0]; - xj = R[0][1]; - xk = R[0][2]; - yi = R[1][0]; - yj = R[1][1]; - yk = R[1][2]; - zi = R[2][0]; - zj = R[2][1]; - zk = R[2][2]; - val = Math.sqrt(xi * xi + yi * yi + zi * zi); - if (val === 0) { - return null; - } - xi /= val; - yi /= val; - zi /= val; - val = Math.sqrt(xj * xj + yj * yj + zj * zj); - if (val === 0) { - return null; - } - xj /= val; - yj /= val; - zj /= val; - val = xi * xj + yi * yj + zi * zj; - if (Math.abs(val) > 1e-4) { - xj -= val * xi; - yj -= val * yi; - zj -= val * zi; - val = Math.sqrt(xj * xj + yj * yj + zj * zj); - if (val === 0) { - return null; - } - xj /= val; - yj /= val; - zj /= val; - } - val = Math.sqrt(xk * xk + yk * yk + zk * zk); - if (val === 0) { - xk = yi * zj - zi * yj; - yk = zi * xj - zj * xi; - zk = xi * yj - yi * xj; - } else { - xk /= val; - yk /= val; - zk /= val; - } - val = xi * xk + yi * yk + zi * zk; - if (Math.abs(val) > 1e-4) { - xk -= val * xi; - yk -= val * yi; - zk -= val * zi; - val = Math.sqrt(xk * xk + yk * yk + zk * zk); - if (val === 0) { - return null; - } - xk /= val; - yk /= val; - zk /= val; - } - val = xj * xk + yj * yk + zj * zk; - if (Math.abs(val) > 1e-4) { - xk -= val * xj; - yk -= val * yj; - zk -= val * zj; - val = Math.sqrt(xk * xk + yk * yk + zk * zk); - if (val === 0) { - return null; - } - xk /= val; - yk /= val; - zk /= val; - } - Q[0][0] = xi; - Q[0][1] = xj; - Q[0][2] = xk; - Q[1][0] = yi; - Q[1][1] = yj; - Q[1][2] = yk; - Q[2][0] = zi; - Q[2][1] = zj; - Q[2][2] = zk; - detQ = this.nifti_mat33_determ(Q); - if (detQ === 0) { - return null; - } - vbest = -666; - ibest = pbest = qbest = rbest = 1; - jbest = 2; - kbest = 3; - for (i = 1; i <= 3; i += 1) { - for (j = 1; j <= 3; j += 1) { - if (i !== j) { - for (k = 1; k <= 3; k += 1) { - if (!(i === k || j === k)) { - P[0][0] = P[0][1] = P[0][2] = P[1][0] = P[1][1] = P[1][2] = P[2][0] = P[2][1] = P[2][2] = 0; - for (p = -1; p <= 1; p += 2) { - for (q = -1; q <= 1; q += 2) { - for (r = -1; r <= 1; r += 2) { - P[0][i - 1] = p; - P[1][j - 1] = q; - P[2][k - 1] = r; - detP = this.nifti_mat33_determ(P); - if (detP * detQ > 0) { - M = this.nifti_mat33_mul(P, Q); - val = M[0][0] + M[1][1] + M[2][2]; - if (val > vbest) { - vbest = val; - ibest = i; - jbest = j; - kbest = k; - pbest = p; - qbest = q; - rbest = r; - } - } - } - } - } - } - } - } - } - } - iChar = jChar = kChar = iSense = jSense = kSense = 0; - switch (ibest * pbest) { - case 1: - iChar = "X"; - iSense = "+"; - break; - case -1: - iChar = "X"; - iSense = "-"; - break; - case 2: - iChar = "Y"; - iSense = "+"; - break; - case -2: - iChar = "Y"; - iSense = "-"; - break; - case 3: - iChar = "Z"; - iSense = "+"; - break; - case -3: - iChar = "Z"; - iSense = "-"; - break; - } - switch (jbest * qbest) { - case 1: - jChar = "X"; - jSense = "+"; - break; - case -1: - jChar = "X"; - jSense = "-"; - break; - case 2: - jChar = "Y"; - jSense = "+"; - break; - case -2: - jChar = "Y"; - jSense = "-"; - break; - case 3: - jChar = "Z"; - jSense = "+"; - break; - case -3: - jChar = "Z"; - jSense = "-"; - break; - } - switch (kbest * rbest) { - case 1: - kChar = "X"; - kSense = "+"; - break; - case -1: - kChar = "X"; - kSense = "-"; - break; - case 2: - kChar = "Y"; - kSense = "+"; - break; - case -2: - kChar = "Y"; - kSense = "-"; - break; - case 3: - kChar = "Z"; - kSense = "+"; - break; - case -3: - kChar = "Z"; - kSense = "-"; - break; - } - return iChar + jChar + kChar + iSense + jSense + kSense; - }; - nifti.NIFTI1.prototype.nifti_mat33_mul = function(A, B) { - var C = [[0, 0, 0], [0, 0, 0], [0, 0, 0]], i, j; - for (i = 0; i < 3; i += 1) { - for (j = 0; j < 3; j += 1) { - C[i][j] = A[i][0] * B[0][j] + A[i][1] * B[1][j] + A[i][2] * B[2][j]; - } - } - return C; - }; - nifti.NIFTI1.prototype.nifti_mat33_determ = function(R) { - var r11, r12, r13, r21, r22, r23, r31, r32, r33; - r11 = R[0][0]; - r12 = R[0][1]; - r13 = R[0][2]; - r21 = R[1][0]; - r22 = R[1][1]; - r23 = R[1][2]; - r31 = R[2][0]; - r32 = R[2][1]; - r33 = R[2][2]; - return r11 * r22 * r33 - r11 * r32 * r23 - r21 * r12 * r33 + r21 * r32 * r13 + r31 * r12 * r23 - r31 * r22 * r13; - }; - nifti.NIFTI1.prototype.getExtensionLocation = function() { - return nifti.NIFTI1.MAGIC_COOKIE + 4; - }; - nifti.NIFTI1.prototype.getExtensionSize = function(data) { - return nifti.Utils.getIntAt(data, this.getExtensionLocation(), this.littleEndian); - }; - nifti.NIFTI1.prototype.getExtensionCode = function(data) { - return nifti.Utils.getIntAt(data, this.getExtensionLocation() + 4, this.littleEndian); - }; - nifti.NIFTI1.prototype.addExtension = function(extension, index = -1) { - if (index == -1) { - this.extensions.push(extension); - } else { - this.extensions.splice(index, 0, extension); - } - this.vox_offset += extension.esize; - }; - nifti.NIFTI1.prototype.removeExtension = function(index) { - let extension = this.extensions[index]; - if (extension) { - this.vox_offset -= extension.esize; - } - this.extensions.splice(index, 1); - }; - nifti.NIFTI1.prototype.toArrayBuffer = function(includeExtensions = false) { - const SHORT_SIZE = 2; - const FLOAT32_SIZE = 4; - let byteSize = 348 + 4; - if (includeExtensions) { - for (let extension of this.extensions) { - byteSize += extension.esize; - } - } - let byteArray = new Uint8Array(byteSize); - let view = new DataView(byteArray.buffer); - view.setInt32(0, 348, this.littleEndian); - view.setUint8(39, this.dim_info); - for (let i = 0; i < 8; i++) { - view.setUint16(40 + SHORT_SIZE * i, this.dims[i], this.littleEndian); - } - view.setFloat32(56, this.intent_p1, this.littleEndian); - view.setFloat32(60, this.intent_p2, this.littleEndian); - view.setFloat32(64, this.intent_p3, this.littleEndian); - view.setInt16(68, this.intent_code, this.littleEndian); - view.setInt16(70, this.datatypeCode, this.littleEndian); - view.setInt16(72, this.numBitsPerVoxel, this.littleEndian); - view.setInt16(74, this.slice_start, this.littleEndian); - for (let i = 0; i < 8; i++) { - view.setFloat32(76 + FLOAT32_SIZE * i, this.pixDims[i], this.littleEndian); - } - view.setFloat32(108, this.vox_offset, this.littleEndian); - view.setFloat32(112, this.scl_slope, this.littleEndian); - view.setFloat32(116, this.scl_inter, this.littleEndian); - view.setInt16(120, this.slice_end, this.littleEndian); - view.setUint8(122, this.slice_code); - view.setUint8(123, this.xyzt_units); - view.setFloat32(124, this.cal_max, this.littleEndian); - view.setFloat32(128, this.cal_min, this.littleEndian); - view.setFloat32(132, this.slice_duration, this.littleEndian); - view.setFloat32(136, this.toffset, this.littleEndian); - byteArray.set(Buffer.from(this.description), 148); - byteArray.set(Buffer.from(this.aux_file), 228); - view.setInt16(252, this.qform_code, this.littleEndian); - view.setInt16(254, this.sform_code, this.littleEndian); - view.setFloat32(256, this.quatern_b, this.littleEndian); - view.setFloat32(260, this.quatern_c, this.littleEndian); - view.setFloat32(264, this.quatern_d, this.littleEndian); - view.setFloat32(268, this.qoffset_x, this.littleEndian); - view.setFloat32(272, this.qoffset_y, this.littleEndian); - view.setFloat32(276, this.qoffset_z, this.littleEndian); - const flattened = this.affine.flat(); - for (let i = 0; i < 12; i++) { - view.setFloat32(280 + FLOAT32_SIZE * i, flattened[i], this.littleEndian); - } - byteArray.set(Buffer.from(this.intent_name), 328); - byteArray.set(Buffer.from(this.magic), 344); - if (includeExtensions) { - byteArray.set(Uint8Array.from([1, 0, 0, 0]), 348); - let extensionByteIndex = this.getExtensionLocation(); - for (const extension of this.extensions) { - view.setInt32(extensionByteIndex, extension.esize, extension.littleEndian); - view.setInt32(extensionByteIndex + 4, extension.ecode, extension.littleEndian); - byteArray.set(new Uint8Array(extension.edata), extensionByteIndex + 8); - extensionByteIndex += extension.esize; - } - } else { - byteArray.set(new Uint8Array(4).fill(0), 348); - } - return byteArray.buffer; - }; - var moduleType = typeof module; - if (moduleType !== "undefined" && module.exports) { - module.exports = nifti.NIFTI1; - } - } - }); - - // src/nifti2.js - var require_nifti2 = __commonJS({ - "src/nifti2.js"(exports, module) { - "use strict"; - var nifti = nifti || {}; - nifti.Utils = nifti.Utils || (typeof __require !== "undefined" ? require_utilities() : null); - nifti.NIFTI1 = nifti.NIFTI1 || (typeof __require !== "undefined" ? require_nifti1() : null); - nifti.NIFTIEXTENSION = nifti.NIFTIEXTENSION || (typeof __require !== "undefined" ? require_nifti_extension() : null); - nifti.NIFTI2 = nifti.NIFTI2 || function() { - this.littleEndian = false; - this.dim_info = 0; - this.dims = []; - this.intent_p1 = 0; - this.intent_p2 = 0; - this.intent_p3 = 0; - this.intent_code = 0; - this.datatypeCode = 0; - this.numBitsPerVoxel = 0; - this.slice_start = 0; - this.slice_end = 0; - this.slice_code = 0; - this.pixDims = []; - this.vox_offset = 0; - this.scl_slope = 1; - this.scl_inter = 0; - this.xyzt_units = 0; - this.cal_max = 0; - this.cal_min = 0; - this.slice_duration = 0; - this.toffset = 0; - this.description = ""; - this.aux_file = ""; - this.intent_name = ""; - this.qform_code = 0; - this.sform_code = 0; - this.quatern_b = 0; - this.quatern_c = 0; - this.quatern_d = 0; - this.qoffset_x = 0; - this.qoffset_y = 0; - this.qoffset_z = 0; - this.affine = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]; - this.magic = 0; - this.extensionFlag = [0, 0, 0, 0]; - this.extensions = []; - }; - nifti.NIFTI2.MAGIC_COOKIE = 540; - nifti.NIFTI2.MAGIC_NUMBER_LOCATION = 4; - nifti.NIFTI2.MAGIC_NUMBER = [110, 43, 50, 0, 13, 10, 26, 10]; - nifti.NIFTI2.MAGIC_NUMBER2 = [110, 105, 50, 0, 13, 10, 26, 10]; - nifti.NIFTI2.prototype.readHeader = function(data) { - var rawData = new DataView(data), magicCookieVal = nifti.Utils.getIntAt(rawData, 0, this.littleEndian), ctr, ctrOut, ctrIn, index, array; - if (magicCookieVal !== nifti.NIFTI2.MAGIC_COOKIE) { - this.littleEndian = true; - magicCookieVal = nifti.Utils.getIntAt(rawData, 0, this.littleEndian); - } - if (magicCookieVal !== nifti.NIFTI2.MAGIC_COOKIE) { - throw new Error("This does not appear to be a NIFTI file!"); - } - this.magic = nifti.Utils.getStringAt(rawData, 4, 12); - this.datatypeCode = nifti.Utils.getShortAt(rawData, 12, this.littleEndian); - this.numBitsPerVoxel = nifti.Utils.getShortAt(rawData, 14, this.littleEndian); - for (ctr = 0; ctr < 8; ctr += 1) { - index = 16 + ctr * 8; - this.dims[ctr] = nifti.Utils.getLongAt(rawData, index, this.littleEndian); - } - this.intent_p1 = nifti.Utils.getDoubleAt(rawData, 80, this.littleEndian); - this.intent_p2 = nifti.Utils.getDoubleAt(rawData, 88, this.littleEndian); - this.intent_p3 = nifti.Utils.getDoubleAt(rawData, 96, this.littleEndian); - for (ctr = 0; ctr < 8; ctr += 1) { - index = 104 + ctr * 8; - this.pixDims[ctr] = nifti.Utils.getDoubleAt(rawData, index, this.littleEndian); - } - this.vox_offset = nifti.Utils.getLongAt(rawData, 168, this.littleEndian); - this.scl_slope = nifti.Utils.getDoubleAt(rawData, 176, this.littleEndian); - this.scl_inter = nifti.Utils.getDoubleAt(rawData, 184, this.littleEndian); - this.cal_max = nifti.Utils.getDoubleAt(rawData, 192, this.littleEndian); - this.cal_min = nifti.Utils.getDoubleAt(rawData, 200, this.littleEndian); - this.slice_duration = nifti.Utils.getDoubleAt(rawData, 208, this.littleEndian); - this.toffset = nifti.Utils.getDoubleAt(rawData, 216, this.littleEndian); - this.slice_start = nifti.Utils.getLongAt(rawData, 224, this.littleEndian); - this.slice_end = nifti.Utils.getLongAt(rawData, 232, this.littleEndian); - this.description = nifti.Utils.getStringAt(rawData, 240, 240 + 80); - this.aux_file = nifti.Utils.getStringAt(rawData, 320, 320 + 24); - this.qform_code = nifti.Utils.getIntAt(rawData, 344, this.littleEndian); - this.sform_code = nifti.Utils.getIntAt(rawData, 348, this.littleEndian); - this.quatern_b = nifti.Utils.getDoubleAt(rawData, 352, this.littleEndian); - this.quatern_c = nifti.Utils.getDoubleAt(rawData, 360, this.littleEndian); - this.quatern_d = nifti.Utils.getDoubleAt(rawData, 368, this.littleEndian); - this.qoffset_x = nifti.Utils.getDoubleAt(rawData, 376, this.littleEndian); - this.qoffset_y = nifti.Utils.getDoubleAt(rawData, 384, this.littleEndian); - this.qoffset_z = nifti.Utils.getDoubleAt(rawData, 392, this.littleEndian); - for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { - for (ctrIn = 0; ctrIn < 4; ctrIn += 1) { - index = 400 + (ctrOut * 4 + ctrIn) * 8; - this.affine[ctrOut][ctrIn] = nifti.Utils.getDoubleAt(rawData, index, this.littleEndian); - } - } - this.affine[3][0] = 0; - this.affine[3][1] = 0; - this.affine[3][2] = 0; - this.affine[3][3] = 1; - this.slice_code = nifti.Utils.getIntAt(rawData, 496, this.littleEndian); - this.xyzt_units = nifti.Utils.getIntAt(rawData, 500, this.littleEndian); - this.intent_code = nifti.Utils.getIntAt(rawData, 504, this.littleEndian); - this.intent_name = nifti.Utils.getStringAt(rawData, 508, 508 + 16); - this.dim_info = nifti.Utils.getByteAt(rawData, 524); - if (rawData.byteLength > nifti.NIFTI2.MAGIC_COOKIE) { - this.extensionFlag[0] = nifti.Utils.getByteAt(rawData, 540); - this.extensionFlag[1] = nifti.Utils.getByteAt(rawData, 540 + 1); - this.extensionFlag[2] = nifti.Utils.getByteAt(rawData, 540 + 2); - this.extensionFlag[3] = nifti.Utils.getByteAt(rawData, 540 + 3); - if (this.extensionFlag[0]) { - this.extensions = nifti.Utils.getExtensionsAt( - rawData, - this.getExtensionLocation(), - this.littleEndian, - this.vox_offset - ); - this.extensionSize = this.extensions[0].esize; - this.extensionCode = this.extensions[0].ecode; - } - } - }; - nifti.NIFTI2.prototype.toFormattedString = function() { - var fmt = nifti.Utils.formatNumber, string = ""; - string += "Datatype = " + +this.datatypeCode + " (" + this.getDatatypeCodeString(this.datatypeCode) + ")\n"; - string += "Bits Per Voxel = = " + this.numBitsPerVoxel + "\n"; - string += "Image Dimensions (1-8): " + this.dims[0] + ", " + this.dims[1] + ", " + this.dims[2] + ", " + this.dims[3] + ", " + this.dims[4] + ", " + this.dims[5] + ", " + this.dims[6] + ", " + this.dims[7] + "\n"; - string += "Intent Parameters (1-3): " + this.intent_p1 + ", " + this.intent_p2 + ", " + this.intent_p3 + "\n"; - string += "Voxel Dimensions (1-8): " + fmt(this.pixDims[0]) + ", " + fmt(this.pixDims[1]) + ", " + fmt(this.pixDims[2]) + ", " + fmt(this.pixDims[3]) + ", " + fmt(this.pixDims[4]) + ", " + fmt(this.pixDims[5]) + ", " + fmt(this.pixDims[6]) + ", " + fmt(this.pixDims[7]) + "\n"; - string += "Image Offset = " + this.vox_offset + "\n"; - string += "Data Scale: Slope = " + fmt(this.scl_slope) + " Intercept = " + fmt(this.scl_inter) + "\n"; - string += "Display Range: Max = " + fmt(this.cal_max) + " Min = " + fmt(this.cal_min) + "\n"; - string += "Slice Duration = " + this.slice_duration + "\n"; - string += "Time Axis Shift = " + this.toffset + "\n"; - string += "Slice Start = " + this.slice_start + "\n"; - string += "Slice End = " + this.slice_end + "\n"; - string += 'Description: "' + this.description + '"\n'; - string += 'Auxiliary File: "' + this.aux_file + '"\n'; - string += "Q-Form Code = " + this.qform_code + " (" + this.getTransformCodeString(this.qform_code) + ")\n"; - string += "S-Form Code = " + this.sform_code + " (" + this.getTransformCodeString(this.sform_code) + ")\n"; - string += "Quaternion Parameters: b = " + fmt(this.quatern_b) + " c = " + fmt(this.quatern_c) + " d = " + fmt(this.quatern_d) + "\n"; - string += "Quaternion Offsets: x = " + this.qoffset_x + " y = " + this.qoffset_y + " z = " + this.qoffset_z + "\n"; - string += "S-Form Parameters X: " + fmt(this.affine[0][0]) + ", " + fmt(this.affine[0][1]) + ", " + fmt(this.affine[0][2]) + ", " + fmt(this.affine[0][3]) + "\n"; - string += "S-Form Parameters Y: " + fmt(this.affine[1][0]) + ", " + fmt(this.affine[1][1]) + ", " + fmt(this.affine[1][2]) + ", " + fmt(this.affine[1][3]) + "\n"; - string += "S-Form Parameters Z: " + fmt(this.affine[2][0]) + ", " + fmt(this.affine[2][1]) + ", " + fmt(this.affine[2][2]) + ", " + fmt(this.affine[2][3]) + "\n"; - string += "Slice Code = " + this.slice_code + "\n"; - string += "Units Code = " + this.xyzt_units + " (" + this.getUnitsCodeString(nifti.NIFTI1.SPATIAL_UNITS_MASK & this.xyzt_units) + ", " + this.getUnitsCodeString(nifti.NIFTI1.TEMPORAL_UNITS_MASK & this.xyzt_units) + ")\n"; - string += "Intent Code = " + this.intent_code + "\n"; - string += 'Intent Name: "' + this.intent_name + '"\n'; - string += "Dim Info = " + this.dim_info + "\n"; - return string; - }; - nifti.NIFTI2.prototype.getExtensionLocation = function() { - return nifti.NIFTI2.MAGIC_COOKIE + 4; - }; - nifti.NIFTI2.prototype.getExtensionSize = nifti.NIFTI1.prototype.getExtensionSize; - nifti.NIFTI2.prototype.getExtensionCode = nifti.NIFTI1.prototype.getExtensionCode; - nifti.NIFTI2.prototype.addExtension = nifti.NIFTI1.prototype.addExtension; - nifti.NIFTI2.prototype.removeExtension = nifti.NIFTI1.prototype.removeExtension; - nifti.NIFTI2.prototype.getDatatypeCodeString = nifti.NIFTI1.prototype.getDatatypeCodeString; - nifti.NIFTI2.prototype.getTransformCodeString = nifti.NIFTI1.prototype.getTransformCodeString; - nifti.NIFTI2.prototype.getUnitsCodeString = nifti.NIFTI1.prototype.getUnitsCodeString; - nifti.NIFTI2.prototype.getQformMat = nifti.NIFTI1.prototype.getQformMat; - nifti.NIFTI2.prototype.convertNiftiQFormToNiftiSForm = nifti.NIFTI1.prototype.convertNiftiQFormToNiftiSForm; - nifti.NIFTI2.prototype.convertNiftiSFormToNEMA = nifti.NIFTI1.prototype.convertNiftiSFormToNEMA; - nifti.NIFTI2.prototype.nifti_mat33_mul = nifti.NIFTI1.prototype.nifti_mat33_mul; - nifti.NIFTI2.prototype.nifti_mat33_determ = nifti.NIFTI1.prototype.nifti_mat33_determ; - nifti.NIFTI2.prototype.toArrayBuffer = function(includeExtensions = false) { - const INT64_SIZE = 8; - const DOUBLE_SIZE = 8; - let byteSize = 540 + 4; - if (includeExtensions) { - for (let extension of this.extensions) { - byteSize += extension.esize; - } - } - let byteArray = new Uint8Array(byteSize); - let view = new DataView(byteArray.buffer); - view.setInt32(0, 540, this.littleEndian); - byteArray.set(Buffer.from(this.magic), 4); - view.setInt16(12, this.datatypeCode, this.littleEndian); - view.setInt16(14, this.numBitsPerVoxel, this.littleEndian); - for (let i = 0; i < 8; i++) { - view.setBigInt64(16 + INT64_SIZE * i, BigInt(this.dims[i]), this.littleEndian); - } - view.setFloat64(80, this.intent_p1, this.littleEndian); - view.setFloat64(88, this.intent_p2, this.littleEndian); - view.setFloat64(96, this.intent_p3, this.littleEndian); - for (let i = 0; i < 8; i++) { - view.setFloat64(104 + DOUBLE_SIZE * i, this.pixDims[i], this.littleEndian); - } - view.setBigInt64(168, BigInt(this.vox_offset), this.littleEndian); - view.setFloat64(176, this.scl_slope, this.littleEndian); - view.setFloat64(184, this.scl_inter, this.littleEndian); - view.setFloat64(192, this.cal_max, this.littleEndian); - view.setFloat64(200, this.cal_min, this.littleEndian); - view.setFloat64(208, this.slice_duration, this.littleEndian); - view.setFloat64(216, this.toffset, this.littleEndian); - view.setBigInt64(224, BigInt(this.slice_start), this.littleEndian); - view.setBigInt64(232, BigInt(this.slice_end), this.littleEndian); - byteArray.set(Buffer.from(this.description), 240); - byteArray.set(Buffer.from(this.aux_file), 320); - view.setInt32(344, this.qform_code, this.littleEndian); - view.setInt32(348, this.sform_code, this.littleEndian); - view.setFloat64(352, this.quatern_b, this.littleEndian); - view.setFloat64(360, this.quatern_c, this.littleEndian); - view.setFloat64(368, this.quatern_d, this.littleEndian); - view.setFloat64(376, this.qoffset_x, this.littleEndian); - view.setFloat64(384, this.qoffset_y, this.littleEndian); - view.setFloat64(392, this.qoffset_z, this.littleEndian); - const flattened = this.affine.flat(); - for (let i = 0; i < 12; i++) { - view.setFloat64(400 + DOUBLE_SIZE * i, flattened[i], this.littleEndian); - } - view.setInt32(496, this.slice_code, this.littleEndian); - view.setInt32(500, this.xyzt_units, this.littleEndian); - view.setInt32(504, this.intent_code, this.littleEndian); - byteArray.set(Buffer.from(this.intent_name), 508); - view.setUint8(524, this.dim_info); - if (includeExtensions) { - byteArray.set(Uint8Array.from([1, 0, 0, 0]), 540); - let extensionByteIndex = this.getExtensionLocation(); - for (const extension of this.extensions) { - view.setInt32(extensionByteIndex, extension.esize, extension.littleEndian); - view.setInt32(extensionByteIndex + 4, extension.ecode, extension.littleEndian); - byteArray.set(new Uint8Array(extension.edata), extensionByteIndex + 8); - extensionByteIndex += extension.esize; - } - } else { - byteArray.set(new Uint8Array(4).fill(0), 540); - } - return byteArray.buffer; - }; - var moduleType = typeof module; - if (moduleType !== "undefined" && module.exports) { - module.exports = nifti.NIFTI2; - } - } - }); + var __publicField = (obj, key, value) => { + __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); + return value; + }; // node_modules/fflate/lib/worker.cjs var require_worker = __commonJS({ @@ -3271,73 +2206,1395 @@ } }); - // src/nifti.js + // dist/src/nifti-extension.js + var require_nifti_extension = __commonJS({ + "dist/src/nifti-extension.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.NIFTIEXTENSION = void 0; + var NIFTIEXTENSION = class { + esize; + ecode; + edata; + littleEndian; + constructor(esize, ecode, edata, littleEndian) { + if (esize % 16 != 0) { + throw new Error("This does not appear to be a NIFTI extension"); + } + this.esize = esize; + this.ecode = ecode; + this.edata = edata; + this.littleEndian = littleEndian; + } + /** + * Returns extension as ArrayBuffer. + * @returns {ArrayBuffer} + */ + toArrayBuffer() { + let byteArray = new Uint8Array(this.esize); + let data = new Uint8Array(this.edata); + byteArray.set(data, 8); + let view = new DataView(byteArray.buffer); + view.setInt32(0, this.esize, this.littleEndian); + view.setInt32(4, this.ecode, this.littleEndian); + return byteArray.buffer; + } + }; + exports.NIFTIEXTENSION = NIFTIEXTENSION; + } + }); + + // dist/src/utilities.js + var require_utilities = __commonJS({ + "dist/src/utilities.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.Utils = void 0; + var nifti_extension_1 = require_nifti_extension(); + var _Utils = class { + /*** Static methods ***/ + static getStringAt(data, start, end) { + var str = "", ctr, ch; + for (ctr = start; ctr < end; ctr += 1) { + ch = data.getUint8(ctr); + if (ch !== 0) { + str += String.fromCharCode(ch); + } + } + return str; + } + static getIntAt(data, start, littleEndian) { + return data.getInt32(start, littleEndian); + } + static getFloatAt(data, start, littleEndian) { + return data.getFloat32(start, littleEndian); + } + static getDoubleAt(data, start, littleEndian) { + return data.getFloat64(start, littleEndian); + } + static getLongAt(data, start, littleEndian) { + var ctr, array = [], value = 0; + for (ctr = 0; ctr < 8; ctr += 1) { + array[ctr] = _Utils.getByteAt(data, start + ctr); + } + for (ctr = array.length - 1; ctr >= 0; ctr--) { + value = value * 256 + array[ctr]; + } + return value; + } + static getExtensionsAt(data, start, littleEndian, voxOffset) { + let extensions = []; + let extensionByteIndex = start; + while (extensionByteIndex < voxOffset) { + let extensionLittleEndian = littleEndian; + let esize = _Utils.getIntAt(data, extensionByteIndex, littleEndian); + if (!esize) { + break; + } + if (esize + extensionByteIndex > voxOffset) { + extensionLittleEndian = !extensionLittleEndian; + esize = _Utils.getIntAt(data, extensionByteIndex, extensionLittleEndian); + if (esize + extensionByteIndex > voxOffset) { + throw new Error("This does not appear to be a valid NIFTI extension"); + } + } + if (esize % 16 != 0) { + throw new Error("This does not appear to be a NIFTI extension"); + } + let ecode = _Utils.getIntAt(data, extensionByteIndex + 4, extensionLittleEndian); + let edata = data.buffer.slice(extensionByteIndex + 8, extensionByteIndex + esize); + console.log("extensionByteIndex: " + (extensionByteIndex + 8) + " esize: " + esize); + console.log(edata); + let extension = new nifti_extension_1.NIFTIEXTENSION(esize, ecode, edata, extensionLittleEndian); + extensions.push(extension); + extensionByteIndex += esize; + } + return extensions; + } + static toArrayBuffer(buffer) { + var ab, view, i; + ab = new ArrayBuffer(buffer.length); + view = new Uint8Array(ab); + for (i = 0; i < buffer.length; i += 1) { + view[i] = buffer[i]; + } + return ab; + } + static isString(obj) { + return typeof obj === "string" || obj instanceof String; + } + static formatNumber(num, shortFormat = void 0) { + let val; + if (_Utils.isString(num)) { + val = Number(num); + } else { + val = num; + } + if (shortFormat) { + val = val.toPrecision(5); + } else { + val = val.toPrecision(7); + } + return parseFloat(val); + } + // http://stackoverflow.com/questions/18638900/javascript-crc32 + static makeCRCTable() { + let c; + let crcTable = []; + for (var n = 0; n < 256; n++) { + c = n; + for (var k = 0; k < 8; k++) { + c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1; + } + crcTable[n] = c; + } + return crcTable; + } + static crc32(dataView) { + if (!_Utils.crcTable) { + _Utils.crcTable = _Utils.makeCRCTable(); + } + const crcTable = _Utils.crcTable; + let crc = 0 ^ -1; + for (var i = 0; i < dataView.byteLength; i++) { + crc = crc >>> 8 ^ crcTable[(crc ^ dataView.getUint8(i)) & 255]; + } + return (crc ^ -1) >>> 0; + } + }; + var Utils = _Utils; + /*** Static Pseudo-constants ***/ + __publicField(Utils, "crcTable", null); + __publicField(Utils, "GUNZIP_MAGIC_COOKIE1", 31); + __publicField(Utils, "GUNZIP_MAGIC_COOKIE2", 139); + __publicField(Utils, "getByteAt", function(data, start) { + return data.getInt8(start); + }); + __publicField(Utils, "getShortAt", function(data, start, littleEndian) { + return data.getInt16(start, littleEndian); + }); + exports.Utils = Utils; + } + }); + + // dist/src/nifti1.js + var require_nifti1 = __commonJS({ + "dist/src/nifti1.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.NIFTI1 = void 0; + var utilities_1 = require_utilities(); + var _NIFTI1 = class { + littleEndian = false; + dim_info = 0; + dims = []; + intent_p1 = 0; + intent_p2 = 0; + intent_p3 = 0; + intent_code = 0; + datatypeCode = 0; + numBitsPerVoxel = 0; + slice_start = 0; + slice_end = 0; + slice_code = 0; + pixDims = []; + vox_offset = 0; + scl_slope = 1; + scl_inter = 0; + xyzt_units = 0; + cal_max = 0; + cal_min = 0; + slice_duration = 0; + toffset = 0; + description = ""; + aux_file = ""; + intent_name = ""; + qform_code = 0; + sform_code = 0; + quatern_a = 0; + quatern_b = 0; + quatern_c = 0; + quatern_d = 0; + qoffset_x = 0; + qoffset_y = 0; + qoffset_z = 0; + affine = [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1] + ]; + qfac = 1; + quatern_R; + magic = "0"; + isHDR = false; + extensionFlag = [0, 0, 0, 0]; + extensionSize = 0; + extensionCode = 0; + extensions = []; + /*** Prototype Methods ***/ + /** + * Reads the header data. + * @param {ArrayBuffer} data + */ + readHeader(data) { + var rawData = new DataView(data), magicCookieVal = utilities_1.Utils.getIntAt(rawData, 0, this.littleEndian), ctr, ctrOut, ctrIn, index; + if (magicCookieVal !== _NIFTI1.MAGIC_COOKIE) { + this.littleEndian = true; + magicCookieVal = utilities_1.Utils.getIntAt(rawData, 0, this.littleEndian); + } + if (magicCookieVal !== _NIFTI1.MAGIC_COOKIE) { + throw new Error("This does not appear to be a NIFTI file!"); + } + this.dim_info = utilities_1.Utils.getByteAt(rawData, 39); + for (ctr = 0; ctr < 8; ctr += 1) { + index = 40 + ctr * 2; + this.dims[ctr] = utilities_1.Utils.getShortAt(rawData, index, this.littleEndian); + } + this.intent_p1 = utilities_1.Utils.getFloatAt(rawData, 56, this.littleEndian); + this.intent_p2 = utilities_1.Utils.getFloatAt(rawData, 60, this.littleEndian); + this.intent_p3 = utilities_1.Utils.getFloatAt(rawData, 64, this.littleEndian); + this.intent_code = utilities_1.Utils.getShortAt(rawData, 68, this.littleEndian); + this.datatypeCode = utilities_1.Utils.getShortAt(rawData, 70, this.littleEndian); + this.numBitsPerVoxel = utilities_1.Utils.getShortAt(rawData, 72, this.littleEndian); + this.slice_start = utilities_1.Utils.getShortAt(rawData, 74, this.littleEndian); + for (ctr = 0; ctr < 8; ctr += 1) { + index = 76 + ctr * 4; + this.pixDims[ctr] = utilities_1.Utils.getFloatAt(rawData, index, this.littleEndian); + } + this.vox_offset = utilities_1.Utils.getFloatAt(rawData, 108, this.littleEndian); + this.scl_slope = utilities_1.Utils.getFloatAt(rawData, 112, this.littleEndian); + this.scl_inter = utilities_1.Utils.getFloatAt(rawData, 116, this.littleEndian); + this.slice_end = utilities_1.Utils.getShortAt(rawData, 120, this.littleEndian); + this.slice_code = utilities_1.Utils.getByteAt(rawData, 122); + this.xyzt_units = utilities_1.Utils.getByteAt(rawData, 123); + this.cal_max = utilities_1.Utils.getFloatAt(rawData, 124, this.littleEndian); + this.cal_min = utilities_1.Utils.getFloatAt(rawData, 128, this.littleEndian); + this.slice_duration = utilities_1.Utils.getFloatAt(rawData, 132, this.littleEndian); + this.toffset = utilities_1.Utils.getFloatAt(rawData, 136, this.littleEndian); + this.description = utilities_1.Utils.getStringAt(rawData, 148, 228); + this.aux_file = utilities_1.Utils.getStringAt(rawData, 228, 252); + this.qform_code = utilities_1.Utils.getShortAt(rawData, 252, this.littleEndian); + this.sform_code = utilities_1.Utils.getShortAt(rawData, 254, this.littleEndian); + this.quatern_b = utilities_1.Utils.getFloatAt(rawData, 256, this.littleEndian); + this.quatern_c = utilities_1.Utils.getFloatAt(rawData, 260, this.littleEndian); + this.quatern_d = utilities_1.Utils.getFloatAt(rawData, 264, this.littleEndian); + this.quatern_a = Math.sqrt(1 - (Math.pow(this.quatern_b, 2) + Math.pow(this.quatern_c, 2) + Math.pow(this.quatern_d, 2))); + this.qoffset_x = utilities_1.Utils.getFloatAt(rawData, 268, this.littleEndian); + this.qoffset_y = utilities_1.Utils.getFloatAt(rawData, 272, this.littleEndian); + this.qoffset_z = utilities_1.Utils.getFloatAt(rawData, 276, this.littleEndian); + if (this.qform_code > 0) { + const a = this.quatern_a; + const b = this.quatern_b; + const c = this.quatern_c; + const d = this.quatern_d; + this.qfac = this.pixDims[0] === 0 ? 1 : this.pixDims[0]; + this.quatern_R = [ + [ + a * a + b * b - c * c - d * d, + 2 * b * c - 2 * a * d, + 2 * b * d + 2 * a * c + ], + [ + 2 * b * c + 2 * a * d, + a * a + c * c - b * b - d * d, + 2 * c * d - 2 * a * b + ], + [ + 2 * b * d - 2 * a * c, + 2 * c * d + 2 * a * b, + a * a + d * d - c * c - b * b + ] + ]; + for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { + for (ctrIn = 0; ctrIn < 3; ctrIn += 1) { + this.affine[ctrOut][ctrIn] = this.quatern_R[ctrOut][ctrIn] * this.pixDims[ctrIn + 1]; + if (ctrIn === 2) { + this.affine[ctrOut][ctrIn] *= this.qfac; + } + } + } + this.affine[0][3] = this.qoffset_x; + this.affine[1][3] = this.qoffset_y; + this.affine[2][3] = this.qoffset_z; + } else if (this.sform_code > 0) { + for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { + for (ctrIn = 0; ctrIn < 4; ctrIn += 1) { + index = 280 + (ctrOut * 4 + ctrIn) * 4; + this.affine[ctrOut][ctrIn] = utilities_1.Utils.getFloatAt(rawData, index, this.littleEndian); + } + } + } + this.affine[3][0] = 0; + this.affine[3][1] = 0; + this.affine[3][2] = 0; + this.affine[3][3] = 1; + this.intent_name = utilities_1.Utils.getStringAt(rawData, 328, 344); + this.magic = utilities_1.Utils.getStringAt(rawData, 344, 348); + this.isHDR = this.magic === String.fromCharCode.apply(null, _NIFTI1.MAGIC_NUMBER2); + if (rawData.byteLength > _NIFTI1.MAGIC_COOKIE) { + this.extensionFlag[0] = utilities_1.Utils.getByteAt(rawData, 348); + this.extensionFlag[1] = utilities_1.Utils.getByteAt(rawData, 348 + 1); + this.extensionFlag[2] = utilities_1.Utils.getByteAt(rawData, 348 + 2); + this.extensionFlag[3] = utilities_1.Utils.getByteAt(rawData, 348 + 3); + if (this.extensionFlag[0]) { + this.extensions = utilities_1.Utils.getExtensionsAt(rawData, this.getExtensionLocation(), this.littleEndian, this.vox_offset); + this.extensionSize = this.extensions[0].esize; + this.extensionCode = this.extensions[0].ecode; + } + } + } + /** + * Returns a formatted string of header fields. + * @returns {string} + */ + toFormattedString() { + var fmt = utilities_1.Utils.formatNumber, string = ""; + string += "Dim Info = " + this.dim_info + "\n"; + string += "Image Dimensions (1-8): " + this.dims[0] + ", " + this.dims[1] + ", " + this.dims[2] + ", " + this.dims[3] + ", " + this.dims[4] + ", " + this.dims[5] + ", " + this.dims[6] + ", " + this.dims[7] + "\n"; + string += "Intent Parameters (1-3): " + this.intent_p1 + ", " + this.intent_p2 + ", " + this.intent_p3 + "\n"; + string += "Intent Code = " + this.intent_code + "\n"; + string += "Datatype = " + this.datatypeCode + " (" + this.getDatatypeCodeString(this.datatypeCode) + ")\n"; + string += "Bits Per Voxel = " + this.numBitsPerVoxel + "\n"; + string += "Slice Start = " + this.slice_start + "\n"; + string += "Voxel Dimensions (1-8): " + fmt(this.pixDims[0]) + ", " + fmt(this.pixDims[1]) + ", " + fmt(this.pixDims[2]) + ", " + fmt(this.pixDims[3]) + ", " + fmt(this.pixDims[4]) + ", " + fmt(this.pixDims[5]) + ", " + fmt(this.pixDims[6]) + ", " + fmt(this.pixDims[7]) + "\n"; + string += "Image Offset = " + this.vox_offset + "\n"; + string += "Data Scale: Slope = " + fmt(this.scl_slope) + " Intercept = " + fmt(this.scl_inter) + "\n"; + string += "Slice End = " + this.slice_end + "\n"; + string += "Slice Code = " + this.slice_code + "\n"; + string += "Units Code = " + this.xyzt_units + " (" + this.getUnitsCodeString(_NIFTI1.SPATIAL_UNITS_MASK & this.xyzt_units) + ", " + this.getUnitsCodeString(_NIFTI1.TEMPORAL_UNITS_MASK & this.xyzt_units) + ")\n"; + string += "Display Range: Max = " + fmt(this.cal_max) + " Min = " + fmt(this.cal_min) + "\n"; + string += "Slice Duration = " + this.slice_duration + "\n"; + string += "Time Axis Shift = " + this.toffset + "\n"; + string += 'Description: "' + this.description + '"\n'; + string += 'Auxiliary File: "' + this.aux_file + '"\n'; + string += "Q-Form Code = " + this.qform_code + " (" + this.getTransformCodeString(this.qform_code) + ")\n"; + string += "S-Form Code = " + this.sform_code + " (" + this.getTransformCodeString(this.sform_code) + ")\n"; + string += "Quaternion Parameters: b = " + fmt(this.quatern_b) + " c = " + fmt(this.quatern_c) + " d = " + fmt(this.quatern_d) + "\n"; + string += "Quaternion Offsets: x = " + this.qoffset_x + " y = " + this.qoffset_y + " z = " + this.qoffset_z + "\n"; + string += "S-Form Parameters X: " + fmt(this.affine[0][0]) + ", " + fmt(this.affine[0][1]) + ", " + fmt(this.affine[0][2]) + ", " + fmt(this.affine[0][3]) + "\n"; + string += "S-Form Parameters Y: " + fmt(this.affine[1][0]) + ", " + fmt(this.affine[1][1]) + ", " + fmt(this.affine[1][2]) + ", " + fmt(this.affine[1][3]) + "\n"; + string += "S-Form Parameters Z: " + fmt(this.affine[2][0]) + ", " + fmt(this.affine[2][1]) + ", " + fmt(this.affine[2][2]) + ", " + fmt(this.affine[2][3]) + "\n"; + string += 'Intent Name: "' + this.intent_name + '"\n'; + if (this.extensionFlag[0]) { + string += "Extension: Size = " + this.extensionSize + " Code = " + this.extensionCode + "\n"; + } + return string; + } + /** + * Returns a human-readable string of datatype. + * @param {number} code + * @returns {string} + */ + getDatatypeCodeString = function(code) { + if (code === _NIFTI1.TYPE_UINT8) { + return "1-Byte Unsigned Integer"; + } else if (code === _NIFTI1.TYPE_INT16) { + return "2-Byte Signed Integer"; + } else if (code === _NIFTI1.TYPE_INT32) { + return "4-Byte Signed Integer"; + } else if (code === _NIFTI1.TYPE_FLOAT32) { + return "4-Byte Float"; + } else if (code === _NIFTI1.TYPE_FLOAT64) { + return "8-Byte Float"; + } else if (code === _NIFTI1.TYPE_RGB24) { + return "RGB"; + } else if (code === _NIFTI1.TYPE_INT8) { + return "1-Byte Signed Integer"; + } else if (code === _NIFTI1.TYPE_UINT16) { + return "2-Byte Unsigned Integer"; + } else if (code === _NIFTI1.TYPE_UINT32) { + return "4-Byte Unsigned Integer"; + } else if (code === _NIFTI1.TYPE_INT64) { + return "8-Byte Signed Integer"; + } else if (code === _NIFTI1.TYPE_UINT64) { + return "8-Byte Unsigned Integer"; + } else { + return "Unknown"; + } + }; + /** + * Returns a human-readable string of transform type. + * @param {number} code + * @returns {string} + */ + getTransformCodeString = function(code) { + if (code === _NIFTI1.XFORM_SCANNER_ANAT) { + return "Scanner"; + } else if (code === _NIFTI1.XFORM_ALIGNED_ANAT) { + return "Aligned"; + } else if (code === _NIFTI1.XFORM_TALAIRACH) { + return "Talairach"; + } else if (code === _NIFTI1.XFORM_MNI_152) { + return "MNI"; + } else { + return "Unknown"; + } + }; + /** + * Returns a human-readable string of spatial and temporal units. + * @param {number} code + * @returns {string} + */ + getUnitsCodeString = function(code) { + if (code === _NIFTI1.UNITS_METER) { + return "Meters"; + } else if (code === _NIFTI1.UNITS_MM) { + return "Millimeters"; + } else if (code === _NIFTI1.UNITS_MICRON) { + return "Microns"; + } else if (code === _NIFTI1.UNITS_SEC) { + return "Seconds"; + } else if (code === _NIFTI1.UNITS_MSEC) { + return "Milliseconds"; + } else if (code === _NIFTI1.UNITS_USEC) { + return "Microseconds"; + } else if (code === _NIFTI1.UNITS_HZ) { + return "Hz"; + } else if (code === _NIFTI1.UNITS_PPM) { + return "PPM"; + } else if (code === _NIFTI1.UNITS_RADS) { + return "Rads"; + } else { + return "Unknown"; + } + }; + /** + * Returns the qform matrix. + * @returns {Array.>} + */ + getQformMat() { + return this.convertNiftiQFormToNiftiSForm(this.quatern_b, this.quatern_c, this.quatern_d, this.qoffset_x, this.qoffset_y, this.qoffset_z, this.pixDims[1], this.pixDims[2], this.pixDims[3], this.pixDims[0]); + } + /** + * Converts qform to an affine. (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {number} qb + * @param {number} qc + * @param {number} qd + * @param {number} qx + * @param {number} qy + * @param {number} qz + * @param {number} dx + * @param {number} dy + * @param {number} dz + * @param {number} qfac + * @returns {Array.>} + */ + convertNiftiQFormToNiftiSForm(qb, qc, qd, qx, qy, qz, dx, dy, dz, qfac) { + var R = [ + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0] + ], a, b = qb, c = qc, d = qd, xd, yd, zd; + R[3][0] = R[3][1] = R[3][2] = 0; + R[3][3] = 1; + a = 1 - (b * b + c * c + d * d); + if (a < 1e-7) { + a = 1 / Math.sqrt(b * b + c * c + d * d); + b *= a; + c *= a; + d *= a; + a = 0; + } else { + a = Math.sqrt(a); + } + xd = dx > 0 ? dx : 1; + yd = dy > 0 ? dy : 1; + zd = dz > 0 ? dz : 1; + if (qfac < 0) { + zd = -zd; + } + R[0][0] = (a * a + b * b - c * c - d * d) * xd; + R[0][1] = 2 * (b * c - a * d) * yd; + R[0][2] = 2 * (b * d + a * c) * zd; + R[1][0] = 2 * (b * c + a * d) * xd; + R[1][1] = (a * a + c * c - b * b - d * d) * yd; + R[1][2] = 2 * (c * d - a * b) * zd; + R[2][0] = 2 * (b * d - a * c) * xd; + R[2][1] = 2 * (c * d + a * b) * yd; + R[2][2] = (a * a + d * d - c * c - b * b) * zd; + R[0][3] = qx; + R[1][3] = qy; + R[2][3] = qz; + return R; + } + /** + * Converts sform to an orientation string (e.g., XYZ+--). (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {Array.>} R + * @returns {string} + */ + convertNiftiSFormToNEMA(R) { + var xi, xj, xk, yi, yj, yk, zi, zj, zk, val, detQ, detP, i, j, k, p, q, r, ibest, jbest, kbest, pbest, qbest, rbest, M, vbest, Q, P, iChar, jChar, kChar, iSense, jSense, kSense; + k = 0; + Q = [ + [0, 0, 0], + [0, 0, 0], + [0, 0, 0] + ]; + P = [ + [0, 0, 0], + [0, 0, 0], + [0, 0, 0] + ]; + xi = R[0][0]; + xj = R[0][1]; + xk = R[0][2]; + yi = R[1][0]; + yj = R[1][1]; + yk = R[1][2]; + zi = R[2][0]; + zj = R[2][1]; + zk = R[2][2]; + val = Math.sqrt(xi * xi + yi * yi + zi * zi); + if (val === 0) { + return null; + } + xi /= val; + yi /= val; + zi /= val; + val = Math.sqrt(xj * xj + yj * yj + zj * zj); + if (val === 0) { + return null; + } + xj /= val; + yj /= val; + zj /= val; + val = xi * xj + yi * yj + zi * zj; + if (Math.abs(val) > 1e-4) { + xj -= val * xi; + yj -= val * yi; + zj -= val * zi; + val = Math.sqrt(xj * xj + yj * yj + zj * zj); + if (val === 0) { + return null; + } + xj /= val; + yj /= val; + zj /= val; + } + val = Math.sqrt(xk * xk + yk * yk + zk * zk); + if (val === 0) { + xk = yi * zj - zi * yj; + yk = zi * xj - zj * xi; + zk = xi * yj - yi * xj; + } else { + xk /= val; + yk /= val; + zk /= val; + } + val = xi * xk + yi * yk + zi * zk; + if (Math.abs(val) > 1e-4) { + xk -= val * xi; + yk -= val * yi; + zk -= val * zi; + val = Math.sqrt(xk * xk + yk * yk + zk * zk); + if (val === 0) { + return null; + } + xk /= val; + yk /= val; + zk /= val; + } + val = xj * xk + yj * yk + zj * zk; + if (Math.abs(val) > 1e-4) { + xk -= val * xj; + yk -= val * yj; + zk -= val * zj; + val = Math.sqrt(xk * xk + yk * yk + zk * zk); + if (val === 0) { + return null; + } + xk /= val; + yk /= val; + zk /= val; + } + Q[0][0] = xi; + Q[0][1] = xj; + Q[0][2] = xk; + Q[1][0] = yi; + Q[1][1] = yj; + Q[1][2] = yk; + Q[2][0] = zi; + Q[2][1] = zj; + Q[2][2] = zk; + detQ = this.nifti_mat33_determ(Q); + if (detQ === 0) { + return null; + } + vbest = -666; + ibest = pbest = qbest = rbest = 1; + jbest = 2; + kbest = 3; + for (i = 1; i <= 3; i += 1) { + for (j = 1; j <= 3; j += 1) { + if (i !== j) { + for (k = 1; k <= 3; k += 1) { + if (!(i === k || j === k)) { + P[0][0] = P[0][1] = P[0][2] = P[1][0] = P[1][1] = P[1][2] = P[2][0] = P[2][1] = P[2][2] = 0; + for (p = -1; p <= 1; p += 2) { + for (q = -1; q <= 1; q += 2) { + for (r = -1; r <= 1; r += 2) { + P[0][i - 1] = p; + P[1][j - 1] = q; + P[2][k - 1] = r; + detP = this.nifti_mat33_determ(P); + if (detP * detQ > 0) { + M = this.nifti_mat33_mul(P, Q); + val = M[0][0] + M[1][1] + M[2][2]; + if (val > vbest) { + vbest = val; + ibest = i; + jbest = j; + kbest = k; + pbest = p; + qbest = q; + rbest = r; + } + } + } + } + } + } + } + } + } + } + iChar = jChar = kChar = iSense = jSense = kSense = ""; + switch (ibest * pbest) { + case 1: + iChar = "X"; + iSense = "+"; + break; + case -1: + iChar = "X"; + iSense = "-"; + break; + case 2: + iChar = "Y"; + iSense = "+"; + break; + case -2: + iChar = "Y"; + iSense = "-"; + break; + case 3: + iChar = "Z"; + iSense = "+"; + break; + case -3: + iChar = "Z"; + iSense = "-"; + break; + } + switch (jbest * qbest) { + case 1: + jChar = "X"; + jSense = "+"; + break; + case -1: + jChar = "X"; + jSense = "-"; + break; + case 2: + jChar = "Y"; + jSense = "+"; + break; + case -2: + jChar = "Y"; + jSense = "-"; + break; + case 3: + jChar = "Z"; + jSense = "+"; + break; + case -3: + jChar = "Z"; + jSense = "-"; + break; + } + switch (kbest * rbest) { + case 1: + kChar = "X"; + kSense = "+"; + break; + case -1: + kChar = "X"; + kSense = "-"; + break; + case 2: + kChar = "Y"; + kSense = "+"; + break; + case -2: + kChar = "Y"; + kSense = "-"; + break; + case 3: + kChar = "Z"; + kSense = "+"; + break; + case -3: + kChar = "Z"; + kSense = "-"; + break; + } + return iChar + jChar + kChar + iSense + jSense + kSense; + } + nifti_mat33_mul = function(A, B) { + var C = [ + [0, 0, 0], + [0, 0, 0], + [0, 0, 0] + ], i, j; + for (i = 0; i < 3; i += 1) { + for (j = 0; j < 3; j += 1) { + C[i][j] = A[i][0] * B[0][j] + A[i][1] * B[1][j] + A[i][2] * B[2][j]; + } + } + return C; + }; + nifti_mat33_determ = function(R) { + var r11, r12, r13, r21, r22, r23, r31, r32, r33; + r11 = R[0][0]; + r12 = R[0][1]; + r13 = R[0][2]; + r21 = R[1][0]; + r22 = R[1][1]; + r23 = R[1][2]; + r31 = R[2][0]; + r32 = R[2][1]; + r33 = R[2][2]; + return r11 * r22 * r33 - r11 * r32 * r23 - r21 * r12 * r33 + r21 * r32 * r13 + r31 * r12 * r23 - r31 * r22 * r13; + }; + /** + * Returns the byte index of the extension. + * @returns {number} + */ + getExtensionLocation() { + return _NIFTI1.MAGIC_COOKIE + 4; + } + /** + * Returns the extension size. + * @param {DataView} data + * @returns {number} + */ + getExtensionSize(data) { + return utilities_1.Utils.getIntAt(data, this.getExtensionLocation(), this.littleEndian); + } + /** + * Returns the extension code. + * @param {DataView} data + * @returns {number} + */ + getExtensionCode(data) { + return utilities_1.Utils.getIntAt(data, this.getExtensionLocation() + 4, this.littleEndian); + } + /** + * Adds an extension + * @param {NIFTIEXTENSION} extension + * @param {number} index + */ + addExtension(extension, index = -1) { + if (index == -1) { + this.extensions.push(extension); + } else { + this.extensions.splice(index, 0, extension); + } + this.vox_offset += extension.esize; + } + /** + * Removes an extension + * @param {number} index + */ + removeExtension(index) { + let extension = this.extensions[index]; + if (extension) { + this.vox_offset -= extension.esize; + } + this.extensions.splice(index, 1); + } + /** + * Returns header as ArrayBuffer. + * @param {boolean} includeExtensions - should extension bytes be included + * @returns {ArrayBuffer} + */ + toArrayBuffer(includeExtensions = false) { + const SHORT_SIZE = 2; + const FLOAT32_SIZE = 4; + let byteSize = 348 + 4; + if (includeExtensions) { + for (let extension of this.extensions) { + byteSize += extension.esize; + } + } + let byteArray = new Uint8Array(byteSize); + let view = new DataView(byteArray.buffer); + view.setInt32(0, 348, this.littleEndian); + view.setUint8(39, this.dim_info); + for (let i = 0; i < 8; i++) { + view.setUint16(40 + SHORT_SIZE * i, this.dims[i], this.littleEndian); + } + view.setFloat32(56, this.intent_p1, this.littleEndian); + view.setFloat32(60, this.intent_p2, this.littleEndian); + view.setFloat32(64, this.intent_p3, this.littleEndian); + view.setInt16(68, this.intent_code, this.littleEndian); + view.setInt16(70, this.datatypeCode, this.littleEndian); + view.setInt16(72, this.numBitsPerVoxel, this.littleEndian); + view.setInt16(74, this.slice_start, this.littleEndian); + for (let i = 0; i < 8; i++) { + view.setFloat32(76 + FLOAT32_SIZE * i, this.pixDims[i], this.littleEndian); + } + view.setFloat32(108, this.vox_offset, this.littleEndian); + view.setFloat32(112, this.scl_slope, this.littleEndian); + view.setFloat32(116, this.scl_inter, this.littleEndian); + view.setInt16(120, this.slice_end, this.littleEndian); + view.setUint8(122, this.slice_code); + view.setUint8(123, this.xyzt_units); + view.setFloat32(124, this.cal_max, this.littleEndian); + view.setFloat32(128, this.cal_min, this.littleEndian); + view.setFloat32(132, this.slice_duration, this.littleEndian); + view.setFloat32(136, this.toffset, this.littleEndian); + byteArray.set(Buffer.from(this.description), 148); + byteArray.set(Buffer.from(this.aux_file), 228); + view.setInt16(252, this.qform_code, this.littleEndian); + view.setInt16(254, this.sform_code, this.littleEndian); + view.setFloat32(256, this.quatern_b, this.littleEndian); + view.setFloat32(260, this.quatern_c, this.littleEndian); + view.setFloat32(264, this.quatern_d, this.littleEndian); + view.setFloat32(268, this.qoffset_x, this.littleEndian); + view.setFloat32(272, this.qoffset_y, this.littleEndian); + view.setFloat32(276, this.qoffset_z, this.littleEndian); + const flattened = this.affine.flat(); + for (let i = 0; i < 12; i++) { + view.setFloat32(280 + FLOAT32_SIZE * i, flattened[i], this.littleEndian); + } + byteArray.set(Buffer.from(this.intent_name), 328); + byteArray.set(Buffer.from(this.magic), 344); + if (includeExtensions) { + byteArray.set(Uint8Array.from([1, 0, 0, 0]), 348); + let extensionByteIndex = this.getExtensionLocation(); + for (const extension of this.extensions) { + view.setInt32(extensionByteIndex, extension.esize, extension.littleEndian); + view.setInt32(extensionByteIndex + 4, extension.ecode, extension.littleEndian); + byteArray.set(new Uint8Array(extension.edata), extensionByteIndex + 8); + extensionByteIndex += extension.esize; + } + } else { + byteArray.set(new Uint8Array(4).fill(0), 348); + } + return byteArray.buffer; + } + }; + var NIFTI1 = _NIFTI1; + /*** Static Pseudo-constants ***/ + // datatype codes + __publicField(NIFTI1, "TYPE_NONE", 0); + __publicField(NIFTI1, "TYPE_BINARY", 1); + __publicField(NIFTI1, "TYPE_UINT8", 2); + __publicField(NIFTI1, "TYPE_INT16", 4); + __publicField(NIFTI1, "TYPE_INT32", 8); + __publicField(NIFTI1, "TYPE_FLOAT32", 16); + __publicField(NIFTI1, "TYPE_COMPLEX64", 32); + __publicField(NIFTI1, "TYPE_FLOAT64", 64); + __publicField(NIFTI1, "TYPE_RGB24", 128); + __publicField(NIFTI1, "TYPE_INT8", 256); + __publicField(NIFTI1, "TYPE_UINT16", 512); + __publicField(NIFTI1, "TYPE_UINT32", 768); + __publicField(NIFTI1, "TYPE_INT64", 1024); + __publicField(NIFTI1, "TYPE_UINT64", 1280); + __publicField(NIFTI1, "TYPE_FLOAT128", 1536); + __publicField(NIFTI1, "TYPE_COMPLEX128", 1792); + __publicField(NIFTI1, "TYPE_COMPLEX256", 2048); + // transform codes + __publicField(NIFTI1, "XFORM_UNKNOWN", 0); + __publicField(NIFTI1, "XFORM_SCANNER_ANAT", 1); + __publicField(NIFTI1, "XFORM_ALIGNED_ANAT", 2); + __publicField(NIFTI1, "XFORM_TALAIRACH", 3); + __publicField(NIFTI1, "XFORM_MNI_152", 4); + // unit codes + __publicField(NIFTI1, "SPATIAL_UNITS_MASK", 7); + __publicField(NIFTI1, "TEMPORAL_UNITS_MASK", 56); + __publicField(NIFTI1, "UNITS_UNKNOWN", 0); + __publicField(NIFTI1, "UNITS_METER", 1); + __publicField(NIFTI1, "UNITS_MM", 2); + __publicField(NIFTI1, "UNITS_MICRON", 3); + __publicField(NIFTI1, "UNITS_SEC", 8); + __publicField(NIFTI1, "UNITS_MSEC", 16); + __publicField(NIFTI1, "UNITS_USEC", 24); + __publicField(NIFTI1, "UNITS_HZ", 32); + __publicField(NIFTI1, "UNITS_PPM", 40); + __publicField(NIFTI1, "UNITS_RADS", 48); + // nifti1 codes + __publicField(NIFTI1, "MAGIC_COOKIE", 348); + __publicField(NIFTI1, "STANDARD_HEADER_SIZE", 348); + __publicField(NIFTI1, "MAGIC_NUMBER_LOCATION", 344); + __publicField(NIFTI1, "MAGIC_NUMBER", [110, 43, 49]); + // n+1 (.nii) + __publicField(NIFTI1, "MAGIC_NUMBER2", [110, 105, 49]); + // ni1 (.hdr/.img) + __publicField(NIFTI1, "EXTENSION_HEADER_SIZE", 8); + exports.NIFTI1 = NIFTI1; + } + }); + + // dist/src/nifti2.js + var require_nifti2 = __commonJS({ + "dist/src/nifti2.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.NIFTI2 = void 0; + var nifti1_1 = require_nifti1(); + var utilities_1 = require_utilities(); + var _NIFTI2 = class { + littleEndian = false; + dim_info = 0; + dims = []; + intent_p1 = 0; + intent_p2 = 0; + intent_p3 = 0; + intent_code = 0; + datatypeCode = 0; + numBitsPerVoxel = 0; + slice_start = 0; + slice_end = 0; + slice_code = 0; + pixDims = []; + vox_offset = 0; + scl_slope = 1; + scl_inter = 0; + xyzt_units = 0; + cal_max = 0; + cal_min = 0; + slice_duration = 0; + toffset = 0; + description = ""; + aux_file = ""; + intent_name = ""; + qform_code = 0; + sform_code = 0; + quatern_b = 0; + quatern_c = 0; + quatern_d = 0; + qoffset_x = 0; + qoffset_y = 0; + qoffset_z = 0; + affine = [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1] + ]; + magic = "0"; + extensionFlag = [0, 0, 0, 0]; + extensions = []; + extensionSize = 0; + extensionCode = 0; + // ni2\0 + /*** Prototype Methods ***/ + /** + * Reads the header data. + * @param {ArrayBuffer} data + */ + readHeader(data) { + var rawData = new DataView(data), magicCookieVal = utilities_1.Utils.getIntAt(rawData, 0, this.littleEndian), ctr, ctrOut, ctrIn, index, array; + if (magicCookieVal !== _NIFTI2.MAGIC_COOKIE) { + this.littleEndian = true; + magicCookieVal = utilities_1.Utils.getIntAt(rawData, 0, this.littleEndian); + } + if (magicCookieVal !== _NIFTI2.MAGIC_COOKIE) { + throw new Error("This does not appear to be a NIFTI file!"); + } + this.magic = utilities_1.Utils.getStringAt(rawData, 4, 12); + this.datatypeCode = utilities_1.Utils.getShortAt(rawData, 12, this.littleEndian); + this.numBitsPerVoxel = utilities_1.Utils.getShortAt(rawData, 14, this.littleEndian); + for (ctr = 0; ctr < 8; ctr += 1) { + index = 16 + ctr * 8; + this.dims[ctr] = utilities_1.Utils.getLongAt(rawData, index, this.littleEndian); + } + this.intent_p1 = utilities_1.Utils.getDoubleAt(rawData, 80, this.littleEndian); + this.intent_p2 = utilities_1.Utils.getDoubleAt(rawData, 88, this.littleEndian); + this.intent_p3 = utilities_1.Utils.getDoubleAt(rawData, 96, this.littleEndian); + for (ctr = 0; ctr < 8; ctr += 1) { + index = 104 + ctr * 8; + this.pixDims[ctr] = utilities_1.Utils.getDoubleAt(rawData, index, this.littleEndian); + } + this.vox_offset = utilities_1.Utils.getLongAt(rawData, 168, this.littleEndian); + this.scl_slope = utilities_1.Utils.getDoubleAt(rawData, 176, this.littleEndian); + this.scl_inter = utilities_1.Utils.getDoubleAt(rawData, 184, this.littleEndian); + this.cal_max = utilities_1.Utils.getDoubleAt(rawData, 192, this.littleEndian); + this.cal_min = utilities_1.Utils.getDoubleAt(rawData, 200, this.littleEndian); + this.slice_duration = utilities_1.Utils.getDoubleAt(rawData, 208, this.littleEndian); + this.toffset = utilities_1.Utils.getDoubleAt(rawData, 216, this.littleEndian); + this.slice_start = utilities_1.Utils.getLongAt(rawData, 224, this.littleEndian); + this.slice_end = utilities_1.Utils.getLongAt(rawData, 232, this.littleEndian); + this.description = utilities_1.Utils.getStringAt(rawData, 240, 240 + 80); + this.aux_file = utilities_1.Utils.getStringAt(rawData, 320, 320 + 24); + this.qform_code = utilities_1.Utils.getIntAt(rawData, 344, this.littleEndian); + this.sform_code = utilities_1.Utils.getIntAt(rawData, 348, this.littleEndian); + this.quatern_b = utilities_1.Utils.getDoubleAt(rawData, 352, this.littleEndian); + this.quatern_c = utilities_1.Utils.getDoubleAt(rawData, 360, this.littleEndian); + this.quatern_d = utilities_1.Utils.getDoubleAt(rawData, 368, this.littleEndian); + this.qoffset_x = utilities_1.Utils.getDoubleAt(rawData, 376, this.littleEndian); + this.qoffset_y = utilities_1.Utils.getDoubleAt(rawData, 384, this.littleEndian); + this.qoffset_z = utilities_1.Utils.getDoubleAt(rawData, 392, this.littleEndian); + for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { + for (ctrIn = 0; ctrIn < 4; ctrIn += 1) { + index = 400 + (ctrOut * 4 + ctrIn) * 8; + this.affine[ctrOut][ctrIn] = utilities_1.Utils.getDoubleAt(rawData, index, this.littleEndian); + } + } + this.affine[3][0] = 0; + this.affine[3][1] = 0; + this.affine[3][2] = 0; + this.affine[3][3] = 1; + this.slice_code = utilities_1.Utils.getIntAt(rawData, 496, this.littleEndian); + this.xyzt_units = utilities_1.Utils.getIntAt(rawData, 500, this.littleEndian); + this.intent_code = utilities_1.Utils.getIntAt(rawData, 504, this.littleEndian); + this.intent_name = utilities_1.Utils.getStringAt(rawData, 508, 508 + 16); + this.dim_info = utilities_1.Utils.getByteAt(rawData, 524); + if (rawData.byteLength > _NIFTI2.MAGIC_COOKIE) { + this.extensionFlag[0] = utilities_1.Utils.getByteAt(rawData, 540); + this.extensionFlag[1] = utilities_1.Utils.getByteAt(rawData, 540 + 1); + this.extensionFlag[2] = utilities_1.Utils.getByteAt(rawData, 540 + 2); + this.extensionFlag[3] = utilities_1.Utils.getByteAt(rawData, 540 + 3); + if (this.extensionFlag[0]) { + this.extensions = utilities_1.Utils.getExtensionsAt(rawData, this.getExtensionLocation(), this.littleEndian, this.vox_offset); + this.extensionSize = this.extensions[0].esize; + this.extensionCode = this.extensions[0].ecode; + } + } + } + /** + * Returns a formatted string of header fields. + * @returns {string} + */ + toFormattedString() { + var fmt = utilities_1.Utils.formatNumber, string = ""; + string += "Datatype = " + +this.datatypeCode + " (" + this.getDatatypeCodeString(this.datatypeCode) + ")\n"; + string += "Bits Per Voxel = = " + this.numBitsPerVoxel + "\n"; + string += "Image Dimensions (1-8): " + this.dims[0] + ", " + this.dims[1] + ", " + this.dims[2] + ", " + this.dims[3] + ", " + this.dims[4] + ", " + this.dims[5] + ", " + this.dims[6] + ", " + this.dims[7] + "\n"; + string += "Intent Parameters (1-3): " + this.intent_p1 + ", " + this.intent_p2 + ", " + this.intent_p3 + "\n"; + string += "Voxel Dimensions (1-8): " + fmt(this.pixDims[0]) + ", " + fmt(this.pixDims[1]) + ", " + fmt(this.pixDims[2]) + ", " + fmt(this.pixDims[3]) + ", " + fmt(this.pixDims[4]) + ", " + fmt(this.pixDims[5]) + ", " + fmt(this.pixDims[6]) + ", " + fmt(this.pixDims[7]) + "\n"; + string += "Image Offset = " + this.vox_offset + "\n"; + string += "Data Scale: Slope = " + fmt(this.scl_slope) + " Intercept = " + fmt(this.scl_inter) + "\n"; + string += "Display Range: Max = " + fmt(this.cal_max) + " Min = " + fmt(this.cal_min) + "\n"; + string += "Slice Duration = " + this.slice_duration + "\n"; + string += "Time Axis Shift = " + this.toffset + "\n"; + string += "Slice Start = " + this.slice_start + "\n"; + string += "Slice End = " + this.slice_end + "\n"; + string += 'Description: "' + this.description + '"\n'; + string += 'Auxiliary File: "' + this.aux_file + '"\n'; + string += "Q-Form Code = " + this.qform_code + " (" + this.getTransformCodeString(this.qform_code) + ")\n"; + string += "S-Form Code = " + this.sform_code + " (" + this.getTransformCodeString(this.sform_code) + ")\n"; + string += "Quaternion Parameters: b = " + fmt(this.quatern_b) + " c = " + fmt(this.quatern_c) + " d = " + fmt(this.quatern_d) + "\n"; + string += "Quaternion Offsets: x = " + this.qoffset_x + " y = " + this.qoffset_y + " z = " + this.qoffset_z + "\n"; + string += "S-Form Parameters X: " + fmt(this.affine[0][0]) + ", " + fmt(this.affine[0][1]) + ", " + fmt(this.affine[0][2]) + ", " + fmt(this.affine[0][3]) + "\n"; + string += "S-Form Parameters Y: " + fmt(this.affine[1][0]) + ", " + fmt(this.affine[1][1]) + ", " + fmt(this.affine[1][2]) + ", " + fmt(this.affine[1][3]) + "\n"; + string += "S-Form Parameters Z: " + fmt(this.affine[2][0]) + ", " + fmt(this.affine[2][1]) + ", " + fmt(this.affine[2][2]) + ", " + fmt(this.affine[2][3]) + "\n"; + string += "Slice Code = " + this.slice_code + "\n"; + string += "Units Code = " + this.xyzt_units + " (" + this.getUnitsCodeString(nifti1_1.NIFTI1.SPATIAL_UNITS_MASK & this.xyzt_units) + ", " + this.getUnitsCodeString(nifti1_1.NIFTI1.TEMPORAL_UNITS_MASK & this.xyzt_units) + ")\n"; + string += "Intent Code = " + this.intent_code + "\n"; + string += 'Intent Name: "' + this.intent_name + '"\n'; + string += "Dim Info = " + this.dim_info + "\n"; + return string; + } + /** + * Returns the byte index of the extension. + * @returns {number} + */ + getExtensionLocation = function() { + return _NIFTI2.MAGIC_COOKIE + 4; + }; + /** + * Returns the extension size. + * @param {DataView} data + * @returns {number} + */ + getExtensionSize = nifti1_1.NIFTI1.prototype.getExtensionSize; + /** + * Returns the extension code. + * @param {DataView} data + * @returns {number} + */ + getExtensionCode = nifti1_1.NIFTI1.prototype.getExtensionCode; + /** + * Adds an extension + * @param {NIFTIEXTENSION} extension + * @param {number} index + */ + addExtension = nifti1_1.NIFTI1.prototype.addExtension; + /** + * Removes an extension + * @param {number} index + */ + removeExtension = nifti1_1.NIFTI1.prototype.removeExtension; + /** + * Returns a human-readable string of datatype. + * @param {number} code + * @returns {string} + */ + getDatatypeCodeString = nifti1_1.NIFTI1.prototype.getDatatypeCodeString; + /** + * Returns a human-readable string of transform type. + * @param {number} code + * @returns {string} + */ + getTransformCodeString = nifti1_1.NIFTI1.prototype.getTransformCodeString; + /** + * Returns a human-readable string of spatial and temporal units. + * @param {number} code + * @returns {string} + */ + getUnitsCodeString = nifti1_1.NIFTI1.prototype.getUnitsCodeString; + /** + * Returns the qform matrix. + * @returns {Array.>} + */ + getQformMat = nifti1_1.NIFTI1.prototype.getQformMat; + /** + * Converts qform to an affine. (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {number} qb + * @param {number} qc + * @param {number} qd + * @param {number} qx + * @param {number} qy + * @param {number} qz + * @param {number} dx + * @param {number} dy + * @param {number} dz + * @param {number} qfac + * @returns {Array.>} + */ + convertNiftiQFormToNiftiSForm = nifti1_1.NIFTI1.prototype.convertNiftiQFormToNiftiSForm; + /** + * Converts sform to an orientation string (e.g., XYZ+--). (See http://nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {Array.>} R + * @returns {string} + */ + convertNiftiSFormToNEMA = nifti1_1.NIFTI1.prototype.convertNiftiSFormToNEMA; + nifti_mat33_mul = nifti1_1.NIFTI1.prototype.nifti_mat33_mul; + nifti_mat33_determ = nifti1_1.NIFTI1.prototype.nifti_mat33_determ; + /** + * Returns header as ArrayBuffer. + * @param {boolean} includeExtensions - should extension bytes be included + * @returns {ArrayBuffer} + */ + toArrayBuffer(includeExtensions = false) { + const INT64_SIZE = 8; + const DOUBLE_SIZE = 8; + let byteSize = 540 + 4; + if (includeExtensions) { + for (let extension of this.extensions) { + byteSize += extension.esize; + } + } + let byteArray = new Uint8Array(byteSize); + let view = new DataView(byteArray.buffer); + view.setInt32(0, 540, this.littleEndian); + byteArray.set(Buffer.from(this.magic), 4); + view.setInt16(12, this.datatypeCode, this.littleEndian); + view.setInt16(14, this.numBitsPerVoxel, this.littleEndian); + for (let i = 0; i < 8; i++) { + view.setBigInt64(16 + INT64_SIZE * i, BigInt(this.dims[i]), this.littleEndian); + } + view.setFloat64(80, this.intent_p1, this.littleEndian); + view.setFloat64(88, this.intent_p2, this.littleEndian); + view.setFloat64(96, this.intent_p3, this.littleEndian); + for (let i = 0; i < 8; i++) { + view.setFloat64(104 + DOUBLE_SIZE * i, this.pixDims[i], this.littleEndian); + } + view.setBigInt64(168, BigInt(this.vox_offset), this.littleEndian); + view.setFloat64(176, this.scl_slope, this.littleEndian); + view.setFloat64(184, this.scl_inter, this.littleEndian); + view.setFloat64(192, this.cal_max, this.littleEndian); + view.setFloat64(200, this.cal_min, this.littleEndian); + view.setFloat64(208, this.slice_duration, this.littleEndian); + view.setFloat64(216, this.toffset, this.littleEndian); + view.setBigInt64(224, BigInt(this.slice_start), this.littleEndian); + view.setBigInt64(232, BigInt(this.slice_end), this.littleEndian); + byteArray.set(Buffer.from(this.description), 240); + byteArray.set(Buffer.from(this.aux_file), 320); + view.setInt32(344, this.qform_code, this.littleEndian); + view.setInt32(348, this.sform_code, this.littleEndian); + view.setFloat64(352, this.quatern_b, this.littleEndian); + view.setFloat64(360, this.quatern_c, this.littleEndian); + view.setFloat64(368, this.quatern_d, this.littleEndian); + view.setFloat64(376, this.qoffset_x, this.littleEndian); + view.setFloat64(384, this.qoffset_y, this.littleEndian); + view.setFloat64(392, this.qoffset_z, this.littleEndian); + const flattened = this.affine.flat(); + for (let i = 0; i < 12; i++) { + view.setFloat64(400 + DOUBLE_SIZE * i, flattened[i], this.littleEndian); + } + view.setInt32(496, this.slice_code, this.littleEndian); + view.setInt32(500, this.xyzt_units, this.littleEndian); + view.setInt32(504, this.intent_code, this.littleEndian); + byteArray.set(Buffer.from(this.intent_name), 508); + view.setUint8(524, this.dim_info); + if (includeExtensions) { + byteArray.set(Uint8Array.from([1, 0, 0, 0]), 540); + let extensionByteIndex = this.getExtensionLocation(); + for (const extension of this.extensions) { + view.setInt32(extensionByteIndex, extension.esize, extension.littleEndian); + view.setInt32(extensionByteIndex + 4, extension.ecode, extension.littleEndian); + byteArray.set(new Uint8Array(extension.edata), extensionByteIndex + 8); + extensionByteIndex += extension.esize; + } + } else { + byteArray.set(new Uint8Array(4).fill(0), 540); + } + return byteArray.buffer; + } + }; + var NIFTI2 = _NIFTI2; + /*** Static Pseudo-constants ***/ + __publicField(NIFTI2, "MAGIC_COOKIE", 540); + __publicField(NIFTI2, "MAGIC_NUMBER_LOCATION", 4); + __publicField(NIFTI2, "MAGIC_NUMBER", [ + 110, + 43, + 50, + 0, + 13, + 10, + 26, + 10 + ]); + // n+2\0 + __publicField(NIFTI2, "MAGIC_NUMBER2", [ + 110, + 105, + 50, + 0, + 13, + 10, + 26, + 10 + ]); + exports.NIFTI2 = NIFTI2; + } + }); + + // dist/src/nifti.js var require_nifti = __commonJS({ - "src/nifti.js"(exports, module) { - var nifti = nifti || {}; - nifti.NIFTI1 = nifti.NIFTI1 || (typeof __require !== "undefined" ? require_nifti1() : null); - nifti.NIFTI2 = nifti.NIFTI2 || (typeof __require !== "undefined" ? require_nifti2() : null); - nifti.NIFTIEXTENSION = nifti.NIFTIEXTENSION || (typeof __require !== "undefined" ? require_nifti_extension() : null); - nifti.Utils = nifti.Utils || (typeof __require !== "undefined" ? require_utilities() : null); - var fflate = fflate || (typeof __require !== "undefined" ? require_lib() : null); - nifti.isNIFTI1 = function(data, isHdrImgPairOK = false) { + "dist/src/nifti.js"(exports) { + var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) { + if (k2 === void 0) + k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { + return m[k]; + } }; + } + Object.defineProperty(o, k2, desc); + } : function(o, m, k, k2) { + if (k2 === void 0) + k2 = k; + o[k2] = m[k]; + }); + var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } : function(o, v) { + o["default"] = v; + }); + var __importStar = exports && exports.__importStar || function(mod) { + if (mod && mod.__esModule) + return mod; + var result = {}; + if (mod != null) { + for (var k in mod) + if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) + __createBinding(result, mod, k); + } + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.readExtensionData = exports.readExtension = exports.readImage = exports.hasExtension = exports.readHeader = exports.decompress = exports.isCompressed = exports.isNIFTI = exports.isNIFTI2 = exports.isNIFTI1 = exports.NIFTIEXTENSION = exports.Utils = exports.NIFTI2 = exports.NIFTI1 = void 0; + var fflate = __importStar(require_lib()); + var nifti1_1 = require_nifti1(); + var nifti2_1 = require_nifti2(); + var utilities_1 = require_utilities(); + var nifti1_2 = require_nifti1(); + Object.defineProperty(exports, "NIFTI1", { enumerable: true, get: function() { + return nifti1_2.NIFTI1; + } }); + var nifti2_2 = require_nifti2(); + Object.defineProperty(exports, "NIFTI2", { enumerable: true, get: function() { + return nifti2_2.NIFTI2; + } }); + var utilities_2 = require_utilities(); + Object.defineProperty(exports, "Utils", { enumerable: true, get: function() { + return utilities_2.Utils; + } }); + var nifti_extension_1 = require_nifti_extension(); + Object.defineProperty(exports, "NIFTIEXTENSION", { enumerable: true, get: function() { + return nifti_extension_1.NIFTIEXTENSION; + } }); + function isNIFTI1(data, isHdrImgPairOK = false) { var buf, mag1, mag2, mag3; - if (data.byteLength < nifti.NIFTI1.STANDARD_HEADER_SIZE) { + if (data.byteLength < nifti1_1.NIFTI1.STANDARD_HEADER_SIZE) { return false; } buf = new DataView(data); if (buf) - mag1 = buf.getUint8(nifti.NIFTI1.MAGIC_NUMBER_LOCATION); - mag2 = buf.getUint8(nifti.NIFTI1.MAGIC_NUMBER_LOCATION + 1); - mag3 = buf.getUint8(nifti.NIFTI1.MAGIC_NUMBER_LOCATION + 2); - if (isHdrImgPairOK && mag1 === nifti.NIFTI1.MAGIC_NUMBER2[0] && mag2 === nifti.NIFTI1.MAGIC_NUMBER2[1] && mag3 === nifti.NIFTI1.MAGIC_NUMBER2[2]) + mag1 = buf.getUint8(nifti1_1.NIFTI1.MAGIC_NUMBER_LOCATION); + mag2 = buf.getUint8(nifti1_1.NIFTI1.MAGIC_NUMBER_LOCATION + 1); + mag3 = buf.getUint8(nifti1_1.NIFTI1.MAGIC_NUMBER_LOCATION + 2); + if (isHdrImgPairOK && mag1 === nifti1_1.NIFTI1.MAGIC_NUMBER2[0] && mag2 === nifti1_1.NIFTI1.MAGIC_NUMBER2[1] && mag3 === nifti1_1.NIFTI1.MAGIC_NUMBER2[2]) return true; - return !!(mag1 === nifti.NIFTI1.MAGIC_NUMBER[0] && mag2 === nifti.NIFTI1.MAGIC_NUMBER[1] && mag3 === nifti.NIFTI1.MAGIC_NUMBER[2]); - }; - nifti.isNIFTI2 = function(data, isHdrImgPairOK = false) { + return !!(mag1 === nifti1_1.NIFTI1.MAGIC_NUMBER[0] && mag2 === nifti1_1.NIFTI1.MAGIC_NUMBER[1] && mag3 === nifti1_1.NIFTI1.MAGIC_NUMBER[2]); + } + exports.isNIFTI1 = isNIFTI1; + function isNIFTI2(data, isHdrImgPairOK = false) { var buf, mag1, mag2, mag3; - if (data.byteLength < nifti.NIFTI1.STANDARD_HEADER_SIZE) { + if (data.byteLength < nifti1_1.NIFTI1.STANDARD_HEADER_SIZE) { return false; } buf = new DataView(data); - mag1 = buf.getUint8(nifti.NIFTI2.MAGIC_NUMBER_LOCATION); - mag2 = buf.getUint8(nifti.NIFTI2.MAGIC_NUMBER_LOCATION + 1); - mag3 = buf.getUint8(nifti.NIFTI2.MAGIC_NUMBER_LOCATION + 2); - if (isHdrImgPairOK && mag1 === nifti.NIFTI2.MAGIC_NUMBER2[0] && mag2 === nifti.NIFTI2.MAGIC_NUMBER2[1] && mag3 === nifti.NIFTI2.MAGIC_NUMBER2[2]) + mag1 = buf.getUint8(nifti2_1.NIFTI2.MAGIC_NUMBER_LOCATION); + mag2 = buf.getUint8(nifti2_1.NIFTI2.MAGIC_NUMBER_LOCATION + 1); + mag3 = buf.getUint8(nifti2_1.NIFTI2.MAGIC_NUMBER_LOCATION + 2); + if (isHdrImgPairOK && mag1 === nifti2_1.NIFTI2.MAGIC_NUMBER2[0] && mag2 === nifti2_1.NIFTI2.MAGIC_NUMBER2[1] && mag3 === nifti2_1.NIFTI2.MAGIC_NUMBER2[2]) return true; - return !!(mag1 === nifti.NIFTI2.MAGIC_NUMBER[0] && mag2 === nifti.NIFTI2.MAGIC_NUMBER[1] && mag3 === nifti.NIFTI2.MAGIC_NUMBER[2]); - }; - nifti.isNIFTI = function(data, isHdrImgPairOK = false) { - return nifti.isNIFTI1(data, isHdrImgPairOK) || nifti.isNIFTI2(data, isHdrImgPairOK); - }; - nifti.isCompressed = function(data) { + return !!(mag1 === nifti2_1.NIFTI2.MAGIC_NUMBER[0] && mag2 === nifti2_1.NIFTI2.MAGIC_NUMBER[1] && mag3 === nifti2_1.NIFTI2.MAGIC_NUMBER[2]); + } + exports.isNIFTI2 = isNIFTI2; + function isNIFTI(data, isHdrImgPairOK = false) { + return isNIFTI1(data, isHdrImgPairOK) || isNIFTI2(data, isHdrImgPairOK); + } + exports.isNIFTI = isNIFTI; + function isCompressed(data) { var buf, magicCookie1, magicCookie2; if (data) { buf = new DataView(data); magicCookie1 = buf.getUint8(0); magicCookie2 = buf.getUint8(1); - if (magicCookie1 === nifti.Utils.GUNZIP_MAGIC_COOKIE1) { + if (magicCookie1 === utilities_1.Utils.GUNZIP_MAGIC_COOKIE1) { return true; } - if (magicCookie2 === nifti.Utils.GUNZIP_MAGIC_COOKIE2) { + if (magicCookie2 === utilities_1.Utils.GUNZIP_MAGIC_COOKIE2) { return true; } } return false; - }; - nifti.decompress = function(data) { - const decompressed = fflate.decompressSync(new Uint8Array(data)).buffer; - return decompressed; - }; - nifti.readHeader = function(data, isHdrImgPairOK = false) { + } + exports.isCompressed = isCompressed; + function decompress(data) { + return fflate.decompressSync(new Uint8Array(data)).buffer; + } + exports.decompress = decompress; + function readHeader(data, isHdrImgPairOK = false) { var header = null; - if (nifti.isCompressed(data)) { - data = nifti.decompress(data); + if (isCompressed(data)) { + data = decompress(data); } - if (nifti.isNIFTI1(data, isHdrImgPairOK)) { - header = new nifti.NIFTI1(); - } else if (nifti.isNIFTI2(data, isHdrImgPairOK)) { - header = new nifti.NIFTI2(); + if (isNIFTI1(data, isHdrImgPairOK)) { + header = new nifti1_1.NIFTI1(); + } else if (isNIFTI2(data, isHdrImgPairOK)) { + header = new nifti2_1.NIFTI2(); } if (header) { header.readHeader(data); @@ -3345,11 +3602,13 @@ console.error("That file does not appear to be NIFTI!"); } return header; - }; - nifti.hasExtension = function(header) { + } + exports.readHeader = readHeader; + function hasExtension(header) { return header.extensionFlag[0] != 0; - }; - nifti.readImage = function(header, data) { + } + exports.hasExtension = hasExtension; + function readImage(header, data) { var imageOffset = header.vox_offset, timeDim = 1, statDim = 1; if (header.dims[4]) { timeDim = header.dims[4]; @@ -3359,19 +3618,18 @@ } var imageSize = header.dims[1] * header.dims[2] * header.dims[3] * timeDim * statDim * (header.numBitsPerVoxel / 8); return data.slice(imageOffset, imageOffset + imageSize); - }; - nifti.readExtension = function(header, data) { + } + exports.readImage = readImage; + function readExtension(header, data) { var loc = header.getExtensionLocation(), size = header.extensionSize; return data.slice(loc, loc + size); - }; - nifti.readExtensionData = function(header, data) { + } + exports.readExtension = readExtension; + function readExtensionData(header, data) { var loc = header.getExtensionLocation(), size = header.extensionSize; return data.slice(loc + 8, loc + size); - }; - var moduleType = typeof module; - if (moduleType !== "undefined" && module.exports) { - module.exports = nifti; } + exports.readExtensionData = readExtensionData; } }); require_nifti(); diff --git a/src/nifti-extension.js b/src/nifti-extension.js deleted file mode 100644 index 4821e8b..0000000 --- a/src/nifti-extension.js +++ /dev/null @@ -1,53 +0,0 @@ -/*jslint browser: true, node: true */ -/*global require, module */ - -"use strict"; - -/*** Imports ***/ - -var nifti = nifti || {}; - -/*** Constructor ***/ - -/** - * The NIFTIEXTENSION constructor. - * @constructor - * @property {number} esize - number of bytes that form the extended header data - * @property {number} ecode - developer group id - * @property {ArrayBuffer} data - extension data - * @property {boolean} littleEndian - is little endian - * @type {Function} - */ -nifti.NIFTIEXTENSION = nifti.NIFTIEXTENSION || function (esize, ecode, edata, littleEndian) { - if(esize % 16 != 0) { - throw new Error("This does not appear to be a NIFTI extension"); - } - this.esize = esize; - this.ecode = ecode; - this.edata = edata; - this.littleEndian = littleEndian; -}; - -/** - * Returns extension as ArrayBuffer. - * @returns {ArrayBuffer} - */ -nifti.NIFTIEXTENSION.prototype.toArrayBuffer = function() { - let byteArray = new Uint8Array(this.esize); - byteArray.set(this.data.buffer, 8); - let view = new DataView(byteArray.buffer); - - // size of extension - view.setInt32(0, this.esize, this.littleEndian); - view.setInt32(4, this.ecode, this.littleEndian); - - return byteArray.buffer; -}; - -/*** Exports ***/ - -var moduleType = typeof module; -if ((moduleType !== 'undefined') && module.exports) { - module.exports = nifti.NIFTIEXTENSION; -} - diff --git a/src/nifti-extension.ts b/src/nifti-extension.ts new file mode 100644 index 0000000..63331a0 --- /dev/null +++ b/src/nifti-extension.ts @@ -0,0 +1,49 @@ +/*** Constructor ***/ +/** + * The NIFTIEXTENSION constructor. + * @constructor + * @property {number} esize - number of bytes that form the extended header data + * @property {number} ecode - developer group id + * @property {ArrayBuffer} data - extension data + * @property {boolean} littleEndian - is little endian + * @type {Function} + */ +export class NIFTIEXTENSION { + esize: number; + ecode: number; + edata: ArrayBuffer; + littleEndian: boolean; + + constructor( + esize: number, + ecode: number, + edata: ArrayBuffer, + littleEndian: boolean + ) { + if (esize % 16 != 0) { + throw new Error("This does not appear to be a NIFTI extension"); + } + this.esize = esize; + this.ecode = ecode; + this.edata = edata; + this.littleEndian = littleEndian; + } + + /** + * Returns extension as ArrayBuffer. + * @returns {ArrayBuffer} + */ + toArrayBuffer() { + let byteArray = new Uint8Array(this.esize); + let data = new Uint8Array(this.edata); + byteArray.set(data, 8); + + let view = new DataView(byteArray.buffer); + + // size of extension + view.setInt32(0, this.esize, this.littleEndian); + view.setInt32(4, this.ecode, this.littleEndian); + + return byteArray.buffer; + } + } \ No newline at end of file diff --git a/src/nifti.js b/src/nifti.js deleted file mode 100644 index 6b67972..0000000 --- a/src/nifti.js +++ /dev/null @@ -1,228 +0,0 @@ - -/*jslint browser: true, node: true */ -/*global require, module */ - -"use strict"; - -/*** Imports ***/ - -/** - * nifti - * @type {*|{}} - */ -var nifti = nifti || {}; -nifti.NIFTI1 = nifti.NIFTI1 || ((typeof require !== 'undefined') ? require('./nifti1.js') : null); -nifti.NIFTI2 = nifti.NIFTI2 || ((typeof require !== 'undefined') ? require('./nifti2.js') : null); -nifti.NIFTIEXTENSION = nifti.NIFTIEXTENSION || ((typeof require !== 'undefined') ? require('./nifti-extension.js') : null); -nifti.Utils = nifti.Utils || ((typeof require !== 'undefined') ? require('./utilities.js') : null); - -var fflate = fflate || ((typeof require !== 'undefined') ? require('fflate') : null); - -/*** Static Methods ***/ - -/** - * Returns true if this data represents a NIFTI-1 header. - * @param {ArrayBuffer} data - * @returns {boolean} - */ -nifti.isNIFTI1 = function (data, isHdrImgPairOK = false) { - var buf, mag1, mag2, mag3; - if (data.byteLength < nifti.NIFTI1.STANDARD_HEADER_SIZE) { - return false; - } - - buf = new DataView(data); - - if (buf) - - mag1 = buf.getUint8(nifti.NIFTI1.MAGIC_NUMBER_LOCATION); - mag2 = buf.getUint8(nifti.NIFTI1.MAGIC_NUMBER_LOCATION + 1); - mag3 = buf.getUint8(nifti.NIFTI1.MAGIC_NUMBER_LOCATION + 2); - - if ((isHdrImgPairOK) && (mag1 === nifti.NIFTI1.MAGIC_NUMBER2[0]) && (mag2 === nifti.NIFTI1.MAGIC_NUMBER2[1]) && - (mag3 === nifti.NIFTI1.MAGIC_NUMBER2[2])) - return true; // hdr/img pair - - return !!((mag1 === nifti.NIFTI1.MAGIC_NUMBER[0]) && (mag2 === nifti.NIFTI1.MAGIC_NUMBER[1]) && - (mag3 === nifti.NIFTI1.MAGIC_NUMBER[2])); -}; - - -/** - * Returns true if this data represents a NIFTI-2 header. - * @param {ArrayBuffer} data - * @returns {boolean} - */ -nifti.isNIFTI2 = function (data, isHdrImgPairOK = false) { - var buf, mag1, mag2, mag3; - - if (data.byteLength < nifti.NIFTI1.STANDARD_HEADER_SIZE) { - return false; - } - - buf = new DataView(data); - mag1 = buf.getUint8(nifti.NIFTI2.MAGIC_NUMBER_LOCATION); - mag2 = buf.getUint8(nifti.NIFTI2.MAGIC_NUMBER_LOCATION + 1); - mag3 = buf.getUint8(nifti.NIFTI2.MAGIC_NUMBER_LOCATION + 2); - - if ((isHdrImgPairOK) && (mag1 === nifti.NIFTI2.MAGIC_NUMBER2[0]) && (mag2 === nifti.NIFTI2.MAGIC_NUMBER2[1]) && - (mag3 === nifti.NIFTI2.MAGIC_NUMBER2[2])) - return true; // hdr/img pair - - return !!((mag1 === nifti.NIFTI2.MAGIC_NUMBER[0]) && (mag2 === nifti.NIFTI2.MAGIC_NUMBER[1]) && - (mag3 === nifti.NIFTI2.MAGIC_NUMBER[2])); -}; - - - -/** - * Returns true if this data represents a NIFTI header. - * @param {ArrayBuffer} data - * @returns {boolean} - */ -nifti.isNIFTI = function (data, isHdrImgPairOK = false) { - return (nifti.isNIFTI1(data, isHdrImgPairOK) || nifti.isNIFTI2(data, isHdrImgPairOK)); -}; - - - -/** - * Returns true if this data is GZIP compressed. - * @param {ArrayBuffer} data - * @returns {boolean} - */ -nifti.isCompressed = function (data) { - var buf, magicCookie1, magicCookie2; - - if (data) { - buf = new DataView(data); - - magicCookie1 = buf.getUint8(0); - magicCookie2 = buf.getUint8(1); - - if (magicCookie1 === nifti.Utils.GUNZIP_MAGIC_COOKIE1) { - return true; - } - - if (magicCookie2 === nifti.Utils.GUNZIP_MAGIC_COOKIE2) { - return true; - } - } - - return false; -}; - - - -/** - * Returns decompressed data. - * @param {ArrayBuffer} data - * @returns {ArrayBuffer} - */ -nifti.decompress = function (data) { - const decompressed = fflate.decompressSync(new Uint8Array(data)).buffer; - return decompressed -}; - - - -/** - * Reads and returns the header object. - * @param {ArrayBuffer} data - * @returns {nifti.NIFTI1|nifti.NIFTI2|null} - */ -nifti.readHeader = function (data, isHdrImgPairOK = false) { - var header = null; - - if (nifti.isCompressed(data)) { - data = nifti.decompress(data); - } - - if (nifti.isNIFTI1(data, isHdrImgPairOK)) { - header = new nifti.NIFTI1(); - } else if (nifti.isNIFTI2(data, isHdrImgPairOK)) { - header = new nifti.NIFTI2(); - } - - if (header) { - header.readHeader(data); - } else { - console.error("That file does not appear to be NIFTI!"); - } - - return header; -}; - - - -/** - * Returns true if this header contains an extension. - * @param {nifti.NIFTI1|nifti.NIFTI2} header - * @returns {boolean} - */ -nifti.hasExtension = function (header) { - return (header.extensionFlag[0] != 0); -}; - - - -/** - * Returns the image data. - * @param {nifti.NIFTI1|nifti.NIFTI2} header - * @param {ArrayBuffer} data - * @returns {ArrayBuffer} - */ -nifti.readImage = function (header, data) { - var imageOffset = header.vox_offset, - timeDim = 1, - statDim = 1; - - if (header.dims[4]) { - timeDim = header.dims[4]; - } - - if (header.dims[5]) { - statDim = header.dims[5]; - } - - var imageSize = header.dims[1] * header.dims[2] * header.dims[3] * timeDim * statDim * (header.numBitsPerVoxel / 8); - return data.slice(imageOffset, imageOffset + imageSize); -}; - - - -/** - * Returns the extension data (including extension header). - * @param {nifti.NIFTI1|nifti.NIFTI2} header - * @param {ArrayBuffer} data - * @returns {ArrayBuffer} - */ -nifti.readExtension = function (header, data) { - var loc = header.getExtensionLocation(), - size = header.extensionSize; - - return data.slice(loc, loc + size); -}; - - - -/** - * Returns the extension data. - * @param {nifti.NIFTI1|nifti.NIFTI2} header - * @param {ArrayBuffer} data - * @returns {ArrayBuffer} - */ -nifti.readExtensionData = function (header, data) { - var loc = header.getExtensionLocation(), - size = header.extensionSize; - - return data.slice(loc + 8, loc + size); // +8 for loc and -8 for esize and ecode -}; - - -/*** Exports ***/ - -var moduleType = typeof module; -if ((moduleType !== 'undefined') && module.exports) { - module.exports = nifti; -} diff --git a/src/nifti.ts b/src/nifti.ts new file mode 100644 index 0000000..84aaa17 --- /dev/null +++ b/src/nifti.ts @@ -0,0 +1,221 @@ +import * as fflate from "fflate"; +import { NIFTI1 } from "./nifti1"; +import { NIFTI2 } from "./nifti2"; +import { Utils } from "./utilities"; +export { NIFTI1 } from "./nifti1"; +export { NIFTI2 } from "./nifti2"; +export { Utils } from "./utilities"; +export { NIFTIEXTENSION } from "./nifti-extension"; + + /*** Static Methods ***/ + /** + * Returns true if this data represents a NIFTI-1 header. + * @param {ArrayBuffer} data + * @returns {boolean} + */ + export function isNIFTI1(data: ArrayBuffer, isHdrImgPairOK = false) { + var buf, mag1, mag2, mag3; + + if (data.byteLength < NIFTI1.STANDARD_HEADER_SIZE) { + return false; + } + + buf = new DataView(data); + + if (buf) mag1 = buf.getUint8(NIFTI1.MAGIC_NUMBER_LOCATION); + mag2 = buf.getUint8(NIFTI1.MAGIC_NUMBER_LOCATION + 1); + mag3 = buf.getUint8(NIFTI1.MAGIC_NUMBER_LOCATION + 2); + + if ( + isHdrImgPairOK && + mag1 === NIFTI1.MAGIC_NUMBER2[0] && + mag2 === NIFTI1.MAGIC_NUMBER2[1] && + mag3 === NIFTI1.MAGIC_NUMBER2[2] + ) + return true; // hdr/img pair + + return !!( + mag1 === NIFTI1.MAGIC_NUMBER[0] && + mag2 === NIFTI1.MAGIC_NUMBER[1] && + mag3 === NIFTI1.MAGIC_NUMBER[2] + ); + } + + /** + * Returns true if this data represents a NIFTI-2 header. + * @param {ArrayBuffer} data + * @returns {boolean} + */ + export function isNIFTI2(data: ArrayBuffer, isHdrImgPairOK = false) { + var buf, mag1, mag2, mag3; + + if (data.byteLength < NIFTI1.STANDARD_HEADER_SIZE) { + return false; + } + + buf = new DataView(data); + mag1 = buf.getUint8(NIFTI2.MAGIC_NUMBER_LOCATION); + mag2 = buf.getUint8(NIFTI2.MAGIC_NUMBER_LOCATION + 1); + mag3 = buf.getUint8(NIFTI2.MAGIC_NUMBER_LOCATION + 2); + + if ( + isHdrImgPairOK && + mag1 === NIFTI2.MAGIC_NUMBER2[0] && + mag2 === NIFTI2.MAGIC_NUMBER2[1] && + mag3 === NIFTI2.MAGIC_NUMBER2[2] + ) + return true; // hdr/img pair + + return !!( + mag1 === NIFTI2.MAGIC_NUMBER[0] && + mag2 === NIFTI2.MAGIC_NUMBER[1] && + mag3 === NIFTI2.MAGIC_NUMBER[2] + ); + } + + /** + * Returns true if this data represents a NIFTI header. + * @param {ArrayBuffer} data + * @returns {boolean} + */ + export function isNIFTI(data: ArrayBuffer, isHdrImgPairOK = false) { + return ( + isNIFTI1(data, isHdrImgPairOK) || + isNIFTI2(data, isHdrImgPairOK) + ); + } + + /** + * Returns true if this data is GZIP compressed. + * @param {ArrayBuffer} data + * @returns {boolean} + */ + export function isCompressed(data: ArrayBuffer) { + var buf, magicCookie1, magicCookie2; + + if (data) { + buf = new DataView(data); + + magicCookie1 = buf.getUint8(0); + magicCookie2 = buf.getUint8(1); + + if (magicCookie1 === Utils.GUNZIP_MAGIC_COOKIE1) { + return true; + } + + if (magicCookie2 === Utils.GUNZIP_MAGIC_COOKIE2) { + return true; + } + } + + return false; + } + + /** + * Returns decompressed data. + * @param {ArrayBuffer} data + * @returns {ArrayBuffer} + */ + export function decompress(data: ArrayBuffer) { + return fflate.decompressSync(new Uint8Array(data)).buffer; + } + + /** + * Reads and returns the header object. + * @param {ArrayBuffer} data + * @returns {NIFTI1|NIFTI2|null} + */ + export function readHeader(data: ArrayBuffer, isHdrImgPairOK = false) { + var header = null; + + if (isCompressed(data)) { + data = decompress(data); + } + + if (isNIFTI1(data, isHdrImgPairOK)) { + header = new NIFTI1(); + } else if (isNIFTI2(data, isHdrImgPairOK)) { + header = new NIFTI2(); + } + + if (header) { + header.readHeader(data); + } else { + console.error("That file does not appear to be NIFTI!"); + } + + return header; + } + + /** + * Returns true if this header contains an extension. + * @param {NIFTI1|NIFTI2} header + * @returns {boolean} + */ + export function hasExtension(header: NIFTI1 | NIFTI2) { + return header.extensionFlag[0] != 0; + } + + /** + * Returns the image data. + * @param {NIFTI1|NIFTI2} header + * @param {ArrayBuffer} data + * @returns {ArrayBuffer} + */ + export function readImage( + header: NIFTI1 | NIFTI2, + data: ArrayBuffer + ) { + var imageOffset = header.vox_offset, + timeDim = 1, + statDim = 1; + + if (header.dims[4]) { + timeDim = header.dims[4]; + } + + if (header.dims[5]) { + statDim = header.dims[5]; + } + + var imageSize = + header.dims[1] * + header.dims[2] * + header.dims[3] * + timeDim * + statDim * + (header.numBitsPerVoxel / 8); + return data.slice(imageOffset, imageOffset + imageSize); + } + + /** + * Returns the extension data (including extension header). + * @param {NIFTI1|NIFTI2} header + * @param {ArrayBuffer} data + * @returns {ArrayBuffer} + */ + export function readExtension( + header: NIFTI1 | NIFTI2, + data: ArrayBuffer + ) { + var loc = header.getExtensionLocation(), + size = header.extensionSize; + + return data.slice(loc, loc + size); + } + + /** + * Returns the extension data. + * @param {NIFTI1|NIFTI2} header + * @param {ArrayBuffer} data + * @returns {ArrayBuffer} + */ + export function readExtensionData( + header: NIFTI1 | NIFTI2, + data: ArrayBuffer + ) { + var loc = header.getExtensionLocation(), + size = header.extensionSize; + + return data.slice(loc + 8, loc + size); // +8 for loc and -8 for esize and ecode + } diff --git a/src/nifti1.js b/src/nifti1.js deleted file mode 100644 index abd93e6..0000000 --- a/src/nifti1.js +++ /dev/null @@ -1,1114 +0,0 @@ - -/*jslint browser: true, node: true */ -/*global */ - -"use strict"; - -const NIFTIEXTENSION = require('./nifti-extension.js'); - -/*** Imports ***/ - -var nifti = nifti || {}; -nifti.Utils = nifti.Utils || ((typeof require !== 'undefined') ? require('./utilities.js') : null); -nifti.NIFTIEXTENSION = nifti.NIFTIEXTENSION || ((typeof require !== 'undefined') ? require('./nifti-extension.js') : null); - -/*** Constructor ***/ - -/** - * The NIFTI1 constructor. - * @constructor - * @property {boolean} littleEndian - * @property {number} dim_info - * @property {number[]} dims - image dimensions - * @property {number} intent_p1 - * @property {number} intent_p2 - * @property {number} intent_p3 - * @property {number} intent_code - * @property {number} datatypeCode - * @property {number} numBitsPerVoxel - * @property {number} slice_start - * @property {number} slice_end - * @property {number} slice_code - * @property {number[]} pixDims - voxel dimensions - * @property {number} vox_offset - * @property {number} scl_slope - * @property {number} scl_inter - * @property {number} xyzt_units - * @property {number} cal_max - * @property {number} cal_min - * @property {number} slice_duration - * @property {number} toffset - * @property {string} description - * @property {string} aux_file - * @property {string} intent_name - * @property {number} qform_code - * @property {number} sform_code - * @property {number} quatern_b - * @property {number} quatern_c - * @property {number} quatern_d - * @property {number} quatern_x - * @property {number} quatern_y - * @property {number} quatern_z - * @property {Array.>} affine - * @property {string} magic - * @property {boolean} isHDR - if hdr/img format - * @property {number[]} extensionFlag - * @property {number} extensionSize - * @property {number} extensionCode - * @property {nifti.NIFTIEXTENSION[]} extensions - * @type {Function} - */ -nifti.NIFTI1 = nifti.NIFTI1 || function () { - this.littleEndian = false; - this.dim_info = 0; - this.dims = []; - this.intent_p1 = 0; - this.intent_p2 = 0; - this.intent_p3 = 0; - this.intent_code = 0; - this.datatypeCode = 0; - this.numBitsPerVoxel = 0; - this.slice_start = 0; - this.slice_end = 0; - this.slice_code = 0; - this.pixDims = []; - this.vox_offset = 0; - this.scl_slope = 1; - this.scl_inter = 0; - this.xyzt_units = 0; - this.cal_max = 0; - this.cal_min = 0; - this.slice_duration = 0; - this.toffset = 0; - this.description = ""; - this.aux_file = ""; - this.intent_name = ""; - this.qform_code = 0; - this.sform_code = 0; - this.quatern_b = 0; - this.quatern_c = 0; - this.quatern_d = 0; - this.qoffset_x = 0; - this.qoffset_y = 0; - this.qoffset_z = 0; - this.affine = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]; - this.magic = 0; - this.isHDR = false; - this.extensionFlag = [0, 0, 0, 0]; - this.extensionSize = 0; - this.extensionCode = 0; - this.extensions = []; -}; - - - -/*** Static Pseudo-constants ***/ - -// datatype codes -nifti.NIFTI1.TYPE_NONE = 0; -nifti.NIFTI1.TYPE_BINARY = 1; -nifti.NIFTI1.TYPE_UINT8 = 2; -nifti.NIFTI1.TYPE_INT16 = 4; -nifti.NIFTI1.TYPE_INT32 = 8; -nifti.NIFTI1.TYPE_FLOAT32 = 16; -nifti.NIFTI1.TYPE_COMPLEX64 = 32; -nifti.NIFTI1.TYPE_FLOAT64 = 64; -nifti.NIFTI1.TYPE_RGB24 = 128; -nifti.NIFTI1.TYPE_INT8 = 256; -nifti.NIFTI1.TYPE_UINT16 = 512; -nifti.NIFTI1.TYPE_UINT32 = 768; -nifti.NIFTI1.TYPE_INT64 = 1024; -nifti.NIFTI1.TYPE_UINT64 = 1280; -nifti.NIFTI1.TYPE_FLOAT128 = 1536; -nifti.NIFTI1.TYPE_COMPLEX128 = 1792; -nifti.NIFTI1.TYPE_COMPLEX256 = 2048; - -// transform codes -nifti.NIFTI1.XFORM_UNKNOWN = 0; -nifti.NIFTI1.XFORM_SCANNER_ANAT = 1; -nifti.NIFTI1.XFORM_ALIGNED_ANAT = 2; -nifti.NIFTI1.XFORM_TALAIRACH = 3; -nifti.NIFTI1.XFORM_MNI_152 = 4; - -// unit codes -nifti.NIFTI1.SPATIAL_UNITS_MASK = 0x07; -nifti.NIFTI1.TEMPORAL_UNITS_MASK = 0x38; -nifti.NIFTI1.UNITS_UNKNOWN = 0; -nifti.NIFTI1.UNITS_METER = 1; -nifti.NIFTI1.UNITS_MM = 2; -nifti.NIFTI1.UNITS_MICRON = 3; -nifti.NIFTI1.UNITS_SEC = 8; -nifti.NIFTI1.UNITS_MSEC = 16; -nifti.NIFTI1.UNITS_USEC = 24; -nifti.NIFTI1.UNITS_HZ = 32; -nifti.NIFTI1.UNITS_PPM = 40; -nifti.NIFTI1.UNITS_RADS = 48; - -// nifti1 codes -nifti.NIFTI1.MAGIC_COOKIE = 348; -nifti.NIFTI1.STANDARD_HEADER_SIZE = 348; -nifti.NIFTI1.MAGIC_NUMBER_LOCATION = 344; -nifti.NIFTI1.MAGIC_NUMBER = [0x6E, 0x2B, 0x31]; // n+1 (.nii) -nifti.NIFTI1.MAGIC_NUMBER2 = [0x6E, 0x69, 0x31]; // ni1 (.hdr/.img) -nifti.NIFTI1.EXTENSION_HEADER_SIZE = 8; - - -/*** Prototype Methods ***/ - -/** - * Reads the header data. - * @param {ArrayBuffer} data - */ -nifti.NIFTI1.prototype.readHeader = function (data) { - var rawData = new DataView(data), - magicCookieVal = nifti.Utils.getIntAt(rawData, 0, this.littleEndian), - ctr, - ctrOut, - ctrIn, - index; - - if (magicCookieVal !== nifti.NIFTI1.MAGIC_COOKIE) { // try as little endian - this.littleEndian = true; - magicCookieVal = nifti.Utils.getIntAt(rawData, 0, this.littleEndian); - } - - if (magicCookieVal !== nifti.NIFTI1.MAGIC_COOKIE) { - throw new Error("This does not appear to be a NIFTI file!"); - } - - this.dim_info = nifti.Utils.getByteAt(rawData, 39); - - for (ctr = 0; ctr < 8; ctr += 1) { - index = 40 + (ctr * 2); - this.dims[ctr] = nifti.Utils.getShortAt(rawData, index, this.littleEndian); - } - - this.intent_p1 = nifti.Utils.getFloatAt(rawData, 56, this.littleEndian); - this.intent_p2 = nifti.Utils.getFloatAt(rawData, 60, this.littleEndian); - this.intent_p3 = nifti.Utils.getFloatAt(rawData, 64, this.littleEndian); - this.intent_code = nifti.Utils.getShortAt(rawData, 68, this.littleEndian); - - this.datatypeCode = nifti.Utils.getShortAt(rawData, 70, this.littleEndian); - this.numBitsPerVoxel = nifti.Utils.getShortAt(rawData, 72, this.littleEndian); - - this.slice_start = nifti.Utils.getShortAt(rawData, 74, this.littleEndian); - - for (ctr = 0; ctr < 8; ctr += 1) { - index = 76 + (ctr * 4); - this.pixDims[ctr] = nifti.Utils.getFloatAt(rawData, index, this.littleEndian); - } - - this.vox_offset = nifti.Utils.getFloatAt(rawData, 108, this.littleEndian); - - this.scl_slope = nifti.Utils.getFloatAt(rawData, 112, this.littleEndian); - this.scl_inter = nifti.Utils.getFloatAt(rawData, 116, this.littleEndian); - - this.slice_end = nifti.Utils.getShortAt(rawData, 120, this.littleEndian); - this.slice_code = nifti.Utils.getByteAt(rawData, 122); - - this.xyzt_units = nifti.Utils.getByteAt(rawData, 123); - - this.cal_max = nifti.Utils.getFloatAt(rawData, 124, this.littleEndian); - this.cal_min = nifti.Utils.getFloatAt(rawData, 128, this.littleEndian); - - this.slice_duration = nifti.Utils.getFloatAt(rawData, 132, this.littleEndian); - this.toffset = nifti.Utils.getFloatAt(rawData, 136, this.littleEndian); - - this.description = nifti.Utils.getStringAt(rawData, 148, 228); - this.aux_file = nifti.Utils.getStringAt(rawData, 228, 252); - - this.qform_code = nifti.Utils.getShortAt(rawData, 252, this.littleEndian); - this.sform_code = nifti.Utils.getShortAt(rawData, 254, this.littleEndian); - - this.quatern_b = nifti.Utils.getFloatAt(rawData, 256, this.littleEndian); - this.quatern_c = nifti.Utils.getFloatAt(rawData, 260, this.littleEndian); - this.quatern_d = nifti.Utils.getFloatAt(rawData, 264, this.littleEndian); - // Added by znshje on 27/11/2021 - // - // quatern_a is a parameter in quaternion [a, b, c, d], which is required in affine calculation (METHOD 2) - // mentioned in the nifti1.h file - // It can be calculated by a = sqrt(1.0-(b*b+c*c+d*d)) - this.quatern_a = Math.sqrt(1.0 - - (Math.pow(this.quatern_b, 2) + Math.pow(this.quatern_c, 2) + Math.pow(this.quatern_d, 2))) - - this.qoffset_x = nifti.Utils.getFloatAt(rawData, 268, this.littleEndian); - this.qoffset_y = nifti.Utils.getFloatAt(rawData, 272, this.littleEndian); - this.qoffset_z = nifti.Utils.getFloatAt(rawData, 276, this.littleEndian); - - // Added by znshje on 27/11/2021 - // - /* See: https://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1.h */ - if ((this.qform_code < 1) && (this.sform_code < 1)) { - // METHOD 0 (used when both SFORM and QFORM are unknown) - this.affine[0][0] = this.pixDims[1]; - this.affine[1][1] = this.pixDims[2]; - this.affine[2][2] = this.pixDims[3]; - } - if ((this.qform_code > 0) && (this.sform_code < this.qform_code)) { - // METHOD 2 (used when qform_code > 0, which should be the "normal" case): - // --------------------------------------------------------------------- - // The (x,y,z) coordinates are given by the pixdim[] scales, a rotation - // matrix, and a shift. This method is intended to represent - // "scanner-anatomical" coordinates, which are often embedded in the - // image header (e.g., DICOM fields (0020,0032), (0020,0037), (0028,0030), - // and (0018,0050)), and represent the nominal orientation and location of - // the data. This method can also be used to represent "aligned" - // coordinates, which would typically result from some post-acquisition - // alignment of the volume to a standard orientation (e.g., the same - // subject on another day, or a rigid rotation to true anatomical - // orientation from the tilted position of the subject in the scanner). - // The formula for (x,y,z) in terms of header parameters and (i,j,k) is: - // - // [ x ] [ R11 R12 R13 ] [ pixdim[1] * i ] [ qoffset_x ] - // [ y ] = [ R21 R22 R23 ] [ pixdim[2] * j ] + [ qoffset_y ] - // [ z ] [ R31 R32 R33 ] [ qfac * pixdim[3] * k ] [ qoffset_z ] - // - // The qoffset_* shifts are in the NIFTI-1 header. Note that the center - // of the (i,j,k)=(0,0,0) voxel (first value in the dataset array) is - // just (x,y,z)=(qoffset_x,qoffset_y,qoffset_z). - // - // The rotation matrix R is calculated from the quatern_* parameters. - // This calculation is described below. - // - // The scaling factor qfac is either 1 or -1. The rotation matrix R - // defined by the quaternion parameters is "proper" (has determinant 1). - // This may not fit the needs of the data; for example, if the image - // grid is - // i increases from Left-to-Right - // j increases from Anterior-to-Posterior - // k increases from Inferior-to-Superior - // Then (i,j,k) is a left-handed triple. In this example, if qfac=1, - // the R matrix would have to be - // - // [ 1 0 0 ] - // [ 0 -1 0 ] which is "improper" (determinant = -1). - // [ 0 0 1 ] - // - // If we set qfac=-1, then the R matrix would be - // - // [ 1 0 0 ] - // [ 0 -1 0 ] which is proper. - // [ 0 0 -1 ] - // - // This R matrix is represented by quaternion [a,b,c,d] = [0,1,0,0] - // (which encodes a 180 degree rotation about the x-axis). - - // Define a, b, c, d for coding covenience - const a = this.quatern_a - const b = this.quatern_b - const c = this.quatern_c - const d = this.quatern_d - - this.qfac = this.pixDims[0] === 0 ? 1 : this.pixDims[0] - - this.quatern_R = [ - [a * a + b * b - c * c - d * d, 2 * b * c - 2 * a * d, 2 * b * d + 2 * a * c], - [2 * b * c + 2 * a * d, a * a + c * c - b * b - d * d, 2 * c * d - 2 * a * b], - [2 * b * d - 2 * a * c, 2 * c * d + 2 * a * b, a * a + d * d - c * c - b * b] - ] - - for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { - for (ctrIn = 0; ctrIn < 3; ctrIn += 1) { - this.affine[ctrOut][ctrIn] = this.quatern_R[ctrOut][ctrIn] * this.pixDims[ctrIn + 1]; - if (ctrIn === 2) { - this.affine[ctrOut][ctrIn] *= this.qfac; - } - } - } - // The last row of affine matrix is the offset vector - this.affine[0][3] = this.qoffset_x - this.affine[1][3] = this.qoffset_y - this.affine[2][3] = this.qoffset_z - } else if (this.sform_code > 0) { - // METHOD 3 (used when sform_code > 0): - // ----------------------------------- - // The (x,y,z) coordinates are given by a general affine transformation - // of the (i,j,k) indexes: - // - // x = srow_x[0] * i + srow_x[1] * j + srow_x[2] * k + srow_x[3] - // y = srow_y[0] * i + srow_y[1] * j + srow_y[2] * k + srow_y[3] - // z = srow_z[0] * i + srow_z[1] * j + srow_z[2] * k + srow_z[3] - // - // The srow_* vectors are in the NIFTI_1 header. Note that no use is - // made of pixdim[] in this method. - for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { - for (ctrIn = 0; ctrIn < 4; ctrIn += 1) { - index = 280 + (((ctrOut * 4) + ctrIn) * 4); - this.affine[ctrOut][ctrIn] = nifti.Utils.getFloatAt(rawData, index, this.littleEndian); - } - } - } - - this.affine[3][0] = 0; - this.affine[3][1] = 0; - this.affine[3][2] = 0; - this.affine[3][3] = 1; - - this.intent_name = nifti.Utils.getStringAt(rawData, 328, 344); - this.magic = nifti.Utils.getStringAt(rawData, 344, 348); - - this.isHDR = (this.magic === nifti.NIFTI1.MAGIC_NUMBER2); - - if (rawData.byteLength > nifti.NIFTI1.MAGIC_COOKIE) { - this.extensionFlag[0] = nifti.Utils.getByteAt(rawData, 348); - this.extensionFlag[1] = nifti.Utils.getByteAt(rawData, 348 + 1); - this.extensionFlag[2] = nifti.Utils.getByteAt(rawData, 348 + 2); - this.extensionFlag[3] = nifti.Utils.getByteAt(rawData, 348 + 3); - if (this.extensionFlag[0]) { - // read our extensions - this.extensions = nifti.Utils.getExtensionsAt(rawData, - this.getExtensionLocation(), - this.littleEndian, - this.vox_offset); - - // set the extensionSize and extensionCode from the first extension found - this.extensionSize = this.extensions[0].esize; - this.extensionCode = this.extensions[0].ecode; - - } - } -}; - - -/** - * Returns a formatted string of header fields. - * @returns {string} - */ -nifti.NIFTI1.prototype.toFormattedString = function () { - var fmt = nifti.Utils.formatNumber, - string = ""; - - string += ("Dim Info = " + this.dim_info + "\n"); - - string += ("Image Dimensions (1-8): " + - this.dims[0] + ", " + - this.dims[1] + ", " + - this.dims[2] + ", " + - this.dims[3] + ", " + - this.dims[4] + ", " + - this.dims[5] + ", " + - this.dims[6] + ", " + - this.dims[7] + "\n"); - - string += ("Intent Parameters (1-3): " + - this.intent_p1 + ", " + - this.intent_p2 + ", " + - this.intent_p3) + "\n"; - - string += ("Intent Code = " + this.intent_code + "\n"); - string += ("Datatype = " + this.datatypeCode + " (" + this.getDatatypeCodeString(this.datatypeCode) + ")\n"); - string += ("Bits Per Voxel = " + this.numBitsPerVoxel + "\n"); - string += ("Slice Start = " + this.slice_start + "\n"); - string += ("Voxel Dimensions (1-8): " + - fmt(this.pixDims[0]) + ", " + - fmt(this.pixDims[1]) + ", " + - fmt(this.pixDims[2]) + ", " + - fmt(this.pixDims[3]) + ", " + - fmt(this.pixDims[4]) + ", " + - fmt(this.pixDims[5]) + ", " + - fmt(this.pixDims[6]) + ", " + - fmt(this.pixDims[7]) + "\n"); - - string += ("Image Offset = " + this.vox_offset + "\n"); - string += ("Data Scale: Slope = " + fmt(this.scl_slope) + " Intercept = " + fmt(this.scl_inter) + "\n"); - string += ("Slice End = " + this.slice_end + "\n"); - string += ("Slice Code = " + this.slice_code + "\n"); - string += ("Units Code = " + this.xyzt_units + " (" + this.getUnitsCodeString(nifti.NIFTI1.SPATIAL_UNITS_MASK & this.xyzt_units) + ", " + this.getUnitsCodeString(nifti.NIFTI1.TEMPORAL_UNITS_MASK & this.xyzt_units) + ")\n"); - string += ("Display Range: Max = " + fmt(this.cal_max) + " Min = " + fmt(this.cal_min) + "\n"); - string += ("Slice Duration = " + this.slice_duration + "\n"); - string += ("Time Axis Shift = " + this.toffset + "\n"); - string += ("Description: \"" + this.description + "\"\n"); - string += ("Auxiliary File: \"" + this.aux_file + "\"\n"); - string += ("Q-Form Code = " + this.qform_code + " (" + this.getTransformCodeString(this.qform_code) + ")\n"); - string += ("S-Form Code = " + this.sform_code + " (" + this.getTransformCodeString(this.sform_code) + ")\n"); - string += ("Quaternion Parameters: " + - "b = " + fmt(this.quatern_b) + " " + - "c = " + fmt(this.quatern_c) + " " + - "d = " + fmt(this.quatern_d) + "\n"); - - string += ("Quaternion Offsets: " + - "x = " + this.qoffset_x + " " + - "y = " + this.qoffset_y + " " + - "z = " + this.qoffset_z + "\n"); - - string += ("S-Form Parameters X: " + - fmt(this.affine[0][0]) + ", " + - fmt(this.affine[0][1]) + ", " + - fmt(this.affine[0][2]) + ", " + - fmt(this.affine[0][3]) + "\n"); - - string += ("S-Form Parameters Y: " + - fmt(this.affine[1][0]) + ", " + - fmt(this.affine[1][1]) + ", " + - fmt(this.affine[1][2]) + ", " + - fmt(this.affine[1][3]) + "\n"); - - string += ("S-Form Parameters Z: " + - fmt(this.affine[2][0]) + ", " + - fmt(this.affine[2][1]) + ", " + - fmt(this.affine[2][2]) + ", " + - fmt(this.affine[2][3]) + "\n"); - - string += ("Intent Name: \"" + this.intent_name + "\"\n"); - - if (this.extensionFlag[0]) { - string += ("Extension: Size = " + this.extensionSize + " Code = " + this.extensionCode + "\n"); - - } - - return string; -}; - - -/** - * Returns a human-readable string of datatype. - * @param {number} code - * @returns {string} - */ -nifti.NIFTI1.prototype.getDatatypeCodeString = function (code) { - if (code === nifti.NIFTI1.TYPE_UINT8) { - return "1-Byte Unsigned Integer"; - } else if (code === nifti.NIFTI1.TYPE_INT16) { - return "2-Byte Signed Integer"; - } else if (code === nifti.NIFTI1.TYPE_INT32) { - return "4-Byte Signed Integer"; - } else if (code === nifti.NIFTI1.TYPE_FLOAT32) { - return "4-Byte Float"; - } else if (code === nifti.NIFTI1.TYPE_FLOAT64) { - return "8-Byte Float"; - } else if (code === nifti.NIFTI1.TYPE_RGB24) { - return "RGB"; - } else if (code === nifti.NIFTI1.TYPE_INT8) { - return "1-Byte Signed Integer"; - } else if (code === nifti.NIFTI1.TYPE_UINT16) { - return "2-Byte Unsigned Integer"; - } else if (code === nifti.NIFTI1.TYPE_UINT32) { - return "4-Byte Unsigned Integer"; - } else if (code === nifti.NIFTI1.TYPE_INT64) { - return "8-Byte Signed Integer"; - } else if (code === nifti.NIFTI1.TYPE_UINT64) { - return "8-Byte Unsigned Integer"; - } else { - return "Unknown"; - } -}; - - -/** - * Returns a human-readable string of transform type. - * @param {number} code - * @returns {string} - */ -nifti.NIFTI1.prototype.getTransformCodeString = function (code) { - if (code === nifti.NIFTI1.XFORM_SCANNER_ANAT) { - return "Scanner"; - } else if (code === nifti.NIFTI1.XFORM_ALIGNED_ANAT) { - return "Aligned"; - } else if (code === nifti.NIFTI1.XFORM_TALAIRACH) { - return "Talairach"; - } else if (code === nifti.NIFTI1.XFORM_MNI_152) { - return "MNI"; - } else { - return "Unknown"; - } -}; - - -/** - * Returns a human-readable string of spatial and temporal units. - * @param {number} code - * @returns {string} - */ -nifti.NIFTI1.prototype.getUnitsCodeString = function (code) { - if (code === nifti.NIFTI1.UNITS_METER) { - return "Meters"; - } else if (code === nifti.NIFTI1.UNITS_MM) { - return "Millimeters"; - } else if (code === nifti.NIFTI1.UNITS_MICRON) { - return "Microns"; - } else if (code === nifti.NIFTI1.UNITS_SEC) { - return "Seconds"; - } else if (code === nifti.NIFTI1.UNITS_MSEC) { - return "Milliseconds"; - } else if (code === nifti.NIFTI1.UNITS_USEC) { - return "Microseconds"; - } else if (code === nifti.NIFTI1.UNITS_HZ) { - return "Hz"; - } else if (code === nifti.NIFTI1.UNITS_PPM) { - return "PPM"; - } else if (code === nifti.NIFTI1.UNITS_RADS) { - return "Rads"; - } else { - return "Unknown"; - } -}; - - -/** - * Returns the qform matrix. - * @returns {Array.>} - */ -nifti.NIFTI1.prototype.getQformMat = function () { - return this.convertNiftiQFormToNiftiSForm(this.quatern_b, this.quatern_c, this.quatern_d, this.qoffset_x, - this.qoffset_y, this.qoffset_z, this.pixDims[1], this.pixDims[2], this.pixDims[3], this.pixDims[0]); -}; - - - -/** - * Converts qform to an affine. (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) - * @param {number} qb - * @param {number} qc - * @param {number} qd - * @param {number} qx - * @param {number} qy - * @param {number} qz - * @param {number} dx - * @param {number} dy - * @param {number} dz - * @param {number} qfac - * @returns {Array.>} - */ -nifti.NIFTI1.prototype.convertNiftiQFormToNiftiSForm = function (qb, qc, qd, qx, qy, qz, dx, dy, dz, - qfac) { - var R = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], - a, - b = qb, - c = qc, - d = qd, - xd, - yd, - zd; - - // last row is always [ 0 0 0 1 ] - R[3][0] = R[3][1] = R[3][2] = 0.0; - R[3][3] = 1.0; - - // compute a parameter from b,c,d - a = 1.0 - (b * b + c * c + d * d); - if (a < 0.0000001) { /* special case */ - - a = 1.0 / Math.sqrt(b * b + c * c + d * d); - b *= a; - c *= a; - d *= a; /* normalize (b,c,d) vector */ - a = 0.0; /* a = 0 ==> 180 degree rotation */ - } else { - - a = Math.sqrt(a); /* angle = 2*arccos(a) */ - } - - // load rotation matrix, including scaling factors for voxel sizes - xd = (dx > 0.0) ? dx : 1.0; /* make sure are positive */ - yd = (dy > 0.0) ? dy : 1.0; - zd = (dz > 0.0) ? dz : 1.0; - - if (qfac < 0.0) { - zd = -zd; /* left handedness? */ - } - - R[0][0] = (a * a + b * b - c * c - d * d) * xd; - R[0][1] = 2.0 * (b * c - a * d) * yd; - R[0][2] = 2.0 * (b * d + a * c) * zd; - R[1][0] = 2.0 * (b * c + a * d) * xd; - R[1][1] = (a * a + c * c - b * b - d * d) * yd; - R[1][2] = 2.0 * (c * d - a * b) * zd; - R[2][0] = 2.0 * (b * d - a * c) * xd; - R[2][1] = 2.0 * (c * d + a * b) * yd; - R[2][2] = (a * a + d * d - c * c - b * b) * zd; - - // load offsets - R[0][3] = qx; - R[1][3] = qy; - R[2][3] = qz; - - return R; -}; - - - -/** - * Converts sform to an orientation string (e.g., XYZ+--). (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) - * @param {Array.>} R - * @returns {string} - */ -nifti.NIFTI1.prototype.convertNiftiSFormToNEMA = function (R) { - var xi, xj, xk, yi, yj, yk, zi, zj, zk, val, detQ, detP, i, j, k, p, q, r, ibest, jbest, kbest, pbest, qbest, rbest, - M, vbest, Q, P, iChar, jChar, kChar, iSense, jSense, kSense; - k = 0; - - Q = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]; - P = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]; - - //if( icod == NULL || jcod == NULL || kcod == NULL ) return ; /* bad */ - - //*icod = *jcod = *kcod = 0 ; /* this.errorMessage returns, if sh*t happens */ - - /* load column vectors for each (i,j,k) direction from matrix */ - - /*-- i axis --*/ /*-- j axis --*/ /*-- k axis --*/ - - xi = R[0][0]; - xj = R[0][1]; - xk = R[0][2]; - - yi = R[1][0]; - yj = R[1][1]; - yk = R[1][2]; - - zi = R[2][0]; - zj = R[2][1]; - zk = R[2][2]; - - /* normalize column vectors to get unit vectors along each ijk-axis */ - - /* normalize i axis */ - val = Math.sqrt(xi * xi + yi * yi + zi * zi); - if (val === 0.0) { /* stupid input */ - return null; - } - - xi /= val; - yi /= val; - zi /= val; - - /* normalize j axis */ - val = Math.sqrt(xj * xj + yj * yj + zj * zj); - if (val === 0.0) { /* stupid input */ - return null; - } - - xj /= val; - yj /= val; - zj /= val; - - /* orthogonalize j axis to i axis, if needed */ - val = xi * xj + yi * yj + zi * zj; /* dot product between i and j */ - if (Math.abs(val) > 1.E-4) { - xj -= val * xi; - yj -= val * yi; - zj -= val * zi; - val = Math.sqrt(xj * xj + yj * yj + zj * zj); /* must renormalize */ - if (val === 0.0) { /* j was parallel to i? */ - return null; - } - xj /= val; - yj /= val; - zj /= val; - } - - /* normalize k axis; if it is zero, make it the cross product i x j */ - val = Math.sqrt(xk * xk + yk * yk + zk * zk); - if (val === 0.0) { - xk = yi * zj - zi * yj; - yk = zi * xj - zj * xi; - zk = xi * yj - yi * xj; - } else { - xk /= val; - yk /= val; - zk /= val; - } - - /* orthogonalize k to i */ - val = xi * xk + yi * yk + zi * zk; /* dot product between i and k */ - if (Math.abs(val) > 1.E-4) { - xk -= val * xi; - yk -= val * yi; - zk -= val * zi; - val = Math.sqrt(xk * xk + yk * yk + zk * zk); - if (val === 0.0) { /* bad */ - return null; - } - xk /= val; - yk /= val; - zk /= val; - } - - /* orthogonalize k to j */ - val = xj * xk + yj * yk + zj * zk; /* dot product between j and k */ - if (Math.abs(val) > 1.e-4) { - xk -= val * xj; - yk -= val * yj; - zk -= val * zj; - val = Math.sqrt(xk * xk + yk * yk + zk * zk); - if (val === 0.0) { /* bad */ - return null; - } - xk /= val; - yk /= val; - zk /= val; - } - - Q[0][0] = xi; - Q[0][1] = xj; - Q[0][2] = xk; - Q[1][0] = yi; - Q[1][1] = yj; - Q[1][2] = yk; - Q[2][0] = zi; - Q[2][1] = zj; - Q[2][2] = zk; - - /* at this point, Q is the rotation matrix from the (i,j,k) to (x,y,z) axes */ - - detQ = this.nifti_mat33_determ(Q); - if (detQ === 0.0) { /* shouldn't happen unless user is a DUFIS */ - return null; - } - - /* Build and test all possible +1/-1 coordinate permutation matrices P; - then find the P such that the rotation matrix M=PQ is closest to the - identity, in the sense of M having the smallest total rotation angle. */ - - /* Despite the formidable looking 6 nested loops, there are - only 3*3*3*2*2*2 = 216 passes, which will run very quickly. */ - - vbest = -666.0; - ibest = pbest = qbest = rbest = 1; - jbest = 2; - kbest = 3; - - for (i = 1; i <= 3; i += 1) { /* i = column number to use for row #1 */ - for (j = 1; j <= 3; j += 1) { /* j = column number to use for row #2 */ - if (i !== j) { - for (k = 1; k <= 3; k += 1) { /* k = column number to use for row #3 */ - if (!(i === k || j === k)) { - P[0][0] = P[0][1] = P[0][2] = P[1][0] = P[1][1] = P[1][2] = P[2][0] = P[2][1] = P[2][2] = 0.0; - for (p = -1; p <= 1; p += 2) { /* p,q,r are -1 or +1 */ - for (q = -1; q <= 1; q += 2) { /* and go into rows #1,2,3 */ - for (r = -1; r <= 1; r += 2) { - P[0][i - 1] = p; - P[1][j - 1] = q; - P[2][k - 1] = r; - detP = this.nifti_mat33_determ(P); /* sign of permutation */ - if ((detP * detQ) > 0.0) { - M = this.nifti_mat33_mul(P, Q); - - /* angle of M rotation = 2.0*acos(0.5*sqrt(1.0+trace(M))) */ - /* we want largest trace(M) == smallest angle == M nearest to I */ - - val = M[0][0] + M[1][1] + M[2][2]; /* trace */ - if (val > vbest) { - vbest = val; - ibest = i; - jbest = j; - kbest = k; - pbest = p; - qbest = q; - rbest = r; - } - } /* doesn't match sign of Q */ - } - } - } - } - } - } - } - } - - /* At this point ibest is 1 or 2 or 3; pbest is -1 or +1; etc. - - The matrix P that corresponds is the best permutation approximation - to Q-inverse; that is, P (approximately) takes (x,y,z) coordinates - to the (i,j,k) axes. - - For example, the first row of P (which contains pbest in column ibest) - determines the way the i axis points relative to the anatomical - (x,y,z) axes. If ibest is 2, then the i axis is along the y axis, - which is direction P2A (if pbest > 0) or A2P (if pbest < 0). - - So, using ibest and pbest, we can assign the output code for - the i axis. Mutatis mutandis for the j and k axes, of course. */ - - iChar = jChar = kChar = iSense = jSense = kSense = 0; - - switch (ibest * pbest) { - case 1: /*i = NIFTI_L2R*/ - iChar = 'X'; - iSense = '+'; - break; - case -1: /*i = NIFTI_R2L*/ - iChar = 'X'; - iSense = '-'; - break; - case 2: /*i = NIFTI_P2A*/ - iChar = 'Y'; - iSense = '+'; - break; - case -2: /*i = NIFTI_A2P*/ - iChar = 'Y'; - iSense = '-'; - break; - case 3: /*i = NIFTI_I2S*/ - iChar = 'Z'; - iSense = '+'; - break; - case -3: /*i = NIFTI_S2I*/ - iChar = 'Z'; - iSense = '-'; - break; - } - - switch (jbest * qbest) { - case 1: /*j = NIFTI_L2R*/ - jChar = 'X'; - jSense = '+'; - break; - case -1: /*j = NIFTI_R2L*/ - jChar = 'X'; - jSense = '-'; - break; - case 2: /*j = NIFTI_P2A*/ - jChar = 'Y'; - jSense = '+'; - break; - case -2: /*j = NIFTI_A2P*/ - jChar = 'Y'; - jSense = '-'; - break; - case 3: /*j = NIFTI_I2S*/ - jChar = 'Z'; - jSense = '+'; - break; - case -3: /*j = NIFTI_S2I*/ - jChar = 'Z'; - jSense = '-'; - break; - } - - switch (kbest * rbest) { - case 1: /*k = NIFTI_L2R*/ - kChar = 'X'; - kSense = '+'; - break; - case -1: /*k = NIFTI_R2L*/ - kChar = 'X'; - kSense = '-'; - break; - case 2: /*k = NIFTI_P2A*/ - kChar = 'Y'; - kSense = '+'; - break; - case -2: /*k = NIFTI_A2P*/ - kChar = 'Y'; - kSense = '-'; - break; - case 3: /*k = NIFTI_I2S*/ - kChar = 'Z'; - kSense = '+'; - break; - case -3: /*k = NIFTI_S2I*/ - kChar = 'Z'; - kSense = '-'; - break; - } - - return (iChar + jChar + kChar + iSense + jSense + kSense); -}; - - - -nifti.NIFTI1.prototype.nifti_mat33_mul = function (A, B) { - var C = [[0, 0, 0], [0, 0, 0], [0, 0, 0]], - i, - j; - - for (i = 0; i < 3; i += 1) { - for (j = 0; j < 3; j += 1) { - C[i][j] = A[i][0] * B[0][j] + A[i][1] * B[1][j] + A[i][2] * B[2][j]; - } - } - - return C; -}; - - - -nifti.NIFTI1.prototype.nifti_mat33_determ = function (R) { - var r11, r12, r13, r21, r22, r23, r31, r32, r33; - /* INPUT MATRIX: */ - r11 = R[0][0]; - r12 = R[0][1]; - r13 = R[0][2]; - r21 = R[1][0]; - r22 = R[1][1]; - r23 = R[1][2]; - r31 = R[2][0]; - r32 = R[2][1]; - r33 = R[2][2]; - - return (r11 * r22 * r33 - r11 * r32 * r23 - r21 * r12 * r33 + r21 * r32 * r13 + r31 * r12 * r23 - r31 * r22 * r13); -}; - - -/** - * Returns the byte index of the extension. - * @returns {number} - */ -nifti.NIFTI1.prototype.getExtensionLocation = function() { - return nifti.NIFTI1.MAGIC_COOKIE + 4; -}; - - -/** - * Returns the extension size. - * @param {DataView} data - * @returns {number} - */ -nifti.NIFTI1.prototype.getExtensionSize = function(data) { - return nifti.Utils.getIntAt(data, this.getExtensionLocation(), this.littleEndian); -}; - -/** - * Returns the extension code. - * @param {DataView} data - * @returns {number} - */ -nifti.NIFTI1.prototype.getExtensionCode = function(data) { - return nifti.Utils.getIntAt(data, this.getExtensionLocation() + 4, this.littleEndian); -}; - -/** - * Adds an extension - * @param {NIFTIEXTENSION} extension - * @param {number} index - */ -nifti.NIFTI1.prototype.addExtension = function(extension, index = -1) { - if(index == -1) { - this.extensions.push(extension); - } - else { - this.extensions.splice(index, 0, extension); - } - this.vox_offset += extension.esize; -} - -/** - * Removes an extension - * @param {number} index - */ - nifti.NIFTI1.prototype.removeExtension = function(index) { - - let extension = this.extensions[index]; - if(extension) { - this.vox_offset -= extension.esize; - } - this.extensions.splice(index, 1); -} - -/** - * Returns header as ArrayBuffer. - * @param {boolean} includeExtensions - should extension bytes be included - * @returns {ArrayBuffer} - */ -nifti.NIFTI1.prototype.toArrayBuffer = function(includeExtensions = false) { - const SHORT_SIZE = 2; - const FLOAT32_SIZE = 4; - let byteSize = 348 + 4; // + 4 for the extension bytes - - // calculate necessary size - if(includeExtensions) { - for(let extension of this.extensions) { - byteSize += extension.esize; - } - } - let byteArray = new Uint8Array(byteSize); - let view = new DataView(byteArray.buffer); - // sizeof_hdr - view.setInt32(0, 348, this.littleEndian); - - // data_type, db_name, extents, session_error, regular are not used - - // dim_info - view.setUint8(39, this.dim_info); - - // dims - for(let i = 0; i < 8; i++) { - view.setUint16(40 + SHORT_SIZE * i, this.dims[i], this.littleEndian); - } - - // intent_p1, intent_p2, intent_p3 - view.setFloat32(56, this.intent_p1, this.littleEndian); - view.setFloat32(60, this.intent_p2, this.littleEndian); - view.setFloat32(64, this.intent_p3, this.littleEndian); - - // intent_code, datatype, bitpix, slice_start - view.setInt16(68, this.intent_code, this.littleEndian); - view.setInt16(70, this.datatypeCode, this.littleEndian); - view.setInt16(72, this.numBitsPerVoxel, this.littleEndian); - view.setInt16(74, this.slice_start, this.littleEndian); - - // pixdim[8], vox_offset, scl_slope, scl_inter - for(let i = 0; i < 8; i++) { - view.setFloat32(76 + FLOAT32_SIZE * i, this.pixDims[i], this.littleEndian); - } - view.setFloat32(108, this.vox_offset, this.littleEndian); - view.setFloat32(112, this.scl_slope, this.littleEndian); - view.setFloat32(116, this.scl_inter, this.littleEndian); - - // slice_end - view.setInt16(120, this.slice_end, this.littleEndian); - - // slice_code, xyzt_units - view.setUint8(122, this.slice_code); - view.setUint8(123, this.xyzt_units); - - // cal_max, cal_min, slice_duration, toffset - view.setFloat32(124, this.cal_max, this.littleEndian); - view.setFloat32(128, this.cal_min, this.littleEndian); - view.setFloat32(132, this.slice_duration, this.littleEndian); - view.setFloat32(136, this.toffset, this.littleEndian); - - // glmax, glmin are unused - - // descrip and aux_file - byteArray.set(Buffer.from(this.description), 148); - byteArray.set(Buffer.from(this.aux_file), 228); - - // qform_code, sform_code - view.setInt16(252, this.qform_code, this.littleEndian); - view.setInt16(254, this.sform_code, this.littleEndian); - - // quatern_b, quatern_c, quatern_d, qoffset_x, qoffset_y, qoffset_z, srow_x[4], srow_y[4], and srow_z[4] - view.setFloat32(256, this.quatern_b, this.littleEndian); - view.setFloat32(260, this.quatern_c, this.littleEndian); - view.setFloat32(264, this.quatern_d, this.littleEndian); - view.setFloat32(268, this.qoffset_x, this.littleEndian); - view.setFloat32(272, this.qoffset_y, this.littleEndian); - view.setFloat32(276, this.qoffset_z, this.littleEndian); - const flattened = this.affine.flat(); - // we only want the first three rows - for(let i = 0; i < 12; i++) { - view.setFloat32(280 + FLOAT32_SIZE * i, flattened[i], this.littleEndian); - } - - // intent_name and magic - byteArray.set(Buffer.from(this.intent_name), 328); - byteArray.set(Buffer.from(this.magic), 344); - - // add our extension data - if(includeExtensions) { - byteArray.set(Uint8Array.from([1, 0, 0, 0]), 348); - let extensionByteIndex = this.getExtensionLocation(); - for(const extension of this.extensions) { - view.setInt32(extensionByteIndex, extension.esize, extension.littleEndian); - view.setInt32(extensionByteIndex + 4, extension.ecode, extension.littleEndian); - byteArray.set(new Uint8Array(extension.edata), extensionByteIndex + 8); - extensionByteIndex += extension.esize; - } - } - else { - // In a .nii file, these 4 bytes will always be present - byteArray.set(new Uint8Array(4).fill(0), 348); - } - - return byteArray.buffer; -}; - -/*** Exports ***/ - -var moduleType = typeof module; -if ((moduleType !== 'undefined') && module.exports) { - module.exports = nifti.NIFTI1; -} diff --git a/src/nifti1.ts b/src/nifti1.ts new file mode 100644 index 0000000..535ef03 --- /dev/null +++ b/src/nifti1.ts @@ -0,0 +1,1334 @@ +import { NIFTIEXTENSION } from "./nifti-extension"; +import { Utils } from "./utilities"; + +/*** Constructor ***/ +/** + * The NIFTI1 constructor. + * @constructor + * @property {boolean} littleEndian + * @property {number} dim_info + * @property {number[]} dims - image dimensions + * @property {number} intent_p1 + * @property {number} intent_p2 + * @property {number} intent_p3 + * @property {number} intent_code + * @property {number} datatypeCode + * @property {number} numBitsPerVoxel + * @property {number} slice_start + * @property {number} slice_end + * @property {number} slice_code + * @property {number[]} pixDims - voxel dimensions + * @property {number} vox_offset + * @property {number} scl_slope + * @property {number} scl_inter + * @property {number} xyzt_units + * @property {number} cal_max + * @property {number} cal_min + * @property {number} slice_duration + * @property {number} toffset + * @property {string} description + * @property {string} aux_file + * @property {string} intent_name + * @property {number} qform_code + * @property {number} sform_code + * @property {number} quatern_b + * @property {number} quatern_c + * @property {number} quatern_d + * @property {number} quatern_x + * @property {number} quatern_y + * @property {number} quatern_z + * @property {Array.>} affine + * @property {string} magic + * @property {boolean} isHDR - if hdr/img format + * @property {number[]} extensionFlag + * @property {number} extensionSize + * @property {number} extensionCode + * @property {nifti.NIFTIEXTENSION[]} extensions + * @type {Function} + */ + export class NIFTI1 { + littleEndian = false; + dim_info = 0; + dims: number[] = []; + intent_p1 = 0.0; + intent_p2 = 0.0; + intent_p3 = 0.0; + intent_code = 0; + datatypeCode = 0; + numBitsPerVoxel = 0; + slice_start = 0; + slice_end = 0; + slice_code = 0; + pixDims: number[] = []; + vox_offset = 0; + scl_slope = 1.0; + scl_inter = 0.0; + xyzt_units = 0; + cal_max = 0.0; + cal_min = 0.0; + slice_duration = 0.0; + toffset = 0.0; + description = ""; + aux_file = ""; + intent_name = ""; + qform_code = 0; + sform_code = 0; + quatern_a = 0.0; + quatern_b = 0.0; + quatern_c = 0.0; + quatern_d = 0.0; + qoffset_x = 0.0; + qoffset_y = 0.0; + qoffset_z = 0.0; + affine = [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1], + ]; + qfac = 1; + quatern_R: number[][] | undefined; + magic = "0"; + isHDR = false; + extensionFlag = [0, 0, 0, 0]; + extensionSize = 0; + extensionCode = 0; + extensions: NIFTIEXTENSION[] = []; + + /*** Static Pseudo-constants ***/ + + // datatype codes + public static readonly TYPE_NONE = 0; + public static readonly TYPE_BINARY = 1; + public static readonly TYPE_UINT8 = 2; + public static readonly TYPE_INT16 = 4; + public static readonly TYPE_INT32 = 8; + public static readonly TYPE_FLOAT32 = 16; + public static readonly TYPE_COMPLEX64 = 32; + public static readonly TYPE_FLOAT64 = 64; + public static readonly TYPE_RGB24 = 128; + public static readonly TYPE_INT8 = 256; + public static readonly TYPE_UINT16 = 512; + public static readonly TYPE_UINT32 = 768; + public static readonly TYPE_INT64 = 1024; + public static readonly TYPE_UINT64 = 1280; + public static readonly TYPE_FLOAT128 = 1536; + public static readonly TYPE_COMPLEX128 = 1792; + public static readonly TYPE_COMPLEX256 = 2048; + + // transform codes + public static readonly XFORM_UNKNOWN = 0; + public static readonly XFORM_SCANNER_ANAT = 1; + public static readonly XFORM_ALIGNED_ANAT = 2; + public static readonly XFORM_TALAIRACH = 3; + public static readonly XFORM_MNI_152 = 4; + + // unit codes + public static readonly SPATIAL_UNITS_MASK = 0x07; + public static readonly TEMPORAL_UNITS_MASK = 0x38; + public static readonly UNITS_UNKNOWN = 0; + public static readonly UNITS_METER = 1; + public static readonly UNITS_MM = 2; + public static readonly UNITS_MICRON = 3; + public static readonly UNITS_SEC = 8; + public static readonly UNITS_MSEC = 16; + public static readonly UNITS_USEC = 24; + public static readonly UNITS_HZ = 32; + public static readonly UNITS_PPM = 40; + public static readonly UNITS_RADS = 48; + + // nifti1 codes + public static readonly MAGIC_COOKIE = 348; + public static readonly STANDARD_HEADER_SIZE = 348; + public static readonly MAGIC_NUMBER_LOCATION = 344; + public static readonly MAGIC_NUMBER = [0x6e, 0x2b, 0x31]; // n+1 (.nii) + public static readonly MAGIC_NUMBER2 = [0x6e, 0x69, 0x31]; // ni1 (.hdr/.img) + public static readonly EXTENSION_HEADER_SIZE = 8; + + /*** Prototype Methods ***/ + + /** + * Reads the header data. + * @param {ArrayBuffer} data + */ + readHeader(data: ArrayBuffer) { + var rawData = new DataView(data), + magicCookieVal = Utils.getIntAt(rawData, 0, this.littleEndian), + ctr, + ctrOut, + ctrIn, + index; + + if (magicCookieVal !== NIFTI1.MAGIC_COOKIE) { + // try as little endian + this.littleEndian = true; + magicCookieVal = Utils.getIntAt(rawData, 0, this.littleEndian); + } + + if (magicCookieVal !== NIFTI1.MAGIC_COOKIE) { + throw new Error("This does not appear to be a NIFTI file!"); + } + + this.dim_info = Utils.getByteAt(rawData, 39); + + for (ctr = 0; ctr < 8; ctr += 1) { + index = 40 + ctr * 2; + this.dims[ctr] = Utils.getShortAt( + rawData, + index, + this.littleEndian + ); + } + + this.intent_p1 = Utils.getFloatAt(rawData, 56, this.littleEndian); + this.intent_p2 = Utils.getFloatAt(rawData, 60, this.littleEndian); + this.intent_p3 = Utils.getFloatAt(rawData, 64, this.littleEndian); + this.intent_code = Utils.getShortAt(rawData, 68, this.littleEndian); + + this.datatypeCode = Utils.getShortAt( + rawData, + 70, + this.littleEndian + ); + this.numBitsPerVoxel = Utils.getShortAt( + rawData, + 72, + this.littleEndian + ); + + this.slice_start = Utils.getShortAt(rawData, 74, this.littleEndian); + + for (ctr = 0; ctr < 8; ctr += 1) { + index = 76 + ctr * 4; + this.pixDims[ctr] = Utils.getFloatAt( + rawData, + index, + this.littleEndian + ); + } + + this.vox_offset = Utils.getFloatAt(rawData, 108, this.littleEndian); + + this.scl_slope = Utils.getFloatAt(rawData, 112, this.littleEndian); + this.scl_inter = Utils.getFloatAt(rawData, 116, this.littleEndian); + + this.slice_end = Utils.getShortAt(rawData, 120, this.littleEndian); + this.slice_code = Utils.getByteAt(rawData, 122); + + this.xyzt_units = Utils.getByteAt(rawData, 123); + + this.cal_max = Utils.getFloatAt(rawData, 124, this.littleEndian); + this.cal_min = Utils.getFloatAt(rawData, 128, this.littleEndian); + + this.slice_duration = Utils.getFloatAt( + rawData, + 132, + this.littleEndian + ); + this.toffset = Utils.getFloatAt(rawData, 136, this.littleEndian); + + this.description = Utils.getStringAt(rawData, 148, 228); + this.aux_file = Utils.getStringAt(rawData, 228, 252); + + this.qform_code = Utils.getShortAt(rawData, 252, this.littleEndian); + this.sform_code = Utils.getShortAt(rawData, 254, this.littleEndian); + + this.quatern_b = Utils.getFloatAt(rawData, 256, this.littleEndian); + this.quatern_c = Utils.getFloatAt(rawData, 260, this.littleEndian); + this.quatern_d = Utils.getFloatAt(rawData, 264, this.littleEndian); + // Added by znshje on 27/11/2021 + // + // quatern_a is a parameter in quaternion [a, b, c, d], which is required in affine calculation (METHOD 2) + // mentioned in the nifti1.h file + // It can be calculated by a = sqrt(1.0-(b*b+c*c+d*d)) + this.quatern_a = Math.sqrt( + 1.0 - + (Math.pow(this.quatern_b, 2) + + Math.pow(this.quatern_c, 2) + + Math.pow(this.quatern_d, 2)) + ); + + this.qoffset_x = Utils.getFloatAt(rawData, 268, this.littleEndian); + this.qoffset_y = Utils.getFloatAt(rawData, 272, this.littleEndian); + this.qoffset_z = Utils.getFloatAt(rawData, 276, this.littleEndian); + + // Added by znshje on 27/11/2021 + // + /* See: https://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1.h */ + if (this.qform_code > 0) { + // METHOD 2 (used when qform_code > 0, which should be the "normal" case): + // --------------------------------------------------------------------- + // The (x,y,z) coordinates are given by the pixdim[] scales, a rotation + // matrix, and a shift. This method is intended to represent + // "scanner-anatomical" coordinates, which are often embedded in the + // image header (e.g., DICOM fields (0020,0032), (0020,0037), (0028,0030), + // and (0018,0050)), and represent the nominal orientation and location of + // the data. This method can also be used to represent "aligned" + // coordinates, which would typically result from some post-acquisition + // alignment of the volume to a standard orientation (e.g., the same + // subject on another day, or a rigid rotation to true anatomical + // orientation from the tilted position of the subject in the scanner). + // The formula for (x,y,z) in terms of header parameters and (i,j,k) is: + // + // [ x ] [ R11 R12 R13 ] [ pixdim[1] * i ] [ qoffset_x ] + // [ y ] = [ R21 R22 R23 ] [ pixdim[2] * j ] + [ qoffset_y ] + // [ z ] [ R31 R32 R33 ] [ qfac * pixdim[3] * k ] [ qoffset_z ] + // + // The qoffset_* shifts are in the NIFTI-1 header. Note that the center + // of the (i,j,k)=(0,0,0) voxel (first value in the dataset array) is + // just (x,y,z)=(qoffset_x,qoffset_y,qoffset_z). + // + // The rotation matrix R is calculated from the quatern_* parameters. + // This calculation is described below. + // + // The scaling factor qfac is either 1 or -1. The rotation matrix R + // defined by the quaternion parameters is "proper" (has determinant 1). + // This may not fit the needs of the data; for example, if the image + // grid is + // i increases from Left-to-Right + // j increases from Anterior-to-Posterior + // k increases from Inferior-to-Superior + // Then (i,j,k) is a left-handed triple. In this example, if qfac=1, + // the R matrix would have to be + // + // [ 1 0 0 ] + // [ 0 -1 0 ] which is "improper" (determinant = -1). + // [ 0 0 1 ] + // + // If we set qfac=-1, then the R matrix would be + // + // [ 1 0 0 ] + // [ 0 -1 0 ] which is proper. + // [ 0 0 -1 ] + // + // This R matrix is represented by quaternion [a,b,c,d] = [0,1,0,0] + // (which encodes a 180 degree rotation about the x-axis). + + // Define a, b, c, d for coding covenience + const a = this.quatern_a; + const b = this.quatern_b; + const c = this.quatern_c; + const d = this.quatern_d; + + this.qfac = this.pixDims[0] === 0 ? 1 : this.pixDims[0]; + + this.quatern_R = [ + [ + a * a + b * b - c * c - d * d, + 2 * b * c - 2 * a * d, + 2 * b * d + 2 * a * c, + ], + [ + 2 * b * c + 2 * a * d, + a * a + c * c - b * b - d * d, + 2 * c * d - 2 * a * b, + ], + [ + 2 * b * d - 2 * a * c, + 2 * c * d + 2 * a * b, + a * a + d * d - c * c - b * b, + ], + ]; + + for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { + for (ctrIn = 0; ctrIn < 3; ctrIn += 1) { + this.affine[ctrOut][ctrIn] = + this.quatern_R[ctrOut][ctrIn] * this.pixDims[ctrIn + 1]; + if (ctrIn === 2) { + this.affine[ctrOut][ctrIn] *= this.qfac; + } + } + } + // The last row of affine matrix is the offset vector + this.affine[0][3] = this.qoffset_x; + this.affine[1][3] = this.qoffset_y; + this.affine[2][3] = this.qoffset_z; + } else if (this.sform_code > 0) { + // METHOD 3 (used when sform_code > 0): + // ----------------------------------- + // The (x,y,z) coordinates are given by a general affine transformation + // of the (i,j,k) indexes: + // + // x = srow_x[0] * i + srow_x[1] * j + srow_x[2] * k + srow_x[3] + // y = srow_y[0] * i + srow_y[1] * j + srow_y[2] * k + srow_y[3] + // z = srow_z[0] * i + srow_z[1] * j + srow_z[2] * k + srow_z[3] + // + // The srow_* vectors are in the NIFTI_1 header. Note that no use is + // made of pixdim[] in this method. + for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { + for (ctrIn = 0; ctrIn < 4; ctrIn += 1) { + index = 280 + (ctrOut * 4 + ctrIn) * 4; + this.affine[ctrOut][ctrIn] = Utils.getFloatAt( + rawData, + index, + this.littleEndian + ); + } + } + } + + this.affine[3][0] = 0; + this.affine[3][1] = 0; + this.affine[3][2] = 0; + this.affine[3][3] = 1; + + this.intent_name = Utils.getStringAt(rawData, 328, 344); + this.magic = Utils.getStringAt(rawData, 344, 348); + + this.isHDR = this.magic === String.fromCharCode.apply(null, NIFTI1.MAGIC_NUMBER2); + + if (rawData.byteLength > NIFTI1.MAGIC_COOKIE) { + this.extensionFlag[0] = Utils.getByteAt(rawData, 348); + this.extensionFlag[1] = Utils.getByteAt(rawData, 348 + 1); + this.extensionFlag[2] = Utils.getByteAt(rawData, 348 + 2); + this.extensionFlag[3] = Utils.getByteAt(rawData, 348 + 3); + if (this.extensionFlag[0]) { + // read our extensions + this.extensions = Utils.getExtensionsAt( + rawData, + this.getExtensionLocation(), + this.littleEndian, + this.vox_offset + ); + + // set the extensionSize and extensionCode from the first extension found + this.extensionSize = this.extensions[0].esize; + this.extensionCode = this.extensions[0].ecode; + } + } + } + + /** + * Returns a formatted string of header fields. + * @returns {string} + */ + toFormattedString(): string { + var fmt = Utils.formatNumber, + string = ""; + + string += "Dim Info = " + this.dim_info + "\n"; + + string += + "Image Dimensions (1-8): " + + this.dims[0] + + ", " + + this.dims[1] + + ", " + + this.dims[2] + + ", " + + this.dims[3] + + ", " + + this.dims[4] + + ", " + + this.dims[5] + + ", " + + this.dims[6] + + ", " + + this.dims[7] + + "\n"; + + string += + "Intent Parameters (1-3): " + + this.intent_p1 + + ", " + + this.intent_p2 + + ", " + + this.intent_p3 + + "\n"; + + string += "Intent Code = " + this.intent_code + "\n"; + string += + "Datatype = " + + this.datatypeCode + + " (" + + this.getDatatypeCodeString(this.datatypeCode) + + ")\n"; + string += "Bits Per Voxel = " + this.numBitsPerVoxel + "\n"; + string += "Slice Start = " + this.slice_start + "\n"; + string += + "Voxel Dimensions (1-8): " + + fmt(this.pixDims[0]) + + ", " + + fmt(this.pixDims[1]) + + ", " + + fmt(this.pixDims[2]) + + ", " + + fmt(this.pixDims[3]) + + ", " + + fmt(this.pixDims[4]) + + ", " + + fmt(this.pixDims[5]) + + ", " + + fmt(this.pixDims[6]) + + ", " + + fmt(this.pixDims[7]) + + "\n"; + + string += "Image Offset = " + this.vox_offset + "\n"; + string += + "Data Scale: Slope = " + + fmt(this.scl_slope) + + " Intercept = " + + fmt(this.scl_inter) + + "\n"; + string += "Slice End = " + this.slice_end + "\n"; + string += "Slice Code = " + this.slice_code + "\n"; + string += + "Units Code = " + + this.xyzt_units + + " (" + + this.getUnitsCodeString( + NIFTI1.SPATIAL_UNITS_MASK & this.xyzt_units + ) + + ", " + + this.getUnitsCodeString( + NIFTI1.TEMPORAL_UNITS_MASK & this.xyzt_units + ) + + ")\n"; + string += + "Display Range: Max = " + + fmt(this.cal_max) + + " Min = " + + fmt(this.cal_min) + + "\n"; + string += "Slice Duration = " + this.slice_duration + "\n"; + string += "Time Axis Shift = " + this.toffset + "\n"; + string += 'Description: "' + this.description + '"\n'; + string += 'Auxiliary File: "' + this.aux_file + '"\n'; + string += + "Q-Form Code = " + + this.qform_code + + " (" + + this.getTransformCodeString(this.qform_code) + + ")\n"; + string += + "S-Form Code = " + + this.sform_code + + " (" + + this.getTransformCodeString(this.sform_code) + + ")\n"; + string += + "Quaternion Parameters: " + + "b = " + + fmt(this.quatern_b) + + " " + + "c = " + + fmt(this.quatern_c) + + " " + + "d = " + + fmt(this.quatern_d) + + "\n"; + + string += + "Quaternion Offsets: " + + "x = " + + this.qoffset_x + + " " + + "y = " + + this.qoffset_y + + " " + + "z = " + + this.qoffset_z + + "\n"; + + string += + "S-Form Parameters X: " + + fmt(this.affine[0][0]) + + ", " + + fmt(this.affine[0][1]) + + ", " + + fmt(this.affine[0][2]) + + ", " + + fmt(this.affine[0][3]) + + "\n"; + + string += + "S-Form Parameters Y: " + + fmt(this.affine[1][0]) + + ", " + + fmt(this.affine[1][1]) + + ", " + + fmt(this.affine[1][2]) + + ", " + + fmt(this.affine[1][3]) + + "\n"; + + string += + "S-Form Parameters Z: " + + fmt(this.affine[2][0]) + + ", " + + fmt(this.affine[2][1]) + + ", " + + fmt(this.affine[2][2]) + + ", " + + fmt(this.affine[2][3]) + + "\n"; + + string += 'Intent Name: "' + this.intent_name + '"\n'; + + if (this.extensionFlag[0]) { + string += + "Extension: Size = " + + this.extensionSize + + " Code = " + + this.extensionCode + + "\n"; + } + + return string; + } + + /** + * Returns a human-readable string of datatype. + * @param {number} code + * @returns {string} + */ + getDatatypeCodeString = function (code: number): string { + if (code === NIFTI1.TYPE_UINT8) { + return "1-Byte Unsigned Integer"; + } else if (code === NIFTI1.TYPE_INT16) { + return "2-Byte Signed Integer"; + } else if (code === NIFTI1.TYPE_INT32) { + return "4-Byte Signed Integer"; + } else if (code === NIFTI1.TYPE_FLOAT32) { + return "4-Byte Float"; + } else if (code === NIFTI1.TYPE_FLOAT64) { + return "8-Byte Float"; + } else if (code === NIFTI1.TYPE_RGB24) { + return "RGB"; + } else if (code === NIFTI1.TYPE_INT8) { + return "1-Byte Signed Integer"; + } else if (code === NIFTI1.TYPE_UINT16) { + return "2-Byte Unsigned Integer"; + } else if (code === NIFTI1.TYPE_UINT32) { + return "4-Byte Unsigned Integer"; + } else if (code === NIFTI1.TYPE_INT64) { + return "8-Byte Signed Integer"; + } else if (code === NIFTI1.TYPE_UINT64) { + return "8-Byte Unsigned Integer"; + } else { + return "Unknown"; + } + }; + + /** + * Returns a human-readable string of transform type. + * @param {number} code + * @returns {string} + */ + getTransformCodeString = function (code: number): string { + if (code === NIFTI1.XFORM_SCANNER_ANAT) { + return "Scanner"; + } else if (code === NIFTI1.XFORM_ALIGNED_ANAT) { + return "Aligned"; + } else if (code === NIFTI1.XFORM_TALAIRACH) { + return "Talairach"; + } else if (code === NIFTI1.XFORM_MNI_152) { + return "MNI"; + } else { + return "Unknown"; + } + }; + + /** + * Returns a human-readable string of spatial and temporal units. + * @param {number} code + * @returns {string} + */ + getUnitsCodeString = function (code: number): string { + if (code === NIFTI1.UNITS_METER) { + return "Meters"; + } else if (code === NIFTI1.UNITS_MM) { + return "Millimeters"; + } else if (code === NIFTI1.UNITS_MICRON) { + return "Microns"; + } else if (code === NIFTI1.UNITS_SEC) { + return "Seconds"; + } else if (code === NIFTI1.UNITS_MSEC) { + return "Milliseconds"; + } else if (code === NIFTI1.UNITS_USEC) { + return "Microseconds"; + } else if (code === NIFTI1.UNITS_HZ) { + return "Hz"; + } else if (code === NIFTI1.UNITS_PPM) { + return "PPM"; + } else if (code === NIFTI1.UNITS_RADS) { + return "Rads"; + } else { + return "Unknown"; + } + }; + + /** + * Returns the qform matrix. + * @returns {Array.>} + */ + getQformMat(): Array> { + return this.convertNiftiQFormToNiftiSForm( + this.quatern_b, + this.quatern_c, + this.quatern_d, + this.qoffset_x, + this.qoffset_y, + this.qoffset_z, + this.pixDims[1], + this.pixDims[2], + this.pixDims[3], + this.pixDims[0] + ); + } + + /** + * Converts qform to an affine. (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {number} qb + * @param {number} qc + * @param {number} qd + * @param {number} qx + * @param {number} qy + * @param {number} qz + * @param {number} dx + * @param {number} dy + * @param {number} dz + * @param {number} qfac + * @returns {Array.>} + */ + convertNiftiQFormToNiftiSForm( + qb: number, + qc: number, + qd: number, + qx: number, + qy: number, + qz: number, + dx: number, + dy: number, + dz: number, + qfac: number + ): Array> { + var R = [ + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + ], + a, + b = qb, + c = qc, + d = qd, + xd, + yd, + zd; + + // last row is always [ 0 0 0 1 ] + R[3][0] = R[3][1] = R[3][2] = 0.0; + R[3][3] = 1.0; + + // compute a parameter from b,c,d + a = 1.0 - (b * b + c * c + d * d); + if (a < 0.0000001) { + /* special case */ + + a = 1.0 / Math.sqrt(b * b + c * c + d * d); + b *= a; + c *= a; + d *= a; /* normalize (b,c,d) vector */ + a = 0.0; /* a = 0 ==> 180 degree rotation */ + } else { + a = Math.sqrt(a); /* angle = 2*arccos(a) */ + } + + // load rotation matrix, including scaling factors for voxel sizes + xd = dx > 0.0 ? dx : 1.0; /* make sure are positive */ + yd = dy > 0.0 ? dy : 1.0; + zd = dz > 0.0 ? dz : 1.0; + + if (qfac < 0.0) { + zd = -zd; /* left handedness? */ + } + + R[0][0] = (a * a + b * b - c * c - d * d) * xd; + R[0][1] = 2.0 * (b * c - a * d) * yd; + R[0][2] = 2.0 * (b * d + a * c) * zd; + R[1][0] = 2.0 * (b * c + a * d) * xd; + R[1][1] = (a * a + c * c - b * b - d * d) * yd; + R[1][2] = 2.0 * (c * d - a * b) * zd; + R[2][0] = 2.0 * (b * d - a * c) * xd; + R[2][1] = 2.0 * (c * d + a * b) * yd; + R[2][2] = (a * a + d * d - c * c - b * b) * zd; + + // load offsets + R[0][3] = qx; + R[1][3] = qy; + R[2][3] = qz; + + return R; + } + + /** + * Converts sform to an orientation string (e.g., XYZ+--). (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {Array.>} R + * @returns {string} + */ + convertNiftiSFormToNEMA(R: Array>): string | null { + var xi, + xj, + xk, + yi, + yj, + yk, + zi, + zj, + zk, + val, + detQ, + detP, + i, + j, + k, + p, + q, + r, + ibest, + jbest, + kbest, + pbest, + qbest, + rbest, + M, + vbest, + Q, + P, + iChar, + jChar, + kChar, + iSense, + jSense, + kSense; + k = 0; + + Q = [ + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ]; + P = [ + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ]; + + //if( icod == NULL || jcod == NULL || kcod == NULL ) return ; /* bad */ + + //*icod = *jcod = *kcod = 0 ; /* this.errorMessage returns, if sh*t happens */ + + /* load column vectors for each (i,j,k) direction from matrix */ + + /*-- i axis --*/ /*-- j axis --*/ /*-- k axis --*/ + + xi = R[0][0]; + xj = R[0][1]; + xk = R[0][2]; + + yi = R[1][0]; + yj = R[1][1]; + yk = R[1][2]; + + zi = R[2][0]; + zj = R[2][1]; + zk = R[2][2]; + + /* normalize column vectors to get unit vectors along each ijk-axis */ + + /* normalize i axis */ + val = Math.sqrt(xi * xi + yi * yi + zi * zi); + if (val === 0.0) { + /* stupid input */ + return null; + } + + xi /= val; + yi /= val; + zi /= val; + + /* normalize j axis */ + val = Math.sqrt(xj * xj + yj * yj + zj * zj); + if (val === 0.0) { + /* stupid input */ + return null; + } + + xj /= val; + yj /= val; + zj /= val; + + /* orthogonalize j axis to i axis, if needed */ + val = xi * xj + yi * yj + zi * zj; /* dot product between i and j */ + if (Math.abs(val) > 1e-4) { + xj -= val * xi; + yj -= val * yi; + zj -= val * zi; + val = Math.sqrt(xj * xj + yj * yj + zj * zj); /* must renormalize */ + if (val === 0.0) { + /* j was parallel to i? */ + return null; + } + xj /= val; + yj /= val; + zj /= val; + } + + /* normalize k axis; if it is zero, make it the cross product i x j */ + val = Math.sqrt(xk * xk + yk * yk + zk * zk); + if (val === 0.0) { + xk = yi * zj - zi * yj; + yk = zi * xj - zj * xi; + zk = xi * yj - yi * xj; + } else { + xk /= val; + yk /= val; + zk /= val; + } + + /* orthogonalize k to i */ + val = xi * xk + yi * yk + zi * zk; /* dot product between i and k */ + if (Math.abs(val) > 1e-4) { + xk -= val * xi; + yk -= val * yi; + zk -= val * zi; + val = Math.sqrt(xk * xk + yk * yk + zk * zk); + if (val === 0.0) { + /* bad */ + return null; + } + xk /= val; + yk /= val; + zk /= val; + } + + /* orthogonalize k to j */ + val = xj * xk + yj * yk + zj * zk; /* dot product between j and k */ + if (Math.abs(val) > 1e-4) { + xk -= val * xj; + yk -= val * yj; + zk -= val * zj; + val = Math.sqrt(xk * xk + yk * yk + zk * zk); + if (val === 0.0) { + /* bad */ + return null; + } + xk /= val; + yk /= val; + zk /= val; + } + + Q[0][0] = xi; + Q[0][1] = xj; + Q[0][2] = xk; + Q[1][0] = yi; + Q[1][1] = yj; + Q[1][2] = yk; + Q[2][0] = zi; + Q[2][1] = zj; + Q[2][2] = zk; + + /* at this point, Q is the rotation matrix from the (i,j,k) to (x,y,z) axes */ + + detQ = this.nifti_mat33_determ(Q); + if (detQ === 0.0) { + /* shouldn't happen unless user is a DUFIS */ + return null; + } + + /* Build and test all possible +1/-1 coordinate permutation matrices P; + then find the P such that the rotation matrix M=PQ is closest to the + identity, in the sense of M having the smallest total rotation angle. */ + + /* Despite the formidable looking 6 nested loops, there are + only 3*3*3*2*2*2 = 216 passes, which will run very quickly. */ + + vbest = -666.0; + ibest = pbest = qbest = rbest = 1; + jbest = 2; + kbest = 3; + + for (i = 1; i <= 3; i += 1) { + /* i = column number to use for row #1 */ + for (j = 1; j <= 3; j += 1) { + /* j = column number to use for row #2 */ + if (i !== j) { + for (k = 1; k <= 3; k += 1) { + /* k = column number to use for row #3 */ + if (!(i === k || j === k)) { + P[0][0] = + P[0][1] = + P[0][2] = + P[1][0] = + P[1][1] = + P[1][2] = + P[2][0] = + P[2][1] = + P[2][2] = + 0.0; + for (p = -1; p <= 1; p += 2) { + /* p,q,r are -1 or +1 */ + for (q = -1; q <= 1; q += 2) { + /* and go into rows #1,2,3 */ + for (r = -1; r <= 1; r += 2) { + P[0][i - 1] = p; + P[1][j - 1] = q; + P[2][k - 1] = r; + detP = + this.nifti_mat33_determ(P); /* sign of permutation */ + if (detP * detQ > 0.0) { + M = this.nifti_mat33_mul(P, Q); + + /* angle of M rotation = 2.0*acos(0.5*sqrt(1.0+trace(M))) */ + /* we want largest trace(M) == smallest angle == M nearest to I */ + + val = M[0][0] + M[1][1] + M[2][2]; /* trace */ + if (val > vbest) { + vbest = val; + ibest = i; + jbest = j; + kbest = k; + pbest = p; + qbest = q; + rbest = r; + } + } /* doesn't match sign of Q */ + } + } + } + } + } + } + } + } + + /* At this point ibest is 1 or 2 or 3; pbest is -1 or +1; etc. + + The matrix P that corresponds is the best permutation approximation + to Q-inverse; that is, P (approximately) takes (x,y,z) coordinates + to the (i,j,k) axes. + + For example, the first row of P (which contains pbest in column ibest) + determines the way the i axis points relative to the anatomical + (x,y,z) axes. If ibest is 2, then the i axis is along the y axis, + which is direction P2A (if pbest > 0) or A2P (if pbest < 0). + + So, using ibest and pbest, we can assign the output code for + the i axis. Mutatis mutandis for the j and k axes, of course. */ + + iChar = jChar = kChar = iSense = jSense = kSense = ""; + + switch (ibest * pbest) { + case 1 /*i = NIFTI_L2R*/: + iChar = "X"; + iSense = "+"; + break; + case -1 /*i = NIFTI_R2L*/: + iChar = "X"; + iSense = "-"; + break; + case 2 /*i = NIFTI_P2A*/: + iChar = "Y"; + iSense = "+"; + break; + case -2 /*i = NIFTI_A2P*/: + iChar = "Y"; + iSense = "-"; + break; + case 3 /*i = NIFTI_I2S*/: + iChar = "Z"; + iSense = "+"; + break; + case -3 /*i = NIFTI_S2I*/: + iChar = "Z"; + iSense = "-"; + break; + } + + switch (jbest * qbest) { + case 1 /*j = NIFTI_L2R*/: + jChar = "X"; + jSense = "+"; + break; + case -1 /*j = NIFTI_R2L*/: + jChar = "X"; + jSense = "-"; + break; + case 2 /*j = NIFTI_P2A*/: + jChar = "Y"; + jSense = "+"; + break; + case -2 /*j = NIFTI_A2P*/: + jChar = "Y"; + jSense = "-"; + break; + case 3 /*j = NIFTI_I2S*/: + jChar = "Z"; + jSense = "+"; + break; + case -3 /*j = NIFTI_S2I*/: + jChar = "Z"; + jSense = "-"; + break; + } + + switch (kbest * rbest) { + case 1 /*k = NIFTI_L2R*/: + kChar = "X"; + kSense = "+"; + break; + case -1 /*k = NIFTI_R2L*/: + kChar = "X"; + kSense = "-"; + break; + case 2 /*k = NIFTI_P2A*/: + kChar = "Y"; + kSense = "+"; + break; + case -2 /*k = NIFTI_A2P*/: + kChar = "Y"; + kSense = "-"; + break; + case 3 /*k = NIFTI_I2S*/: + kChar = "Z"; + kSense = "+"; + break; + case -3 /*k = NIFTI_S2I*/: + kChar = "Z"; + kSense = "-"; + break; + } + + return iChar + jChar + kChar + iSense + jSense + kSense; + } + + nifti_mat33_mul = function (A: number[][], B: number[][]) { + var C = [ + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ], + i, + j; + + for (i = 0; i < 3; i += 1) { + for (j = 0; j < 3; j += 1) { + C[i][j] = A[i][0] * B[0][j] + A[i][1] * B[1][j] + A[i][2] * B[2][j]; + } + } + + return C; + }; + + nifti_mat33_determ = function (R: number[][]) { + var r11, r12, r13, r21, r22, r23, r31, r32, r33; + /* INPUT MATRIX: */ + r11 = R[0][0]; + r12 = R[0][1]; + r13 = R[0][2]; + r21 = R[1][0]; + r22 = R[1][1]; + r23 = R[1][2]; + r31 = R[2][0]; + r32 = R[2][1]; + r33 = R[2][2]; + + return ( + r11 * r22 * r33 - + r11 * r32 * r23 - + r21 * r12 * r33 + + r21 * r32 * r13 + + r31 * r12 * r23 - + r31 * r22 * r13 + ); + }; + + /** + * Returns the byte index of the extension. + * @returns {number} + */ + getExtensionLocation() { + return NIFTI1.MAGIC_COOKIE + 4; + } + + /** + * Returns the extension size. + * @param {DataView} data + * @returns {number} + */ + getExtensionSize(data: DataView) { + return Utils.getIntAt( + data, + this.getExtensionLocation(), + this.littleEndian + ); + } + + /** + * Returns the extension code. + * @param {DataView} data + * @returns {number} + */ + getExtensionCode(data: DataView) { + return Utils.getIntAt( + data, + this.getExtensionLocation() + 4, + this.littleEndian + ); + } + + /** + * Adds an extension + * @param {NIFTIEXTENSION} extension + * @param {number} index + */ + addExtension(extension: NIFTIEXTENSION, index = -1) { + if (index == -1) { + this.extensions.push(extension); + } else { + this.extensions.splice(index, 0, extension); + } + this.vox_offset += extension.esize; + } + + /** + * Removes an extension + * @param {number} index + */ + removeExtension(index: number) { + let extension = this.extensions[index]; + if (extension) { + this.vox_offset -= extension.esize; + } + this.extensions.splice(index, 1); + } + + /** + * Returns header as ArrayBuffer. + * @param {boolean} includeExtensions - should extension bytes be included + * @returns {ArrayBuffer} + */ + toArrayBuffer(includeExtensions = false) { + const SHORT_SIZE = 2; + const FLOAT32_SIZE = 4; + let byteSize = 348 + 4; // + 4 for the extension bytes + + // calculate necessary size + if (includeExtensions) { + for (let extension of this.extensions) { + byteSize += extension.esize; + } + } + let byteArray = new Uint8Array(byteSize); + let view = new DataView(byteArray.buffer); + // sizeof_hdr + view.setInt32(0, 348, this.littleEndian); + + // data_type, db_name, extents, session_error, regular are not used + + // dim_info + view.setUint8(39, this.dim_info); + + // dims + for (let i = 0; i < 8; i++) { + view.setUint16(40 + SHORT_SIZE * i, this.dims[i], this.littleEndian); + } + + // intent_p1, intent_p2, intent_p3 + view.setFloat32(56, this.intent_p1, this.littleEndian); + view.setFloat32(60, this.intent_p2, this.littleEndian); + view.setFloat32(64, this.intent_p3, this.littleEndian); + + // intent_code, datatype, bitpix, slice_start + view.setInt16(68, this.intent_code, this.littleEndian); + view.setInt16(70, this.datatypeCode, this.littleEndian); + view.setInt16(72, this.numBitsPerVoxel, this.littleEndian); + view.setInt16(74, this.slice_start, this.littleEndian); + + // pixdim[8], vox_offset, scl_slope, scl_inter + for (let i = 0; i < 8; i++) { + view.setFloat32( + 76 + FLOAT32_SIZE * i, + this.pixDims[i], + this.littleEndian + ); + } + view.setFloat32(108, this.vox_offset, this.littleEndian); + view.setFloat32(112, this.scl_slope, this.littleEndian); + view.setFloat32(116, this.scl_inter, this.littleEndian); + + // slice_end + view.setInt16(120, this.slice_end, this.littleEndian); + + // slice_code, xyzt_units + view.setUint8(122, this.slice_code); + view.setUint8(123, this.xyzt_units); + + // cal_max, cal_min, slice_duration, toffset + view.setFloat32(124, this.cal_max, this.littleEndian); + view.setFloat32(128, this.cal_min, this.littleEndian); + view.setFloat32(132, this.slice_duration, this.littleEndian); + view.setFloat32(136, this.toffset, this.littleEndian); + + // glmax, glmin are unused + + // descrip and aux_file + byteArray.set(Buffer.from(this.description), 148); + byteArray.set(Buffer.from(this.aux_file), 228); + + // qform_code, sform_code + view.setInt16(252, this.qform_code, this.littleEndian); + view.setInt16(254, this.sform_code, this.littleEndian); + + // quatern_b, quatern_c, quatern_d, qoffset_x, qoffset_y, qoffset_z, srow_x[4], srow_y[4], and srow_z[4] + view.setFloat32(256, this.quatern_b, this.littleEndian); + view.setFloat32(260, this.quatern_c, this.littleEndian); + view.setFloat32(264, this.quatern_d, this.littleEndian); + view.setFloat32(268, this.qoffset_x, this.littleEndian); + view.setFloat32(272, this.qoffset_y, this.littleEndian); + view.setFloat32(276, this.qoffset_z, this.littleEndian); + const flattened = this.affine.flat(); + // we only want the first three rows + for (let i = 0; i < 12; i++) { + view.setFloat32( + 280 + FLOAT32_SIZE * i, + flattened[i], + this.littleEndian + ); + } + + // intent_name and magic + byteArray.set(Buffer.from(this.intent_name), 328); + byteArray.set(Buffer.from(this.magic), 344); + + // add our extension data + if (includeExtensions) { + byteArray.set(Uint8Array.from([1, 0, 0, 0]), 348); + let extensionByteIndex = this.getExtensionLocation(); + for (const extension of this.extensions) { + view.setInt32( + extensionByteIndex, + extension.esize, + extension.littleEndian + ); + view.setInt32( + extensionByteIndex + 4, + extension.ecode, + extension.littleEndian + ); + byteArray.set( + new Uint8Array(extension.edata), + extensionByteIndex + 8 + ); + extensionByteIndex += extension.esize; + } + } else { + // In a .nii file, these 4 bytes will always be present + byteArray.set(new Uint8Array(4).fill(0), 348); + } + + return byteArray.buffer; + } + } \ No newline at end of file diff --git a/src/nifti2.js b/src/nifti2.js deleted file mode 100644 index 4e3e351..0000000 --- a/src/nifti2.js +++ /dev/null @@ -1,559 +0,0 @@ - -/*jslint browser: true, node: true */ -/*global */ - -"use strict"; - -/*** Imports ***/ - -var nifti = nifti || {}; -nifti.Utils = nifti.Utils || ((typeof require !== 'undefined') ? require('./utilities.js') : null); -nifti.NIFTI1 = nifti.NIFTI1 || ((typeof require !== 'undefined') ? require('./nifti1.js') : null); -nifti.NIFTIEXTENSION = nifti.NIFTIEXTENSION || ((typeof require !== 'undefined') ? require('./nifti-extension.js') : null); - -/*** Constructor ***/ - -/** - * The NIFTI2 constructor. - * @constructor - * @property {boolean} littleEndian - * @property {number} dim_info - * @property {number[]} dims - image dimensions - * @property {number} intent_p1 - * @property {number} intent_p2 - * @property {number} intent_p3 - * @property {number} intent_code - * @property {number} datatypeCode - * @property {number} numBitsPerVoxel - * @property {number} slice_start - * @property {number} slice_end - * @property {number} slice_code - * @property {number[]} pixDims - voxel dimensions - * @property {number} vox_offset - * @property {number} scl_slope - * @property {number} scl_inter - * @property {number} xyzt_units - * @property {number} cal_max - * @property {number} cal_min - * @property {number} slice_duration - * @property {number} toffset - * @property {string} description - * @property {string} aux_file - * @property {string} intent_name - * @property {number} qform_code - * @property {number} sform_code - * @property {number} quatern_b - * @property {number} quatern_c - * @property {number} quatern_d - * @property {number} quatern_x - * @property {number} quatern_y - * @property {number} quatern_z - * @property {Array.>} affine - * @property {string} magic - * @property {number[]} extensionFlag - * @property {nifti.NIFTIEXTENSION[]} extensions - * @type {Function} - */ -nifti.NIFTI2 = nifti.NIFTI2 || function () { - this.littleEndian = false; - this.dim_info = 0; - this.dims = []; - this.intent_p1 = 0; - this.intent_p2 = 0; - this.intent_p3 = 0; - this.intent_code = 0; - this.datatypeCode = 0; - this.numBitsPerVoxel = 0; - this.slice_start = 0; - this.slice_end = 0; - this.slice_code = 0; - this.pixDims = []; - this.vox_offset = 0; - this.scl_slope = 1; - this.scl_inter = 0; - this.xyzt_units = 0; - this.cal_max = 0; - this.cal_min = 0; - this.slice_duration = 0; - this.toffset = 0; - this.description = ""; - this.aux_file = ""; - this.intent_name = ""; - this.qform_code = 0; - this.sform_code = 0; - this.quatern_b = 0; - this.quatern_c = 0; - this.quatern_d = 0; - this.qoffset_x = 0; - this.qoffset_y = 0; - this.qoffset_z = 0; - this.affine = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]; - this.magic = 0; - this.extensionFlag = [0, 0, 0, 0]; - this.extensions = []; -}; - - - -/*** Static Pseudo-constants ***/ - -nifti.NIFTI2.MAGIC_COOKIE = 540; -nifti.NIFTI2.MAGIC_NUMBER_LOCATION = 4; -nifti.NIFTI2.MAGIC_NUMBER = [0x6E, 0x2B, 0x32, 0, 0x0D, 0x0A, 0x1A, 0x0A]; // n+2\0 -nifti.NIFTI2.MAGIC_NUMBER2 = [0x6E, 0x69, 0x32, 0, 0x0D, 0x0A, 0x1A, 0x0A]; // ni2\0 - - - -/*** Prototype Methods ***/ - -/** - * Reads the header data. - * @param {ArrayBuffer} data - */ -nifti.NIFTI2.prototype.readHeader = function (data) { - var rawData = new DataView(data), - magicCookieVal = nifti.Utils.getIntAt(rawData, 0, this.littleEndian), - ctr, - ctrOut, - ctrIn, - index, - array; - - if (magicCookieVal !== nifti.NIFTI2.MAGIC_COOKIE) { // try as little endian - this.littleEndian = true; - magicCookieVal = nifti.Utils.getIntAt(rawData, 0, this.littleEndian); - } - - if (magicCookieVal !== nifti.NIFTI2.MAGIC_COOKIE) { - throw new Error("This does not appear to be a NIFTI file!"); - } - this.magic = nifti.Utils.getStringAt(rawData, 4, 12); - this.datatypeCode = nifti.Utils.getShortAt(rawData, 12, this.littleEndian); - this.numBitsPerVoxel = nifti.Utils.getShortAt(rawData, 14, this.littleEndian); - - for (ctr = 0; ctr < 8; ctr += 1) { - index = 16 + (ctr * 8); - this.dims[ctr] = nifti.Utils.getLongAt(rawData, index, this.littleEndian); - } - - this.intent_p1 = nifti.Utils.getDoubleAt(rawData, 80, this.littleEndian); - this.intent_p2 = nifti.Utils.getDoubleAt(rawData, 88, this.littleEndian); - this.intent_p3 = nifti.Utils.getDoubleAt(rawData, 96, this.littleEndian); - - for (ctr = 0; ctr < 8; ctr += 1) { - index = 104 + (ctr * 8); - this.pixDims[ctr] = nifti.Utils.getDoubleAt(rawData, index, this.littleEndian); - } - - this.vox_offset = nifti.Utils.getLongAt(rawData, 168, this.littleEndian); - - this.scl_slope = nifti.Utils.getDoubleAt(rawData, 176, this.littleEndian); - this.scl_inter = nifti.Utils.getDoubleAt(rawData, 184, this.littleEndian); - - this.cal_max = nifti.Utils.getDoubleAt(rawData, 192, this.littleEndian); - this.cal_min = nifti.Utils.getDoubleAt(rawData, 200, this.littleEndian); - - this.slice_duration = nifti.Utils.getDoubleAt(rawData, 208, this.littleEndian); - - this.toffset = nifti.Utils.getDoubleAt(rawData, 216, this.littleEndian); - - this.slice_start = nifti.Utils.getLongAt(rawData, 224, this.littleEndian); - this.slice_end = nifti.Utils.getLongAt(rawData, 232, this.littleEndian); - - this.description = nifti.Utils.getStringAt(rawData, 240, 240 + 80); - this.aux_file = nifti.Utils.getStringAt(rawData, 320, 320 + 24); - - this.qform_code = nifti.Utils.getIntAt(rawData, 344, this.littleEndian); - this.sform_code = nifti.Utils.getIntAt(rawData, 348, this.littleEndian); - - this.quatern_b = nifti.Utils.getDoubleAt(rawData, 352, this.littleEndian); - this.quatern_c = nifti.Utils.getDoubleAt(rawData, 360, this.littleEndian); - this.quatern_d = nifti.Utils.getDoubleAt(rawData, 368, this.littleEndian); - this.qoffset_x = nifti.Utils.getDoubleAt(rawData, 376, this.littleEndian); - this.qoffset_y = nifti.Utils.getDoubleAt(rawData, 384, this.littleEndian); - this.qoffset_z = nifti.Utils.getDoubleAt(rawData, 392, this.littleEndian); - - for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { - for (ctrIn = 0; ctrIn < 4; ctrIn += 1) { - index = 400 + (((ctrOut * 4) + ctrIn) * 8); - this.affine[ctrOut][ctrIn] = nifti.Utils.getDoubleAt(rawData, index, this.littleEndian); - } - } - - this.affine[3][0] = 0; - this.affine[3][1] = 0; - this.affine[3][2] = 0; - this.affine[3][3] = 1; - - this.slice_code = nifti.Utils.getIntAt(rawData, 496, this.littleEndian); - this.xyzt_units = nifti.Utils.getIntAt(rawData, 500, this.littleEndian); - this.intent_code = nifti.Utils.getIntAt(rawData, 504, this.littleEndian); - this.intent_name = nifti.Utils.getStringAt(rawData, 508, 508 + 16); - - this.dim_info = nifti.Utils.getByteAt(rawData, 524); - - if (rawData.byteLength > nifti.NIFTI2.MAGIC_COOKIE) { - this.extensionFlag[0] = nifti.Utils.getByteAt(rawData, 540); - this.extensionFlag[1] = nifti.Utils.getByteAt(rawData, 540 + 1); - this.extensionFlag[2] = nifti.Utils.getByteAt(rawData, 540 + 2); - this.extensionFlag[3] = nifti.Utils.getByteAt(rawData, 540 + 3); - - if (this.extensionFlag[0]) { - // read our extensions - this.extensions = nifti.Utils.getExtensionsAt(rawData, - this.getExtensionLocation(), - this.littleEndian, - this.vox_offset); - - // set the extensionSize and extensionCode from the first extension found - this.extensionSize = this.extensions[0].esize; - this.extensionCode = this.extensions[0].ecode; - } - } -}; - - - -/** - * Returns a formatted string of header fields. - * @returns {string} - */ -nifti.NIFTI2.prototype.toFormattedString = function () { - var fmt = nifti.Utils.formatNumber, - string = ""; - - string += ("Datatype = " + + this.datatypeCode + " (" + this.getDatatypeCodeString(this.datatypeCode) + ")\n"); - string += ("Bits Per Voxel = " + " = " + this.numBitsPerVoxel + "\n"); - string += ("Image Dimensions" + " (1-8): " + - this.dims[0] + ", " + - this.dims[1] + ", " + - this.dims[2] + ", " + - this.dims[3] + ", " + - this.dims[4] + ", " + - this.dims[5] + ", " + - this.dims[6] + ", " + - this.dims[7] + "\n"); - - string += ("Intent Parameters (1-3): " + - this.intent_p1 + ", " + - this.intent_p2 + ", " + - this.intent_p3) + "\n"; - - string += ("Voxel Dimensions (1-8): " + - fmt(this.pixDims[0]) + ", " + - fmt(this.pixDims[1]) + ", " + - fmt(this.pixDims[2]) + ", " + - fmt(this.pixDims[3]) + ", " + - fmt(this.pixDims[4]) + ", " + - fmt(this.pixDims[5]) + ", " + - fmt(this.pixDims[6]) + ", " + - fmt(this.pixDims[7]) + "\n"); - - string += ("Image Offset = " + this.vox_offset + "\n"); - string += ("Data Scale: Slope = " + fmt(this.scl_slope) + " Intercept = " + fmt(this.scl_inter) + "\n"); - string += ("Display Range: Max = " + fmt(this.cal_max) + " Min = " + fmt(this.cal_min) + "\n"); - string += ("Slice Duration = " + this.slice_duration + "\n"); - string += ("Time Axis Shift = " + this.toffset + "\n"); - string += ("Slice Start = " + this.slice_start + "\n"); - string += ("Slice End = " + this.slice_end + "\n"); - string += ("Description: \"" + this.description + "\"\n"); - string += ("Auxiliary File: \"" + this.aux_file + "\"\n"); - string += ("Q-Form Code = " + this.qform_code + " (" + this.getTransformCodeString(this.qform_code) + ")\n"); - string += ("S-Form Code = " + this.sform_code + " (" + this.getTransformCodeString(this.sform_code) + ")\n"); - string += ("Quaternion Parameters: " + - "b = " + fmt(this.quatern_b) + " " + - "c = " + fmt(this.quatern_c) + " " + - "d = " + fmt(this.quatern_d) + "\n"); - - string += ("Quaternion Offsets: " + - "x = " + this.qoffset_x + " " + - "y = " + this.qoffset_y + " " + - "z = " + this.qoffset_z + "\n"); - - string += ("S-Form Parameters X: " + - fmt(this.affine[0][0]) + ", " + - fmt(this.affine[0][1]) + ", " + - fmt(this.affine[0][2]) + ", " + - fmt(this.affine[0][3]) + "\n"); - - string += ("S-Form Parameters Y: " + - fmt(this.affine[1][0]) + ", " + - fmt(this.affine[1][1]) + ", " + - fmt(this.affine[1][2]) + ", " + - fmt(this.affine[1][3]) + "\n"); - - string += ("S-Form Parameters Z: " + - fmt(this.affine[2][0]) + ", " + - fmt(this.affine[2][1]) + ", " + - fmt(this.affine[2][2]) + ", " + - fmt(this.affine[2][3]) + "\n"); - - string += ("Slice Code = " + this.slice_code + "\n"); - string += ("Units Code = " + this.xyzt_units + " (" + this.getUnitsCodeString(nifti.NIFTI1.SPATIAL_UNITS_MASK & this.xyzt_units) + ", " + this.getUnitsCodeString(nifti.NIFTI1.TEMPORAL_UNITS_MASK & this.xyzt_units) + ")\n"); - string += ("Intent Code = " + this.intent_code + "\n"); - string += ("Intent Name: \"" + this.intent_name + "\"\n"); - - string += ("Dim Info = " + this.dim_info + "\n"); - - return string; -}; - - - -/** - * Returns the byte index of the extension. - * @returns {number} - */ -nifti.NIFTI2.prototype.getExtensionLocation = function() { - return nifti.NIFTI2.MAGIC_COOKIE + 4; -}; - - - -/** - * Returns the extension size. - * @param {DataView} data - * @returns {number} - */ -nifti.NIFTI2.prototype.getExtensionSize = nifti.NIFTI1.prototype.getExtensionSize; - -/** - * Returns the extension code. - * @param {DataView} data - * @returns {number} - */ -nifti.NIFTI2.prototype.getExtensionCode = nifti.NIFTI1.prototype.getExtensionCode; - -/** - * Adds an extension - * @param {NIFTIEXTENSION} extension - * @param {number} index - */ - nifti.NIFTI2.prototype.addExtension = nifti.NIFTI1.prototype.addExtension; - -/** - * Removes an extension - * @param {number} index - */ - nifti.NIFTI2.prototype.removeExtension = nifti.NIFTI1.prototype.removeExtension; - - - -/** - * Returns a human-readable string of datatype. - * @param {number} code - * @returns {string} - */ -nifti.NIFTI2.prototype.getDatatypeCodeString = nifti.NIFTI1.prototype.getDatatypeCodeString; - - - -/** - * Returns a human-readable string of transform type. - * @param {number} code - * @returns {string} - */ -nifti.NIFTI2.prototype.getTransformCodeString = nifti.NIFTI1.prototype.getTransformCodeString; - - - -/** - * Returns a human-readable string of spatial and temporal units. - * @param {number} code - * @returns {string} - */ -nifti.NIFTI2.prototype.getUnitsCodeString = nifti.NIFTI1.prototype.getUnitsCodeString; - - - -/** - * Returns the qform matrix. - * @returns {Array.>} - */ -nifti.NIFTI2.prototype.getQformMat = nifti.NIFTI1.prototype.getQformMat; - - - -/** - * Converts qform to an affine. (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) - * @param {number} qb - * @param {number} qc - * @param {number} qd - * @param {number} qx - * @param {number} qy - * @param {number} qz - * @param {number} dx - * @param {number} dy - * @param {number} dz - * @param {number} qfac - * @returns {Array.>} - */ -nifti.NIFTI2.prototype.convertNiftiQFormToNiftiSForm = nifti.NIFTI1.prototype.convertNiftiQFormToNiftiSForm; - - - -/** - * Converts sform to an orientation string (e.g., XYZ+--). (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) - * @param {Array.>} R - * @returns {string} - */ -nifti.NIFTI2.prototype.convertNiftiSFormToNEMA = nifti.NIFTI1.prototype.convertNiftiSFormToNEMA; - - - -nifti.NIFTI2.prototype.nifti_mat33_mul = nifti.NIFTI1.prototype.nifti_mat33_mul; - - - -nifti.NIFTI2.prototype.nifti_mat33_determ = nifti.NIFTI1.prototype.nifti_mat33_determ; - -/** - * Returns header as ArrayBuffer. - * @param {boolean} includeExtensions - should extension bytes be included - * @returns {ArrayBuffer} - */ - nifti.NIFTI2.prototype.toArrayBuffer = function(includeExtensions = false) { - const INT64_SIZE = 8; - const DOUBLE_SIZE = 8; - - let byteSize = 540 + 4; // +4 for extension bytes - // calculate necessary size - if(includeExtensions) { - for(let extension of this.extensions) { - byteSize += extension.esize; - } - } - - let byteArray = new Uint8Array(byteSize); - let view = new DataView(byteArray.buffer); - // sizeof_hdr - view.setInt32(0, 540, this.littleEndian); - - // magic - byteArray.set(Buffer.from(this.magic), 4); - - // datatype - view.setInt16(12, this.datatypeCode, this.littleEndian); - - // bitpix - view.setInt16(14, this.numBitsPerVoxel, this.littleEndian); - - // dim[8] - for(let i = 0; i < 8; i++) { - view.setBigInt64(16 + INT64_SIZE * i, BigInt(this.dims[i]), this.littleEndian); - } - - // intent_p1 - view.setFloat64(80, this.intent_p1, this.littleEndian); - - // intent_p2 - view.setFloat64(88, this.intent_p2, this.littleEndian); - - // intent_p3 - view.setFloat64(96, this.intent_p3, this.littleEndian); - - // pixdim - for(let i = 0; i < 8; i++) { - view.setFloat64(104 + DOUBLE_SIZE * i, this.pixDims[i], this.littleEndian); - } - - // vox_offset - view.setBigInt64(168, BigInt(this.vox_offset), this.littleEndian); - - // scl_slope - view.setFloat64(176, this.scl_slope, this.littleEndian); - - // scl_inter - view.setFloat64(184, this.scl_inter, this.littleEndian); - - // cal_max - view.setFloat64(192, this.cal_max, this.littleEndian); - - // cal_min - view.setFloat64(200, this.cal_min, this.littleEndian); - - // slice_duration - view.setFloat64(208, this.slice_duration, this.littleEndian); - - // toffset - view.setFloat64(216, this.toffset, this.littleEndian); - - // slice_start - view.setBigInt64(224, BigInt(this.slice_start), this.littleEndian); - - // slice end - view.setBigInt64(232, BigInt(this.slice_end), this.littleEndian); - - // descrip - byteArray.set(Buffer.from(this.description), 240); - - // aux_file - byteArray.set(Buffer.from(this.aux_file), 320); - - // qform_code - view.setInt32(344, this.qform_code, this.littleEndian); - - // sform_code - view.setInt32(348, this.sform_code, this.littleEndian); - - // quatern_b - view.setFloat64(352, this.quatern_b, this.littleEndian); - - // quatern_c - view.setFloat64(360, this.quatern_c, this.littleEndian); - - // quatern_d - view.setFloat64(368, this.quatern_d, this.littleEndian); - - // qoffset_x - view.setFloat64(376, this.qoffset_x, this.littleEndian); - - // qoffset_y - view.setFloat64(384, this.qoffset_y, this.littleEndian); - - // qoffset_z - view.setFloat64(392, this.qoffset_z, this.littleEndian); - - // srow_x[4], srow_y[4], and srow_z[4] - const flattened = this.affine.flat(); - // we only want the first three rows - for(let i = 0; i < 12; i++) { - view.setFloat64(400 + DOUBLE_SIZE * i, flattened[i], this.littleEndian); - } - - // slice_code - view.setInt32(496, this.slice_code, this.littleEndian); - // xyzt_units - view.setInt32(500, this.xyzt_units, this.littleEndian); - // intent_code - view.setInt32(504, this.intent_code, this.littleEndian); - // intent_name - byteArray.set(Buffer.from(this.intent_name), 508); - // dim_info - view.setUint8(524, this.dim_info); - - // add our extension data - if(includeExtensions) { - byteArray.set(Uint8Array.from([1, 0, 0, 0]), 540); - let extensionByteIndex = this.getExtensionLocation(); - for(const extension of this.extensions) { - view.setInt32(extensionByteIndex, extension.esize, extension.littleEndian); - view.setInt32(extensionByteIndex + 4, extension.ecode, extension.littleEndian); - byteArray.set(new Uint8Array(extension.edata), extensionByteIndex + 8); - extensionByteIndex += extension.esize; - } - } - else { - // In a .nii file, these 4 bytes will always be present - byteArray.set(new Uint8Array(4).fill(0), 540); - } - - return byteArray.buffer; - } - -/*** Exports ***/ - -var moduleType = typeof module; -if ((moduleType !== 'undefined') && module.exports) { - module.exports = nifti.NIFTI2; -} diff --git a/src/nifti2.ts b/src/nifti2.ts new file mode 100644 index 0000000..0b701ef --- /dev/null +++ b/src/nifti2.ts @@ -0,0 +1,633 @@ +import { NIFTIEXTENSION } from "./nifti-extension"; +import { NIFTI1 } from "./nifti1"; +import { Utils } from "./utilities"; + +/** + * The NIFTI2 constructor. + * @constructor + * @property {boolean} littleEndian + * @property {number} dim_info + * @property {number[]} dims - image dimensions + * @property {number} intent_p1 + * @property {number} intent_p2 + * @property {number} intent_p3 + * @property {number} intent_code + * @property {number} datatypeCode + * @property {number} numBitsPerVoxel + * @property {number} slice_start + * @property {number} slice_end + * @property {number} slice_code + * @property {number[]} pixDims - voxel dimensions + * @property {number} vox_offset + * @property {number} scl_slope + * @property {number} scl_inter + * @property {number} xyzt_units + * @property {number} cal_max + * @property {number} cal_min + * @property {number} slice_duration + * @property {number} toffset + * @property {string} description + * @property {string} aux_file + * @property {string} intent_name + * @property {number} qform_code + * @property {number} sform_code + * @property {number} quatern_b + * @property {number} quatern_c + * @property {number} quatern_d + * @property {number} quatern_x + * @property {number} quatern_y + * @property {number} quatern_z + * @property {Array.>} affine + * @property {string} magic + * @property {number[]} extensionFlag + * @property {NIFTIEXTENSION[]} extensions + * @type {Function} + */ +export class NIFTI2 { + littleEndian = false; + dim_info = 0; + dims: number[] = []; + intent_p1 = 0; + intent_p2 = 0; + intent_p3 = 0; + intent_code = 0; + datatypeCode = 0; + numBitsPerVoxel = 0; + slice_start = 0; + slice_end = 0; + slice_code = 0; + pixDims: number[] = []; + vox_offset = 0; + scl_slope = 1; + scl_inter = 0; + xyzt_units = 0; + cal_max = 0; + cal_min = 0; + slice_duration = 0; + toffset = 0; + description = ""; + aux_file = ""; + intent_name = ""; + qform_code = 0; + sform_code = 0; + quatern_b = 0; + quatern_c = 0; + quatern_d = 0; + qoffset_x = 0; + qoffset_y = 0; + qoffset_z = 0; + affine = [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1], + ]; + magic = "0"; + extensionFlag = [0, 0, 0, 0]; + extensions: NIFTIEXTENSION[] = []; + extensionSize = 0; + extensionCode = 0; + + /*** Static Pseudo-constants ***/ + + public static readonly MAGIC_COOKIE = 540; + public static readonly MAGIC_NUMBER_LOCATION = 4; + public static readonly MAGIC_NUMBER = [ + 0x6e, 0x2b, 0x32, 0, 0x0d, 0x0a, 0x1a, 0x0a, + ]; // n+2\0 + public static readonly MAGIC_NUMBER2 = [ + 0x6e, 0x69, 0x32, 0, 0x0d, 0x0a, 0x1a, 0x0a, + ]; // ni2\0 + + /*** Prototype Methods ***/ + + /** + * Reads the header data. + * @param {ArrayBuffer} data + */ + readHeader(data: ArrayBuffer) { + var rawData = new DataView(data), + magicCookieVal = Utils.getIntAt(rawData, 0, this.littleEndian), + ctr, + ctrOut, + ctrIn, + index, + array; + + if (magicCookieVal !== NIFTI2.MAGIC_COOKIE) { + // try as little endian + this.littleEndian = true; + magicCookieVal = Utils.getIntAt(rawData, 0, this.littleEndian); + } + + if (magicCookieVal !== NIFTI2.MAGIC_COOKIE) { + throw new Error("This does not appear to be a NIFTI file!"); + } + this.magic = Utils.getStringAt(rawData, 4, 12); + this.datatypeCode = Utils.getShortAt(rawData, 12, this.littleEndian); + this.numBitsPerVoxel = Utils.getShortAt(rawData, 14, this.littleEndian); + + for (ctr = 0; ctr < 8; ctr += 1) { + index = 16 + ctr * 8; + this.dims[ctr] = Utils.getLongAt(rawData, index, this.littleEndian); + } + + this.intent_p1 = Utils.getDoubleAt(rawData, 80, this.littleEndian); + this.intent_p2 = Utils.getDoubleAt(rawData, 88, this.littleEndian); + this.intent_p3 = Utils.getDoubleAt(rawData, 96, this.littleEndian); + + for (ctr = 0; ctr < 8; ctr += 1) { + index = 104 + ctr * 8; + this.pixDims[ctr] = Utils.getDoubleAt(rawData, index, this.littleEndian); + } + + this.vox_offset = Utils.getLongAt(rawData, 168, this.littleEndian); + + this.scl_slope = Utils.getDoubleAt(rawData, 176, this.littleEndian); + this.scl_inter = Utils.getDoubleAt(rawData, 184, this.littleEndian); + + this.cal_max = Utils.getDoubleAt(rawData, 192, this.littleEndian); + this.cal_min = Utils.getDoubleAt(rawData, 200, this.littleEndian); + + this.slice_duration = Utils.getDoubleAt(rawData, 208, this.littleEndian); + + this.toffset = Utils.getDoubleAt(rawData, 216, this.littleEndian); + + this.slice_start = Utils.getLongAt(rawData, 224, this.littleEndian); + this.slice_end = Utils.getLongAt(rawData, 232, this.littleEndian); + + this.description = Utils.getStringAt(rawData, 240, 240 + 80); + this.aux_file = Utils.getStringAt(rawData, 320, 320 + 24); + + this.qform_code = Utils.getIntAt(rawData, 344, this.littleEndian); + this.sform_code = Utils.getIntAt(rawData, 348, this.littleEndian); + + this.quatern_b = Utils.getDoubleAt(rawData, 352, this.littleEndian); + this.quatern_c = Utils.getDoubleAt(rawData, 360, this.littleEndian); + this.quatern_d = Utils.getDoubleAt(rawData, 368, this.littleEndian); + this.qoffset_x = Utils.getDoubleAt(rawData, 376, this.littleEndian); + this.qoffset_y = Utils.getDoubleAt(rawData, 384, this.littleEndian); + this.qoffset_z = Utils.getDoubleAt(rawData, 392, this.littleEndian); + + for (ctrOut = 0; ctrOut < 3; ctrOut += 1) { + for (ctrIn = 0; ctrIn < 4; ctrIn += 1) { + index = 400 + (ctrOut * 4 + ctrIn) * 8; + this.affine[ctrOut][ctrIn] = Utils.getDoubleAt( + rawData, + index, + this.littleEndian + ); + } + } + + this.affine[3][0] = 0; + this.affine[3][1] = 0; + this.affine[3][2] = 0; + this.affine[3][3] = 1; + + this.slice_code = Utils.getIntAt(rawData, 496, this.littleEndian); + this.xyzt_units = Utils.getIntAt(rawData, 500, this.littleEndian); + this.intent_code = Utils.getIntAt(rawData, 504, this.littleEndian); + this.intent_name = Utils.getStringAt(rawData, 508, 508 + 16); + + this.dim_info = Utils.getByteAt(rawData, 524); + + if (rawData.byteLength > NIFTI2.MAGIC_COOKIE) { + this.extensionFlag[0] = Utils.getByteAt(rawData, 540); + this.extensionFlag[1] = Utils.getByteAt(rawData, 540 + 1); + this.extensionFlag[2] = Utils.getByteAt(rawData, 540 + 2); + this.extensionFlag[3] = Utils.getByteAt(rawData, 540 + 3); + + if (this.extensionFlag[0]) { + // read our extensions + this.extensions = Utils.getExtensionsAt( + rawData, + this.getExtensionLocation(), + this.littleEndian, + this.vox_offset + ); + + // set the extensionSize and extensionCode from the first extension found + this.extensionSize = this.extensions[0].esize; + this.extensionCode = this.extensions[0].ecode; + } + } + } + + /** + * Returns a formatted string of header fields. + * @returns {string} + */ + toFormattedString() { + var fmt = Utils.formatNumber, + string = ""; + + string += + "Datatype = " + + +this.datatypeCode + + " (" + + this.getDatatypeCodeString(this.datatypeCode) + + ")\n"; + string += "Bits Per Voxel = " + " = " + this.numBitsPerVoxel + "\n"; + string += + "Image Dimensions" + + " (1-8): " + + this.dims[0] + + ", " + + this.dims[1] + + ", " + + this.dims[2] + + ", " + + this.dims[3] + + ", " + + this.dims[4] + + ", " + + this.dims[5] + + ", " + + this.dims[6] + + ", " + + this.dims[7] + + "\n"; + + string += + "Intent Parameters (1-3): " + + this.intent_p1 + + ", " + + this.intent_p2 + + ", " + + this.intent_p3 + + "\n"; + + string += + "Voxel Dimensions (1-8): " + + fmt(this.pixDims[0]) + + ", " + + fmt(this.pixDims[1]) + + ", " + + fmt(this.pixDims[2]) + + ", " + + fmt(this.pixDims[3]) + + ", " + + fmt(this.pixDims[4]) + + ", " + + fmt(this.pixDims[5]) + + ", " + + fmt(this.pixDims[6]) + + ", " + + fmt(this.pixDims[7]) + + "\n"; + + string += "Image Offset = " + this.vox_offset + "\n"; + string += + "Data Scale: Slope = " + + fmt(this.scl_slope) + + " Intercept = " + + fmt(this.scl_inter) + + "\n"; + string += + "Display Range: Max = " + + fmt(this.cal_max) + + " Min = " + + fmt(this.cal_min) + + "\n"; + string += "Slice Duration = " + this.slice_duration + "\n"; + string += "Time Axis Shift = " + this.toffset + "\n"; + string += "Slice Start = " + this.slice_start + "\n"; + string += "Slice End = " + this.slice_end + "\n"; + string += 'Description: "' + this.description + '"\n'; + string += 'Auxiliary File: "' + this.aux_file + '"\n'; + string += + "Q-Form Code = " + + this.qform_code + + " (" + + this.getTransformCodeString(this.qform_code) + + ")\n"; + string += + "S-Form Code = " + + this.sform_code + + " (" + + this.getTransformCodeString(this.sform_code) + + ")\n"; + string += + "Quaternion Parameters: " + + "b = " + + fmt(this.quatern_b) + + " " + + "c = " + + fmt(this.quatern_c) + + " " + + "d = " + + fmt(this.quatern_d) + + "\n"; + + string += + "Quaternion Offsets: " + + "x = " + + this.qoffset_x + + " " + + "y = " + + this.qoffset_y + + " " + + "z = " + + this.qoffset_z + + "\n"; + + string += + "S-Form Parameters X: " + + fmt(this.affine[0][0]) + + ", " + + fmt(this.affine[0][1]) + + ", " + + fmt(this.affine[0][2]) + + ", " + + fmt(this.affine[0][3]) + + "\n"; + + string += + "S-Form Parameters Y: " + + fmt(this.affine[1][0]) + + ", " + + fmt(this.affine[1][1]) + + ", " + + fmt(this.affine[1][2]) + + ", " + + fmt(this.affine[1][3]) + + "\n"; + + string += + "S-Form Parameters Z: " + + fmt(this.affine[2][0]) + + ", " + + fmt(this.affine[2][1]) + + ", " + + fmt(this.affine[2][2]) + + ", " + + fmt(this.affine[2][3]) + + "\n"; + + string += "Slice Code = " + this.slice_code + "\n"; + string += + "Units Code = " + + this.xyzt_units + + " (" + + this.getUnitsCodeString(NIFTI1.SPATIAL_UNITS_MASK & this.xyzt_units) + + ", " + + this.getUnitsCodeString(NIFTI1.TEMPORAL_UNITS_MASK & this.xyzt_units) + + ")\n"; + string += "Intent Code = " + this.intent_code + "\n"; + string += 'Intent Name: "' + this.intent_name + '"\n'; + + string += "Dim Info = " + this.dim_info + "\n"; + + return string; + } + + /** + * Returns the byte index of the extension. + * @returns {number} + */ + getExtensionLocation = function () { + return NIFTI2.MAGIC_COOKIE + 4; + }; + + /** + * Returns the extension size. + * @param {DataView} data + * @returns {number} + */ + getExtensionSize = NIFTI1.prototype.getExtensionSize; + + /** + * Returns the extension code. + * @param {DataView} data + * @returns {number} + */ + getExtensionCode = NIFTI1.prototype.getExtensionCode; + + /** + * Adds an extension + * @param {NIFTIEXTENSION} extension + * @param {number} index + */ + addExtension = NIFTI1.prototype.addExtension; + + /** + * Removes an extension + * @param {number} index + */ + removeExtension = NIFTI1.prototype.removeExtension; + + /** + * Returns a human-readable string of datatype. + * @param {number} code + * @returns {string} + */ + getDatatypeCodeString = NIFTI1.prototype.getDatatypeCodeString; + + /** + * Returns a human-readable string of transform type. + * @param {number} code + * @returns {string} + */ + getTransformCodeString = NIFTI1.prototype.getTransformCodeString; + + /** + * Returns a human-readable string of spatial and temporal units. + * @param {number} code + * @returns {string} + */ + getUnitsCodeString = NIFTI1.prototype.getUnitsCodeString; + + /** + * Returns the qform matrix. + * @returns {Array.>} + */ + getQformMat = NIFTI1.prototype.getQformMat; + + /** + * Converts qform to an affine. (See http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {number} qb + * @param {number} qc + * @param {number} qd + * @param {number} qx + * @param {number} qy + * @param {number} qz + * @param {number} dx + * @param {number} dy + * @param {number} dz + * @param {number} qfac + * @returns {Array.>} + */ + convertNiftiQFormToNiftiSForm = + NIFTI1.prototype.convertNiftiQFormToNiftiSForm; + + /** + * Converts sform to an orientation string (e.g., XYZ+--). (See http://nimh.nih.gov/pub/dist/src/niftilib/nifti1_io.c) + * @param {Array.>} R + * @returns {string} + */ + convertNiftiSFormToNEMA = NIFTI1.prototype.convertNiftiSFormToNEMA; + + nifti_mat33_mul = NIFTI1.prototype.nifti_mat33_mul; + + nifti_mat33_determ = NIFTI1.prototype.nifti_mat33_determ; + + /** + * Returns header as ArrayBuffer. + * @param {boolean} includeExtensions - should extension bytes be included + * @returns {ArrayBuffer} + */ + toArrayBuffer(includeExtensions = false) { + const INT64_SIZE = 8; + const DOUBLE_SIZE = 8; + + let byteSize = 540 + 4; // +4 for extension bytes + // calculate necessary size + if (includeExtensions) { + for (let extension of this.extensions) { + byteSize += extension.esize; + } + } + + let byteArray = new Uint8Array(byteSize); + let view = new DataView(byteArray.buffer); + // sizeof_hdr + view.setInt32(0, 540, this.littleEndian); + + // magic + byteArray.set(Buffer.from(this.magic), 4); + + // datatype + view.setInt16(12, this.datatypeCode, this.littleEndian); + + // bitpix + view.setInt16(14, this.numBitsPerVoxel, this.littleEndian); + + // dim[8] + for (let i = 0; i < 8; i++) { + view.setBigInt64( + 16 + INT64_SIZE * i, + BigInt(this.dims[i]), + this.littleEndian + ); + } + + // intent_p1 + view.setFloat64(80, this.intent_p1, this.littleEndian); + + // intent_p2 + view.setFloat64(88, this.intent_p2, this.littleEndian); + + // intent_p3 + view.setFloat64(96, this.intent_p3, this.littleEndian); + + // pixdim + for (let i = 0; i < 8; i++) { + view.setFloat64( + 104 + DOUBLE_SIZE * i, + this.pixDims[i], + this.littleEndian + ); + } + + // vox_offset + view.setBigInt64(168, BigInt(this.vox_offset), this.littleEndian); + + // scl_slope + view.setFloat64(176, this.scl_slope, this.littleEndian); + + // scl_inter + view.setFloat64(184, this.scl_inter, this.littleEndian); + + // cal_max + view.setFloat64(192, this.cal_max, this.littleEndian); + + // cal_min + view.setFloat64(200, this.cal_min, this.littleEndian); + + // slice_duration + view.setFloat64(208, this.slice_duration, this.littleEndian); + + // toffset + view.setFloat64(216, this.toffset, this.littleEndian); + + // slice_start + view.setBigInt64(224, BigInt(this.slice_start), this.littleEndian); + + // slice end + view.setBigInt64(232, BigInt(this.slice_end), this.littleEndian); + + // descrip + byteArray.set(Buffer.from(this.description), 240); + + // aux_file + byteArray.set(Buffer.from(this.aux_file), 320); + + // qform_code + view.setInt32(344, this.qform_code, this.littleEndian); + + // sform_code + view.setInt32(348, this.sform_code, this.littleEndian); + + // quatern_b + view.setFloat64(352, this.quatern_b, this.littleEndian); + + // quatern_c + view.setFloat64(360, this.quatern_c, this.littleEndian); + + // quatern_d + view.setFloat64(368, this.quatern_d, this.littleEndian); + + // qoffset_x + view.setFloat64(376, this.qoffset_x, this.littleEndian); + + // qoffset_y + view.setFloat64(384, this.qoffset_y, this.littleEndian); + + // qoffset_z + view.setFloat64(392, this.qoffset_z, this.littleEndian); + + // srow_x[4], srow_y[4], and srow_z[4] + const flattened = this.affine.flat(); + // we only want the first three rows + for (let i = 0; i < 12; i++) { + view.setFloat64(400 + DOUBLE_SIZE * i, flattened[i], this.littleEndian); + } + + // slice_code + view.setInt32(496, this.slice_code, this.littleEndian); + // xyzt_units + view.setInt32(500, this.xyzt_units, this.littleEndian); + // intent_code + view.setInt32(504, this.intent_code, this.littleEndian); + // intent_name + byteArray.set(Buffer.from(this.intent_name), 508); + // dim_info + view.setUint8(524, this.dim_info); + + // add our extension data + if (includeExtensions) { + byteArray.set(Uint8Array.from([1, 0, 0, 0]), 540); + let extensionByteIndex = this.getExtensionLocation(); + for (const extension of this.extensions) { + view.setInt32( + extensionByteIndex, + extension.esize, + extension.littleEndian + ); + view.setInt32( + extensionByteIndex + 4, + extension.ecode, + extension.littleEndian + ); + byteArray.set(new Uint8Array(extension.edata), extensionByteIndex + 8); + extensionByteIndex += extension.esize; + } + } else { + // In a .nii file, these 4 bytes will always be present + byteArray.set(new Uint8Array(4).fill(0), 540); + } + + return byteArray.buffer; + } +} \ No newline at end of file diff --git a/src/utilities.js b/src/utilities.js deleted file mode 100644 index f03b436..0000000 --- a/src/utilities.js +++ /dev/null @@ -1,196 +0,0 @@ - -/*jslint browser: true, node: true */ -/*global require, module */ - -"use strict"; - -/*** Imports ***/ - -var nifti = nifti || {}; -nifti.Utils = nifti.Utils || {}; -nifti.NIFTIEXTENSION = nifti.NIFTIEXTENSION || ((typeof require !== 'undefined') ? require('./nifti-extension.js') : null); - - -/*** Static Pseudo-constants ***/ - -nifti.Utils.crcTable = null; -nifti.Utils.GUNZIP_MAGIC_COOKIE1 = 31; -nifti.Utils.GUNZIP_MAGIC_COOKIE2 = 139; - - - -/*** Static methods ***/ - -nifti.Utils.getStringAt = function (data, start, end) { - var str = "", ctr, ch; - - for (ctr = start; ctr < end; ctr += 1) { - ch = data.getUint8(ctr); - - if (ch !== 0) { - str += String.fromCharCode(ch); - } - } - - return str; -}; - - - -nifti.Utils.getByteAt = function (data, start) { - return data.getInt8(start); -}; - - - -nifti.Utils.getShortAt = function (data, start, littleEndian) { - return data.getInt16(start, littleEndian); -}; - - - -nifti.Utils.getIntAt = function (data, start, littleEndian) { - return data.getInt32(start, littleEndian); -}; - - - -nifti.Utils.getFloatAt = function (data, start, littleEndian) { - return data.getFloat32(start, littleEndian); -}; - - - -nifti.Utils.getDoubleAt = function (data, start, littleEndian) { - return data.getFloat64(start, littleEndian); -}; - - - -nifti.Utils.getLongAt = function (data, start, littleEndian) { - var ctr, array = [], value = 0; - - for (ctr = 0; ctr < 8; ctr += 1) { - array[ctr] = nifti.Utils.getByteAt(data, start + ctr, littleEndian); - } - - for (ctr = array.length - 1; ctr >= 0; ctr--) { - value = (value * 256) + array[ctr]; - } - - return value; -}; - -nifti.Utils.getExtensionsAt = function (data, start, littleEndian, voxOffset) { - let extensions = []; - let extensionByteIndex = start; - - // Multiple extended header sections are allowed - while(extensionByteIndex < voxOffset ) { - // assume same endianess as header until proven otherwise - let extensionLittleEndian = littleEndian; - let esize = nifti.Utils.getIntAt(data, extensionByteIndex, littleEndian); - if(!esize) { - break; // no more extensions - } - - // check if this takes us past vox_offset - if(esize + extensionByteIndex > voxOffset) { - // check if reversing byte order gets a proper size - extensionLittleEndian = !extensionLittleEndian; - esize = nifti.Utils.getIntAt(data, extensionByteIndex, extensionLittleEndian); - if(esize + extensionByteIndex > voxOffset) { - throw new Error('This does not appear to be a valid NIFTI extension'); - } - } - - // esize must be a positive integral multiple of 16 - if(esize % 16 != 0) { - throw new Error("This does not appear to be a NIFTI extension"); - } - - let ecode = nifti.Utils.getIntAt(data, extensionByteIndex + 4, extensionLittleEndian); - let edata = data.buffer.slice(extensionByteIndex + 8, extensionByteIndex + esize); - console.log('extensionByteIndex: ' + (extensionByteIndex + 8) + ' esize: ' + esize); - console.log(edata); - let extension = new nifti.NIFTIEXTENSION(esize, ecode, edata, extensionLittleEndian); - extensions.push(extension); - extensionByteIndex += esize; - } - return extensions; -} - - -nifti.Utils.toArrayBuffer = function (buffer) { - var ab, view, i; - - ab = new ArrayBuffer(buffer.length); - view = new Uint8Array(ab); - for (i = 0; i < buffer.length; i += 1) { - view[i] = buffer[i]; - } - return ab; -}; - - - -nifti.Utils.isString = function (obj) { - return (typeof obj === "string" || obj instanceof String); -}; - - -nifti.Utils.formatNumber = function (num, shortFormat) { - var val = 0; - - if (nifti.Utils.isString(num)) { - val = Number(num); - } else { - val = num; - } - - if (shortFormat) { - val = val.toPrecision(5); - } else { - val = val.toPrecision(7); - } - - return parseFloat(val); -}; - - - -// http://stackoverflow.com/questions/18638900/javascript-crc32 -nifti.Utils.makeCRCTable = function(){ - var c; - var crcTable = []; - for(var n =0; n < 256; n++){ - c = n; - for(var k =0; k < 8; k++){ - c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); - } - crcTable[n] = c; - } - return crcTable; -}; - - - -nifti.Utils.crc32 = function(dataView) { - var crcTable = nifti.Utils.crcTable || (nifti.Utils.crcTable = nifti.Utils.makeCRCTable()); - var crc = 0 ^ (-1); - - for (var i = 0; i < dataView.byteLength; i++ ) { - crc = (crc >>> 8) ^ crcTable[(crc ^ dataView.getUint8(i)) & 0xFF]; - } - - return (crc ^ (-1)) >>> 0; -}; - - - -/*** Exports ***/ - -var moduleType = typeof module; -if ((moduleType !== 'undefined') && module.exports) { - module.exports = nifti.Utils; -} diff --git a/src/utilities.ts b/src/utilities.ts new file mode 100644 index 0000000..825caf1 --- /dev/null +++ b/src/utilities.ts @@ -0,0 +1,208 @@ +import { NIFTIEXTENSION } from "./nifti-extension"; + +type TypedArray = + | Int8Array + | Uint8Array + | Uint8ClampedArray + | Int16Array + | Uint16Array + | Int32Array + | Uint32Array + | Float32Array + | Float64Array; + +export class Utils { + /*** Static Pseudo-constants ***/ + + public static crcTable: number[] | null = null; + public static readonly GUNZIP_MAGIC_COOKIE1 = 31; + public static readonly GUNZIP_MAGIC_COOKIE2 = 139; + + /*** Static methods ***/ + + static getStringAt(data: DataView, start: number, end: number): string { + var str = "", + ctr, + ch; + + for (ctr = start; ctr < end; ctr += 1) { + ch = data.getUint8(ctr); + + if (ch !== 0) { + str += String.fromCharCode(ch); + } + } + + return str; + } + + static getByteAt = function (data: DataView, start: number): number { + return data.getInt8(start); + }; + + static getShortAt = function ( + data: DataView, + start: number, + littleEndian: boolean + ) { + return data.getInt16(start, littleEndian); + }; + + static getIntAt( + data: DataView, + start: number, + littleEndian: boolean + ): number { + return data.getInt32(start, littleEndian); + } + + static getFloatAt(data: DataView, start: number, littleEndian: boolean) { + return data.getFloat32(start, littleEndian); + } + + static getDoubleAt(data: DataView, start: number, littleEndian: boolean) { + return data.getFloat64(start, littleEndian); + } + + static getLongAt(data: DataView, start: number, littleEndian: boolean) { + var ctr, + array = [], + value = 0; + + for (ctr = 0; ctr < 8; ctr += 1) { + array[ctr] = Utils.getByteAt(data, start + ctr); + } + + for (ctr = array.length - 1; ctr >= 0; ctr--) { + value = value * 256 + array[ctr]; + } + + return value; + } + + static getExtensionsAt( + data: DataView, + start: number, + littleEndian: boolean, + voxOffset: number + ) { + let extensions = []; + let extensionByteIndex = start; + + // Multiple extended header sections are allowed + while (extensionByteIndex < voxOffset) { + // assume same endianess as header until proven otherwise + let extensionLittleEndian = littleEndian; + let esize = Utils.getIntAt(data, extensionByteIndex, littleEndian); + if (!esize) { + break; // no more extensions + } + + // check if this takes us past vox_offset + if (esize + extensionByteIndex > voxOffset) { + // check if reversing byte order gets a proper size + extensionLittleEndian = !extensionLittleEndian; + esize = Utils.getIntAt( + data, + extensionByteIndex, + extensionLittleEndian + ); + if (esize + extensionByteIndex > voxOffset) { + throw new Error("This does not appear to be a valid NIFTI extension"); + } + } + + // esize must be a positive integral multiple of 16 + if (esize % 16 != 0) { + throw new Error("This does not appear to be a NIFTI extension"); + } + + let ecode = Utils.getIntAt( + data, + extensionByteIndex + 4, + extensionLittleEndian + ); + let edata = data.buffer.slice( + extensionByteIndex + 8, + extensionByteIndex + esize + ); + console.log( + "extensionByteIndex: " + (extensionByteIndex + 8) + " esize: " + esize + ); + console.log(edata); + let extension = new NIFTIEXTENSION( + esize, + ecode, + edata, + extensionLittleEndian + ); + extensions.push(extension); + extensionByteIndex += esize; + } + return extensions; + } + + static toArrayBuffer(buffer: TypedArray): ArrayBuffer { + var ab, view, i; + + ab = new ArrayBuffer(buffer.length); + view = new Uint8Array(ab); + for (i = 0; i < buffer.length; i += 1) { + view[i] = buffer[i]; + } + return ab; + } + + static isString(obj: Object): boolean { + return typeof obj === "string" || obj instanceof String; + } + + static formatNumber( + num: any, + shortFormat: boolean | undefined = undefined + ): number { + let val; + + if (Utils.isString(num)) { + val = Number(num); + } else { + val = num; + } + + if (shortFormat) { + val = val.toPrecision(5); + } else { + val = val.toPrecision(7); + } + + return parseFloat(val); + } + + // http://stackoverflow.com/questions/18638900/javascript-crc32 + static makeCRCTable(): number[] { + let c; + let crcTable: number[] = []; + for (var n = 0; n < 256; n++) { + c = n; + for (var k = 0; k < 8; k++) { + c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1; + } + crcTable[n] = c; + } + return crcTable; + } + + static crc32(dataView: DataView): number { + if (!Utils.crcTable) { + Utils.crcTable = Utils.makeCRCTable(); + } + const crcTable = Utils.crcTable; + let crc = 0 ^ -1; + + for (var i = 0; i < dataView.byteLength; i++) { + crc = (crc >>> 8) ^ crcTable[(crc ^ dataView.getUint8(i)) & 0xff]; + } + + return (crc ^ -1) >>> 0; + } +} \ No newline at end of file diff --git a/tests/driver-nifti1-5D-small.js b/tests/driver-nifti1-5D-small.js index 11329e1..13dd59e 100644 --- a/tests/driver-nifti1-5D-small.js +++ b/tests/driver-nifti1-5D-small.js @@ -7,9 +7,9 @@ var assert = require("assert"); var fs = require('fs'); -var nifti = require('../src/nifti.js'); +var nifti = require('../dist/src/nifti.js'); -var buf = fs.readFileSync('./tests/data/5D_small.nii'); +var buf = fs.readFileSync('./data/5D_small.nii'); var data = nifti.Utils.toArrayBuffer(buf); var nifti1 = null; var imageData = null; diff --git a/tests/driver-nifti1-5D.js b/tests/driver-nifti1-5D.js index 37c70af..a2abe02 100644 --- a/tests/driver-nifti1-5D.js +++ b/tests/driver-nifti1-5D.js @@ -7,9 +7,9 @@ var assert = require("assert"); var fs = require('fs'); -var nifti = require('../src/nifti.js'); +var nifti = require('../dist/src/nifti.js'); -var buf = fs.readFileSync('./tests/data/5D_zeros.nii.gz'); +var buf = fs.readFileSync('./data/5D_zeros.nii.gz'); var data = nifti.Utils.toArrayBuffer(buf); var nifti1 = null; var imageData = null; diff --git a/tests/driver-nifti1-big.js b/tests/driver-nifti1-big.js index 7449081..965618b 100644 --- a/tests/driver-nifti1-big.js +++ b/tests/driver-nifti1-big.js @@ -7,9 +7,9 @@ var assert = require("assert"); var fs = require('fs'); -var nifti = require('../src/nifti.js'); +var nifti = require('../dist/src/nifti.js'); -var buf = fs.readFileSync('./tests/data/big.nii.gz'); +var buf = fs.readFileSync('./data/big.nii.gz'); var data = nifti.Utils.toArrayBuffer(buf); var nifti1 = null; diff --git a/tests/driver-nifti1-extension.js b/tests/driver-nifti1-extension.js index 2605925..4ae8ccf 100644 --- a/tests/driver-nifti1-extension.js +++ b/tests/driver-nifti1-extension.js @@ -7,10 +7,10 @@ var assert = require("assert"); var fs = require('fs'); -var nifti = require('../src/nifti.js'); +var nifti = require('../dist/src/nifti.js'); // var buf = fs.readFileSync('./tests/data/afni.nii.gz'); -var buf = fs.readFileSync('./tests/data/with_extension.nii.gz'); +var buf = fs.readFileSync('./data/with_extension.nii.gz'); var data = nifti.Utils.toArrayBuffer(buf); var nifti1 = null; var extension = null; diff --git a/tests/driver-nifti1-gz.js b/tests/driver-nifti1-gz.js index 4f5debe..79a3807 100644 --- a/tests/driver-nifti1-gz.js +++ b/tests/driver-nifti1-gz.js @@ -7,9 +7,9 @@ var assert = require("assert"); var fs = require('fs'); -var nifti = require('../src/nifti.js'); +var nifti = require('../dist/src/nifti.js'); -var buf = fs.readFileSync('./tests/data/avg152T1_LR_nifti.nii.gz'); +var buf = fs.readFileSync('./data/avg152T1_LR_nifti.nii.gz'); var data = nifti.Utils.toArrayBuffer(buf); var nifti1 = null; diff --git a/tests/driver-nifti1-little.js b/tests/driver-nifti1-little.js index 038147f..b45e6ab 100644 --- a/tests/driver-nifti1-little.js +++ b/tests/driver-nifti1-little.js @@ -7,9 +7,9 @@ var assert = require("assert"); var fs = require('fs'); -var nifti = require('../src/nifti.js'); +var nifti = require('../dist/src/nifti.js'); -var buf = fs.readFileSync('./tests/data/little.nii.gz'); +var buf = fs.readFileSync('./data/little.nii.gz'); var data = nifti.Utils.toArrayBuffer(buf); var nifti1 = null; diff --git a/tests/driver-nifti1-pair.js b/tests/driver-nifti1-pair.js index b923623..52e6bd4 100644 --- a/tests/driver-nifti1-pair.js +++ b/tests/driver-nifti1-pair.js @@ -16,11 +16,11 @@ var assert = require("assert"); var fs = require('fs'); -var nifti = require('../src/nifti.js'); +var nifti = require('../dist/src/nifti.js'); -var buf = fs.readFileSync('./tests/data/air.hdr.gz'); +var buf = fs.readFileSync('./data/air.hdr.gz'); var data = nifti.Utils.toArrayBuffer(buf); -var ibuf = fs.readFileSync('./tests/data/air.img.gz'); +var ibuf = fs.readFileSync('./data/air.img.gz'); var idata = nifti.Utils.toArrayBuffer(ibuf); var nifti1 = null; @@ -84,7 +84,9 @@ describe('NIFTI-Reader-JS', function () { nifti1 = nifti.readHeader(data, true); bytes = nifti1.toArrayBuffer(); clone = nifti.readHeader(bytes, true); - assert.deepEqual(clone, nifti1); + var nifti1Text = JSON.stringify(nifti1); + var cloneText = JSON.stringify(clone); + assert.equal(cloneText, nifti1Text); }); }); diff --git a/tests/driver-nifti1.js b/tests/driver-nifti1.js index 7671219..4cc2980 100644 --- a/tests/driver-nifti1.js +++ b/tests/driver-nifti1.js @@ -7,9 +7,9 @@ var assert = require("assert"); var fs = require('fs'); -var nifti = require('../src/nifti.js'); +var nifti = require('../dist/src/nifti.js'); -var buf = fs.readFileSync('./tests/data/avg152T1_LR_nifti.nii'); +var buf = fs.readFileSync('./data/avg152T1_LR_nifti.nii'); var data = nifti.Utils.toArrayBuffer(buf); var nifti1 = null; var bytes = null; @@ -59,7 +59,9 @@ describe('NIFTI-Reader-JS', function () { nifti1 = nifti.readHeader(data); bytes = nifti1.toArrayBuffer(); clone = nifti.readHeader(bytes); - assert.deepEqual(clone, nifti1); + var nifti1Text = JSON.stringify(nifti1); + var cloneText = JSON.stringify(clone); + assert.equal(cloneText, nifti1Text); }); }); }); diff --git a/tests/driver-nifti2-extension.js b/tests/driver-nifti2-extension.js index 15f7771..b32cef7 100644 --- a/tests/driver-nifti2-extension.js +++ b/tests/driver-nifti2-extension.js @@ -6,9 +6,9 @@ var assert = require("assert"); var fs = require("fs"); -var nifti = require("../src/nifti.js"); +var nifti = require("../dist/src/nifti.js"); -var buf = fs.readFileSync("./tests/data/avg152T1_LR_nifti2.nii.gz"); +var buf = fs.readFileSync("./data/avg152T1_LR_nifti2.nii.gz"); var data = nifti.Utils.toArrayBuffer(buf); var nifti2 = null; diff --git a/tests/driver-nifti2-gz.js b/tests/driver-nifti2-gz.js index 4d4cfd8..ec03e49 100644 --- a/tests/driver-nifti2-gz.js +++ b/tests/driver-nifti2-gz.js @@ -7,9 +7,9 @@ var assert = require("assert"); var fs = require('fs'); -var nifti = require('../src/nifti.js'); +var nifti = require('../dist/src/nifti.js'); -var buf = fs.readFileSync('./tests/data/avg152T1_LR_nifti2.nii.gz'); +var buf = fs.readFileSync('./data/avg152T1_LR_nifti2.nii.gz'); var data = nifti.Utils.toArrayBuffer(buf); var nifti2 = null; var bytes = null; @@ -64,7 +64,9 @@ describe('NIFTI-Reader-JS', function () { it('data returned from toArrayBuffer preserves all nifti-2 properties', function() { bytes = nifti2.toArrayBuffer(); clone = nifti.readHeader(bytes); - assert.deepEqual(clone, nifti2); + var nifti2Text = JSON.stringify(nifti2); + var cloneText = JSON.stringify(clone); + assert.equal(cloneText, nifti2Text); }); }); diff --git a/tests/driver-nifti2-pair.js b/tests/driver-nifti2-pair.js index ae67d35..6363ec0 100644 --- a/tests/driver-nifti2-pair.js +++ b/tests/driver-nifti2-pair.js @@ -16,11 +16,11 @@ var assert = require("assert"); var fs = require('fs'); -var nifti = require('../src/nifti.js'); +var nifti = require('../dist/src/nifti.js'); -var buf = fs.readFileSync('./tests/data/air2.hdr.gz'); +var buf = fs.readFileSync('./data/air2.hdr.gz'); var data = nifti.Utils.toArrayBuffer(buf); -var ibuf = fs.readFileSync('./tests/data/air2.img.gz'); +var ibuf = fs.readFileSync('./data/air2.img.gz'); var idata = nifti.Utils.toArrayBuffer(ibuf); var nifti2 = null; @@ -84,7 +84,9 @@ describe('NIFTI-Reader-JS', function () { nifti2 = nifti.readHeader(data, true); bytes = nifti2.toArrayBuffer(); clone = nifti.readHeader(bytes, true); - assert.deepEqual(clone, nifti2); + var nifti2Text = JSON.stringify(nifti2); + var cloneText = JSON.stringify(clone); + assert.equal(cloneText, nifti2Text); }); }); diff --git a/tests/driver-not-nifti.js b/tests/driver-not-nifti.js index 4816d22..cf81de4 100644 --- a/tests/driver-not-nifti.js +++ b/tests/driver-not-nifti.js @@ -7,9 +7,9 @@ var assert = require("assert"); var fs = require('fs'); -var nifti = require('../src/nifti.js'); +var nifti = require('../dist/src/nifti.js'); -var buf = fs.readFileSync('./tests/data/not-nifti.nii'); +var buf = fs.readFileSync('./data/not-nifti.nii'); var data = nifti.Utils.toArrayBuffer(buf); describe('NIFTI-Reader-JS', function () { diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5f6c94d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,105 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + "outDir": "dist", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "include": [ + "./src/**/*", + "./__tests__/**/*" + ], + } \ No newline at end of file From ebfa577eaaf62bd03d1f1dd574697b7d833d4ccc Mon Sep 17 00:00:00 2001 From: Taylor Hanayik Date: Fri, 12 May 2023 16:25:42 +0100 Subject: [PATCH 2/3] add github actions --- .github/workflows/test-linux-node18.yml | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/test-linux-node18.yml diff --git a/.github/workflows/test-linux-node18.yml b/.github/workflows/test-linux-node18.yml new file mode 100644 index 0000000..11225ff --- /dev/null +++ b/.github/workflows/test-linux-node18.yml @@ -0,0 +1,30 @@ +# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: test-linux-node18 + +on: + pull_request: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [18.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + cache: "npm" + - run: rm package-lock.json + - run: npm install + - run: npm run build --if-present + - run: npm run test + - run: npm run test-js \ No newline at end of file From 34b829ccac6a8182e9649ff895eb7997ff92e662 Mon Sep 17 00:00:00 2001 From: Taylor Hanayik Date: Fri, 12 May 2023 16:36:07 +0100 Subject: [PATCH 3/3] 0.6.5 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 560ab05..4983a6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "nifti-reader-js", - "version": "0.6.4", + "version": "0.6.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "nifti-reader-js", - "version": "0.6.4", + "version": "0.6.5", "license": "MIT", "dependencies": { "fflate": "*" diff --git a/package.json b/package.json index b6ec571..ccc84c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nifti-reader-js", - "version": "0.6.4", + "version": "0.6.5", "description": "A JavaScript NIfTI file format reader.", "main": "dist/src/nifti.js", "types": "dist/src/nifti.d.ts",