@loaders.gl/netcdf 3.1.0-alpha.4 → 3.1.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es5/index.js +2 -2
- package/dist/es5/iobuffer/iobuffer.js +259 -318
- package/dist/es5/iobuffer/iobuffer.js.map +1 -1
- package/dist/es5/netcdf-loader.js +11 -62
- package/dist/es5/netcdf-loader.js.map +1 -1
- package/dist/es5/netcdfjs/netcdf-reader.js +97 -155
- package/dist/es5/netcdfjs/netcdf-reader.js.map +1 -1
- package/dist/es5/netcdfjs/read-data.js +12 -12
- package/dist/es5/netcdfjs/read-data.js.map +1 -1
- package/dist/es5/netcdfjs/read-header.js +58 -58
- package/dist/es5/netcdfjs/read-header.js.map +1 -1
- package/dist/es5/netcdfjs/read-type.js +3 -3
- package/dist/es5/netcdfjs/read-type.js.map +1 -1
- package/dist/esm/netcdf-loader.js +1 -1
- package/dist/esm/netcdf-loader.js.map +1 -1
- package/dist/esm/netcdfjs/netcdf-reader.js +7 -7
- package/dist/esm/netcdfjs/netcdf-reader.js.map +1 -1
- package/dist/esm/netcdfjs/read-header.js +2 -2
- package/dist/esm/netcdfjs/read-header.js.map +1 -1
- package/dist/esm/netcdfjs/read-type.js +1 -1
- package/dist/esm/netcdfjs/read-type.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/iobuffer/iobuffer.d.ts +254 -0
- package/dist/iobuffer/iobuffer.d.ts.map +1 -0
- package/dist/iobuffer/iobuffer.js +427 -0
- package/dist/netcdf-loader.d.ts +52 -0
- package/dist/netcdf-loader.d.ts.map +1 -0
- package/dist/netcdf-loader.js +52 -0
- package/dist/netcdfjs/netcdf-reader.d.ts +68 -0
- package/dist/netcdfjs/netcdf-reader.d.ts.map +1 -0
- package/dist/netcdfjs/netcdf-reader.js +165 -0
- package/dist/netcdfjs/netcdf-types.d.ts +70 -0
- package/dist/netcdfjs/netcdf-types.d.ts.map +1 -0
- package/dist/netcdfjs/netcdf-types.js +2 -0
- package/dist/netcdfjs/read-data.d.ts +18 -0
- package/dist/netcdfjs/read-data.d.ts.map +1 -0
- package/dist/netcdfjs/read-data.js +49 -0
- package/dist/netcdfjs/read-header.d.ts +16 -0
- package/dist/netcdfjs/read-header.d.ts.map +1 -0
- package/dist/netcdfjs/read-header.js +230 -0
- package/dist/netcdfjs/read-type.d.ts +36 -0
- package/dist/netcdfjs/read-type.d.ts.map +1 -0
- package/dist/netcdfjs/read-type.js +140 -0
- package/package.json +7 -8
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NetCDFReader = void 0;
|
|
4
|
+
const iobuffer_1 = require("../iobuffer/iobuffer");
|
|
5
|
+
const read_header_1 = require("./read-header");
|
|
6
|
+
const read_data_1 = require("./read-data");
|
|
7
|
+
/**
|
|
8
|
+
* Reads a NetCDF v3.x file
|
|
9
|
+
* https://www.unidata.ucar.edu/software/netcdf/docs/file_format_specifications.html
|
|
10
|
+
* @param {ArrayBuffer} data - ArrayBuffer or any Typed Array (including Node.js' Buffer from v4) with the data
|
|
11
|
+
* @constructor
|
|
12
|
+
*/
|
|
13
|
+
class NetCDFReader {
|
|
14
|
+
constructor(data) {
|
|
15
|
+
const buffer = new iobuffer_1.IOBuffer(data);
|
|
16
|
+
buffer.setBigEndian();
|
|
17
|
+
// Validate that it's a NetCDF file
|
|
18
|
+
const magic = buffer.readChars(3);
|
|
19
|
+
if (magic !== 'CDF') {
|
|
20
|
+
throw new Error(`NetCDF: file should start with 'CDF', found ${magic}`);
|
|
21
|
+
}
|
|
22
|
+
// Check the NetCDF format
|
|
23
|
+
const version = buffer.readByte();
|
|
24
|
+
if (version > 2) {
|
|
25
|
+
throw new Error(`NetCDF: unsupported version ${version}`);
|
|
26
|
+
}
|
|
27
|
+
// Read the header
|
|
28
|
+
this.header = (0, read_header_1.readNetCDFHeader)(buffer, version);
|
|
29
|
+
this.buffer = buffer;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* @return {string} - Version for the NetCDF format
|
|
33
|
+
*/
|
|
34
|
+
get version() {
|
|
35
|
+
if (this.header.version === 1) {
|
|
36
|
+
return 'classic format';
|
|
37
|
+
}
|
|
38
|
+
return '64-bit offset format';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get metadata for the record dimension
|
|
42
|
+
*/
|
|
43
|
+
get recordDimension() {
|
|
44
|
+
return this.header.recordDimension;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get list of dimensions (each with `name` and `size`)
|
|
48
|
+
*/
|
|
49
|
+
get dimensions() {
|
|
50
|
+
return this.header.dimensions;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get list of global attributes with:
|
|
54
|
+
* * `name`: String with the name of the attribute
|
|
55
|
+
* * `type`: String with the type of the attribute
|
|
56
|
+
* * `value`: A number or string with the value of the attribute
|
|
57
|
+
*/
|
|
58
|
+
get attributes() {
|
|
59
|
+
return this.header.attributes;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get list of variables
|
|
63
|
+
*/
|
|
64
|
+
get variables() {
|
|
65
|
+
return this.header.variables;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Check if an attribute exists
|
|
69
|
+
* @param attributeName - Name of the attribute to find
|
|
70
|
+
* @return
|
|
71
|
+
*/
|
|
72
|
+
attributeExists(attributeName) {
|
|
73
|
+
const attribute = this.attributes.find((val) => val.name === attributeName);
|
|
74
|
+
return attribute !== undefined;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Returns the value of an attribute
|
|
78
|
+
* @param attributeName
|
|
79
|
+
* @return Value of the attributeName or null
|
|
80
|
+
*/
|
|
81
|
+
getAttribute(attributeName) {
|
|
82
|
+
const attribute = this.attributes.find((val) => val.name === attributeName);
|
|
83
|
+
if (attribute)
|
|
84
|
+
return attribute.value;
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if a dataVariable exists
|
|
89
|
+
* @param variableName - Name of the variable to find
|
|
90
|
+
* @return
|
|
91
|
+
*/
|
|
92
|
+
dataVariableExists(variableName) {
|
|
93
|
+
const variable = this.header.variables.find(function (val) {
|
|
94
|
+
return val.name === variableName;
|
|
95
|
+
});
|
|
96
|
+
return variable !== undefined;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Returns the value of a variable as a string
|
|
100
|
+
* @param variableName
|
|
101
|
+
* @return Value of the variable as a string or null
|
|
102
|
+
*/
|
|
103
|
+
getDataVariableAsString(variableName) {
|
|
104
|
+
const variable = this.getDataVariable(variableName);
|
|
105
|
+
if (variable)
|
|
106
|
+
return variable.join('');
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Retrieves the data for a given variable
|
|
111
|
+
* @param variableName - Name of the variable to search or variable object
|
|
112
|
+
* @return List with the variable values
|
|
113
|
+
*/
|
|
114
|
+
getDataVariable(variableName) {
|
|
115
|
+
let variable;
|
|
116
|
+
if (typeof variableName === 'string') {
|
|
117
|
+
// search the variable
|
|
118
|
+
variable = this.header.variables.find(function (val) {
|
|
119
|
+
return val.name === variableName;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
variable = variableName;
|
|
124
|
+
}
|
|
125
|
+
// throws if variable not found
|
|
126
|
+
if (variable === undefined) {
|
|
127
|
+
throw new Error(`NetCDF: variable not found: ${variableName}`);
|
|
128
|
+
}
|
|
129
|
+
// go to the offset position
|
|
130
|
+
this.buffer.seek(variable.offset);
|
|
131
|
+
if (variable.record) {
|
|
132
|
+
// record variable case
|
|
133
|
+
return (0, read_data_1.readRecord)(this.buffer, variable, this.header.recordDimension);
|
|
134
|
+
}
|
|
135
|
+
// non-record variable case
|
|
136
|
+
return (0, read_data_1.readNonRecord)(this.buffer, variable);
|
|
137
|
+
}
|
|
138
|
+
toString() {
|
|
139
|
+
const result = [];
|
|
140
|
+
result.push('DIMENSIONS');
|
|
141
|
+
for (const dimension of this.dimensions) {
|
|
142
|
+
result.push(` ${dimension.name.padEnd(30)} = size: ${dimension.size}`);
|
|
143
|
+
}
|
|
144
|
+
result.push('');
|
|
145
|
+
result.push('GLOBAL ATTRIBUTES');
|
|
146
|
+
for (const attribute of this.attributes) {
|
|
147
|
+
result.push(` ${attribute.name.padEnd(30)} = ${attribute.value}`);
|
|
148
|
+
}
|
|
149
|
+
const variables = JSON.parse(JSON.stringify(this.variables));
|
|
150
|
+
result.push('');
|
|
151
|
+
result.push('VARIABLES:');
|
|
152
|
+
for (const variable of variables) {
|
|
153
|
+
variable.value = this.getDataVariable(variable);
|
|
154
|
+
let stringify = JSON.stringify(variable.value);
|
|
155
|
+
if (stringify.length > 50)
|
|
156
|
+
stringify = stringify.substring(0, 50);
|
|
157
|
+
if (!isNaN(variable.value.length)) {
|
|
158
|
+
stringify += ` (length: ${variable.value.length})`;
|
|
159
|
+
}
|
|
160
|
+
result.push(` ${variable.name.padEnd(30)} = ${stringify}`);
|
|
161
|
+
}
|
|
162
|
+
return result.join('\n');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
exports.NetCDFReader = NetCDFReader;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Header describing a NetDCF file
|
|
3
|
+
* @param recordDimension: Number with the length of record dimension
|
|
4
|
+
* @param dimensions: List of dimensions
|
|
5
|
+
* @param attributes: List of global attributes
|
|
6
|
+
* @param variables: List of variables
|
|
7
|
+
*/
|
|
8
|
+
export declare type NetCDFHeader = {
|
|
9
|
+
version: number;
|
|
10
|
+
recordDimension: NetCDFRecordDimension;
|
|
11
|
+
dimensions: NetCDFDimension[];
|
|
12
|
+
attributes: NetCDFAttribute[];
|
|
13
|
+
variables: NetCDFVariable[];
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Metadata for the record dimension
|
|
17
|
+
* @param length Number of elements in the record dimension
|
|
18
|
+
* @param id Id in the list of dimensions for the record dimension
|
|
19
|
+
* @param name name of the record dimension
|
|
20
|
+
* @param recordStep the record variables step size
|
|
21
|
+
*/
|
|
22
|
+
export declare type NetCDFRecordDimension = {
|
|
23
|
+
length: number;
|
|
24
|
+
id: number;
|
|
25
|
+
name: string;
|
|
26
|
+
recordStep: number;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* `dimensions` is an array of dimension objects:
|
|
30
|
+
* @param name name of the dimension
|
|
31
|
+
* @param size size of the dimension
|
|
32
|
+
* @param recordId: id of the dimension that has unlimited size or undefined,
|
|
33
|
+
* @param recordName: name of the dimension that has unlimited size
|
|
34
|
+
*/
|
|
35
|
+
export declare type NetCDFDimension = {
|
|
36
|
+
name: string;
|
|
37
|
+
size: number;
|
|
38
|
+
recordId: number;
|
|
39
|
+
recordName: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Number of recordStep and list of variables with:
|
|
43
|
+
* @param name String with the name of the variable
|
|
44
|
+
* @param dimensions Array with the dimension IDs of the variable
|
|
45
|
+
* @param attributes Array with the attributes of the variable
|
|
46
|
+
* @param type String with the type of the variable
|
|
47
|
+
* @param size Number with the size of the variable
|
|
48
|
+
* @param offset Number with the offset where of the variable begins
|
|
49
|
+
* @param record True if is a record variable, false otherwise (unlimited size)
|
|
50
|
+
*/
|
|
51
|
+
export declare type NetCDFVariable = {
|
|
52
|
+
name: string;
|
|
53
|
+
dimensions: [];
|
|
54
|
+
attributes: [];
|
|
55
|
+
type: string;
|
|
56
|
+
size: number;
|
|
57
|
+
offset: number;
|
|
58
|
+
record: boolean;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* @param name name of the attribute
|
|
62
|
+
* @param type type of the attribute
|
|
63
|
+
* @param value number or string with the value of the attribute
|
|
64
|
+
*/
|
|
65
|
+
export declare type NetCDFAttribute = {
|
|
66
|
+
name: string;
|
|
67
|
+
type: string;
|
|
68
|
+
value: string;
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=netcdf-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"netcdf-types.d.ts","sourceRoot":"","sources":["../../src/netcdfjs/netcdf-types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,oBAAY,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,qBAAqB,CAAC;IACvC,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B,CAAC;AAEF;;;;;;GAMG;AACH,oBAAY,qBAAqB,GAAG;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;;;GAMG;AACH,oBAAY,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;;;;;;GASG;AACH,oBAAY,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,EAAE,CAAC;IACf,UAAU,EAAE,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF;;;;GAIG;AACH,oBAAY,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { IOBuffer } from '../iobuffer/iobuffer';
|
|
2
|
+
import type { NetCDFRecordDimension, NetCDFVariable } from './netcdf-types';
|
|
3
|
+
/**
|
|
4
|
+
* Read data for the given non-record variable
|
|
5
|
+
* @param buffer - Buffer for the file data
|
|
6
|
+
* @param variable - Variable metadata
|
|
7
|
+
* @return Data of the element
|
|
8
|
+
*/
|
|
9
|
+
export declare function readNonRecord(buffer: IOBuffer, variable: NetCDFVariable): (string | number | number[] | Uint8Array)[];
|
|
10
|
+
/**
|
|
11
|
+
* Read data for the given record variable
|
|
12
|
+
* @param buffer - Buffer for the file data
|
|
13
|
+
* @param variable - Variable metadata
|
|
14
|
+
* @param recordDimension - Record dimension metadata
|
|
15
|
+
* @return - Data of the element
|
|
16
|
+
*/
|
|
17
|
+
export declare function readRecord(buffer: IOBuffer, variable: NetCDFVariable, recordDimension: NetCDFRecordDimension): (string | number | number[] | Uint8Array)[];
|
|
18
|
+
//# sourceMappingURL=read-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-data.d.ts","sourceRoot":"","sources":["../../src/netcdfjs/read-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAC,qBAAqB,EAAE,cAAc,EAAC,MAAM,gBAAgB,CAAC;AAK1E;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,QAAQ,EAChB,QAAQ,EAAE,cAAc,GACvB,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,UAAU,CAAC,EAAE,CAc7C;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,QAAQ,EAChB,QAAQ,EAAE,cAAc,EACxB,eAAe,EAAE,qBAAqB,GACrC,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,UAAU,CAAC,EAAE,CAoB7C"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readRecord = exports.readNonRecord = void 0;
|
|
4
|
+
const read_type_1 = require("./read-type");
|
|
5
|
+
// const STREAMING = 4294967295;
|
|
6
|
+
/**
|
|
7
|
+
* Read data for the given non-record variable
|
|
8
|
+
* @param buffer - Buffer for the file data
|
|
9
|
+
* @param variable - Variable metadata
|
|
10
|
+
* @return Data of the element
|
|
11
|
+
*/
|
|
12
|
+
function readNonRecord(buffer, variable) {
|
|
13
|
+
// variable type
|
|
14
|
+
const type = (0, read_type_1.str2num)(variable.type);
|
|
15
|
+
// size of the data
|
|
16
|
+
const size = variable.size / (0, read_type_1.num2bytes)(type);
|
|
17
|
+
// iterates over the data
|
|
18
|
+
const data = new Array(size);
|
|
19
|
+
for (let i = 0; i < size; i++) {
|
|
20
|
+
data[i] = (0, read_type_1.readType)(buffer, type, 1);
|
|
21
|
+
}
|
|
22
|
+
return data;
|
|
23
|
+
}
|
|
24
|
+
exports.readNonRecord = readNonRecord;
|
|
25
|
+
/**
|
|
26
|
+
* Read data for the given record variable
|
|
27
|
+
* @param buffer - Buffer for the file data
|
|
28
|
+
* @param variable - Variable metadata
|
|
29
|
+
* @param recordDimension - Record dimension metadata
|
|
30
|
+
* @return - Data of the element
|
|
31
|
+
*/
|
|
32
|
+
function readRecord(buffer, variable, recordDimension) {
|
|
33
|
+
// variable type
|
|
34
|
+
const type = (0, read_type_1.str2num)(variable.type);
|
|
35
|
+
const width = variable.size ? variable.size / (0, read_type_1.num2bytes)(type) : 1;
|
|
36
|
+
// size of the data
|
|
37
|
+
// TODO streaming data
|
|
38
|
+
const size = recordDimension.length;
|
|
39
|
+
// iterates over the data
|
|
40
|
+
const data = new Array(size);
|
|
41
|
+
const step = recordDimension.recordStep;
|
|
42
|
+
for (let i = 0; i < size; i++) {
|
|
43
|
+
const currentOffset = buffer.offset;
|
|
44
|
+
data[i] = (0, read_type_1.readType)(buffer, type, width);
|
|
45
|
+
buffer.seek(currentOffset + step);
|
|
46
|
+
}
|
|
47
|
+
return data;
|
|
48
|
+
}
|
|
49
|
+
exports.readRecord = readRecord;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IOBuffer } from '../iobuffer/iobuffer';
|
|
2
|
+
import type { NetCDFHeader } from './netcdf-types';
|
|
3
|
+
/**
|
|
4
|
+
* Read the header of the file
|
|
5
|
+
* @param buffer - Buffer for the file data
|
|
6
|
+
* @param version - Version of the file
|
|
7
|
+
* @return - Header
|
|
8
|
+
*/
|
|
9
|
+
export declare function readNetCDFHeader(buffer: IOBuffer, version: number): NetCDFHeader;
|
|
10
|
+
/**
|
|
11
|
+
* Reads the name
|
|
12
|
+
* @param buffer - Buffer for the file data
|
|
13
|
+
* @return Name
|
|
14
|
+
*/
|
|
15
|
+
export declare function readName(buffer: IOBuffer): string;
|
|
16
|
+
//# sourceMappingURL=read-header.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-header.d.ts","sourceRoot":"","sources":["../../src/netcdfjs/read-header.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAC,YAAY,EAAmD,MAAM,gBAAgB,CAAC;AAWnG;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,CA4BhF;AA2MD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAWjD"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readName = exports.readNetCDFHeader = void 0;
|
|
4
|
+
const read_type_1 = require("./read-type");
|
|
5
|
+
// Grammar constants
|
|
6
|
+
const ZERO = 0;
|
|
7
|
+
const NC_DIMENSION = 10;
|
|
8
|
+
const NC_VARIABLE = 11;
|
|
9
|
+
const NC_ATTRIBUTE = 12;
|
|
10
|
+
const NC_UNLIMITED = 0;
|
|
11
|
+
/**
|
|
12
|
+
* Read the header of the file
|
|
13
|
+
* @param buffer - Buffer for the file data
|
|
14
|
+
* @param version - Version of the file
|
|
15
|
+
* @return - Header
|
|
16
|
+
*/
|
|
17
|
+
function readNetCDFHeader(buffer, version) {
|
|
18
|
+
// Length of record dimension
|
|
19
|
+
// sum of the varSize's of all the record variables.
|
|
20
|
+
const recordDimensionLength = buffer.readUint32();
|
|
21
|
+
// List of dimensions
|
|
22
|
+
const dimList = readDimensionsList(buffer);
|
|
23
|
+
// List of global attributes
|
|
24
|
+
const attributes = readAttributesList(buffer);
|
|
25
|
+
// List of variables
|
|
26
|
+
const variableList = readVariablesList(buffer, dimList.recordId, version);
|
|
27
|
+
const header = {
|
|
28
|
+
version,
|
|
29
|
+
recordDimension: {
|
|
30
|
+
length: recordDimensionLength,
|
|
31
|
+
id: dimList.recordId,
|
|
32
|
+
name: dimList.recordName,
|
|
33
|
+
recordStep: variableList.recordStep
|
|
34
|
+
},
|
|
35
|
+
dimensions: dimList.dimensions,
|
|
36
|
+
variables: variableList.variables,
|
|
37
|
+
attributes
|
|
38
|
+
};
|
|
39
|
+
return header;
|
|
40
|
+
}
|
|
41
|
+
exports.readNetCDFHeader = readNetCDFHeader;
|
|
42
|
+
/**
|
|
43
|
+
* Read list of dimensions
|
|
44
|
+
* @ignore
|
|
45
|
+
* @param {IOBuffer} buffer - Buffer for the file data
|
|
46
|
+
*/
|
|
47
|
+
function readDimensionsList(buffer) {
|
|
48
|
+
const dimList = buffer.readUint32();
|
|
49
|
+
if (dimList === ZERO) {
|
|
50
|
+
if (buffer.readUint32() !== ZERO) {
|
|
51
|
+
throw new Error('NetCDF: wrong empty tag for list of dimensions');
|
|
52
|
+
}
|
|
53
|
+
// TODO - is this empty dimension list supported / recoverable?
|
|
54
|
+
return {
|
|
55
|
+
recordId: 0,
|
|
56
|
+
recordName: '',
|
|
57
|
+
dimensions: []
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (dimList !== NC_DIMENSION) {
|
|
61
|
+
throw new Error('NetCDF: wrong tag for list of dimensions');
|
|
62
|
+
}
|
|
63
|
+
// Length of dimensions
|
|
64
|
+
const dimensionSize = buffer.readUint32();
|
|
65
|
+
const dimensions = new Array(dimensionSize);
|
|
66
|
+
let recordId;
|
|
67
|
+
let recordName;
|
|
68
|
+
for (let dim = 0; dim < dimensionSize; dim++) {
|
|
69
|
+
// Read name
|
|
70
|
+
const name = readName(buffer);
|
|
71
|
+
// Read dimension size
|
|
72
|
+
const size = buffer.readUint32();
|
|
73
|
+
if (size === NC_UNLIMITED) {
|
|
74
|
+
// in netcdf 3 one field can be of size unlimmited
|
|
75
|
+
recordId = dim;
|
|
76
|
+
recordName = name;
|
|
77
|
+
}
|
|
78
|
+
dimensions[dim] = {
|
|
79
|
+
name,
|
|
80
|
+
size
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
dimensions,
|
|
85
|
+
recordId,
|
|
86
|
+
recordName
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* List of attributes
|
|
91
|
+
* @ignore
|
|
92
|
+
* @param buffer - Buffer for the file data
|
|
93
|
+
* @return List of attributes with:
|
|
94
|
+
*/
|
|
95
|
+
function readAttributesList(buffer) {
|
|
96
|
+
const gAttList = buffer.readUint32();
|
|
97
|
+
if (gAttList === ZERO) {
|
|
98
|
+
if (buffer.readUint32() !== ZERO) {
|
|
99
|
+
throw new Error('NetCDF: wrong empty tag for list of attributes');
|
|
100
|
+
}
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
if (gAttList !== NC_ATTRIBUTE) {
|
|
104
|
+
throw new Error('NetCDF: wrong tag for list of attributes');
|
|
105
|
+
}
|
|
106
|
+
// Length of attributes
|
|
107
|
+
const attributeSize = buffer.readUint32();
|
|
108
|
+
const attributes = new Array(attributeSize);
|
|
109
|
+
for (let gAtt = 0; gAtt < attributeSize; gAtt++) {
|
|
110
|
+
// Read name
|
|
111
|
+
const name = readName(buffer);
|
|
112
|
+
// Read type
|
|
113
|
+
const type = buffer.readUint32();
|
|
114
|
+
if (type < 1 || type > 6) {
|
|
115
|
+
throw new Error(`NetCDF: non valid type ${type}`);
|
|
116
|
+
}
|
|
117
|
+
// Read attribute
|
|
118
|
+
const size = buffer.readUint32();
|
|
119
|
+
const value = (0, read_type_1.readType)(buffer, type, size);
|
|
120
|
+
// Apply padding
|
|
121
|
+
padding(buffer);
|
|
122
|
+
attributes[gAtt] = {
|
|
123
|
+
name,
|
|
124
|
+
type: (0, read_type_1.num2str)(type),
|
|
125
|
+
value
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return attributes;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* List of variables
|
|
132
|
+
* @param buffer - Buffer for the file data
|
|
133
|
+
* @param recordId - Id of the unlimited dimension (also called record dimension)
|
|
134
|
+
* This value may be undefined if there is no unlimited dimension
|
|
135
|
+
* @param {number} version - Version of the file
|
|
136
|
+
*/
|
|
137
|
+
// eslint-disable-next-line max-statements, complexity
|
|
138
|
+
function readVariablesList(buffer, recordId, version) {
|
|
139
|
+
const varList = buffer.readUint32();
|
|
140
|
+
let recordStep = 0;
|
|
141
|
+
if (varList === ZERO) {
|
|
142
|
+
if (buffer.readUint32() !== ZERO) {
|
|
143
|
+
throw new Error('NetCDF: wrong empty tag for list of variables');
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
recordStep,
|
|
147
|
+
variables: []
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
if (varList !== NC_VARIABLE) {
|
|
151
|
+
throw new Error('NetCDF: wrong tag for list of variables');
|
|
152
|
+
}
|
|
153
|
+
// Length of variables
|
|
154
|
+
const variableSize = buffer.readUint32();
|
|
155
|
+
const variables = new Array(variableSize);
|
|
156
|
+
for (let v = 0; v < variableSize; v++) {
|
|
157
|
+
// Read name
|
|
158
|
+
const name = readName(buffer);
|
|
159
|
+
// Read dimensionality of the variable
|
|
160
|
+
const dimensionality = buffer.readUint32();
|
|
161
|
+
// Index into the list of dimensions
|
|
162
|
+
const dimensionsIds = new Array(dimensionality);
|
|
163
|
+
for (let dim = 0; dim < dimensionality; dim++) {
|
|
164
|
+
dimensionsIds[dim] = buffer.readUint32();
|
|
165
|
+
}
|
|
166
|
+
// Read variables size
|
|
167
|
+
const attributes = readAttributesList(buffer);
|
|
168
|
+
// Read type
|
|
169
|
+
const type = buffer.readUint32();
|
|
170
|
+
if (type < 1 && type > 6) {
|
|
171
|
+
throw new Error(`NetCDF: non valid type ${type}`);
|
|
172
|
+
}
|
|
173
|
+
// Read variable size
|
|
174
|
+
// The 32-bit varSize field is not large enough to contain the size of variables that require
|
|
175
|
+
// more than 2^32 - 4 bytes, so 2^32 - 1 is used in the varSize field for such variables.
|
|
176
|
+
const varSize = buffer.readUint32();
|
|
177
|
+
// Read offset
|
|
178
|
+
let offset = buffer.readUint32();
|
|
179
|
+
if (version === 2) {
|
|
180
|
+
if (offset > 0) {
|
|
181
|
+
throw new Error('NetCDF: offsets larger than 4GB not supported');
|
|
182
|
+
}
|
|
183
|
+
offset = buffer.readUint32();
|
|
184
|
+
}
|
|
185
|
+
let record = false;
|
|
186
|
+
// Count amount of record variables
|
|
187
|
+
if (typeof recordId !== 'undefined' && dimensionsIds[0] === recordId) {
|
|
188
|
+
recordStep += varSize;
|
|
189
|
+
record = true;
|
|
190
|
+
}
|
|
191
|
+
variables[v] = {
|
|
192
|
+
name,
|
|
193
|
+
dimensions: dimensionsIds,
|
|
194
|
+
attributes,
|
|
195
|
+
type: (0, read_type_1.num2str)(type),
|
|
196
|
+
size: varSize,
|
|
197
|
+
offset,
|
|
198
|
+
record
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
variables,
|
|
203
|
+
recordStep
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
// HELPERS
|
|
207
|
+
/**
|
|
208
|
+
* Reads the name
|
|
209
|
+
* @param buffer - Buffer for the file data
|
|
210
|
+
* @return Name
|
|
211
|
+
*/
|
|
212
|
+
function readName(buffer) {
|
|
213
|
+
// Read name
|
|
214
|
+
const nameLength = buffer.readUint32();
|
|
215
|
+
const name = buffer.readChars(nameLength);
|
|
216
|
+
// validate name
|
|
217
|
+
// TODO
|
|
218
|
+
// Apply padding
|
|
219
|
+
padding(buffer);
|
|
220
|
+
return name;
|
|
221
|
+
}
|
|
222
|
+
exports.readName = readName;
|
|
223
|
+
/**
|
|
224
|
+
* Moves 1, 2, or 3 bytes to next 4-byte boundary
|
|
225
|
+
*/
|
|
226
|
+
function padding(buffer) {
|
|
227
|
+
if (buffer.offset % 4 !== 0) {
|
|
228
|
+
buffer.skip(4 - (buffer.offset % 4));
|
|
229
|
+
}
|
|
230
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { IOBuffer } from '../iobuffer/iobuffer';
|
|
2
|
+
export declare const TYPES: {
|
|
3
|
+
BYTE: number;
|
|
4
|
+
CHAR: number;
|
|
5
|
+
SHORT: number;
|
|
6
|
+
INT: number;
|
|
7
|
+
FLOAT: number;
|
|
8
|
+
DOUBLE: number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Given a type and a size reads the next element
|
|
12
|
+
* @param buffer - Buffer for the file data
|
|
13
|
+
* @param type - Type of the data to read
|
|
14
|
+
* @param size - Size of the element to read
|
|
15
|
+
* @return
|
|
16
|
+
*/
|
|
17
|
+
export declare function readType(buffer: IOBuffer, type: number, size: number): string | number | number[] | Uint8Array;
|
|
18
|
+
/**
|
|
19
|
+
* Parse a number into their respective type
|
|
20
|
+
* @param type - integer that represents the type
|
|
21
|
+
* @return parsed value of the type
|
|
22
|
+
*/
|
|
23
|
+
export declare function num2str(type: number): string;
|
|
24
|
+
/**
|
|
25
|
+
* Parse a number type identifier to his size in bytes
|
|
26
|
+
* @param type - integer that represents the type
|
|
27
|
+
* @return size of the type
|
|
28
|
+
*/
|
|
29
|
+
export declare function num2bytes(type: number): number;
|
|
30
|
+
/**
|
|
31
|
+
* Reverse search of num2str
|
|
32
|
+
* @param type string that represents the type
|
|
33
|
+
* @return parsed value of the type
|
|
34
|
+
*/
|
|
35
|
+
export declare function str2num(type: string): number;
|
|
36
|
+
//# sourceMappingURL=read-type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-type.d.ts","sourceRoot":"","sources":["../../src/netcdfjs/read-type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AAE9C,eAAO,MAAM,KAAK;;;;;;;CAOjB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,QAAQ,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,UAAU,CAkBzC;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkB5C;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkB9C;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkB5C"}
|