UNPKG

3dmol

Version:

Object oriented Javascript molecular visualization library

1,771 lines (1,544 loc) 98.3 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define('netcdfjs',[], factory); else if(typeof exports === 'object') exports["netcdfjs"] = factory(); else root["netcdfjs"] = factory(); })(this, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // identity function for calling harmony imports with the correct context /******/ __webpack_require__.i = function(value) { return value; }; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 6); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /** * Throws a non-valid NetCDF exception if the statement it's true * @ignore * @param {boolean} statement - Throws if true * @param {string} 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 * @ignore * @param {IOBuffer} buffer - Buffer for the file data */ function padding(buffer) { if (buffer.offset % 4 !== 0) { buffer.skip(4 - buffer.offset % 4); } } /** * Reads the name * @ignore * @param {IOBuffer} buffer - Buffer for the file data * @return {string} - Name */ function readName(buffer) { // Read name var nameLength = buffer.readUint32(); var name = buffer.readChars(nameLength); // validate name // TODO // Apply padding padding(buffer); return name; } module.exports.notNetcdf = notNetcdf; module.exports.padding = padding; module.exports.readName = readName; /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const notNetcdf = __webpack_require__(0).notNetcdf; const types = { BYTE: 1, CHAR: 2, SHORT: 3, INT: 4, FLOAT: 5, DOUBLE: 6 }; /** * Parse a number into their respective type * @ignore * @param {number} type - integer that represents the type * @return {string} - 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'; /* istanbul ignore next */ default: return 'undefined'; } } /** * Parse a number type identifier to his size in bytes * @ignore * @param {number} type - integer that represents the type * @return {number} -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; /* istanbul ignore next */ default: return -1; } } /** * Reverse search of num2str * @ignore * @param {string} type - string that represents the type * @return {number} - 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 * @ignore * @param {number} size - Size of the element to read * @param {function} bufferReader - Function to read next value * @return {Array<number>|number} */ function readNumber(size, bufferReader) { if (size !== 1) { var numbers = new Array(size); for (var i = 0; i < size; i++) { numbers[i] = bufferReader(); } return numbers; } else { return bufferReader(); } } /** * Given a type and a size reads the next element * @ignore * @param {IOBuffer} buffer - Buffer for the file data * @param {number} type - Type of the data to read * @param {number} size - Size of the element to read * @return {string|Array<number>|number} */ function readType(buffer, type, size) { switch (type) { case types.BYTE: return 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)); /* istanbul ignore next */ default: notNetcdf(true, 'non valid type ' + type); return undefined; } } /** * Removes null terminate value * @ignore * @param {string} value - String to trim * @return {string} - Trimmed string */ function trimNull(value) { if (value.charCodeAt(value.length - 1) === 0) { return value.substring(0, value.length - 1); } return value; } module.exports = types; module.exports.num2str = num2str; module.exports.num2bytes = num2bytes; module.exports.str2num = str2num; module.exports.readType = readType; /***/ }), /* 2 */ /***/ (function(module, exports) { var g; // This works in non-strict mode g = (function() { return this; })(); try { // This works if eval is allowed (see CSP) g = g || Function("return this")() || (1,eval)("this"); } catch(e) { // This works if the window reference is available if(typeof window === "object") g = window; } // g can still be undefined, but nothing to do about it... // We return undefined, instead of nothing here, so it's // easier to handle this case. if(!global) { ...} module.exports = g; /***/ }), /* 3 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const types = __webpack_require__(1); // const STREAMING = 4294967295; /** * Read data for the given non-record variable * @ignore * @param {IOBuffer} buffer - Buffer for the file data * @param {object} variable - Variable metadata * @return {Array} - Data of the element */ function nonRecord(buffer, variable) { // variable type const type = types.str2num(variable.type); // size of the data var size = variable.size / types.num2bytes(type); // iterates over the data var data = new Array(size); for (var i = 0; i < size; i++) { data[i] = types.readType(buffer, type, 1); } return data; } /** * Read data for the given record variable * @ignore * @param {IOBuffer} buffer - Buffer for the file data * @param {object} variable - Variable metadata * @param {object} recordDimension - Record dimension metadata * @return {Array} - Data of the element */ function record(buffer, variable, recordDimension) { // variable type const type = types.str2num(variable.type); const width = variable.size ? variable.size / types.num2bytes(type) : 1; // size of the data // TODO streaming data var size = recordDimension.length; // iterates over the data var data = new Array(size); const step = recordDimension.recordStep; for (var i = 0; i < size; i++) { var currentOffset = buffer.offset; data[i] = types.readType(buffer, type, width); buffer.seek(currentOffset + step); } return data; } module.exports.nonRecord = nonRecord; module.exports.record = record; /***/ }), /* 4 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const utils = __webpack_require__(0); const types = __webpack_require__(1); // Grammar constants const ZERO = 0; const NC_DIMENSION = 10; const NC_VARIABLE = 11; const NC_ATTRIBUTE = 12; /** * Read the header of the file * @ignore * @param {IOBuffer} buffer - Buffer for the file data * @param {number} version - Version of the file * @return {object} - Object with the fields: * * `recordDimension`: Number with the length of record dimension * * `dimensions`: List of dimensions * * `globalAttributes`: List of global attributes * * `variables`: List of variables */ function header(buffer, version) { // Length of record dimension // sum of the varSize's of all the record variables. var header = { recordDimension: { length: buffer.readUint32() } }; // Version header.version = version; // List of dimensions var dimList = dimensionsList(buffer); header.recordDimension.id = dimList.recordId; header.recordDimension.name = dimList.recordName; header.dimensions = dimList.dimensions; // List of global attributes header.globalAttributes = attributesList(buffer); // List of variables var variables = variablesList(buffer, dimList.recordId, version); header.variables = variables.variables; header.recordDimension.recordStep = variables.recordStep; return header; } /** * List of dimensions * @ignore * @param {IOBuffer} buffer - Buffer for the file data * @return {object} - List of dimensions and record dimension with: * * `name`: String with the name of the dimension * * `size`: Number with the size of the dimension */ function dimensionsList(buffer) { var recordId, recordName; const dimList = buffer.readUint32(); if (dimList === ZERO) { utils.notNetcdf(buffer.readUint32() !== ZERO, 'wrong empty tag for list of dimensions'); return []; } else { utils.notNetcdf(dimList !== NC_DIMENSION, 'wrong tag for list of dimensions'); // Length of dimensions const dimensionSize = buffer.readUint32(); var dimensions = new Array(dimensionSize); for (var dim = 0; dim < dimensionSize; dim++) { // Read name var name = utils.readName(buffer); // Read dimension size const size = buffer.readUint32(); if (size === 0) { recordId = dim; recordName = name; } dimensions[dim] = { name: name, size: size }; } } return { dimensions: dimensions, recordId: recordId, recordName: recordName }; } /** * List of attributes * @ignore * @param {IOBuffer} buffer - Buffer for the file data * @return {Array<object>} - List of 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 */ function attributesList(buffer) { const gAttList = buffer.readUint32(); if (gAttList === ZERO) { utils.notNetcdf(buffer.readUint32() !== ZERO, 'wrong empty tag for list of attributes'); return []; } else { utils.notNetcdf(gAttList !== NC_ATTRIBUTE, 'wrong tag for list of attributes'); // Length of attributes const attributeSize = buffer.readUint32(); var attributes = new Array(attributeSize); for (var gAtt = 0; gAtt < attributeSize; gAtt++) { // Read name var name = utils.readName(buffer); // Read type var type = buffer.readUint32(); utils.notNetcdf(type < 1 || type > 6, 'non valid type ' + type); // Read attribute var size = buffer.readUint32(); var value = types.readType(buffer, type, size); // Apply padding utils.padding(buffer); attributes[gAtt] = { name: name, type: types.num2str(type), value: value }; } } return attributes; } /** * List of variables * @ignore * @param {IOBuffer} buffer - Buffer for the file data * @param {number} recordId - Id if the record dimension * @param {number} version - Version of the file * @return {object} - Number of recordStep and list of variables with: * * `name`: String with the name of the variable * * `dimensions`: Array with the dimension IDs of the variable * * `attributes`: Array with the attributes of the variable * * `type`: String with the type of the variable * * `size`: Number with the size of the variable * * `offset`: Number with the offset where of the variable begins * * `record`: True if is a record variable, false otherwise */ function variablesList(buffer, recordId, version) { const varList = buffer.readUint32(); var recordStep = 0; if (varList === ZERO) { utils.notNetcdf(buffer.readUint32() !== ZERO, 'wrong empty tag for list of variables'); return []; } else { utils.notNetcdf(varList !== NC_VARIABLE, 'wrong tag for list of variables'); // Length of variables const variableSize = buffer.readUint32(); var variables = new Array(variableSize); for (var v = 0; v < variableSize; v++) { // Read name var name = utils.readName(buffer); // Read dimensionality of the variable const dimensionality = buffer.readUint32(); // Index into the list of dimensions var dimensionsIds = new Array(dimensionality); for (var dim = 0; dim < dimensionality; dim++) { dimensionsIds[dim] = buffer.readUint32(); } // Read variables size var attributes = attributesList(buffer); // Read type var type = buffer.readUint32(); utils.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 var offset = buffer.readUint32(); if (version === 2) { utils.notNetcdf(offset > 0, 'offsets larger than 4GB not supported'); offset = buffer.readUint32(); } // Count amount of record variables if (dimensionsIds[0] === recordId) { recordStep += varSize; } variables[v] = { name: name, dimensions: dimensionsIds, attributes: attributes, type: types.num2str(type), size: varSize, offset: offset, record: dimensionsIds[0] === recordId }; } } return { variables: variables, recordStep: recordStep }; } module.exports = header; /***/ }), /* 5 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(Buffer) { const utf8 = __webpack_require__(11); const defaultByteLength = 1024 * 8; const charArray = []; /** * IOBuffer * @constructor * @param {undefined|number|ArrayBuffer|TypedArray|IOBuffer|Buffer} data - The data to construct the IOBuffer with. * * If it's a number, it will initialize the buffer with the number as the buffer's length<br> * If it's undefined, it will initialize the buffer with a default length of 8 Kb<br> * If its an ArrayBuffer, a TypedArray, an IOBuffer instance, * or a Node.js Buffer, it will create a view over the underlying ArrayBuffer. * @param {object} [options] * @param {number} [options.offset=0] - Ignore the first n bytes of the ArrayBuffer * @property {ArrayBuffer} buffer - Reference to the internal ArrayBuffer object * @property {number} length - Byte length of the internal ArrayBuffer * @property {number} offset - The current offset of the buffer's pointer * @property {number} byteLength - Byte length of the internal ArrayBuffer * @property {number} byteOffset - Byte offset of the internal ArrayBuffer */ class IOBuffer { constructor(data, options) { options = options || {}; var dataIsGiven = false; if (data === undefined) { data = defaultByteLength; } if (typeof data === 'number') { data = new ArrayBuffer(data); } else { dataIsGiven = true; this._lastWrittenByte = data.byteLength; } const offset = options.offset ? options.offset >>> 0 : 0; let byteLength = data.byteLength - offset; let dvOffset = offset; if (data.buffer) { 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 {number} [byteLength=1] The needed memory in bytes * @return {boolean} Returns true if there is sufficient space and false otherwise */ available(byteLength) { if (byteLength === undefined) byteLength = 1; return (this.offset + byteLength) <= this.length; } /** * Check if little-endian mode is used for reading and writing multi-byte values * @return {boolean} 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 * @return {IOBuffer} */ setLittleEndian() { this.littleEndian = true; return this; } /** * Check if big-endian mode is used for reading and writing multi-byte values * @return {boolean} 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 * @return {IOBuffer} */ setBigEndian() { this.littleEndian = false; return this; } /** * Move the pointer n bytes forward * @param {number} n * @return {IOBuffer} */ skip(n) { if (n === undefined) n = 1; this.offset += n; return this; } /** * Move the pointer to the given offset * @param {number} offset * @return {IOBuffer} */ seek(offset) { this.offset = offset; return this; } /** * Store the current pointer offset. * @see {@link IOBuffer#reset} * @return {IOBuffer} */ mark() { this._mark = this.offset; return this; } /** * Move the pointer back to the last pointer offset set by mark * @see {@link IOBuffer#mark} * @return {IOBuffer} */ reset() { this.offset = this._mark; return this; } /** * Push the current pointer offset to the mark stack * @see {@link IOBuffer#popMark} * @return {IOBuffer} */ 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} * @return {IOBuffer} */ 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 * @return {IOBuffer} */ 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 {number} [byteLength = 1] * @return {IOBuffer} */ ensureAvailable(byteLength) { if (byteLength === undefined) 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 = 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 * @return {boolean} */ readBoolean() { return this.readUint8() !== 0; } /** * Read a signed 8-bit integer and move pointer forward * @return {number} */ readInt8() { return this._data.getInt8(this.offset++); } /** * Read an unsigned 8-bit integer and move pointer forward * @return {number} */ readUint8() { return this._data.getUint8(this.offset++); } /** * Alias for {@link IOBuffer#readUint8} * @return {number} */ readByte() { return this.readUint8(); } /** * Read n bytes and move pointer forward. * @param {number} n * @return {Uint8Array} */ readBytes(n) { if (n === undefined) n = 1; var bytes = new Uint8Array(n); for (var i = 0; i < n; i++) { bytes[i] = this.readByte(); } return bytes; } /** * Read a 16-bit signed integer and move pointer forward * @return {number} */ readInt16() { var value = this._data.getInt16(this.offset, this.littleEndian); this.offset += 2; return value; } /** * Read a 16-bit unsigned integer and move pointer forward * @return {number} */ readUint16() { var value = this._data.getUint16(this.offset, this.littleEndian); this.offset += 2; return value; } /** * Read a 32-bit signed integer and move pointer forward * @return {number} */ readInt32() { var value = this._data.getInt32(this.offset, this.littleEndian); this.offset += 4; return value; } /** * Read a 32-bit unsigned integer and move pointer forward * @return {number} */ readUint32() { var value = this._data.getUint32(this.offset, this.littleEndian); this.offset += 4; return value; } /** * Read a 32-bit floating number and move pointer forward * @return {number} */ readFloat32() { var value = this._data.getFloat32(this.offset, this.littleEndian); this.offset += 4; return value; } /** * Read a 64-bit floating number and move pointer forward * @return {number} */ readFloat64() { var value = this._data.getFloat64(this.offset, this.littleEndian); this.offset += 8; return value; } /** * Read 1-byte ascii character and move pointer forward * @return {string} */ readChar() { return String.fromCharCode(this.readInt8()); } /** * Read n 1-byte ascii characters and move pointer forward * @param {number} n * @return {string} */ readChars(n) { if (n === undefined) n = 1; charArray.length = n; for (var i = 0; i < n; i++) { charArray[i] = this.readChar(); } return charArray.join(''); } /** * Read the next n bytes, return a UTF-8 decoded string and move pointer forward * @param {number} n * @return {string} */ readUtf8(n) { if (n === undefined) n = 1; const bString = this.readChars(n); return utf8.decode(bString); } /** * Write 0xff if the passed value is truthy, 0x00 otherwise * @param {any} value * @return {IOBuffer} */ writeBoolean(value) { this.writeUint8(value ? 0xff : 0x00); return this; } /** * Write value as an 8-bit signed integer * @param {number} value * @return {IOBuffer} */ writeInt8(value) { this.ensureAvailable(1); this._data.setInt8(this.offset++, value); this._updateLastWrittenByte(); return this; } /** * Write value as a 8-bit unsigned integer * @param {number} value * @return {IOBuffer} */ writeUint8(value) { this.ensureAvailable(1); this._data.setUint8(this.offset++, value); this._updateLastWrittenByte(); return this; } /** * An alias for {@link IOBuffer#writeUint8} * @param {number} value * @return {IOBuffer} */ writeByte(value) { return this.writeUint8(value); } /** * Write bytes * @param {Array|Uint8Array} bytes * @return {IOBuffer} */ writeBytes(bytes) { this.ensureAvailable(bytes.length); for (var i = 0; i < bytes.length; i++) { this._data.setUint8(this.offset++, bytes[i]); } this._updateLastWrittenByte(); return this; } /** * Write value as an 16-bit signed integer * @param {number} value * @return {IOBuffer} */ 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 * @param {number} value * @return {IOBuffer} */ writeUint16(value) { this.ensureAvailable(2); this._data.setUint16(this.offset, value, this.littleEndian); this.offset += 2; this._updateLastWrittenByte(); return this; } /** * Write a 32-bit signed integer at the current pointer offset * @param {number} value * @return {IOBuffer} */ writeInt32(value) { this.ensureAvailable(4); this._data.setInt32(this.offset, value, this.littleEndian); this.offset += 4; this._updateLastWrittenByte(); return this; } /** * Write a 32-bit unsigned integer at the current pointer offset * @param {number} value - The value to set * @return {IOBuffer} */ writeUint32(value) { this.ensureAvailable(4); this._data.setUint32(this.offset, value, this.littleEndian); this.offset += 4; this._updateLastWrittenByte(); return this; } /** * Write a 32-bit floating number at the current pointer offset * @param {number} value - The value to set * @return {IOBuffer} */ writeFloat32(value) { this.ensureAvailable(4); this._data.setFloat32(this.offset, value, this.littleEndian); this.offset += 4; this._updateLastWrittenByte(); return this; } /** * Write a 64-bit floating number at the current pointer offset * @param {number} value * @return {IOBuffer} */ writeFloat64(value) { this.ensureAvailable(8); this._data.setFloat64(this.offset, value, this.littleEndian); this.offset += 8; this._updateLastWrittenByte(); return this; } /** * Write the charCode of the passed string's first character to the current pointer offset * @param {string} str - The character to set * @return {IOBuffer} */ writeChar(str) { return this.writeUint8(str.charCodeAt(0)); } /** * Write the charCodes of the passed string's characters to the current pointer offset * @param {string} str * @return {IOBuffer} */ writeChars(str) { for (var i = 0; i < str.length; i++) { this.writeUint8(str.charCodeAt(i)); } return this; } /** * UTF-8 encode and write the passed string to the current pointer offset * @param {string} str * @return {IOBuffer} */ writeUtf8(str) { const bString = utf8.encode(str); return this.writeChars(bString); } /** * 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. * @return {Uint8Array} */ toArray() { return new Uint8Array(this.buffer, this.byteOffset, this._lastWrittenByte); } /** * Same as {@link IOBuffer#toArray} but returns a Buffer if possible. Otherwise returns a Uint8Array. * @return {Buffer|Uint8Array} */ getBuffer() { if (typeof Buffer !== 'undefined') { return Buffer.from(this.toArray()); } else { return this.toArray(); } } /** * Update the last written byte offset * @private */ _updateLastWrittenByte() { if (this.offset > this._lastWrittenByte) { this._lastWrittenByte = this.offset; } } } module.exports = IOBuffer; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(8).Buffer)) /***/ }), /* 6 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const IOBuffer = __webpack_require__(5); const utils = __webpack_require__(0); const data = __webpack_require__(3); const readHeader = __webpack_require__(4); /** * Reads a NetCDF v3.x file * https://www.unidata.ucar.edu/software/netcdf/docs/file_format_specifications.html * @param {ArrayBuffer} data - ArrayBuffer or any Typed Array (including Node.js' Buffer from v4) with the data * @constructor */ class NetCDFReader { constructor(data) { const buffer = new IOBuffer(data); buffer.setBigEndian(); // Validate that it's a NetCDF file utils.notNetcdf(buffer.readChars(3) !== 'CDF', 'should start with CDF'); // Check the NetCDF format const version = buffer.readByte(); utils.notNetcdf(version > 2, 'unknown version'); // Read the header this.header = readHeader(buffer, version); this.buffer = buffer; } /** * @return {string} - 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<object>} - 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<object>} - 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; } /** * @return {Array<object>} - List of variables with: * * `name`: String with the name of the variable * * `dimensions`: Array with the dimension IDs of the variable * * `attributes`: Array with the attributes of the variable * * `type`: String with the type of the variable * * `size`: Number with the size of the variable * * `offset`: Number with the offset where of the variable begins * * `record`: True if is a record variable, false otherwise */ get variables() { return this.header.variables; } /** * Retrieves the data for a given variable * @param {string|object} variableName - Name of the variable to search or variable object * @return {Array} - List with the variable values */ getDataVariable(variableName) { var variable; if (typeof variableName === 'string') { // search the variable variable = this.header.variables.find(function (val) { return val.name === variableName; }); } else { variable = variableName; } // throws if variable not found utils.notNetcdf(variable === undefined, 'variable not found'); // go to the offset position this.buffer.seek(variable.offset); if (variable.record) { // record variable case return data.record(this.buffer, variable, this.header.recordDimension); } else { // non-record variable case return data.nonRecord(this.buffer, variable); } } } module.exports = NetCDFReader; /***/ }), /* 7 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; exports.byteLength = byteLength exports.toByteArray = toByteArray exports.fromByteArray = fromByteArray var lookup = [] var revLookup = [] var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' for (var i = 0, len = code.length; i < len; ++i) { lookup[i] = code[i] revLookup[code.charCodeAt(i)] = i } revLookup['-'.charCodeAt(0)] = 62 revLookup['_'.charCodeAt(0)] = 63 function placeHoldersCount (b64) { var len = b64.length if (len % 4 > 0) { throw new Error('Invalid string. Length must be a multiple of 4') } // the number of equal signs (place holders) // if there are two placeholders, than the two characters before it // represent one byte // if there is only one, then the three characters before it represent 2 bytes // this is just a cheap hack to not do indexOf twice return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0 } function byteLength (b64) { // base64 is 4/3 + up to two characters of the original data return b64.length * 3 / 4 - placeHoldersCount(b64) } function toByteArray (b64) { var i, j, l, tmp, placeHolders, arr var len = b64.length placeHolders = placeHoldersCount(b64) arr = new Arr(len * 3 / 4 - placeHolders) // if there are placeholders, only get up to the last complete 4 chars l = placeHolders > 0 ? len - 4 : len var L = 0 for (i = 0, j = 0; i < l; i += 4, j += 3) { tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)] arr[L++] = (tmp >> 16) & 0xFF arr[L++] = (tmp >> 8) & 0xFF arr[L++] = tmp & 0xFF } if (placeHolders === 2) { tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4) arr[L++] = tmp & 0xFF } else if (placeHolders === 1) { tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2) arr[L++] = (tmp >> 8) & 0xFF arr[L++] = tmp & 0xFF } return arr } function tripletToBase64 (num) { return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F] } function encodeChunk (uint8, start, end) { var tmp var output = [] for (var i = start; i < end; i += 3) { tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) output.push(tripletToBase64(tmp)) } return output.join('') } function fromByteArray (uint8) { var tmp var len = uint8.length var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes var output = '' var parts = [] var maxChunkLength = 16383 // must be multiple of 3 // go through the array every three bytes, we'll deal with trailing stuff later for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) } // pad the end with zeros, but make sure to not forget the extra bytes if (extraBytes === 1) { tmp = uint8[len - 1] output += lookup[tmp >> 2] output += lookup[(tmp << 4) & 0x3F] output += '==' } else if (extraBytes === 2) { tmp = (uint8[len - 2] << 8) + (uint8[len - 1]) output += lookup[tmp >> 10] output += lookup[(tmp >> 4) & 0x3F] output += lookup[(tmp << 2) & 0x3F] output += '=' } parts.push(output) return parts.join('') } /***/ }), /* 8 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(global) {/*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> * @license MIT */ /* eslint-disable no-proto */ var base64 = __webpack_require__(7) var ieee754 = __webpack_require__(9) var isArray = __webpack_require__(10) exports.Buffer = Buffer exports.SlowBuffer = SlowBuffer exports.INSPECT_MAX_BYTES = 50 /** * If `Buffer.TYPED_ARRAY_SUPPORT`: * === true Use Uint8Array implementation (fastest) * === false Use Object implementation (most compatible, even IE6) * * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, * Opera 11.6+, iOS 4.2+. * * Due to various browser bugs, sometimes the Object implementation will be used even * when the browser supports typed arrays. * * Note: * * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. * * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. * * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of * incorrect length in some situations. * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they * get the Object implementation, which is slower but behaves correctly. */ Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined ? global.TYPED_ARRAY_SUPPORT : typedArraySupport() /* * Export kMaxLength after typed array support is determined. */ exports.kMaxLength = kMaxLength() function typedArraySupport () { try { var arr = new Uint8Array(1) arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} return arr.foo() === 42 && // typed array instances can be augmented typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` } catch (e) { return false } } function kMaxLength () { return Buffer.TYPED_ARRAY_SUPPORT ? 0x7fffffff : 0x3fffffff } function createBuffer (that, length) { if (kMaxLength() < length) { throw new RangeError('Invalid typed array length') } if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance that = new Uint8Array(length) that.__proto__ = Buffer.prototype } else { // Fallback: Return an object instance of the Buffer class if (that === null) { that = new Buffer(length) } that.length = length } return that } /** * The Buffer constructor returns instances of `Uint8Array` that have their * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of * `Uint8Array`, so the returned instances will have all the node `Buffer` methods * and the `Uint8Array` methods. Square bracket notation works as expected -- it * returns a single octet. * * The `Uint8Array` prototype remains unmodified. */ function Buffer (arg, encodingOrOffset, length) { if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) { return new Buffer(arg, encodingOrOffset, length) } // Common case. if (typeof arg === 'number') { if (typeof encodingOrOffset === 'string') { throw new Error( 'If encoding is specified then the first argument must be a string' ) } return allocUnsafe(this, arg) } return from(this, arg, encodingOrOffset, length) } Buffer.poolSize = 8192 // not used by this implementation // TODO: Legacy, not needed anymore. Remove in next major version. Buffer._augment = function (arr) { arr.__proto__ = Buffer.prototype return arr } function from (that, value, encodingOrOffset, length) { if (typeof value === 'number') { throw new TypeError('"value" argument must not be a number') } if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { return fromArrayBuffer(that, value, encodingOrOffset, length) } if (typeof value === 'string') { return fromString(that, value, encodingOrOffset) } return fromObject(that, value) } /** * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError * if value is a number. * Buffer.from(str[, encoding]) * Buffer.from(array) * Buffer.from(buffer) * Buffer.from(arrayBuffer[, byteOffset[, length]]) **/ Buffer.from = function (value, encodingOrOffset, length) { return from(null, value, encodingOrOffset, length) } if (Buffer.TYPED_ARRAY_SUPPORT) { Buffer.prototype.__proto__ = Uint8Array.prototype Buffer.__proto__ = Uint8Array if (typeof Symbol !== 'undefined' && Symbol.species && Buffer[Symbol.species] === Buffer) { // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 Object.defineProperty(Buffer, Symbol.species, { value: null, configurable: true }) } } function assertSize (size) { if (typeof size !== 'number') { throw new TypeError('"size" argument must be a number') } else if (size < 0) { throw new RangeError('"size" argument must not be negative') } } function alloc (that, size, fill, encoding) { assertSize(size) if (size <= 0) { return createBuffer(that, size) } if (fill !== undefined) { // Only pay attention to encoding if it's a string. This // prevents accidentally sending in a number that would // be interpretted as a start offset. return typeof encoding === 'string' ? createBuffer(that, size).fill(fill, encoding) : createBuffer(that, size).fill(fill) } return createBuffer(that, size) } /** * Creates a new filled Buffer instance. * alloc(size[, fill[, encoding]]) **/ Buffer.alloc = function (size, fill, encoding) { return alloc(null, size, fill, encoding) } function allocUnsafe (that, size) { assertSize(size) that = createBuffer(that, size < 0 ? 0 : checked(size) | 0) if (!Buffer.TYPED_ARRAY_SUPPORT) { for (var i = 0; i < size; ++i) { that[i] = 0 } } return that } /** * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. * */ Buffer.allocUnsafe = function (size) { return allocUnsafe(null, size) } /** * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. */ Buffer.allocUnsafeSlow = function (size) { return allocUnsafe(null, size) } function fromString (that, string, encoding) { if (typeof encoding !== 'string' || encoding === '') { encoding = 'utf8' } if (!Buffer.isEncoding(encoding)) { throw new TypeError('"encoding" must be a valid string encoding') } var length = byteLength(string, encoding) | 0 that = createBuffer(that, length) var actual = that.write(string, encoding) if (actual !== length) { // Writing a hex string, for example, that contains invalid characters will // cause everything after the first invalid character to be ignored. (e.g. // 'abxxcd' will be treated as 'ab') that = that.slice(0, actual) } return that } function fromArrayLike (that, array) { var length = array.length < 0 ? 0 : checked(array.length) | 0 that = createBuffer(that, length) for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } function fromArrayBuffer (that, array, byteOffset, length) { array.byteLength // this throws if `array` is not a valid ArrayBuffer if (byteOffset < 0 || array.byteLength < byteOffset) { throw new RangeError('\'offset\' is out of bounds') } if (array.byteLength < byteOffset + (length || 0)) { throw new RangeError('\'length\' is out of bounds') } if (byteOffset === undefined && length === undefined) { array = new Uint8Array(array) } else if (length === undefined) { array = new Uint8Array(array, byteOffset) } else { array = new Uint8Array(array, byteOffset, length) } if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance that = array that.__proto__ = Buffer.prototype } else { // Fallback: Return an object instance of the Buffer class that = fromArrayLike(that, array) } return that } function fromObject (that, obj) { if (Buffer.isBuffer(obj)) { var len = checked(obj.length) | 0 that = createBuffer(that, len) if (that.length === 0) { return that } obj.copy(that, 0, 0, len) return that } if (obj) { if ((typeof ArrayBuffer !== 'undefined' && obj.buffer instanceof ArrayBuffer) || 'length' in obj) { if (typeof obj.length !== 'number' || isnan(obj.length)) { return createBuffer(that, 0) } return fromArrayLike(that, obj) } if (obj.type === 'Buffer' && isArray(obj.data)) { return fromArrayLike(that, obj.data) } } throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.') } function checked (length) { // Note: cannot use `length < kMaxLength()` here because that fails when // length is NaN (which is otherwise coerced to zero.) if (length >= kMaxLength()) { throw new RangeError('Attempt to allocate Buffer larger than maximum ' + 'size: 0x' + kMaxLength().toString(16) + ' bytes') } return length | 0 } function SlowBuffer (length) { if (+length != length) { // eslint-disable-line eqeqeq length = 0 } return Buffer.alloc(+length) } Buffer.isBuffer = function isBuffer (b) { return !!(b != null && b._isBuffer) } Buffer.compare = function compare (a, b) { if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { throw new TypeError('Arguments must be Buffers') } if (a === b) return 0 var x = a.length var y = b.length for (var i = 0, len = Math.min(x, y); i < len; ++i) { if (a[i] !== b[i]) { x = a[i] y = b[i] break } } if (x < y) return -1 if (y < x) return 1 return 0 } Buffer.isEncoding = function isEncoding (encoding) { switch (String(encoding).toLowerCa