NetCDF = {
class NetCDF extends netcdf {
constructor(buf) {
super(buf);
}
notFound(type, name) {
throw new Error(`Not found: ${type} ${name}`);
}
getVariableMetadata(varName) {
return (
this.variables.find(v => v.name === varName) ||
this.notFound('variable', varName)
);
}
getVariableAttributes(varName) {
return this.getVariableMetadata(varName).attributes;
}
getVariableAttribute(varName, attrName) {
return (
this.getVariableMetadata(varName).find(a => a.name === attrName) ||
this.notFound(`${varName} attribute`, attrName)
);
}
getVariableAttributesNames(varName) {
return this.getVariableMetadata(varName).attributes.map(n => n.name);
}
getVariableNames() {
return this.variables.map(v => v.name);
}
dataIterator(fn, size, start, end, step = 1) {
const gen = this.gen_dataIterator(fn, size, start, end, step);
gen[Symbol.iterator] = () => gen;
gen.map = f => {
const r = [];
let i = 0;
for (const v of gen) {
r[i] = f(v, i);
i++;
}
return r;
};
gen.foreach = f => {
let i = 0;
for (const v of gen) {
f(v, i++);
}
};
return gen;
}
*gen_dataIterator(fn, size, start, end, step = 1) {
if (step == 0) throw new Error("Illegal step size");
end = Math.min(size, end === undefined ? start + step : end);
start = Math.max(0, start);
if (step > 0) {
for (let i = start; i < end; i += step) {
yield fn(i);
}
} else {
for (let i = start; i > end; i += step) {
yield fn(i);
}
}
}
getDataVariableView(varName, forceType) {
const meta = this.getVariableMetadata(varName);
const { offset, dimensions: vdims, type, stride, size: varSize } = meta;
const dimensions = this.header.dimensions;
const {
recordStep,
id: recordId,
length: recordCount
} = this.header.recordDimension;
const { access, size } = TYPES[forceType || type] || [];
if (!access) {
throw new Error(`Unknown type: ${forceType || type}`);
}
if (vdims.length === 0) {
// Scalar
const dv = new DataView(this.buffer.buffer, offset, size);
return v => access(dv, 0)(0, v);
}
const calc_stride = dim =>
dim === vdims.length - 1
? vdims[dim] === recordId
? recordStep
: size
: dimensions[vdims[dim]].size * calc_stride(dim + 1);
const strd =
stride || (meta.stride = vdims.map((d, i) => calc_stride(i)));
const iter1Record = (pos, dim) => {
const stride = strd[dim];
if (dim === vdims.length - 1) {
const dv = new DataView(this.buffer.buffer, offset + pos, varSize);
return j =>
j === undefined
? dv
: j instanceof Array
? this.dataIterator(
access(dv, pos),
dimensions[vdims[dim]].size,
...j
)
: access(dv, pos);
} else {
return j =>
j instanceof Array
? this.dataIterator(
i => iter1Record(pos + stride * i, dim + 1),
dimensions[vdims[dim]].size,
...j
)
: iter1Record(pos + stride * j, dim + 1);
}
};
return iter1Record(0, 0);
}
}
return NetCDF;
}