3dmol
Version:
JavaScript/TypeScript molecular visualization library
1,486 lines (1,416 loc) • 5.26 MB
JavaScript
/*!
* 3dmol v2.5.2
* JavaScript/TypeScript molecular visualization library
* Author: David Koes and contributors
*/
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["3Dmol"] = factory();
else
root["3Dmol"] = factory();
})(this, () => {
return /******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/iobuffer/lib-esm/IOBuffer.js":
/*!***************************************************!*\
!*** ./node_modules/iobuffer/lib-esm/IOBuffer.js ***!
\***************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ IOBuffer: () => (/* binding */ IOBuffer)
/* harmony export */ });
/* harmony import */ var _text__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./text */ "./node_modules/iobuffer/lib-esm/text.js");
const defaultByteLength = 1024 * 8;
const hostBigEndian = (() => {
const array = new Uint8Array(4);
const view = new Uint32Array(array.buffer);
return !((view[0] = 1) & array[0]);
})();
const typedArrays = {
int8: globalThis.Int8Array,
uint8: globalThis.Uint8Array,
int16: globalThis.Int16Array,
uint16: globalThis.Uint16Array,
int32: globalThis.Int32Array,
uint32: globalThis.Uint32Array,
uint64: globalThis.BigUint64Array,
int64: globalThis.BigInt64Array,
float32: globalThis.Float32Array,
float64: globalThis.Float64Array,
};
class IOBuffer {
/**
* Reference to the internal ArrayBuffer object.
*/
buffer;
/**
* Byte length of the internal ArrayBuffer.
*/
byteLength;
/**
* Byte offset of the internal ArrayBuffer.
*/
byteOffset;
/**
* Byte length of the internal ArrayBuffer.
*/
length;
/**
* The current offset of the buffer's pointer.
*/
offset;
lastWrittenByte;
littleEndian;
_data;
_mark;
_marks;
/**
* Create a new IOBuffer.
* @param data - The data to construct the IOBuffer with.
* If data is a number, it will be the new buffer's length<br>
* If data is `undefined`, the buffer will be initialized with a default length of 8Kb<br>
* If data is an ArrayBuffer, SharedArrayBuffer, an ArrayBufferView (Typed Array), an IOBuffer instance,
* or a Node.js Buffer, a view will be created over the underlying ArrayBuffer.
* @param options - An object for the options.
* @returns A new IOBuffer instance.
*/
constructor(data = defaultByteLength, options = {}) {
let dataIsGiven = false;
if (typeof data === 'number') {
data = new ArrayBuffer(data);
}
else {
dataIsGiven = true;
this.lastWrittenByte = data.byteLength;
}
const offset = options.offset ? options.offset >>> 0 : 0;
const byteLength = data.byteLength - offset;
let dvOffset = offset;
if (ArrayBuffer.isView(data) || data instanceof IOBuffer) {
if (data.byteLength !== data.buffer.byteLength) {
dvOffset = data.byteOffset + offset;
}
data = data.buffer;
}
if (dataIsGiven) {
this.lastWrittenByte = byteLength;
}
else {
this.lastWrittenByte = 0;
}
this.buffer = data;
this.length = byteLength;
this.byteLength = byteLength;
this.byteOffset = dvOffset;
this.offset = 0;
this.littleEndian = true;
this._data = new DataView(this.buffer, dvOffset, byteLength);
this._mark = 0;
this._marks = [];
}
/**
* Checks if the memory allocated to the buffer is sufficient to store more
* bytes after the offset.
* @param byteLength - The needed memory in bytes.
* @returns `true` if there is sufficient space and `false` otherwise.
*/
available(byteLength = 1) {
return this.offset + byteLength <= this.length;
}
/**
* Check if little-endian mode is used for reading and writing multi-byte
* values.
* @returns `true` if little-endian mode is used, `false` otherwise.
*/
isLittleEndian() {
return this.littleEndian;
}
/**
* Set little-endian mode for reading and writing multi-byte values.
* @returns This.
*/
setLittleEndian() {
this.littleEndian = true;
return this;
}
/**
* Check if big-endian mode is used for reading and writing multi-byte values.
* @returns `true` if big-endian mode is used, `false` otherwise.
*/
isBigEndian() {
return !this.littleEndian;
}
/**
* Switches to big-endian mode for reading and writing multi-byte values.
* @returns This.
*/
setBigEndian() {
this.littleEndian = false;
return this;
}
/**
* Move the pointer n bytes forward.
* @param n - Number of bytes to skip.
* @returns This.
*/
skip(n = 1) {
this.offset += n;
return this;
}
/**
* Move the pointer n bytes backward.
* @param n - Number of bytes to move back.
* @returns This.
*/
back(n = 1) {
this.offset -= n;
return this;
}
/**
* Move the pointer to the given offset.
* @param offset - The offset to move to.
* @returns This.
*/
seek(offset) {
this.offset = offset;
return this;
}
/**
* Store the current pointer offset.
* @see {@link IOBuffer#reset}
* @returns This.
*/
mark() {
this._mark = this.offset;
return this;
}
/**
* Move the pointer back to the last pointer offset set by mark.
* @see {@link IOBuffer#mark}
* @returns This.
*/
reset() {
this.offset = this._mark;
return this;
}
/**
* Push the current pointer offset to the mark stack.
* @see {@link IOBuffer#popMark}
* @returns This.
*/
pushMark() {
this._marks.push(this.offset);
return this;
}
/**
* Pop the last pointer offset from the mark stack, and set the current
* pointer offset to the popped value.
* @see {@link IOBuffer#pushMark}
* @returns This.
*/
popMark() {
const offset = this._marks.pop();
if (offset === undefined) {
throw new Error('Mark stack empty');
}
this.seek(offset);
return this;
}
/**
* Move the pointer offset back to 0.
* @returns This.
*/
rewind() {
this.offset = 0;
return this;
}
/**
* Make sure the buffer has sufficient memory to write a given byteLength at
* the current pointer offset.
* If the buffer's memory is insufficient, this method will create a new
* buffer (a copy) with a length that is twice (byteLength + current offset).
* @param byteLength - The needed memory in bytes.
* @returns This.
*/
ensureAvailable(byteLength = 1) {
if (!this.available(byteLength)) {
const lengthNeeded = this.offset + byteLength;
const newLength = lengthNeeded * 2;
const newArray = new Uint8Array(newLength);
newArray.set(new Uint8Array(this.buffer));
this.buffer = newArray.buffer;
this.length = newLength;
this.byteLength = newLength;
this._data = new DataView(this.buffer);
}
return this;
}
/**
* Read a byte and return false if the byte's value is 0, or true otherwise.
* Moves pointer forward by one byte.
* @returns The read boolean.
*/
readBoolean() {
return this.readUint8() !== 0;
}
/**
* Read a signed 8-bit integer and move pointer forward by 1 byte.
* @returns The read byte.
*/
readInt8() {
return this._data.getInt8(this.offset++);
}
/**
* Read an unsigned 8-bit integer and move pointer forward by 1 byte.
* @returns The read byte.
*/
readUint8() {
return this._data.getUint8(this.offset++);
}
/**
* Alias for {@link IOBuffer#readUint8}.
* @returns The read byte.
*/
readByte() {
return this.readUint8();
}
/**
* Read `n` bytes and move pointer forward by `n` bytes.
* @param n - Number of bytes to read.
* @returns The read bytes.
*/
readBytes(n = 1) {
return this.readArray(n, 'uint8');
}
/**
* Creates an array of corresponding to the type `type` and size `size`.
* For example type `uint8` will create a `Uint8Array`.
* @param size - size of the resulting array
* @param type - number type of elements to read
* @returns The read array.
*/
readArray(size, type) {
const bytes = typedArrays[type].BYTES_PER_ELEMENT * size;
const offset = this.byteOffset + this.offset;
const slice = this.buffer.slice(offset, offset + bytes);
if (this.littleEndian === hostBigEndian &&
type !== 'uint8' &&
type !== 'int8') {
const slice = new Uint8Array(this.buffer.slice(offset, offset + bytes));
slice.reverse();
const returnArray = new typedArrays[type](slice.buffer);
this.offset += bytes;
returnArray.reverse();
return returnArray;
}
const returnArray = new typedArrays[type](slice);
this.offset += bytes;
return returnArray;
}
/**
* Read a 16-bit signed integer and move pointer forward by 2 bytes.
* @returns The read value.
*/
readInt16() {
const value = this._data.getInt16(this.offset, this.littleEndian);
this.offset += 2;
return value;
}
/**
* Read a 16-bit unsigned integer and move pointer forward by 2 bytes.
* @returns The read value.
*/
readUint16() {
const value = this._data.getUint16(this.offset, this.littleEndian);
this.offset += 2;
return value;
}
/**
* Read a 32-bit signed integer and move pointer forward by 4 bytes.
* @returns The read value.
*/
readInt32() {
const value = this._data.getInt32(this.offset, this.littleEndian);
this.offset += 4;
return value;
}
/**
* Read a 32-bit unsigned integer and move pointer forward by 4 bytes.
* @returns The read value.
*/
readUint32() {
const value = this._data.getUint32(this.offset, this.littleEndian);
this.offset += 4;
return value;
}
/**
* Read a 32-bit floating number and move pointer forward by 4 bytes.
* @returns The read value.
*/
readFloat32() {
const value = this._data.getFloat32(this.offset, this.littleEndian);
this.offset += 4;
return value;
}
/**
* Read a 64-bit floating number and move pointer forward by 8 bytes.
* @returns The read value.
*/
readFloat64() {
const value = this._data.getFloat64(this.offset, this.littleEndian);
this.offset += 8;
return value;
}
/**
* Read a 64-bit signed integer number and move pointer forward by 8 bytes.
* @returns The read value.
*/
readBigInt64() {
const value = this._data.getBigInt64(this.offset, this.littleEndian);
this.offset += 8;
return value;
}
/**
* Read a 64-bit unsigned integer number and move pointer forward by 8 bytes.
* @returns The read value.
*/
readBigUint64() {
const value = this._data.getBigUint64(this.offset, this.littleEndian);
this.offset += 8;
return value;
}
/**
* Read a 1-byte ASCII character and move pointer forward by 1 byte.
* @returns The read character.
*/
readChar() {
// eslint-disable-next-line unicorn/prefer-code-point
return String.fromCharCode(this.readInt8());
}
/**
* Read `n` 1-byte ASCII characters and move pointer forward by `n` bytes.
* @param n - Number of characters to read.
* @returns The read characters.
*/
readChars(n = 1) {
let result = '';
for (let i = 0; i < n; i++) {
result += this.readChar();
}
return result;
}
/**
* Read the next `n` bytes, return a UTF-8 decoded string and move pointer
* forward by `n` bytes.
* @param n - Number of bytes to read.
* @returns The decoded string.
*/
readUtf8(n = 1) {
return (0,_text__WEBPACK_IMPORTED_MODULE_0__.decode)(this.readBytes(n));
}
/**
* Read the next `n` bytes, return a string decoded with `encoding` and move pointer
* forward by `n` bytes.
* If no encoding is passed, the function is equivalent to @see {@link IOBuffer#readUtf8}
* @param n - Number of bytes to read.
* @param encoding - The encoding to use. Default is 'utf8'.
* @returns The decoded string.
*/
decodeText(n = 1, encoding = 'utf8') {
return (0,_text__WEBPACK_IMPORTED_MODULE_0__.decode)(this.readBytes(n), encoding);
}
/**
* Write 0xff if the passed value is truthy, 0x00 otherwise and move pointer
* forward by 1 byte.
* @param value - The value to write.
* @returns This.
*/
writeBoolean(value) {
this.writeUint8(value ? 0xff : 0x00);
return this;
}
/**
* Write `value` as an 8-bit signed integer and move pointer forward by 1 byte.
* @param value - The value to write.
* @returns This.
*/
writeInt8(value) {
this.ensureAvailable(1);
this._data.setInt8(this.offset++, value);
this._updateLastWrittenByte();
return this;
}
/**
* Write `value` as an 8-bit unsigned integer and move pointer forward by 1
* byte.
* @param value - The value to write.
* @returns This.
*/
writeUint8(value) {
this.ensureAvailable(1);
this._data.setUint8(this.offset++, value);
this._updateLastWrittenByte();
return this;
}
/**
* An alias for {@link IOBuffer#writeUint8}.
* @param value - The value to write.
* @returns This.
*/
writeByte(value) {
return this.writeUint8(value);
}
/**
* Write all elements of `bytes` as uint8 values and move pointer forward by
* `bytes.length` bytes.
* @param bytes - The array of bytes to write.
* @returns This.
*/
writeBytes(bytes) {
this.ensureAvailable(bytes.length);
// eslint-disable-next-line @typescript-eslint/prefer-for-of
for (let i = 0; i < bytes.length; i++) {
this._data.setUint8(this.offset++, bytes[i]);
}
this._updateLastWrittenByte();
return this;
}
/**
* Write `value` as a 16-bit signed integer and move pointer forward by 2
* bytes.
* @param value - The value to write.
* @returns This.
*/
writeInt16(value) {
this.ensureAvailable(2);
this._data.setInt16(this.offset, value, this.littleEndian);
this.offset += 2;
this._updateLastWrittenByte();
return this;
}
/**
* Write `value` as a 16-bit unsigned integer and move pointer forward by 2
* bytes.
* @param value - The value to write.
* @returns This.
*/
writeUint16(value) {
this.ensureAvailable(2);
this._data.setUint16(this.offset, value, this.littleEndian);
this.offset += 2;
this._updateLastWrittenByte();
return this;
}
/**
* Write `value` as a 32-bit signed integer and move pointer forward by 4
* bytes.
* @param value - The value to write.
* @returns This.
*/
writeInt32(value) {
this.ensureAvailable(4);
this._data.setInt32(this.offset, value, this.littleEndian);
this.offset += 4;
this._updateLastWrittenByte();
return this;
}
/**
* Write `value` as a 32-bit unsigned integer and move pointer forward by 4
* bytes.
* @param value - The value to write.
* @returns This.
*/
writeUint32(value) {
this.ensureAvailable(4);
this._data.setUint32(this.offset, value, this.littleEndian);
this.offset += 4;
this._updateLastWrittenByte();
return this;
}
/**
* Write `value` as a 32-bit floating number and move pointer forward by 4
* bytes.
* @param value - The value to write.
* @returns This.
*/
writeFloat32(value) {
this.ensureAvailable(4);
this._data.setFloat32(this.offset, value, this.littleEndian);
this.offset += 4;
this._updateLastWrittenByte();
return this;
}
/**
* Write `value` as a 64-bit floating number and move pointer forward by 8
* bytes.
* @param value - The value to write.
* @returns This.
*/
writeFloat64(value) {
this.ensureAvailable(8);
this._data.setFloat64(this.offset, value, this.littleEndian);
this.offset += 8;
this._updateLastWrittenByte();
return this;
}
/**
* Write `value` as a 64-bit signed bigint and move pointer forward by 8
* bytes.
* @param value - The value to write.
* @returns This.
*/
writeBigInt64(value) {
this.ensureAvailable(8);
this._data.setBigInt64(this.offset, value, this.littleEndian);
this.offset += 8;
this._updateLastWrittenByte();
return this;
}
/**
* Write `value` as a 64-bit unsigned bigint and move pointer forward by 8
* bytes.
* @param value - The value to write.
* @returns This.
*/
writeBigUint64(value) {
this.ensureAvailable(8);
this._data.setBigUint64(this.offset, value, this.littleEndian);
this.offset += 8;
this._updateLastWrittenByte();
return this;
}
/**
* Write the charCode of `str`'s first character as an 8-bit unsigned integer
* and move pointer forward by 1 byte.
* @param str - The character to write.
* @returns This.
*/
writeChar(str) {
// eslint-disable-next-line unicorn/prefer-code-point
return this.writeUint8(str.charCodeAt(0));
}
/**
* Write the charCodes of all `str`'s characters as 8-bit unsigned integers
* and move pointer forward by `str.length` bytes.
* @param str - The characters to write.
* @returns This.
*/
writeChars(str) {
for (let i = 0; i < str.length; i++) {
// eslint-disable-next-line unicorn/prefer-code-point
this.writeUint8(str.charCodeAt(i));
}
return this;
}
/**
* UTF-8 encode and write `str` to the current pointer offset and move pointer
* forward according to the encoded length.
* @param str - The string to write.
* @returns This.
*/
writeUtf8(str) {
return this.writeBytes((0,_text__WEBPACK_IMPORTED_MODULE_0__.encode)(str));
}
/**
* Export a Uint8Array view of the internal buffer.
* The view starts at the byte offset and its length
* is calculated to stop at the last written byte or the original length.
* @returns A new Uint8Array view.
*/
toArray() {
return new Uint8Array(this.buffer, this.byteOffset, this.lastWrittenByte);
}
/**
* Get the total number of bytes written so far, regardless of the current offset.
* @returns - Total number of bytes.
*/
getWrittenByteLength() {
return this.lastWrittenByte - this.byteOffset;
}
/**
* Update the last written byte offset
* @private
*/
_updateLastWrittenByte() {
if (this.offset > this.lastWrittenByte) {
this.lastWrittenByte = this.offset;
}
}
}
//# sourceMappingURL=IOBuffer.js.map
/***/ }),
/***/ "./node_modules/iobuffer/lib-esm/text.js":
/*!***********************************************!*\
!*** ./node_modules/iobuffer/lib-esm/text.js ***!
\***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ decode: () => (/* binding */ decode),
/* harmony export */ encode: () => (/* binding */ encode)
/* harmony export */ });
function decode(bytes, encoding = 'utf8') {
const decoder = new TextDecoder(encoding);
return decoder.decode(bytes);
}
const encoder = new TextEncoder();
function encode(str) {
return encoder.encode(str);
}
//# sourceMappingURL=text.js.map
/***/ }),
/***/ "./node_modules/netcdfjs/lib-esm/data.js":
/*!***********************************************!*\
!*** ./node_modules/netcdfjs/lib-esm/data.js ***!
\***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ nonRecord: () => (/* binding */ nonRecord),
/* harmony export */ record: () => (/* binding */ record)
/* harmony export */ });
/* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./types */ "./node_modules/netcdfjs/lib-esm/types.js");
// const STREAMING = 4294967295;
/**
* Read data for the given non-record variable
* @param buffer - Buffer for the file data
* @param variable - Variable metadata
* @return - Data of the element
*/
function nonRecord(buffer, variable) {
// variable type
const type = (0,_types__WEBPACK_IMPORTED_MODULE_0__.str2num)(variable.type);
// size of the data
const size = variable.size / (0,_types__WEBPACK_IMPORTED_MODULE_0__.num2bytes)(type);
// iterates over the data
const data = new Array(size);
for (let i = 0; i < size; i++) {
data[i] = (0,_types__WEBPACK_IMPORTED_MODULE_0__.readType)(buffer, type, 1);
}
return data;
}
/**
* Read data for the given record variable
* @param buffer - Buffer for the file data
* @param variable - Variable metadata
* @param recordDimension - Record dimension metadata
* @return - Data of the element
*/
function record(buffer, variable, recordDimension) {
// variable type
const type = (0,_types__WEBPACK_IMPORTED_MODULE_0__.str2num)(variable.type);
const width = variable.size ? variable.size / (0,_types__WEBPACK_IMPORTED_MODULE_0__.num2bytes)(type) : 1;
// size of the data
// TODO streaming data
const size = recordDimension.length;
// iterates over the data
const data = new Array(size);
const step = recordDimension.recordStep;
if (step) {
for (let i = 0; i < size; i++) {
const currentOffset = buffer.offset;
data[i] = (0,_types__WEBPACK_IMPORTED_MODULE_0__.readType)(buffer, type, width);
buffer.seek(currentOffset + step);
}
}
else {
throw new Error('recordDimension.recordStep is undefined');
}
return data;
}
//# sourceMappingURL=data.js.map
/***/ }),
/***/ "./node_modules/netcdfjs/lib-esm/header.js":
/*!*************************************************!*\
!*** ./node_modules/netcdfjs/lib-esm/header.js ***!
\*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ header: () => (/* binding */ header)
/* harmony export */ });
/* harmony import */ var _types__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./types */ "./node_modules/netcdfjs/lib-esm/types.js");
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils */ "./node_modules/netcdfjs/lib-esm/utils.js");
// Grammar constants
const ZERO = 0;
const NC_DIMENSION = 10;
const NC_VARIABLE = 11;
const NC_ATTRIBUTE = 12;
const NC_UNLIMITED = 0;
/**
* Reads the file header as @see {@link Header}
* @param buffer - Buffer for the file data
* @param version - Version of the file
* @returns
*/
function header(buffer, version) {
const header = { version };
const recordDimension = {
length: buffer.readUint32(),
};
const dimList = dimensionsList(buffer);
if (!Array.isArray(dimList)) {
recordDimension.id = dimList.recordId;
recordDimension.name = dimList.recordName;
header.dimensions = dimList.dimensions;
}
header.globalAttributes = attributesList(buffer);
const variables = variablesList(buffer, recordDimension?.id, version);
if (!Array.isArray(variables)) {
header.variables = variables.variables;
recordDimension.recordStep = variables.recordStep;
}
header.recordDimension = recordDimension;
return header;
}
/**
* List of dimensions
* @param buffer - Buffer for the file data
* @return List of dimensions
*/
function dimensionsList(buffer) {
const result = {};
let recordId, recordName;
const dimList = buffer.readUint32();
let dimensions;
if (dimList === ZERO) {
(0,_utils__WEBPACK_IMPORTED_MODULE_1__.notNetcdf)(buffer.readUint32() !== ZERO, 'wrong empty tag for list of dimensions');
return [];
}
else {
(0,_utils__WEBPACK_IMPORTED_MODULE_1__.notNetcdf)(dimList !== NC_DIMENSION, 'wrong tag for list of dimensions');
// Length of dimensions
const dimensionSize = buffer.readUint32();
dimensions = new Array(dimensionSize);
//populate `name` and `size` for each dimension
for (let dim = 0; dim < dimensionSize; dim++) {
// Read name
const name = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.readName)(buffer);
// Read dimension size
const size = buffer.readUint32();
if (size === NC_UNLIMITED) {
// in netcdf 3 one field can be of size unlimited
recordId = dim;
recordName = name;
}
dimensions[dim] = {
name,
size,
};
}
}
if (recordId !== undefined) {
result.recordId = recordId;
}
if (recordName !== undefined) {
result.recordName = recordName;
}
result.dimensions = dimensions;
return result;
}
/**
* List of attributes
* @param buffer - Buffer for the file data
* @return - List of attributes with:
*/
function attributesList(buffer) {
const gAttList = buffer.readUint32();
let attributes;
if (gAttList === ZERO) {
(0,_utils__WEBPACK_IMPORTED_MODULE_1__.notNetcdf)(buffer.readUint32() !== ZERO, 'wrong empty tag for list of attributes');
return [];
}
else {
(0,_utils__WEBPACK_IMPORTED_MODULE_1__.notNetcdf)(gAttList !== NC_ATTRIBUTE, 'wrong tag for list of attributes');
// Length of attributes
const attributeSize = buffer.readUint32();
attributes = new Array(attributeSize);
// Populate `name`, `type` and `value` for each attribute
for (let gAtt = 0; gAtt < attributeSize; gAtt++) {
// Read name
const name = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.readName)(buffer);
// Read type
const type = buffer.readUint32();
(0,_utils__WEBPACK_IMPORTED_MODULE_1__.notNetcdf)(type < 1 || type > 6, `non valid type ${type}`);
// Read attribute
const size = buffer.readUint32();
const value = (0,_types__WEBPACK_IMPORTED_MODULE_0__.readType)(buffer, type, size);
// Apply padding
(0,_utils__WEBPACK_IMPORTED_MODULE_1__.padding)(buffer);
attributes[gAtt] = {
name,
type: (0,_types__WEBPACK_IMPORTED_MODULE_0__.num2str)(type),
value,
};
}
}
return attributes;
}
/**
* @param buffer - Buffer for the file data
* @param recordId - Id of the unlimited dimension (also called record dimension)
* This value may be undefined if there is no unlimited dimension
* @param version - Version of the file
* @return - Number of recordStep and list of variables @see {@link Variables}
*/
function variablesList(buffer, recordId, version) {
const varList = buffer.readUint32();
let recordStep = 0;
let variables;
if (varList === ZERO) {
(0,_utils__WEBPACK_IMPORTED_MODULE_1__.notNetcdf)(buffer.readUint32() !== ZERO, 'wrong empty tag for list of variables');
return [];
}
else {
(0,_utils__WEBPACK_IMPORTED_MODULE_1__.notNetcdf)(varList !== NC_VARIABLE, 'wrong tag for list of variables');
// Length of variables
const variableSize = buffer.readUint32();
variables = new Array(variableSize);
for (let v = 0; v < variableSize; v++) {
// Read name
const name = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.readName)(buffer);
// Read dimensionality of the variable
const dimensionality = buffer.readUint32();
// Index into the list of dimensions
const dimensionsIds = new Array(dimensionality);
for (let dim = 0; dim < dimensionality; dim++) {
dimensionsIds[dim] = buffer.readUint32();
}
// Read variables size
const attributes = attributesList(buffer);
// Read type
const type = buffer.readUint32();
(0,_utils__WEBPACK_IMPORTED_MODULE_1__.notNetcdf)(type < 1 && type > 6, `non valid type ${type}`);
// Read variable size
// The 32-bit varSize field is not large enough to contain the size of variables that require
// more than 2^32 - 4 bytes, so 2^32 - 1 is used in the varSize field for such variables.
const varSize = buffer.readUint32();
// Read offset
let offset = buffer.readUint32();
if (version === 2) {
(0,_utils__WEBPACK_IMPORTED_MODULE_1__.notNetcdf)(offset > 0, 'offsets larger than 4GB not supported');
offset = buffer.readUint32();
}
let record = false;
// Count amount of record variables
if (typeof recordId !== 'undefined' && dimensionsIds[0] === recordId) {
recordStep += varSize;
record = true;
}
variables[v] = {
name,
dimensions: dimensionsIds,
attributes,
type: (0,_types__WEBPACK_IMPORTED_MODULE_0__.num2str)(type),
size: varSize,
offset,
record,
};
}
}
return {
variables,
recordStep,
};
}
//# sourceMappingURL=header.js.map
/***/ }),
/***/ "./node_modules/netcdfjs/lib-esm/index.js":
/*!************************************************!*\
!*** ./node_modules/netcdfjs/lib-esm/index.js ***!
\************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ NetCDFReader: () => (/* reexport safe */ _parser__WEBPACK_IMPORTED_MODULE_0__.NetCDFReader)
/* harmony export */ });
/* harmony import */ var _parser__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./parser */ "./node_modules/netcdfjs/lib-esm/parser.js");
//# sourceMappingURL=index.js.map
/***/ }),
/***/ "./node_modules/netcdfjs/lib-esm/parser.js":
/*!*************************************************!*\
!*** ./node_modules/netcdfjs/lib-esm/parser.js ***!
\*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ NetCDFReader: () => (/* binding */ NetCDFReader)
/* harmony export */ });
/* harmony import */ var iobuffer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! iobuffer */ "./node_modules/iobuffer/lib-esm/IOBuffer.js");
/* harmony import */ var _data__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./data */ "./node_modules/netcdfjs/lib-esm/data.js");
/* harmony import */ var _header__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./header */ "./node_modules/netcdfjs/lib-esm/header.js");
/* harmony import */ var _toString__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./toString */ "./node_modules/netcdfjs/lib-esm/toString.js");
/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./utils */ "./node_modules/netcdfjs/lib-esm/utils.js");
/**
* Reads a NetCDF v3.x file
* [See specification](https://www.unidata.ucar.edu/software/netcdf/docs/file_format_specifications.html)
* @param data - ArrayBuffer or any Typed Array (including Node.js' Buffer from v4) with the data
* @constructor
*/
class NetCDFReader {
constructor(data) {
this.toString = _toString__WEBPACK_IMPORTED_MODULE_3__.toString;
const buffer = new iobuffer__WEBPACK_IMPORTED_MODULE_0__.IOBuffer(data);
buffer.setBigEndian();
// Validate that it's a NetCDF file
(0,_utils__WEBPACK_IMPORTED_MODULE_4__.notNetcdf)(buffer.readChars(3) !== 'CDF', 'should start with CDF');
// Check the NetCDF format
const version = buffer.readByte();
(0,_utils__WEBPACK_IMPORTED_MODULE_4__.notNetcdf)(version > 2, 'unknown version');
// Read the header
this.header = (0,_header__WEBPACK_IMPORTED_MODULE_2__.header)(buffer, version);
this.buffer = buffer;
}
/**
* @return - Version for the NetCDF format
*/
get version() {
if (this.header.version === 1) {
return 'classic format';
}
else {
return '64-bit offset format';
}
}
/**
* @return {object} - Metadata for the record dimension
* * `length`: Number of elements in the record dimension
* * `id`: Id number in the list of dimensions for the record dimension
* * `name`: String with the name of the record dimension
* * `recordStep`: Number with the record variables step size
*/
get recordDimension() {
return this.header.recordDimension;
}
/**
* @return - Array - List of dimensions with:
* * `name`: String with the name of the dimension
* * `size`: Number with the size of the dimension
*/
get dimensions() {
return this.header.dimensions;
}
/**
* @return - Array - List of global attributes with:
* * `name`: String with the name of the attribute
* * `type`: String with the type of the attribute
* * `value`: A number or string with the value of the attribute
*/
get globalAttributes() {
return this.header.globalAttributes;
}
/**
* Returns the value of an attribute
* @param - AttributeName
* @return - Value of the attributeName or null
*/
getAttribute(attributeName) {
const attribute = this.globalAttributes.find((val) => val.name === attributeName);
if (attribute)
return attribute.value;
return null;
}
/**
* Returns the value of a variable as a string
* @param - variableName
* @return - Value of the variable as a string or null
*/
getDataVariableAsString(variableName) {
const variable = this.getDataVariable(variableName);
if (variable)
return variable.join('');
return null;
}
get variables() {
return this.header.variables;
}
/**
* Retrieves the data for a given variable
* @param variableName - Name of the variable to search or variable object
* @return The variable values
*/
getDataVariable(variableName) {
let variable;
if (typeof variableName === 'string') {
// search the variable
variable = this.header.variables.find((val) => {
return val.name === variableName;
});
}
else {
variable = variableName;
}
// throws if variable not found
if (variable === undefined) {
throw new Error('Not a valid NetCDF v3.x file: variable not found');
}
// go to the offset position
this.buffer.seek(variable.offset);
if (variable.record) {
// record variable case
return (0,_data__WEBPACK_IMPORTED_MODULE_1__.record)(this.buffer, variable, this.header.recordDimension);
}
else {
// non-record variable case
return (0,_data__WEBPACK_IMPORTED_MODULE_1__.nonRecord)(this.buffer, variable);
}
}
/**
* Check if a dataVariable exists
* @param variableName - Name of the variable to find
* @return boolean
*/
dataVariableExists(variableName) {
const variable = this.header.variables.find((val) => {
return val.name === variableName;
});
return variable !== undefined;
}
/**
* Check if an attribute exists
* @param attributeName - Name of the attribute to find
* @return boolean
*/
attributeExists(attributeName) {
const attribute = this.globalAttributes.find((val) => val.name === attributeName);
return attribute !== undefined;
}
}
//# sourceMappingURL=parser.js.map
/***/ }),
/***/ "./node_modules/netcdfjs/lib-esm/toString.js":
/*!***************************************************!*\
!*** ./node_modules/netcdfjs/lib-esm/toString.js ***!
\***************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ toString: () => (/* binding */ toString)
/* harmony export */ });
function toString() {
const result = [];
result.push('DIMENSIONS');
for (const dimension of this.dimensions) {
result.push(` ${dimension.name.padEnd(30)} = size: ${dimension.size}`);
}
result.push('');
result.push('GLOBAL ATTRIBUTES');
for (const attribute of this.globalAttributes) {
result.push(` ${attribute.name.padEnd(30)} = ${attribute.value}`);
}
const variables = JSON.parse(JSON.stringify(this.variables));
result.push('');
result.push('VARIABLES:');
for (const variable of variables) {
variable.value = this.getDataVariable(variable);
let stringify = JSON.stringify(variable.value);
if (stringify.length > 50)
stringify = stringify.substring(0, 50);
if (!isNaN(variable.value.length)) {
stringify += ` (length: ${variable.value.length})`;
}
result.push(` ${variable.name.padEnd(30)} = ${stringify}`);
}
return result.join('\n');
}
//# sourceMappingURL=toString.js.map
/***/ }),
/***/ "./node_modules/netcdfjs/lib-esm/types.js":
/*!************************************************!*\
!*** ./node_modules/netcdfjs/lib-esm/types.js ***!
\************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ num2bytes: () => (/* binding */ num2bytes),
/* harmony export */ num2str: () => (/* binding */ num2str),
/* harmony export */ readType: () => (/* binding */ readType),
/* harmony export */ str2num: () => (/* binding */ str2num)
/* harmony export */ });
const types = {
BYTE: 1,
CHAR: 2,
SHORT: 3,
INT: 4,
FLOAT: 5,
DOUBLE: 6,
};
/**
* Parse a number into their respective type
* @param type - integer that represents the type
* @return - parsed value of the type
*/
function num2str(type) {
switch (Number(type)) {
case types.BYTE:
return 'byte';
case types.CHAR:
return 'char';
case types.SHORT:
return 'short';
case types.INT:
return 'int';
case types.FLOAT:
return 'float';
case types.DOUBLE:
return 'double';
default:
return 'undefined';
}
}
/**
* Parse a number type identifier to his size in bytes
* @param type - integer that represents the type
* @return size of the type
*/
function num2bytes(type) {
switch (Number(type)) {
case types.BYTE:
return 1;
case types.CHAR:
return 1;
case types.SHORT:
return 2;
case types.INT:
return 4;
case types.FLOAT:
return 4;
case types.DOUBLE:
return 8;
default:
return -1;
}
}
/**
* Reverse search of num2str
* @param type - string that represents the type
* @return parsed value of the type
*/
function str2num(type) {
switch (String(type)) {
case 'byte':
return types.BYTE;
case 'char':
return types.CHAR;
case 'short':
return types.SHORT;
case 'int':
return types.INT;
case 'float':
return types.FLOAT;
case 'double':
return types.DOUBLE;
/* istanbul ignore next */
default:
return -1;
}
}
/**
* Auxiliary function to read numeric data
* @param size - Size of the element to read
* @param bufferReader - Function to read next value
* @return
*/
function readNumber(size, bufferReader) {
if (size !== 1) {
const numbers = new Array(size);
for (let i = 0; i < size; i++) {
numbers[i] = bufferReader();
}
return numbers;
}
else {
return bufferReader();
}
}
/**
* Given a type and a size reads the next element
* @param buffer - Buffer for the file data
* @param type - Type of the data to read
* @param size - Size of the element to read
* @return
*/
function readType(buffer, type, size) {
switch (type) {
case types.BYTE:
return Array.from(buffer.readBytes(size));
case types.CHAR:
return trimNull(buffer.readChars(size));
case types.SHORT:
return readNumber(size, buffer.readInt16.bind(buffer));
case types.INT:
return readNumber(size, buffer.readInt32.bind(buffer));
case types.FLOAT:
return readNumber(size, buffer.readFloat32.bind(buffer));
case types.DOUBLE:
return readNumber(size, buffer.readFloat64.bind(buffer));
default:
throw new Error(`non valid type ${type}`);
}
}
/**
* Removes null terminate value
* @param value - String to trim
* @return - Trimmed string
*/
function trimNull(value) {
if (value.charCodeAt(value.length - 1) === 0) {
return value.substring(0, value.length - 1);
}
return value;
}
//# sourceMappingURL=types.js.map
/***/ }),
/***/ "./node_modules/netcdfjs/lib-esm/utils.js":
/*!************************************************!*\
!*** ./node_modules/netcdfjs/lib-esm/utils.js ***!
\************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ notNetcdf: () => (/* binding */ notNetcdf),
/* harmony export */ padding: () => (/* binding */ padding),
/* harmony export */ readName: () => (/* binding */ readName)
/* harmony export */ });
/**
* Throws a non-valid NetCDF exception if the statement it's true
* @ignore
* @param statement - Throws if true
* @param reason - Reason to throw
*/
function notNetcdf(statement, reason) {
if (statement) {
throw new TypeError(`Not a valid NetCDF v3.x file: ${reason}`);
}
}
/**
* Moves 1, 2, or 3 bytes to next 4-byte boundary
* @param buffer - Buffer for the file data
*/
function padding(buffer) {
if (buffer.offset % 4 !== 0) {
buffer.skip(4 - (buffer.offset % 4));
}
}
/**
* Reads the name
* @param buffer - Buffer for the file data
* @return Name
*/
function readName(buffer) {
// Read name
const nameLength = buffer.readUint32();
const name = buffer.readChars(nameLength);
// validate name
// TODO
// Apply padding
padding(buffer);
return name;
}
//# sourceMappingURL=utils.js.map
/***/ }),
/***/ "./node_modules/pako/dist/pako.esm.mjs":
/*!*********************************************!*\
!*** ./node_modules/pako/dist/pako.esm.mjs ***!
\*********************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ Deflate: () => (/* binding */ Deflate_1),
/* harmony export */ Inflate: () => (/* binding */ Inflate_1),
/* harmony export */ constants: () => (/* binding */ constants_1),
/* harmony export */ "default": () => (/* binding */ pako),
/* harmony export */ deflate: () => (/* binding */ deflate_1),
/* harmony export */ deflateRaw: () => (/* binding */ deflateRaw_1),
/* harmony export */ gzip: () => (/* binding */ gzip_1),
/* harmony export */ inflate: () => (/* binding */ inflate_1),
/* harmony export */ inflateRaw: () => (/* binding */ inflateRaw_1),
/* harmony export */ ungzip: () => (/* binding */ ungzip_1)
/* harmony export */ });
/*! pako 2.1.0 https://github.com/nodeca/pako @license (MIT AND Zlib) */
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
/* eslint-disable space-unary-ops */
/* Public constants ==========================================================*/
/* ===========================================================================*/
//const Z_FILTERED = 1;
//const Z_HUFFMAN_ONLY = 2;
//const Z_RLE = 3;
const Z_FIXED$1 = 4;
//const Z_DEFAULT_STRATEGY = 0;
/* Possible values of the data_type field (though see inflate()) */
const Z_BINARY = 0;
const Z_TEXT = 1;
//const Z_ASCII = 1; // = Z_TEXT
const Z_UNKNOWN$1 = 2;
/*============================================================================*/
function zero$1(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } }
// From zutil.h
const STORED_BLOCK = 0;
const STATIC_TREES = 1;
const DYN_TREES = 2;
/* The three kinds of block type */
const MIN_MATCH$1 = 3;
const MAX_MATCH$1 = 258;
/* The minimum and maximum match lengths */
// From deflate.h
/* ===========================================================================
* Internal compression state.
*/
const LENGTH_CODES$1 = 29;
/* number of length codes, not counting the special END_BLOCK code */
const LITERALS$1 = 256;
/* number of literal bytes 0..255 */
const L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1;
/* number of Literal or Length codes, including the END_BLOCK code */
const D_CODES$1 = 30;
/* number of distance codes */
const BL_CODES$1 = 19;
/* number of codes used to transfer the bit lengths */
const HEAP_SIZE$1 = 2 * L_CODES$1 + 1;
/* maximum heap size */
const MAX_BITS$1 = 15;
/* All codes must not exceed MAX_BITS bits */
const Buf_size = 16;
/* size of bit buffer in bi_buf */
/* ===========================================================================
* Constants
*/
const MAX_BL_BITS = 7;
/* Bit length codes must not exceed MAX_BL_BITS bits */
const END_BLOCK = 256;
/* end of block literal code */
const REP_3_6 = 16;
/* repeat previous bit length 3-6 times (2 bits of repeat count) */
const REPZ_3_10 = 17;
/* repeat a zero length 3-10 times (3 bits of repeat count) */
const REPZ_11_138 = 18;
/* repeat a zero length 11-138 times (7 bits of repeat count) */
/* eslint-disable comma-spacing,array-bracket-spacing */
const extra_lbits = /* extra bits for each length code */
new Uint8Array([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]);
const extra_dbits = /* extra bits for each distance code */
new Uint8Array([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]);
const extra_blbits = /* extra bits for each bit length code */
new Uint8