UNPKG

gis-tools-ts

Version:

A collection of geospatial tools primarily designed for WGS84, Web Mercator, and S2.

165 lines 6.41 kB
/** * Unpack a data field that was packed using a simple packing algorithm, using info from the GRIB2 * Data Representation Template 5.0. * @param reader - The raw data to convert * @param drs - The data representation section * @returns - The converted data */ export function spectralSimpleUnpacking(reader, drs) { const { dataRepresentation, numberOfDataPoints: ndpts } = drs; const { numberOfBits: nbits, decimalScaleFactor, referenceValue: ref, binaryScaleFactor, } = dataRepresentation; const dscale = Math.pow(10, decimalScaleFactor); const bscale = Math.pow(2, binaryScaleFactor); const res = new Array(ndpts); // If nbits equals 0, we have a constant field where the reference value is the data value at // each gridpoint. if (nbits !== 0) { const ifld = gbits(reader, 0, nbits, 0, ndpts); for (let j = 0; j < ndpts; j++) res[j] = (ifld[j] * bscale + ref) * dscale; } else { for (let j = 0; j < ndpts; j++) res[j] = ref; } return res; } /** * @param reader - The raw data to convert * @param drs - The data representation section * @returns - The unpacked values */ export function spectralComplexUnpacking(reader, drs) { // igdstmpl[0], igdstmpl[2], igdstmpl[2] const { dataRepresentation, numberOfDataPoints: ndpts } = drs; const { numberOfBits: nbits, decimalScaleFactor, referenceValue: ref, binaryScaleFactor, precision, Js, Ks, Ms, Ts, P, } = dataRepresentation; const dscale = Math.pow(10, decimalScaleFactor); const bscale = Math.pow(2, binaryScaleFactor); const JJ = ref; const KK = decimalScaleFactor; const MM = decimalScaleFactor; const res = new Array(ndpts); if (precision.code === 1) { /* unpacked floats are 32-bit IEEE */ let ifld = gbits(reader, 0, 32, 0, Ts); const iofst = 32 * Ts; const unpk = rdieee(ifld, Ts); /* read IEEE unpacked floats */ ifld = gbits(reader, iofst, nbits, 0, ndpts - Ts); /* unpack scaled data */ // Calculate Laplacian scaling factors for each possible wave number. const pscale = new Array(JJ + MM + 1); const tscale = P * 1e-6; for (let n = Js; n <= JJ + MM; n++) pscale[n] = Math.pow(n * (n + 1), -tscale); /* Assemble spectral coeffs back to original order. */ let inc = 0; let incu = 0; let incp = 0; for (let m = 0; m <= MM; m++) { let Nm = JJ; /* triangular or trapezoidal */ if (KK === JJ + MM) Nm = JJ + m; /* rhombodial */ let Ns = Js; /* triangular or trapezoidal */ if (Ks === Js + Ms) Ns = Js + m; /* rhombodial */ for (let n = m; n <= Nm; n++) { if (n <= Ns && m <= Ms) { /* grab unpacked value */ res[inc++] = unpk[incu++]; /* real part */ res[inc++] = unpk[incu++]; /* imaginary part */ } else { /* Calc coeff from packed value */ res[inc++] = (ifld[incp++] * bscale + ref) * dscale * pscale[n]; /* real part */ res[inc++] = (ifld[incp++] * bscale + ref) * dscale * pscale[n]; /* imaginary part */ } } } } return res; } /** * Unpack arbitrary size values from a packed bit string, right * justifying each value in the unpacked iout array. * @author NOAA Programmer * @param reader - Pointer to character array input. * @param iskip - Initial number of bits to skip. * @param nbits - Number of bits to take. * @param nskip - Additional number of bits to skip on each iteration. * @param n - Number of iterations. * @returns - The unpacked values */ function gbits(reader, iskip, nbits, nskip, n) { const res = []; let i, tbit, bitcnt, ibit, itmp; let nbit, index; const ones = [1, 3, 7, 15, 31, 63, 127, 255]; /* nbit is the start position of the field in bits */ nbit = iskip; for (i = 0; i < n; i++) { bitcnt = nbits; index = nbit / 8; ibit = nbit % 8; nbit = nbit + nbits + nskip; /* first byte */ tbit = bitcnt < 8 - ibit ? bitcnt : 8 - ibit; // find min itmp = reader.getInt8(index) & ones[7 - ibit]; if (tbit !== 8 - ibit) itmp >>= 8 - ibit - tbit; index++; bitcnt = bitcnt - tbit; /* now transfer whole bytes */ while (bitcnt >= 8) { itmp = (itmp << 8) | reader.getInt8(index); bitcnt = bitcnt - 8; index++; } /* get data from last byte */ if (bitcnt > 0) { itmp = (itmp << bitcnt) | ((reader.getInt8(index) >> (8 - bitcnt)) & ones[bitcnt - 1]); } res[i] = itmp; } return res; } /** * Read a list of real values in 32-bit IEEE floating point format. * @author Stephen Gilbert * date 2002-10-25 * @param rieee - g2int array of floating point values in 32-bit IEEE * format. * @param num Number of floating point values to convert. * @returns - The unpacked values */ function rdieee(rieee, num) { const res = []; let isign, iexp, imant, sign, temp; const two23 = 1.1920928955078125e-7; // Math.pow(2.0, -23); const two126 = 1.1754943508222875e-38; // Math.pow(2.0, -126); const msk1 = 0x80000000; /* 10000000000000000000000000000000 binary */ const msk2 = 0x7f800000; /* 01111111100000000000000000000000 binary */ const msk3 = 0x007fffff; /* 00000000011111111111111111111111 binary */ for (let j = 0; j < num; j++) { /* Extract sign bit, exponent, and mantissa */ isign = (rieee[j] & msk1) >> 31; iexp = (rieee[j] & msk2) >> 23; imant = rieee[j] & msk3; /*printf("SAGieee= %ld %ld %ld\n",isign,iexp,imant); */ sign = 1.0; if (isign === 1) sign = -1.0; if (iexp > 0 && iexp < 255) { temp = Math.pow(2.0, iexp - 127); res[j] = sign * temp * (1.0 + two23 * imant); } else if (iexp === 0) { if (imant !== 0) res[j] = sign * two126 * two23 * imant; else res[j] = sign * 0.0; } else if (iexp === 255) res[j] = sign * 1e37; } return res; } //# sourceMappingURL=spectral.js.map