@aguacerowx/mapsgl 0.0.31 → 0.0.41
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/index.js +34 -2
- package/package.json +13 -3
- package/src/GridRenderLayer.js +105 -86
- package/src/MapManager.js +47 -15
- package/src/NexradSitesOverlay.js +148 -0
- package/src/NexradWeatherController.js +491 -0
- package/src/NwsWatchesWarningsOverlay.js +768 -0
- package/src/SatelliteShaderManager.js +999 -0
- package/src/WeatherLayerManager.js +800 -110
- package/src/WorkerPool.js +340 -0
- package/src/nexrad/MapboxRadarLayer.bundled.js +810 -0
- package/src/nexrad/MapboxRadarLayer.ts +784 -0
- package/src/nexrad/PreprocessedSweepParser.ts +226 -0
- package/src/nexrad/buildRadarRayGeometry.ts +97 -0
- package/src/nexrad/level3StormRelative.ts +116 -0
- package/src/nexrad/loadNexradSites.ts +41 -0
- package/src/nexrad/nexradArchiveCache.ts +64 -0
- package/src/nexrad/nexradCrossSectionSampleAtLatLon.ts +121 -0
- package/src/nexrad/nexradLevel3Products.ts +549 -0
- package/src/nexrad/nexradMapboxFrameOpts.js +106 -0
- package/src/nexrad/radarArchiveCore.bundled.js +4206 -0
- package/src/nexrad/radarArchiveCore.bundled.js.map +7 -0
- package/src/nexrad/radarArchiveCore.ts +1737 -0
- package/src/nexrad/radarDecode.worker.bundled.js +809 -0
- package/src/nexrad/radarDecode.worker.ts +227 -0
- package/src/nexrad/radarFrameGpuMatch.ts +111 -0
- package/src/nwsAlertsSupport.js +860 -0
- package/src/nwsEventColorsDefaults.js +133 -0
- package/src/nwsSdkConstants.js +360 -0
- package/src/nwsWarningCustomizationKey.gen.js +496 -0
- package/src/satelliteDefaultColormaps.js +37 -0
- package/src/satelliteKtxWorker.js +225 -0
- package/src/satelliteShader.js +17 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../node_modules/seek-bzip/lib/bitreader.js", "../../../../node_modules/seek-bzip/lib/stream.js", "../../../../node_modules/seek-bzip/lib/crc32.js", "../../../../node_modules/seek-bzip/package.json", "../../../../node_modules/seek-bzip/lib/index.js", "radarArchiveCore.ts", "nexradLevel3Products.ts", "level3StormRelative.ts", "nexradArchiveCache.ts", "loadNexradSites.ts"],
|
|
4
|
+
"sourcesContent": ["/*\nnode-bzip - a pure-javascript Node.JS module for decoding bzip2 data\n\nCopyright (C) 2012 Eli Skeggs\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nAdapted from bzip2.js, copyright 2011 antimatter15 (antimatter15@gmail.com).\n\nBased on micro-bunzip by Rob Landley (rob@landley.net).\n\nBased on bzip2 decompression code by Julian R Seward (jseward@acm.org),\nwhich also acknowledges contributions by Mike Burrows, David Wheeler,\nPeter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten,\nRobert Sedgewick, and Jon L. Bentley.\n*/\n\nvar BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF];\n\n// offset in bytes\nvar BitReader = function(stream) {\n this.stream = stream;\n this.bitOffset = 0;\n this.curByte = 0;\n this.hasByte = false;\n};\n\nBitReader.prototype._ensureByte = function() {\n if (!this.hasByte) {\n this.curByte = this.stream.readByte();\n this.hasByte = true;\n }\n};\n\n// reads bits from the buffer\nBitReader.prototype.read = function(bits) {\n var result = 0;\n while (bits > 0) {\n this._ensureByte();\n var remaining = 8 - this.bitOffset;\n // if we're in a byte\n if (bits >= remaining) {\n result <<= remaining;\n result |= BITMASK[remaining] & this.curByte;\n this.hasByte = false;\n this.bitOffset = 0;\n bits -= remaining;\n } else {\n result <<= bits;\n var shift = remaining - bits;\n result |= (this.curByte & (BITMASK[bits] << shift)) >> shift;\n this.bitOffset += bits;\n bits = 0;\n }\n }\n return result;\n};\n\n// seek to an arbitrary point in the buffer (expressed in bits)\nBitReader.prototype.seek = function(pos) {\n var n_bit = pos % 8;\n var n_byte = (pos - n_bit) / 8;\n this.bitOffset = n_bit;\n this.stream.seek(n_byte);\n this.hasByte = false;\n};\n\n// reads 6 bytes worth of data using the read method\nBitReader.prototype.pi = function() {\n var buf = new Buffer(6), i;\n for (i = 0; i < buf.length; i++) {\n buf[i] = this.read(8);\n }\n return buf.toString('hex');\n};\n\nmodule.exports = BitReader;\n", "/* very simple input/output stream interface */\nvar Stream = function() {\n};\n\n// input streams //////////////\n/** Returns the next byte, or -1 for EOF. */\nStream.prototype.readByte = function() {\n throw new Error(\"abstract method readByte() not implemented\");\n};\n/** Attempts to fill the buffer; returns number of bytes read, or\n * -1 for EOF. */\nStream.prototype.read = function(buffer, bufOffset, length) {\n var bytesRead = 0;\n while (bytesRead < length) {\n var c = this.readByte();\n if (c < 0) { // EOF\n return (bytesRead===0) ? -1 : bytesRead;\n }\n buffer[bufOffset++] = c;\n bytesRead++;\n }\n return bytesRead;\n};\nStream.prototype.seek = function(new_pos) {\n throw new Error(\"abstract method seek() not implemented\");\n};\n\n// output streams ///////////\nStream.prototype.writeByte = function(_byte) {\n throw new Error(\"abstract method readByte() not implemented\");\n};\nStream.prototype.write = function(buffer, bufOffset, length) {\n var i;\n for (i=0; i<length; i++) {\n this.writeByte(buffer[bufOffset++]);\n }\n return length;\n};\nStream.prototype.flush = function() {\n};\n\nmodule.exports = Stream;\n", "/* CRC32, used in Bzip2 implementation.\n * This is a port of CRC32.java from the jbzip2 implementation at\n * https://code.google.com/p/jbzip2\n * which is:\n * Copyright (c) 2011 Matthew Francis\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n * This JavaScript implementation is:\n * Copyright (c) 2013 C. Scott Ananian\n * with the same licensing terms as Matthew Francis' original implementation.\n */\nmodule.exports = (function() {\n\n /**\n * A static CRC lookup table\n */\n var crc32Lookup = new Uint32Array([\n 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,\n 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,\n 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,\n 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,\n 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,\n 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,\n 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,\n 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,\n 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,\n 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,\n 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,\n 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,\n 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,\n 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,\n 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,\n 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,\n 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,\n 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,\n 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,\n 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,\n 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,\n 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,\n 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,\n 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,\n 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,\n 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,\n 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,\n 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,\n 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,\n 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,\n 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,\n 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4\n ]);\n\n var CRC32 = function() {\n /**\n * The current CRC\n */\n var crc = 0xffffffff;\n\n /**\n * @return The current CRC\n */\n this.getCRC = function() {\n return (~crc) >>> 0; // return an unsigned value\n };\n\n /**\n * Update the CRC with a single byte\n * @param value The value to update the CRC with\n */\n this.updateCRC = function(value) {\n crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff];\n };\n\n /**\n * Update the CRC with a sequence of identical bytes\n * @param value The value to update the CRC with\n * @param count The number of bytes\n */\n this.updateCRCRun = function(value, count) {\n while (count-- > 0) {\n crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff];\n }\n };\n };\n return CRC32;\n})();\n", "{\n \"name\": \"seek-bzip\",\n \"version\": \"2.0.0\",\n \"contributors\": [\n \"C. Scott Ananian (http://cscott.net)\",\n \"Eli Skeggs\",\n \"Kevin Kwok\",\n \"Rob Landley (http://landley.net)\"\n ],\n \"description\": \"a pure-JavaScript Node.JS module for random-access decoding bzip2 data\",\n \"main\": \"./lib/index.js\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/cscott/seek-bzip.git\"\n },\n \"license\": \"MIT\",\n \"bin\": {\n \"seek-bunzip\": \"./bin/seek-bunzip\",\n \"seek-table\": \"./bin/seek-bzip-table\"\n },\n \"directories\": {\n \"test\": \"test\"\n },\n \"dependencies\": {\n \"commander\": \"^6.0.0\"\n },\n \"devDependencies\": {\n \"fibers\": \"^5.0.0\",\n \"mocha\": \"^8.1.0\"\n },\n \"scripts\": {\n \"test\": \"mocha\"\n }\n}\n", "/*\nseek-bzip - a pure-javascript module for seeking within bzip2 data\n\nCopyright (C) 2013 C. Scott Ananian\nCopyright (C) 2012 Eli Skeggs\nCopyright (C) 2011 Kevin Kwok\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nAdapted from node-bzip, copyright 2012 Eli Skeggs.\nAdapted from bzip2.js, copyright 2011 Kevin Kwok (antimatter15@gmail.com).\n\nBased on micro-bunzip by Rob Landley (rob@landley.net).\n\nBased on bzip2 decompression code by Julian R Seward (jseward@acm.org),\nwhich also acknowledges contributions by Mike Burrows, David Wheeler,\nPeter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten,\nRobert Sedgewick, and Jon L. Bentley.\n*/\n\nvar BitReader = require('./bitreader');\nvar Stream = require('./stream');\nvar CRC32 = require('./crc32');\nvar pjson = require('../package.json');\n\nvar MAX_HUFCODE_BITS = 20;\nvar MAX_SYMBOLS = 258;\nvar SYMBOL_RUNA = 0;\nvar SYMBOL_RUNB = 1;\nvar MIN_GROUPS = 2;\nvar MAX_GROUPS = 6;\nvar GROUP_SIZE = 50;\n\nvar WHOLEPI = \"314159265359\";\nvar SQRTPI = \"177245385090\";\n\nvar mtf = function(array, index) {\n var src = array[index], i;\n for (i = index; i > 0; i--) {\n array[i] = array[i-1];\n }\n array[0] = src;\n return src;\n};\n\nvar Err = {\n OK: 0,\n LAST_BLOCK: -1,\n NOT_BZIP_DATA: -2,\n UNEXPECTED_INPUT_EOF: -3,\n UNEXPECTED_OUTPUT_EOF: -4,\n DATA_ERROR: -5,\n OUT_OF_MEMORY: -6,\n OBSOLETE_INPUT: -7,\n END_OF_BLOCK: -8\n};\nvar ErrorMessages = {};\nErrorMessages[Err.LAST_BLOCK] = \"Bad file checksum\";\nErrorMessages[Err.NOT_BZIP_DATA] = \"Not bzip data\";\nErrorMessages[Err.UNEXPECTED_INPUT_EOF] = \"Unexpected input EOF\";\nErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = \"Unexpected output EOF\";\nErrorMessages[Err.DATA_ERROR] = \"Data error\";\nErrorMessages[Err.OUT_OF_MEMORY] = \"Out of memory\";\nErrorMessages[Err.OBSOLETE_INPUT] = \"Obsolete (pre 0.9.5) bzip format not supported.\";\n\nvar _throw = function(status, optDetail) {\n var msg = ErrorMessages[status] || 'unknown error';\n if (optDetail) { msg += ': '+optDetail; }\n var e = new TypeError(msg);\n e.errorCode = status;\n throw e;\n};\n\nvar Bunzip = function(inputStream, outputStream) {\n this.writePos = this.writeCurrent = this.writeCount = 0;\n\n this._start_bunzip(inputStream, outputStream);\n};\nBunzip.prototype._init_block = function() {\n var moreBlocks = this._get_next_block();\n if ( !moreBlocks ) {\n this.writeCount = -1;\n return false; /* no more blocks */\n }\n this.blockCRC = new CRC32();\n return true;\n};\n/* XXX micro-bunzip uses (inputStream, inputBuffer, len) as arguments */\nBunzip.prototype._start_bunzip = function(inputStream, outputStream) {\n /* Ensure that file starts with \"BZh['1'-'9'].\" */\n var buf = new Buffer(4);\n if (inputStream.read(buf, 0, 4) !== 4 ||\n String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh')\n _throw(Err.NOT_BZIP_DATA, 'bad magic');\n\n var level = buf[3] - 0x30;\n if (level < 1 || level > 9)\n _throw(Err.NOT_BZIP_DATA, 'level out of range');\n\n this.reader = new BitReader(inputStream);\n\n /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of\n uncompressed data. Allocate intermediate buffer for block. */\n this.dbufSize = 100000 * level;\n this.nextoutput = 0;\n this.outputStream = outputStream;\n this.streamCRC = 0;\n};\nBunzip.prototype._get_next_block = function() {\n var i, j, k;\n var reader = this.reader;\n // this is get_next_block() function from micro-bunzip:\n /* Read in header signature and CRC, then validate signature.\n (last block signature means CRC is for whole file, return now) */\n var h = reader.pi();\n if (h === SQRTPI) { // last block\n return false; /* no more blocks */\n }\n if (h !== WHOLEPI)\n _throw(Err.NOT_BZIP_DATA);\n this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned)\n this.streamCRC = (this.targetBlockCRC ^\n ((this.streamCRC << 1) | (this.streamCRC>>>31))) >>> 0;\n /* We can add support for blockRandomised if anybody complains. There was\n some code for this in busybox 1.0.0-pre3, but nobody ever noticed that\n it didn't actually work. */\n if (reader.read(1))\n _throw(Err.OBSOLETE_INPUT);\n var origPointer = reader.read(24);\n if (origPointer > this.dbufSize)\n _throw(Err.DATA_ERROR, 'initial position out of bounds');\n /* mapping table: if some byte values are never used (encoding things\n like ascii text), the compression code removes the gaps to have fewer\n symbols to deal with, and writes a sparse bitfield indicating which\n values were present. We make a translation table to convert the symbols\n back to the corresponding bytes. */\n var t = reader.read(16);\n var symToByte = new Buffer(256), symTotal = 0;\n for (i = 0; i < 16; i++) {\n if (t & (1 << (0xF - i))) {\n var o = i * 16;\n k = reader.read(16);\n for (j = 0; j < 16; j++)\n if (k & (1 << (0xF - j)))\n symToByte[symTotal++] = o + j;\n }\n }\n\n /* How many different huffman coding groups does this block use? */\n var groupCount = reader.read(3);\n if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS)\n _throw(Err.DATA_ERROR);\n /* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding\n group. Read in the group selector list, which is stored as MTF encoded\n bit runs. (MTF=Move To Front, as each value is used it's moved to the\n start of the list.) */\n var nSelectors = reader.read(15);\n if (nSelectors === 0)\n _throw(Err.DATA_ERROR);\n\n var mtfSymbol = new Buffer(256);\n for (i = 0; i < groupCount; i++)\n mtfSymbol[i] = i;\n\n var selectors = new Buffer(nSelectors); // was 32768...\n\n for (i = 0; i < nSelectors; i++) {\n /* Get next value */\n for (j = 0; reader.read(1); j++)\n if (j >= groupCount) _throw(Err.DATA_ERROR);\n /* Decode MTF to get the next selector */\n selectors[i] = mtf(mtfSymbol, j);\n }\n\n /* Read the huffman coding tables for each group, which code for symTotal\n literal symbols, plus two run symbols (RUNA, RUNB) */\n var symCount = symTotal + 2;\n var groups = [], hufGroup;\n for (j = 0; j < groupCount; j++) {\n var length = new Buffer(symCount), temp = new Uint16Array(MAX_HUFCODE_BITS + 1);\n /* Read huffman code lengths for each symbol. They're stored in\n a way similar to mtf; record a starting value for the first symbol,\n and an offset from the previous value for everys symbol after that. */\n t = reader.read(5); // lengths\n for (i = 0; i < symCount; i++) {\n for (;;) {\n if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR);\n /* If first bit is 0, stop. Else second bit indicates whether\n to increment or decrement the value. */\n if(!reader.read(1))\n break;\n if(!reader.read(1))\n t++;\n else\n t--;\n }\n length[i] = t;\n }\n\n /* Find largest and smallest lengths in this group */\n var minLen, maxLen;\n minLen = maxLen = length[0];\n for (i = 1; i < symCount; i++) {\n if (length[i] > maxLen)\n maxLen = length[i];\n else if (length[i] < minLen)\n minLen = length[i];\n }\n\n /* Calculate permute[], base[], and limit[] tables from length[].\n *\n * permute[] is the lookup table for converting huffman coded symbols\n * into decoded symbols. base[] is the amount to subtract from the\n * value of a huffman symbol of a given length when using permute[].\n *\n * limit[] indicates the largest numerical value a symbol with a given\n * number of bits can have. This is how the huffman codes can vary in\n * length: each code with a value>limit[length] needs another bit.\n */\n hufGroup = {};\n groups.push(hufGroup);\n hufGroup.permute = new Uint16Array(MAX_SYMBOLS);\n hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 2);\n hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1);\n hufGroup.minLen = minLen;\n hufGroup.maxLen = maxLen;\n /* Calculate permute[]. Concurently, initialize temp[] and limit[]. */\n var pp = 0;\n for (i = minLen; i <= maxLen; i++) {\n temp[i] = hufGroup.limit[i] = 0;\n for (t = 0; t < symCount; t++)\n if (length[t] === i)\n hufGroup.permute[pp++] = t;\n }\n /* Count symbols coded for at each bit length */\n for (i = 0; i < symCount; i++)\n temp[length[i]]++;\n /* Calculate limit[] (the largest symbol-coding value at each bit\n * length, which is (previous limit<<1)+symbols at this level), and\n * base[] (number of symbols to ignore at each bit length, which is\n * limit minus the cumulative count of symbols coded for already). */\n pp = t = 0;\n for (i = minLen; i < maxLen; i++) {\n pp += temp[i];\n /* We read the largest possible symbol size and then unget bits\n after determining how many we need, and those extra bits could\n be set to anything. (They're noise from future symbols.) At\n each level we're really only interested in the first few bits,\n so here we set all the trailing to-be-ignored bits to 1 so they\n don't affect the value>limit[length] comparison. */\n hufGroup.limit[i] = pp - 1;\n pp <<= 1;\n t += temp[i];\n hufGroup.base[i + 1] = pp - t;\n }\n hufGroup.limit[maxLen + 1] = Number.MAX_VALUE; /* Sentinal value for reading next sym. */\n hufGroup.limit[maxLen] = pp + temp[maxLen] - 1;\n hufGroup.base[minLen] = 0;\n }\n /* We've finished reading and digesting the block header. Now read this\n block's huffman coded symbols from the file and undo the huffman coding\n and run length encoding, saving the result into dbuf[dbufCount++]=uc */\n\n /* Initialize symbol occurrence counters and symbol Move To Front table */\n var byteCount = new Uint32Array(256);\n for (i = 0; i < 256; i++)\n mtfSymbol[i] = i;\n /* Loop through compressed symbols. */\n var runPos = 0, dbufCount = 0, selector = 0, uc;\n var dbuf = this.dbuf = new Uint32Array(this.dbufSize);\n symCount = 0;\n for (;;) {\n /* Determine which huffman coding group to use. */\n if (!(symCount--)) {\n symCount = GROUP_SIZE - 1;\n if (selector >= nSelectors) { _throw(Err.DATA_ERROR); }\n hufGroup = groups[selectors[selector++]];\n }\n /* Read next huffman-coded symbol. */\n i = hufGroup.minLen;\n j = reader.read(i);\n for (;;i++) {\n if (i > hufGroup.maxLen) { _throw(Err.DATA_ERROR); }\n if (j <= hufGroup.limit[i])\n break;\n j = (j << 1) | reader.read(1);\n }\n /* Huffman decode value to get nextSym (with bounds checking) */\n j -= hufGroup.base[i];\n if (j < 0 || j >= MAX_SYMBOLS) { _throw(Err.DATA_ERROR); }\n var nextSym = hufGroup.permute[j];\n /* We have now decoded the symbol, which indicates either a new literal\n byte, or a repeated run of the most recent literal byte. First,\n check if nextSym indicates a repeated run, and if so loop collecting\n how many times to repeat the last literal. */\n if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) {\n /* If this is the start of a new run, zero out counter */\n if (!runPos){\n runPos = 1;\n t = 0;\n }\n /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at\n each bit position, add 1 or 2 instead. For example,\n 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2.\n You can make any bit pattern that way using 1 less symbol than\n the basic or 0/1 method (except all bits 0, which would use no\n symbols, but a run of length 0 doesn't mean anything in this\n context). Thus space is saved. */\n if (nextSym === SYMBOL_RUNA)\n t += runPos;\n else\n t += 2 * runPos;\n runPos <<= 1;\n continue;\n }\n /* When we hit the first non-run symbol after a run, we now know\n how many times to repeat the last literal, so append that many\n copies to our buffer of decoded symbols (dbuf) now. (The last\n literal used is the one at the head of the mtfSymbol array.) */\n if (runPos){\n runPos = 0;\n if (dbufCount + t > this.dbufSize) { _throw(Err.DATA_ERROR); }\n uc = symToByte[mtfSymbol[0]];\n byteCount[uc] += t;\n while (t--)\n dbuf[dbufCount++] = uc;\n }\n /* Is this the terminating symbol? */\n if (nextSym > symTotal)\n break;\n /* At this point, nextSym indicates a new literal character. Subtract\n one to get the position in the MTF array at which this literal is\n currently to be found. (Note that the result can't be -1 or 0,\n because 0 and 1 are RUNA and RUNB. But another instance of the\n first symbol in the mtf array, position 0, would have been handled\n as part of a run above. Therefore 1 unused mtf position minus\n 2 non-literal nextSym values equals -1.) */\n if (dbufCount >= this.dbufSize) { _throw(Err.DATA_ERROR); }\n i = nextSym - 1;\n uc = mtf(mtfSymbol, i);\n uc = symToByte[uc];\n /* We have our literal byte. Save it into dbuf. */\n byteCount[uc]++;\n dbuf[dbufCount++] = uc;\n }\n /* At this point, we've read all the huffman-coded symbols (and repeated\n runs) for this block from the input stream, and decoded them into the\n intermediate buffer. There are dbufCount many decoded bytes in dbuf[].\n Now undo the Burrows-Wheeler transform on dbuf.\n See http://dogma.net/markn/articles/bwt/bwt.htm\n */\n if (origPointer < 0 || origPointer >= dbufCount) { _throw(Err.DATA_ERROR); }\n /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */\n j = 0;\n for (i = 0; i < 256; i++) {\n k = j + byteCount[i];\n byteCount[i] = j;\n j = k;\n }\n /* Figure out what order dbuf would be in if we sorted it. */\n for (i = 0; i < dbufCount; i++) {\n uc = dbuf[i] & 0xff;\n dbuf[byteCount[uc]] |= (i << 8);\n byteCount[uc]++;\n }\n /* Decode first byte by hand to initialize \"previous\" byte. Note that it\n doesn't get output, and if the first three characters are identical\n it doesn't qualify as a run (hence writeRunCountdown=5). */\n var pos = 0, current = 0, run = 0;\n if (dbufCount) {\n pos = dbuf[origPointer];\n current = (pos & 0xff);\n pos >>= 8;\n run = -1;\n }\n this.writePos = pos;\n this.writeCurrent = current;\n this.writeCount = dbufCount;\n this.writeRun = run;\n\n return true; /* more blocks to come */\n};\n/* Undo burrows-wheeler transform on intermediate buffer to produce output.\n If start_bunzip was initialized with out_fd=-1, then up to len bytes of\n data are written to outbuf. Return value is number of bytes written or\n error (all errors are negative numbers). If out_fd!=-1, outbuf and len\n are ignored, data is written to out_fd and return is RETVAL_OK or error.\n*/\nBunzip.prototype._read_bunzip = function(outputBuffer, len) {\n var copies, previous, outbyte;\n /* james@jamestaylor.org: writeCount goes to -1 when the buffer is fully\n decoded, which results in this returning RETVAL_LAST_BLOCK, also\n equal to -1... Confusing, I'm returning 0 here to indicate no\n bytes written into the buffer */\n if (this.writeCount < 0) { return 0; }\n\n var gotcount = 0;\n var dbuf = this.dbuf, pos = this.writePos, current = this.writeCurrent;\n var dbufCount = this.writeCount, outputsize = this.outputsize;\n var run = this.writeRun;\n\n while (dbufCount) {\n dbufCount--;\n previous = current;\n pos = dbuf[pos];\n current = pos & 0xff;\n pos >>= 8;\n if (run++ === 3){\n copies = current;\n outbyte = previous;\n current = -1;\n } else {\n copies = 1;\n outbyte = current;\n }\n this.blockCRC.updateCRCRun(outbyte, copies);\n while (copies--) {\n this.outputStream.writeByte(outbyte);\n this.nextoutput++;\n }\n if (current != previous)\n run = 0;\n }\n this.writeCount = dbufCount;\n // check CRC\n if (this.blockCRC.getCRC() !== this.targetBlockCRC) {\n _throw(Err.DATA_ERROR, \"Bad block CRC \"+\n \"(got \"+this.blockCRC.getCRC().toString(16)+\n \" expected \"+this.targetBlockCRC.toString(16)+\")\");\n }\n return this.nextoutput;\n};\n\nvar coerceInputStream = function(input) {\n if ('readByte' in input) { return input; }\n var inputStream = new Stream();\n inputStream.pos = 0;\n inputStream.readByte = function() { return input[this.pos++]; };\n inputStream.seek = function(pos) { this.pos = pos; };\n inputStream.eof = function() { return this.pos >= input.length; };\n return inputStream;\n};\nvar coerceOutputStream = function(output) {\n var outputStream = new Stream();\n var resizeOk = true;\n if (output) {\n if (typeof(output)==='number') {\n outputStream.buffer = new Buffer(output);\n resizeOk = false;\n } else if ('writeByte' in output) {\n return output;\n } else {\n outputStream.buffer = output;\n resizeOk = false;\n }\n } else {\n outputStream.buffer = new Buffer(16384);\n }\n outputStream.pos = 0;\n outputStream.writeByte = function(_byte) {\n if (resizeOk && this.pos >= this.buffer.length) {\n var newBuffer = new Buffer(this.buffer.length*2);\n this.buffer.copy(newBuffer);\n this.buffer = newBuffer;\n }\n this.buffer[this.pos++] = _byte;\n };\n outputStream.getBuffer = function() {\n // trim buffer\n if (this.pos !== this.buffer.length) {\n if (!resizeOk)\n throw new TypeError('outputsize does not match decoded input');\n var newBuffer = new Buffer(this.pos);\n this.buffer.copy(newBuffer, 0, 0, this.pos);\n this.buffer = newBuffer;\n }\n return this.buffer;\n };\n outputStream._coerced = true;\n return outputStream;\n};\n\n/* Static helper functions */\nBunzip.Err = Err;\n// 'input' can be a stream or a buffer\n// 'output' can be a stream or a buffer or a number (buffer size)\nBunzip.decode = function(input, output, multistream) {\n // make a stream from a buffer, if necessary\n var inputStream = coerceInputStream(input);\n var outputStream = coerceOutputStream(output);\n\n var bz = new Bunzip(inputStream, outputStream);\n while (true) {\n if ('eof' in inputStream && inputStream.eof()) break;\n if (bz._init_block()) {\n bz._read_bunzip();\n } else {\n var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned)\n if (targetStreamCRC !== bz.streamCRC) {\n _throw(Err.DATA_ERROR, \"Bad stream CRC \"+\n \"(got \"+bz.streamCRC.toString(16)+\n \" expected \"+targetStreamCRC.toString(16)+\")\");\n }\n if (multistream &&\n 'eof' in inputStream &&\n !inputStream.eof()) {\n // note that start_bunzip will also resync the bit reader to next byte\n bz._start_bunzip(inputStream, outputStream);\n } else break;\n }\n }\n if ('getBuffer' in outputStream)\n return outputStream.getBuffer();\n};\nBunzip.decodeBlock = function(input, pos, output) {\n // make a stream from a buffer, if necessary\n var inputStream = coerceInputStream(input);\n var outputStream = coerceOutputStream(output);\n var bz = new Bunzip(inputStream, outputStream);\n bz.reader.seek(pos);\n /* Fill the decode buffer for the block */\n var moreBlocks = bz._get_next_block();\n if (moreBlocks) {\n /* Init the CRC for writing */\n bz.blockCRC = new CRC32();\n\n /* Zero this so the current byte from before the seek is not written */\n bz.writeCopies = 0;\n\n /* Decompress the block and write to stdout */\n bz._read_bunzip();\n // XXX keep writing?\n }\n if ('getBuffer' in outputStream)\n return outputStream.getBuffer();\n};\n/* Reads bzip2 file from stream or buffer `input`, and invoke\n * `callback(position, size)` once for each bzip2 block,\n * where position gives the starting position (in *bits*)\n * and size gives uncompressed size of the block (in *bytes*). */\nBunzip.table = function(input, callback, multistream) {\n // make a stream from a buffer, if necessary\n var inputStream = new Stream();\n inputStream.delegate = coerceInputStream(input);\n inputStream.pos = 0;\n inputStream.readByte = function() {\n this.pos++;\n return this.delegate.readByte();\n };\n if (inputStream.delegate.eof) {\n inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate);\n }\n var outputStream = new Stream();\n outputStream.pos = 0;\n outputStream.writeByte = function() { this.pos++; };\n\n var bz = new Bunzip(inputStream, outputStream);\n var blockSize = bz.dbufSize;\n while (true) {\n if ('eof' in inputStream && inputStream.eof()) break;\n\n var position = inputStream.pos*8 + bz.reader.bitOffset;\n if (bz.reader.hasByte) { position -= 8; }\n\n if (bz._init_block()) {\n var start = outputStream.pos;\n bz._read_bunzip();\n callback(position, outputStream.pos - start);\n } else {\n var crc = bz.reader.read(32); // (but we ignore the crc)\n if (multistream &&\n 'eof' in inputStream &&\n !inputStream.eof()) {\n // note that start_bunzip will also resync the bit reader to next byte\n bz._start_bunzip(inputStream, outputStream);\n console.assert(bz.dbufSize === blockSize,\n \"shouldn't change block size within multistream file\");\n } else break;\n }\n }\n};\n\nBunzip.Stream = Stream;\n\nBunzip.version = pjson.version;\nBunzip.license = pjson.license;\n\nmodule.exports = Bunzip;\n", "\uFEFF/* eslint-disable */\n// Vendored from aguacero-frontend RadarLayer.tsx \u2014 fetch/decode only (no React).\nimport { Buffer } from 'buffer';\nimport * as bzip from 'seek-bzip';\nimport {\n getNexradLevel3EntryByRadarKey,\n level3EetHeightKmFromLevel,\n level3ValuePacking,\n nexradLevel3IsHydrometeorClassification,\n nexradLevel3UsesTiltIndexedS3Products,\n nexradLevel3S3ProductForSiteTilt,\n type Level3DecodeMode,\n} from './nexradLevel3Products.js';\nimport {\n applyLevel3StormRelativeToFrame,\n parseLevel3StormMotionFromBuffer,\n pickNearestLevel3ObjectKey,\n} from './level3StormRelative.js';\nimport type { NexradSite } from './PreprocessedSweepParser.js';\nimport { archiveCache, setArchiveCache, type DecodedRadarFrame } from './nexradArchiveCache.js';\nimport { loadNexradSites } from './loadNexradSites.js';\nimport { sampleNexradFrameAtLatLon } from './nexradCrossSectionSampleAtLatLon.js';\n\nlet NEXRAD_ARCHIVE_API_KEY = '';\nexport function setNexradArchiveApiKey(k: string) {\n NEXRAD_ARCHIVE_API_KEY = k || '';\n}\n\nfunction createRadarDecodeWorker(): Worker {\n return new Worker(new URL('./radarDecode.worker.js', import.meta.url), { type: 'module' });\n}\n\nconst LEVEL2_BASE_URL = 'https://d3dc62msmxkrd7.cloudfront.net/level-2';\nconst LEVEL3_BASE_URL = 'https://unidata-nexrad-level3.s3.amazonaws.com';\n\nconst PREFETCH_DELAY_MS = 0;\nconst PREFETCH_CONCURRENCY = 6;\n\n/** Underscore-style throttle for no-arg work \u00E2\u20AC\u201D coalesces bursts (slider scrub) without delaying the first call. */\nfunction throttleVoid(fn: () => void, waitMs: number): () => void {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n let previous = 0;\n return () => {\n const now = Date.now();\n const remaining = waitMs - (now - previous);\n if (remaining <= 0 || remaining > waitMs) {\n if (timeout) {\n clearTimeout(timeout);\n timeout = null;\n }\n previous = now;\n fn();\n } else if (!timeout) {\n timeout = setTimeout(() => {\n timeout = null;\n previous = Date.now();\n fn();\n }, remaining);\n }\n };\n}\n\n/**\n * Level-III KDP/N0H: throttle runSlot so rapid slider motion coalesces **fetches** (~10/s max) while a trailing\n * edge still applies the final time. MapboxRadarLayer caches the polar mesh on layout + coarse ray-boundary\n * fingerprint so scrubbing is fast while sweep registration stays geographic.\n */\nfunction createLatestPayloadThrottle(waitMs: number): (run: () => void) => void {\n let latest: (() => void) | null = null;\n const runLatest = () => {\n const fn = latest;\n latest = null;\n fn?.();\n };\n const throttled = throttleVoid(runLatest, waitMs);\n return (run: () => void) => {\n latest = run;\n throttled();\n };\n}\n\nconst azimuthKeyedRunSlotThrottleBySlot = new Map<string, ReturnType<typeof createLatestPayloadThrottle>>();\n\nfunction getAzimuthKeyedRunSlotThrottle(slotLayerId: string): (run: () => void) => void {\n let t = azimuthKeyedRunSlotThrottleBySlot.get(slotLayerId);\n if (!t) {\n t = createLatestPayloadThrottle(110);\n azimuthKeyedRunSlotThrottleBySlot.set(slotLayerId, t);\n }\n return t;\n}\nconst DECODE_WORKER_POOL_SIZE = 2;\nconst PREFETCH_WORKER_START_INDEX = 1;\n\n// \u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC Fetch / parse with deduplication \u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\n\n// Tracks in-flight fetches so concurrent calls for the same URL share one request.\nconst inflightFetches = new Map<string, Promise<DecodedRadarFrame | null>>();\nconst inflightFetchMeta = new Map<\n string,\n {\n requestId: number;\n startedAt: number;\n callers: number;\n objectKey: string;\n radarVariable: string;\n radarSource: 'level2' | 'level3';\n priority: 'display' | 'prefetch';\n }\n>();\nlet radarFetchRequestSeq = 0;\n\ntype RadarDecodeWorkerResponse = {\n type: 'DECODE_RESULT';\n requestId: number;\n gateData: Uint8Array | null;\n nRays?: number;\n nGates?: number;\n stationLat?: number;\n stationLon?: number;\n firstGateKm?: number;\n gateWidthKm?: number;\n valueScale?: number;\n valueOffset?: number;\n rayBoundariesDeg?: Float32Array;\n error?: string;\n};\n\nlet radarDecodeWorkers: Worker[] = [];\nlet radarDecodeRequestId = 0;\nconst radarDecodePending = new Map<number, {\n resolve: (frame: DecodedRadarFrame | null) => void;\n reject: (error: Error) => void;\n}>();\nconst radarDecodeRequestMeta = new Map<number, { objectKey: string; workerIndex: number }>();\nlet radarDecodePrefetchWorkerIndex = PREFETCH_WORKER_START_INDEX;\n\nfunction createDecodeWorker(workerIndex: number): Worker {\n const worker = createRadarDecodeWorker();\n worker.onmessage = (event: MessageEvent<RadarDecodeWorkerResponse>) => {\n const message = event.data;\n if (!message || message.type !== 'DECODE_RESULT') return;\n const pending = radarDecodePending.get(message.requestId);\n if (!pending) return;\n radarDecodePending.delete(message.requestId);\n radarDecodeRequestMeta.delete(message.requestId);\n if (message.error) {\n pending.reject(new Error(message.error));\n return;\n }\n if (\n !message.gateData\n || typeof message.nRays !== 'number'\n || typeof message.nGates !== 'number'\n || typeof message.stationLat !== 'number'\n || typeof message.stationLon !== 'number'\n || typeof message.firstGateKm !== 'number'\n || typeof message.gateWidthKm !== 'number'\n || typeof message.valueScale !== 'number'\n || typeof message.valueOffset !== 'number'\n || !(message.rayBoundariesDeg instanceof Float32Array)\n ) {\n pending.resolve(null);\n return;\n }\n pending.resolve({\n gateData: message.gateData,\n nRays: message.nRays,\n nGates: message.nGates,\n stationLat: message.stationLat,\n stationLon: message.stationLon,\n firstGateKm: message.firstGateKm,\n gateWidthKm: message.gateWidthKm,\n valueScale: message.valueScale,\n valueOffset: message.valueOffset,\n rayBoundariesDeg: message.rayBoundariesDeg,\n });\n };\n worker.onerror = (error) => {\n radarDecodePending.forEach(({ reject }) => reject(new Error(error.message || 'Radar decode worker failed')));\n radarDecodePending.clear();\n radarDecodeRequestMeta.clear();\n };\n return worker;\n}\n\nfunction getRadarDecodeWorkers(): Worker[] {\n if (radarDecodeWorkers.length > 0) return radarDecodeWorkers;\n radarDecodeWorkers = Array.from({ length: DECODE_WORKER_POOL_SIZE }, (_, idx) => createDecodeWorker(idx));\n return radarDecodeWorkers;\n}\n\nfunction getDecodeWorkerForPriority(priority: 'display' | 'prefetch'): { worker: Worker; workerIndex: number } {\n const workers = getRadarDecodeWorkers();\n if (priority === 'display' || workers.length === 1) {\n return { worker: workers[0], workerIndex: 0 };\n }\n const prefetchWorkerCount = Math.max(workers.length - PREFETCH_WORKER_START_INDEX, 1);\n const offset = (radarDecodePrefetchWorkerIndex - PREFETCH_WORKER_START_INDEX + prefetchWorkerCount) % prefetchWorkerCount;\n const workerIndex = PREFETCH_WORKER_START_INDEX + offset;\n radarDecodePrefetchWorkerIndex = PREFETCH_WORKER_START_INDEX + ((offset + 1) % prefetchWorkerCount);\n return { worker: workers[Math.min(workerIndex, workers.length - 1)], workerIndex: Math.min(workerIndex, workers.length - 1) };\n}\n\n/** Get physical value at lat/lon from a decoded radar frame. Returns null if outside coverage or no data. */\nfunction getSampleAtLatLonForRadarFrame(\n frame: DecodedRadarFrame,\n lat: number,\n lon: number,\n smoothPolar: boolean,\n): { value: number; groundRangeKm: number } | null {\n return sampleNexradFrameAtLatLon(frame, lat, lon, { smoothPolar });\n}\n\nexport function objectKeyToUrl(objectKey: string, radarSource: 'level2' | 'level3' = 'level2'): string {\n if (objectKey.startsWith('http')) return objectKey;\n const baseUrl = radarSource === 'level3' ? LEVEL3_BASE_URL : LEVEL2_BASE_URL;\n return `${baseUrl.replace(/\\/$/, '')}/${objectKey}`;\n}\n\nclass Level3Raf {\n private offset = 0;\n private view: DataView;\n private bytes: Uint8Array;\n\n constructor(input: Uint8Array | ArrayBuffer) {\n this.bytes = input instanceof Uint8Array ? input : new Uint8Array(input);\n this.view = new DataView(this.bytes.buffer, this.bytes.byteOffset, this.bytes.byteLength);\n }\n\n getPos(): number { return this.offset; }\n getLength(): number { return this.bytes.length; }\n seek(pos: number): void { this.offset = pos; }\n skip(delta: number): void { this.offset += delta; }\n read(bytes = 1): Uint8Array {\n const out = this.bytes.subarray(this.offset, this.offset + bytes);\n this.offset += bytes;\n return out;\n }\n readByte(): number {\n const v = this.view.getUint8(this.offset);\n this.offset += 1;\n return v;\n }\n readShort(): number {\n const v = this.view.getInt16(this.offset, false);\n this.offset += 2;\n return v;\n }\n readUShort(): number {\n const v = this.view.getUint16(this.offset, false);\n this.offset += 2;\n return v;\n }\n readInt(): number {\n const v = this.view.getInt32(this.offset, false);\n this.offset += 4;\n return v;\n }\n readUInt32(): number {\n const v = this.view.getUint32(this.offset, false);\n this.offset += 4;\n return v;\n }\n readString(bytes: number): string {\n const slice = this.read(bytes);\n return String.fromCharCode(...slice);\n }\n}\n\nfunction concatUint8(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.length + b.length);\n out.set(a, 0);\n out.set(b, a.length);\n return out;\n}\n\n/**\n * NEXRAD Level-III: range to gate g (m) = g * range_scale_symbology * multiplier[message_code] + first_bin (m).\n * Without multipliers, super-res products (e.g. message 153 reflectivity, 154 velocity) decode ~4\u00C3\u2014 too coarse in range.\n * Aligned with Py-ART / jjhelmus `PRODUCT_RANGE_RESOLUTION`.\n */\nconst LEVEL3_PRODUCT_RANGE_SCALE_MUL: Record<number, number> = {\n 19: 1, 20: 2, 25: 0.25, 27: 1, 28: 0.25, 30: 1, 32: 1, 34: 1, 56: 1,\n 57: 1000,\n 78: 1, 79: 1, 80: 1, 94: 1, 99: 0.25,\n 134: 1000, 135: 1000, 138: 1,\n 153: 0.25, 154: 0.25, 155: 0.25, 159: 0.25, 161: 0.25, 163: 0.25, 165: 0.25,\n 166: 0.25, 167: 0.25, 168: 0.25,\n 169: 1000, 170: 1000, 171: 1000, 172: 1000, 173: 1000, 174: 1000, 175: 1000,\n /** Py-ART `PRODUCT_RANGE_RESOLUTION`: 176/177 are digital-style radials (0.25\u00C3\u2014), not 1 km like 169\u00E2\u20AC\u201C175. */\n 176: 0.25, 177: 0.25,\n 181: 150, 182: 150, 186: 300,\n};\n\n/**\n * MetPy `GenericDigitalMapper` products: symbology levels map as (L - offset) / scale\n * where scale/offset are big-endian float32 from PDB thr1\u00E2\u20AC\u201Cthr2 and thr3\u00E2\u20AC\u201Cthr4 (see MetPy `nexrad.float32`).\n * DAA (170) was incorrectly decoded as min + L*inc, producing bogus inches and fan artifacts.\n */\nconst LEVEL3_GENERIC_DIGITAL_PRODUCT_CODES = new Set([\n 159, 161, 163, 167, 168,\n 170, 172, 173, 174, 175, 176,\n]);\n\n/**\n * NWS digital accumulation (MetPy `GenericDigitalMapper`) carries **depth in millimeters**.\n * Layer colormap / readout expect **inches** (see `nexradLevel3Products` precip packing).\n */\nconst LEVEL3_GENERIC_DIGITAL_DEPTH_MM_TO_IN_PRODUCTS = new Set([170, 172, 173, 174, 175]);\n\n/**\n * MetPy `DigitalHMCMapper`: digital / hybrid hydrometeor classification (165, 177).\n * 8-bit radial (packet 0x0010): `lut[i] = i // 10` is the **1-based** NWS category (1=BI \u00E2\u20AC\u00A6 6=RA \u00E2\u20AC\u00A6 12=GH).\n * Fill colormap / `NEXRAD_HYDROMETEOR_CLASS_LABELS` use **0-based** indices in the same order \u00E2\u2020\u2019 `floor(level/10) - 1`.\n * 150 = range-fold.\n * 4-bit raster / RLE (0xBA07, 0xAF1F): levels 2\u00E2\u20AC\u201C15 \u00E2\u2020\u2019 0-based class index `level \u00E2\u02C6\u2019 2`.\n */\nconst LEVEL3_DIGITAL_HMC_PRODUCT_CODES = new Set([165, 177]);\n\nfunction level3PhysicalFromDigitalHmc(level: number, precision: 'byte' | 'nibble'): number | null {\n if (!Number.isFinite(level)) return null;\n if (precision === 'nibble') {\n if (level < 2 || level > 15) return null;\n return level - 2;\n }\n if (level === 150) return null;\n if (level < 10 || level >= 256) return null;\n const cls = Math.floor(level / 10) - 1;\n if (cls < 0 || cls > 11) return null;\n return cls;\n}\n\n/**\n * Per-product mm calibration before \u00C3\u00B725.4 for generic digital accumulation (170, 172\u00E2\u20AC\u201C175).\n * 170 (DAA) field\u00E2\u20AC\u2018checked at 0.125. 172\u00E2\u20AC\u201C175 were too low at 0.125, too high at 1.0; 0.5 still ~2\u00C3\u2014 high\n * in the field \u00E2\u2020\u2019 0.25 for those products (halve again if needed).\n */\nfunction level3GenericDigitalAccumMmFactor(productCode: number): number {\n switch (productCode) {\n case 170: // DAA \u00E2\u20AC\u201D 1\u00E2\u20AC\u2018hour digital accumulation array\n return 0.125;\n case 172: // Digital storm total accumulation (generic)\n case 173: // DU3 \u00E2\u20AC\u201D user\u00E2\u20AC\u2018selectable (e.g. 3\u00E2\u20AC\u2018hour)\n case 174: // Digital one\u00E2\u20AC\u2018hour difference accumulation\n case 175: // Digital storm total difference accumulation\n return 0.25;\n default:\n return 1;\n }\n}\n\ntype Level3GenericDigitalParams = {\n scale: number;\n offset: number;\n leadingFlags: number;\n trailingFlags: number;\n maxDataVal: number;\n};\n\nfunction level3UnpackFloat32FromThresholdPair(short0: number, short1: number): number {\n const buf = new ArrayBuffer(4);\n const view = new DataView(buf);\n view.setUint16(0, short0 & 0xffff, false);\n view.setUint16(2, short1 & 0xffff, false);\n return view.getFloat32(0, false);\n}\n\nfunction parseLevel3GenericDigitalParams(dep: number[]): Level3GenericDigitalParams | null {\n /**\n * `raf.read(48)` is read **after** PDB fields through `el_num`, so this 24-short block is:\n * dep[0]=dep3, dep[1]=thr1, dep[2]=thr2, \u00E2\u20AC\u00A6 dep[16]=thr16, dep[17]=dep4, \u00E2\u20AC\u00A6\n * MetPy GenericDigitalMapper: scale=float32(thr1,thr2), offset=float32(thr3,thr4),\n * max=thr6, leading=thr7, trailing=thr8 \u00E2\u2020\u2019 dep indices 1..8.\n */\n if (dep.length < 9) return null;\n const scale = level3UnpackFloat32FromThresholdPair(dep[1], dep[2]);\n const offset = level3UnpackFloat32FromThresholdPair(dep[3], dep[4]);\n const maxDataVal = dep[6] & 0xffff;\n const leadingFlags = dep[7];\n const trailingFlags = dep[8];\n if (!Number.isFinite(scale) || scale === 0 || !Number.isFinite(offset)) return null;\n if (leadingFlags < 0 || leadingFlags > 255 || trailingFlags < 0 || trailingFlags > 255) return null;\n if (maxDataVal < leadingFlags) return null;\n return { scale, offset, leadingFlags, trailingFlags, maxDataVal };\n}\n\nfunction level3PhysicalFromGenericDigital(\n level: number,\n p: Level3GenericDigitalParams,\n productCode: number,\n): number | null {\n if (!Number.isFinite(level)) return null;\n if (level < p.leadingFlags) return null;\n const upper = p.maxDataVal - p.trailingFlags;\n if (level > upper) return null;\n let out = (level - p.offset) / p.scale;\n if (!Number.isFinite(out)) return null;\n if (LEVEL3_GENERIC_DIGITAL_DEPTH_MM_TO_IN_PRODUCTS.has(productCode)) {\n out *= level3GenericDigitalAccumMmFactor(productCode);\n out /= 25.4;\n }\n return out;\n}\n\ntype Level3SymbologyMode =\n | 'reflectivity'\n /**\n * MetPy `DigitalMapper` linear products (precip inches, etc.): phys = min + (L - 2) * inc.\n * Kept separate from `reflectivity` so legacy/category-style symbology is unchanged.\n */\n | 'standard_digital'\n /** Packet 0x0010: full-byte data levels; NEXRAD digital velocity uses threshold + (L-2)*inc. */\n | 'digital_velocity_byte'\n /**\n * Packet 0xAF1F: 4-bit levels in RLE nibbles. Threshold+increment from the PDB only spans a\n * small negative band (~\u00E2\u02C6\u201964\u00E2\u20AC\u00A6\u00E2\u02C6\u201957 m/s), so values fall entirely outside typical \u00E2\u02C6\u201930\u00E2\u20AC\u00A6+30 m/s\n * colormaps and the map looks empty. Use a centered mapping (0 m/s \u00E2\u2030\u02C6 level 8, ~4 m/s per step).\n */\n | 'digital_velocity_rle4';\n\n/**\n * Map symbology data level to a physical value (dBZ, m/s, etc.) depending on product/packet mode.\n */\nconst LEVEL3_MSG134_PRODUCTS = new Set([134]);\n\n// Replace the reflectivity branch in level3PhysicalFromDataLevel:\nfunction level3PhysicalFromDataLevel(\n level: number,\n minimumDataValue: number,\n dataIncrement: number,\n mode: Level3SymbologyMode,\n msg134Params?: { linearScale: number; linearOffset: number; logStart: number; logScale: number; logOffset: number } | null,\n): number | null {\n if (!Number.isFinite(level)) return null;\n if (mode === 'digital_velocity_byte') {\n if (level < 2) return null;\n return minimumDataValue + (level - 2) * dataIncrement;\n }\n if (mode === 'digital_velocity_rle4') {\n if (level < 2) return null;\n const MS_PER_STEP = 4;\n const CENTER_LEVEL = 8;\n return (level - CENTER_LEVEL) * MS_PER_STEP;\n }\n // Product 134 (Digital VIL): piecewise linear + log, params from threshold halfwords\n if (msg134Params) {\n if (level < 2) return null;\n const { linearScale, linearOffset, logStart, logScale, logOffset } = msg134Params;\n if (level < logStart) {\n return (level - linearOffset) / linearScale;\n } else {\n return Math.exp((level - logOffset) / logScale);\n }\n }\n if (mode === 'standard_digital') {\n if (level < 2) return null;\n return minimumDataValue + (level - 2) * dataIncrement;\n }\n if (level <= 1) return null;\n return minimumDataValue + level * dataIncrement;\n}\n\nfunction parseLevel3Packet0010(\n raf: Level3Raf,\n minimumDataValue: number,\n dataIncrement: number,\n levelMode: Level3SymbologyMode,\n l3ProductCode: number,\n msg134Params?: { linearScale: number; linearOffset: number; logStart: number; logScale: number; logOffset: number } | null,\n eetThresholds?: { dataMask: number; scale: number; offset: number } | null,\n genericDigital?: Level3GenericDigitalParams | null,\n) {\n const packetCode = raf.readUShort();\n if (packetCode !== 16) throw new Error(`Unexpected packet code ${packetCode}`);\n const firstBinMeters = raf.readShort();\n let numberBins = raf.readShort();\n raf.readShort(); // iSweepCenter\n raf.readShort(); // jSweepCenter\n const rangeScaleRaw = raf.readShort();\n const numberRadials = raf.readShort();\n // Py-ART: packet 16 sometimes has nbins \u00E2\u2030\u00A0 per-radial nbytes; true gate count follows first radial header.\n if (numberRadials > 0) {\n const peek = raf.getPos();\n const nbytesFirst = raf.readShort();\n raf.seek(peek);\n if (nbytesFirst !== numberBins) {\n numberBins = nbytesFirst;\n }\n }\n const radials: Array<{ startAngle: number; angleDelta: number; bins: Array<number | null> }> = [];\n for (let r = 0; r < numberRadials; r++) {\n const bytesInRadial = raf.readShort();\n const startAngle = raf.readShort() / 10;\n const angleDelta = raf.readShort() / 10;\n const bins: Array<number | null> = [];\n for (let i = 0; i < numberBins; i++) {\n const level = raf.readByte();\n if (eetThresholds) {\n bins.push(\n level3EetHeightKmFromLevel(level, eetThresholds.dataMask, eetThresholds.scale, eetThresholds.offset),\n );\n } else if (LEVEL3_DIGITAL_HMC_PRODUCT_CODES.has(l3ProductCode)) {\n bins.push(level3PhysicalFromDigitalHmc(level, 'byte'));\n } else if (genericDigital) {\n bins.push(level3PhysicalFromGenericDigital(level, genericDigital, l3ProductCode));\n } else {\n bins.push(level3PhysicalFromDataLevel(level, minimumDataValue, dataIncrement, levelMode, msg134Params));\n }\n }\n if (bytesInRadial > numberBins) raf.skip(bytesInRadial - numberBins);\n radials.push({ startAngle, angleDelta, bins });\n }\n return { firstBinMeters, numberBins, rangeScaleRaw, numberRadials, radials };\n}\nfunction parseLevel3PacketAF1F(\n raf: Level3Raf,\n minimumDataValue: number,\n dataIncrement: number,\n levelMode: Level3SymbologyMode,\n l3ProductCode: number,\n msg134Params?: { linearScale: number; linearOffset: number; logStart: number; logScale: number; logOffset: number } | null,\n eetThresholds?: { dataMask: number; scale: number; offset: number } | null,\n genericDigital?: Level3GenericDigitalParams | null,\n) {\n const packetCode = raf.readUShort();\n if (packetCode !== 0xAF1F) throw new Error(`Unexpected packet code ${packetCode}`);\n const firstBinMeters = raf.readShort();\n const numberBins = raf.readShort();\n raf.readShort(); // iSweepCenter\n raf.readShort(); // jSweepCenter\n const rangeScaleRaw = raf.readShort();\n const numRadials = raf.readShort();\n const radials: Array<{ startAngle: number; angleDelta: number; bins: Array<number | null> }> = [];\n for (let r = 0; r < numRadials; r++) {\n const rleBytes = raf.readShort() * 2;\n const startAngle = raf.readShort() / 10;\n const angleDelta = raf.readShort() / 10;\n const bins: Array<number | null> = [];\n for (let i = 0; i < rleBytes; i++) {\n const byte = raf.readByte();\n const run = byte >> 4;\n const level = byte & 0x0f;\n const value = eetThresholds\n ? level3EetHeightKmFromLevel(level, eetThresholds.dataMask, eetThresholds.scale, eetThresholds.offset)\n : LEVEL3_DIGITAL_HMC_PRODUCT_CODES.has(l3ProductCode)\n ? level3PhysicalFromDigitalHmc(level, 'nibble')\n : genericDigital\n ? level3PhysicalFromGenericDigital(level, genericDigital, l3ProductCode)\n : level3PhysicalFromDataLevel(level, minimumDataValue, dataIncrement, levelMode, msg134Params);\n for (let j = 0; j < run; j++) bins.push(value);\n }\n if (bins.length > numberBins) bins.length = numberBins;\n while (bins.length < numberBins) bins.push(null);\n radials.push({ startAngle, angleDelta, bins });\n }\n return { firstBinMeters, numberBins, rangeScaleRaw, numberRadials: numRadials, radials };\n}\n\nfunction buildRayBoundariesFromLevel3Radials(radials: any[]): Float32Array {\n const n = radials.length;\n const boundaries = new Float32Array(n + 1);\n let prev = -Infinity;\n for (let i = 0; i < n; i++) {\n const startAngle = Number(radials[i]?.startAngle);\n const angleDelta = Number(radials[i]?.angleDelta);\n const start = Number.isFinite(startAngle) ? startAngle : 0;\n const delta = Number.isFinite(angleDelta) && angleDelta > 0 ? angleDelta : 1;\n let lower = start - delta * 0.5;\n while (lower <= prev) lower += 360;\n boundaries[i] = lower;\n prev = lower;\n }\n const lastDeltaRaw = Number(radials[n - 1]?.angleDelta);\n const lastDelta = Number.isFinite(lastDeltaRaw) && lastDeltaRaw > 0 ? lastDeltaRaw : 1;\n boundaries[n] = boundaries[n - 1] + lastDelta;\n return boundaries;\n}\n\nfunction encodeSigned16ToHiLo(value: number): [number, number] {\n const signed = Math.max(-32768, Math.min(32767, value));\n const raw = signed < 0 ? signed + 65536 : signed;\n return [(raw >> 8) & 0xff, raw & 0xff];\n}\n\nfunction level3RadialSpatialScore(p: { numberBins: number; numberRadials: number } | null | undefined): number {\n if (!p) return -1;\n const nb = Number(p.numberBins);\n const nr = Number(p.numberRadials);\n if (!Number.isFinite(nb) || !Number.isFinite(nr) || nb <= 0 || nr <= 0) return -1;\n return nb * nr;\n}\n\ntype Level3RadialPick = { kind: 0x10 | 0xaf1f; packet: any };\n\nfunction level3RadialPickIsBetter(cand: Level3RadialPick, prev: Level3RadialPick | null): boolean {\n const sC = level3RadialSpatialScore(cand.packet);\n const sP = level3RadialSpatialScore(prev?.packet);\n if (sC > sP) return true;\n if (sC < sP) return false;\n if (!prev) return true;\n /** Same footprint: prefer full-byte digital radial (0x10) over 4-bit RLE (0xAF1F) for smoother velocity. */\n if (cand.kind === 0x10 && prev.kind === 0xaf1f) return true;\n return false;\n}\n\n/**\n * Advance past a non-radial symbology packet so later packets in the same layer can be read.\n * Caller must position RAF at the packet code; we consume code + body.\n * Uniform text (1, 8): u16 payload length then that many bytes (MetPy / ICD).\n */\nfunction trySkipLevel3OverlayPacket(raf: Level3Raf, packetCode: number, layerEnd: number): boolean {\n const pos0 = raf.getPos();\n if (packetCode !== 1 && packetCode !== 2 && packetCode !== 8) return false;\n if (layerEnd - pos0 < 4) return false;\n const codeRead = raf.readUShort();\n if (codeRead !== packetCode) {\n raf.seek(pos0);\n return false;\n }\n const payloadBytes = raf.readUShort();\n if (payloadBytes > layerEnd - raf.getPos()) {\n raf.seek(pos0);\n return false;\n }\n raf.skip(payloadBytes);\n return true;\n}\n\n/** Symbology packet 0xBA07: raster image (RLE rows). MetPy `packet_map[0xba07]`. Used by NVL (57), EET, etc. */\nconst LEVEL3_PACKET_RASTER_BA07 = 0xba07;\n/** First u32 after packet code; MetPy asserts this for raster payload. */\nconst LEVEL3_RASTER_INNER_CODE = 0x800000c0;\n\nfunction unpackLevel3RasterRle(rowBytes: Uint8Array): number[] {\n const unpacked: number[] = [];\n for (let i = 0; i < rowBytes.length; i++) {\n const b = rowBytes[i];\n const run = b >> 4;\n const val = b & 0x0f;\n for (let j = 0; j < run; j++) unpacked.push(val);\n }\n return unpacked;\n}\n\nfunction level3CombineRasterScale(int16: number, frac16: number): number {\n const i = Math.abs(int16);\n const f = Math.abs(frac16) / 10000;\n const s = i + f;\n return s > 0 ? s : 1;\n}\n\ntype Level3ParsedRaster = {\n iStart: number;\n jStart: number;\n cellKmX: number;\n cellKmY: number;\n startXKm: number;\n startYKm: number;\n nCols: number;\n nRows: number;\n rows: number[][];\n};\n\n/**\n * Parse raster symbology (packet 0xBA07). RAF must be positioned at the packet code (first u16).\n * Leaves RAF at `layerEnd` on success or after skipping on failure.\n */\nfunction parseLevel3PacketRasterBA07(raf: Level3Raf, layerEnd: number, objectKey: string): Level3ParsedRaster | null {\n const pos0 = raf.getPos();\n const packetCode = raf.readUShort();\n if (packetCode !== LEVEL3_PACKET_RASTER_BA07) {\n raf.seek(pos0);\n return null;\n }\n const room = layerEnd - raf.getPos();\n if (room < 20) {\n raf.seek(layerEnd);\n return null;\n }\n const inner = raf.readUInt32();\n if (inner !== LEVEL3_RASTER_INNER_CODE) {\n raf.seek(layerEnd);\n return null;\n }\n const iStart = raf.readShort();\n const jStart = raf.readShort();\n const xscaleInt = raf.readShort();\n const xscaleFrac = raf.readShort();\n const yscaleInt = raf.readShort();\n const yscaleFrac = raf.readShort();\n const numRows = raf.readUShort();\n const packing = raf.readUShort();\n if (packing !== 2) {\n console.warn('[aguacero][nexrad-l3][raster-ba07-packing]', { objectKey, packing, hint: 'MetPy expects packing=2; raster parse skipped for this layer' });\n raf.seek(layerEnd);\n return null;\n }\n if (numRows <= 0 || numRows > 2000 || raf.getPos() > layerEnd) {\n raf.seek(layerEnd);\n return null;\n }\n const cellKmX = level3CombineRasterScale(xscaleInt, xscaleFrac);\n const cellKmY = level3CombineRasterScale(yscaleInt, yscaleFrac);\n /** Match MetPy: start corner from integer scales only (see `metpy.io.nexrad` `_unpack_packet_raster_data`). */\n const startXKm = iStart * xscaleInt;\n const startYKm = jStart * yscaleInt;\n const rows: number[][] = [];\n let nCols = -1;\n for (let r = 0; r < numRows; r++) {\n if (raf.getPos() + 2 > layerEnd) {\n raf.seek(layerEnd);\n return null;\n }\n const rowNumBytes = raf.readUShort();\n if (rowNumBytes === 0 || raf.getPos() + rowNumBytes > layerEnd) {\n raf.seek(layerEnd);\n return null;\n }\n const rowBytes = raf.read(rowNumBytes);\n const expanded = unpackLevel3RasterRle(rowBytes);\n if (nCols < 0) nCols = expanded.length;\n else if (expanded.length !== nCols) {\n raf.seek(layerEnd);\n return null;\n }\n rows.push(expanded);\n }\n if (nCols <= 0) {\n raf.seek(layerEnd);\n return null;\n }\n if (raf.getPos() < layerEnd) {\n raf.seek(layerEnd);\n }\n return {\n iStart,\n jStart,\n cellKmX,\n cellKmY,\n startXKm,\n startYKm,\n nCols,\n nRows: numRows,\n rows,\n };\n}\n\nfunction level3RasterPdbScales(\n decodeMode: Level3DecodeMode,\n productCode: number,\n minimumDataValue: number,\n dataIncrement: number,\n depProductDescriptionShorts: number[] | null,\n objectKey: string,\n genericDigital: Level3GenericDigitalParams | null,\n): {\n minT: number;\n dataInc: number;\n symMode: Level3SymbologyMode;\n vilLevelThresholds: number[] | null;\n} {\n const minBad =\n !Number.isFinite(minimumDataValue) || Math.abs(minimumDataValue) > 500;\n const incBad = !Number.isFinite(dataIncrement) || dataIncrement <= 0;\n const bad = minBad || incBad;\n let minT = minimumDataValue;\n let dataInc = dataIncrement;\n let vilLevelThresholds: number[] | null = null;\n /**\n * NVL often encodes an invalid linear min (e.g. -32766 sentinel), while real level thresholds\n * are present in product-description shorts 33..46 (values like 5,10,...,70 kg/m\u00C2\u00B2).\n * Prefer those thresholds when present so data-level 2..15 map to physically meaningful VIL.\n */\n if (\n decodeMode === 'vil' &&\n productCode === 57 &&\n Array.isArray(depProductDescriptionShorts) &&\n depProductDescriptionShorts.length >= 17 &&\n depProductDescriptionShorts[1] <= -30000\n ) {\n const byLevel = new Array<number>(16).fill(Number.NaN);\n let validCount = 0;\n for (let level = 2; level <= 15; level++) {\n const raw = depProductDescriptionShorts[level + 1];\n if (Number.isFinite(raw) && raw > 0) {\n byLevel[level] = raw;\n validCount += 1;\n }\n }\n if (validCount >= 8) {\n vilLevelThresholds = byLevel;\n }\n }\n if (bad) {\n /** VIL: PDB min is often garbage; increment 0.1 is still valid. phys = minT + level*inc with level\u00E2\u2030\u00A52 \u00E2\u2020\u2019 use minT = -inc so level 2 \u00E2\u2020\u2019 +inc (e.g. 0.1). */\n if (decodeMode === 'vil' && minBad && !incBad && dataIncrement >= 0.05 && dataIncrement <= 2) {\n minT = -dataIncrement;\n dataInc = dataIncrement;\n } else if (decodeMode === 'vil') {\n minT = 0;\n dataInc = 1;\n } else if (decodeMode === 'precip') {\n minT = 0;\n dataInc = 0.25;\n } else if (decodeMode === 'tops_kft') {\n minT = 0;\n dataInc = 1;\n } else if (decodeMode === 'categorical') {\n minT = 0;\n dataInc = 1;\n } else if (decodeMode === 'generic_physical') {\n minT = -2;\n dataInc = 0.05;\n } else {\n minT = -32;\n dataInc = 0.5;\n }\n }\n const symMode: Level3SymbologyMode =\n decodeMode === 'velocity'\n ? 'digital_velocity_byte'\n : decodeMode === 'precip' && !genericDigital\n ? 'standard_digital'\n : 'reflectivity';\n return { minT, dataInc, symMode, vilLevelThresholds };\n}\n\n/** Resample Cartesian raster (km east/north from radar) into the polar texture the Mapbox radar shader expects. */\nfunction level3RasterToPolarFrame(\n raster: Level3ParsedRaster,\n stationLat: number,\n stationLon: number,\n decodeMode: Level3DecodeMode,\n minT: number,\n dataInc: number,\n symMode: Level3SymbologyMode,\n vilLevelThresholds: number[] | null,\n eetThresholds: { dataMask: number; scale: number; offset: number } | null,\n valueScale: number,\n valueOffset: number,\n objectKey: string,\n genericDigital: Level3GenericDigitalParams | null = null,\n l3ProductCode = 0,\n): DecodedRadarFrame | null {\n const { rows, nCols, nRows, startXKm, startYKm, cellKmX, cellKmY, iStart, jStart } = raster;\n const widthKm = nCols * cellKmX;\n const heightKm = nRows * cellKmY;\n /**\n * ICD raster I/J origin 0 with a square grid is a box **centered** on the radar (\u00C2\u00B1half extent in km).\n * Treating (0,0) as the southwest corner only covers the northeast quadrant \u00E2\u20AC\u201D data appears displaced\n * toward +x,+y (e.g. Atlantic for East Coast sites) and few polar samples hit the grid.\n */\n let originXK = startXKm;\n let originYK = startYKm;\n if (iStart === 0 && jStart === 0 && nCols === nRows && nCols >= 16) {\n originXK = startXKm - widthKm / 2;\n originYK = startYKm - heightKm / 2;\n }\n const xMin = originXK;\n const xMax = originXK + widthKm;\n const yMin = originYK;\n const yMax = originYK + heightKm;\n const corner = (x: number, y: number) => Math.hypot(x, y);\n let maxR = corner(xMin, yMin);\n maxR = Math.max(maxR, corner(xMax, yMin));\n maxR = Math.max(maxR, corner(xMin, yMax));\n maxR = Math.max(maxR, corner(xMax, yMax));\n maxR = Math.min(460, Math.max(50, maxR * 1.02));\n\n const nRays = 720;\n const gateWidthKm = 0.5;\n const nGates = Math.min(920, Math.max(64, Math.ceil(maxR / gateWidthKm)));\n const firstGateKm = 0;\n\n const gateData = new Uint8Array(nRays * nGates * 2);\n const rayBoundariesDeg = new Float32Array(nRays + 1);\n const deltaAz = 360 / nRays;\n for (let i = 0; i <= nRays; i++) {\n rayBoundariesDeg[i] = i * deltaAz - deltaAz * 0.5;\n }\n\n let samples = 0;\n let nodata = 0;\n for (let rayIdx = 0; rayIdx < nRays; rayIdx++) {\n const azDeg = (rayIdx + 0.5) * deltaAz;\n const azRad = (azDeg * Math.PI) / 180;\n const sinAz = Math.sin(azRad);\n const cosAz = Math.cos(azRad);\n for (let g = 0; g < nGates; g++) {\n const rKm = firstGateKm + (g + 0.5) * gateWidthKm;\n const xKm = rKm * sinAz;\n const yKm = rKm * cosAz;\n const fc = (xKm - originXK) / cellKmX;\n const fr = (yKm - originYK) / cellKmY;\n const c = Math.floor(fc);\n const r = Math.floor(fr);\n let level: number | null = null;\n if (c >= 0 && c < nCols && r >= 0 && r < nRows) {\n level = rows[r][c] ?? null;\n }\n let phys: number | null = null;\n if (level != null && Number.isFinite(level)) {\n if (\n decodeMode === 'vil' &&\n vilLevelThresholds &&\n level >= 0 &&\n level < vilLevelThresholds.length &&\n Number.isFinite(vilLevelThresholds[level])\n ) {\n phys = vilLevelThresholds[level];\n } else if (decodeMode === 'tops_kft' && eetThresholds) {\n phys = level3EetHeightKmFromLevel(\n level,\n eetThresholds.dataMask,\n eetThresholds.scale,\n eetThresholds.offset,\n );\n } else if (LEVEL3_DIGITAL_HMC_PRODUCT_CODES.has(l3ProductCode)) {\n phys = level3PhysicalFromDigitalHmc(level, 'nibble');\n } else if (genericDigital) {\n phys = level3PhysicalFromGenericDigital(level, genericDigital, l3ProductCode);\n } else {\n phys = level3PhysicalFromDataLevel(level, minT, dataInc, symMode);\n }\n }\n if (phys == null || !Number.isFinite(phys)) {\n nodata++;\n const offset = (rayIdx * nGates + g) * 2;\n gateData[offset] = 0x80;\n gateData[offset + 1] = 0x00;\n continue;\n }\n samples++;\n const rawSigned = Math.round((phys - valueOffset) / valueScale);\n const [hi, lo] = encodeSigned16ToHiLo(rawSigned);\n const offset = (rayIdx * nGates + g) * 2;\n gateData[offset] = hi;\n gateData[offset + 1] = lo;\n }\n }\n if (samples < 8) {\n console.warn('[aguacero][nexrad-l3][raster-nearly-empty]', { objectKey, samples, nodata });\n return null;\n }\n return {\n gateData,\n nRays,\n nGates,\n stationLat,\n stationLon,\n firstGateKm,\n gateWidthKm,\n valueScale,\n valueOffset,\n rayBoundariesDeg,\n };\n}\n\n/**\n * Validate Level-III Product Description Block (PDB) start at `pos`.\n *\n * Two valid layouts are seen in the wild:\n * 1) Divider-first PDB (`0xFFFF`, then lat/lon)\n * 2) Message-header-first (`productCode`, ... , divider at +18, then lat/lon)\n *\n * Use strict plausibility checks so we don't lock onto random halfwords.\n */\nfunction isValidLevel3PdbStart(bytes: Uint8Array, pos: number): boolean {\n const len = bytes.length;\n if (pos + 14 > len) return false;\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const latLonPlausible = (latMilli: number, lonMilli: number): boolean => {\n const lat = latMilli / 1000;\n const lon = lonMilli / 1000;\n return (\n lat >= -60 &&\n lat <= 72 &&\n lon >= -180 &&\n lon <= 180 &&\n Math.abs(lat) > 1 &&\n Math.abs(lon) > 1\n );\n };\n\n // Layout A: divider-first\n if (bytes[pos] === 0xff && bytes[pos + 1] === 0xff) {\n const latMilli = view.getInt32(pos + 2, false);\n const lonMilli = view.getInt32(pos + 6, false);\n return latLonPlausible(latMilli, lonMilli);\n }\n\n // Layout B: message-header-first (divider at +18, lat/lon at +20/+24)\n if (pos + 28 <= len) {\n const productCode = view.getUint16(pos, false);\n const divider = view.getInt16(pos + 18, false);\n if (productCode >= 1 && productCode <= 499 && divider === -1) {\n const latMilli = view.getInt32(pos + 20, false);\n const lonMilli = view.getInt32(pos + 24, false);\n if (latLonPlausible(latMilli, lonMilli)) return true;\n }\n }\n\n return false;\n}\n\n/**\n * PDB byte offset within the Level-III file (after optional SDUS trim).\n * NOAAPort/Unidata objects use a short ASCII preamble (SDUS line + product/site line) then binary.\n * A naive scan for 0xFFFF+lat/lon matches an *internal* digital divider (e.g. DVL at byte ~48) and\n * mis-parses symbology offsets \u00E2\u20AC\u201D only consider candidates that start immediately after a line break.\n */\nfunction findLevel3PdbByteOffset(bytes: Uint8Array): number {\n const len = bytes.length;\n let pos = 0;\n while (pos < len) {\n let lineEnd = pos;\n while (lineEnd < len && bytes[lineEnd] !== 0x0a && bytes[lineEnd] !== 0x0d) lineEnd++;\n while (lineEnd < len && (bytes[lineEnd] === 0x0a || bytes[lineEnd] === 0x0d)) lineEnd++;\n const nextStart = lineEnd;\n if (nextStart >= len - 2) break;\n if (isValidLevel3PdbStart(bytes, nextStart)) return nextStart;\n pos = nextStart;\n }\n if (len < 30) return 30;\n const end = Math.min(len - 14, 900);\n for (let i = 16; i <= end; i++) {\n if (isValidLevel3PdbStart(bytes, i)) return i;\n }\n return 30;\n}\n\n/** Decode Level-III radial raster (symbology block, packets 0x0010 / 0xAF1F) or raster image 0xBA07. */\nfunction decodeLevel3RasterProduct(buffer: ArrayBuffer, objectKey: string, radarVariable: string): DecodedRadarFrame | null {\n try {\n const bytes = new Uint8Array(buffer);\n const marker = [83, 68, 85, 83]; // SDUS\n let startIndex = 0;\n for (let i = 0; i <= bytes.length - marker.length; i++) {\n if (\n bytes[i] === marker[0] &&\n bytes[i + 1] === marker[1] &&\n bytes[i + 2] === marker[2] &&\n bytes[i + 3] === marker[3]\n ) {\n startIndex = i;\n break;\n }\n }\n const trimmed = startIndex > 0 ? bytes.subarray(startIndex) : bytes;\n const raf = new Level3Raf(trimmed);\n\n const fileType = raf.readString(6);\n if (!fileType.startsWith('SDUS')) {\n throw new Error(`Unexpected Level3 header ${fileType}`);\n }\n const pdbByteOffset = findLevel3PdbByteOffset(trimmed);\n raf.seek(pdbByteOffset);\n const headerWord0 = raf.readShort();\n let stationLat: number;\n let stationLon: number;\n let productCode: number;\n if (headerWord0 === -1) {\n stationLat = raf.readInt() / 1000;\n stationLon = raf.readInt() / 1000;\n raf.readShort(); // height\n productCode = raf.readUShort();\n } else {\n raf.seek(pdbByteOffset);\n productCode = raf.readUShort();\n raf.readShort(); // julianDate\n raf.readInt(); // seconds\n raf.readInt(); // length\n raf.readShort(); // source\n raf.readShort(); // dest\n raf.readShort(); // blocks\n const divider = raf.readShort();\n if (divider !== -1) throw new Error(`Invalid product divider ${divider}`);\n stationLat = raf.readInt() / 1000;\n stationLon = raf.readInt() / 1000;\n raf.readShort(); // height\n raf.readShort(); // code\n }\n raf.readShort(); // mode\n raf.readShort(); // vcp\n raf.readShort(); // sequenceNumber\n raf.readShort(); // volumeScanNumber\n raf.readShort(); // volumeScanDate\n raf.readInt(); // volumeScanTime\n raf.readShort(); // productDate\n raf.readInt(); // productTime\n raf.read(4); // dependent27_28\n raf.readShort(); // elevationNumber\n\n const dep30_53 = new Level3Raf(raf.read(48));\n const depProductDescriptionShorts: number[] = [];\n for (let i = 0; i < 24; i++) {\n depProductDescriptionShorts.push(dep30_53.readShort());\n }\n const minimumDataValue = depProductDescriptionShorts[1] / 10;\n const dataIncrement = depProductDescriptionShorts[2] / 10;\n const compressionMethod = depProductDescriptionShorts[21];\n const genericDigitalParams = LEVEL3_GENERIC_DIGITAL_PRODUCT_CODES.has(productCode)\n ? parseLevel3GenericDigitalParams(depProductDescriptionShorts)\n : null;\n\n if (LEVEL3_GENERIC_DIGITAL_PRODUCT_CODES.has(productCode) && !genericDigitalParams) {\n console.warn('[aguacero][nexrad-l3][generic-digital-params-null]', {\n objectKey,\n radarVariable,\n productCode,\n depHead: depProductDescriptionShorts.slice(0, 12),\n hint: 'Continuing with legacy min/inc; precip values may be wrong \u00E2\u20AC\u201D check dep alignment / PDB offset.',\n });\n }\n\n // Product 134 (Digital VIL) uses a piecewise linear+log scale encoded\n // in threshold halfwords 31-35, not the standard min+level*inc formula.\n let msg134Params: { linearScale: number; linearOffset: number; logStart: number; logScale: number; logOffset: number } | null = null;\n if (productCode === 134 && depProductDescriptionShorts.length >= 6) {\n const hw31 = depProductDescriptionShorts[1];\n const hw32 = depProductDescriptionShorts[2];\n const hw33 = depProductDescriptionShorts[3];\n const hw34 = depProductDescriptionShorts[4];\n const hw35 = depProductDescriptionShorts[5];\n msg134Params = {\n linearScale: int16ToFloat16(hw31),\n linearOffset: int16ToFloat16(hw32),\n logStart: hw33,\n logScale: int16ToFloat16(hw34),\n logOffset: int16ToFloat16(hw35),\n };\n }\n const l3Entry = getNexradLevel3EntryByRadarKey(radarVariable);\n const decodeMode: Level3DecodeMode =\n l3Entry?.decodeMode ??\n (radarVariable === 'VEL' ||\n radarVariable === 'N0G' ||\n radarVariable === 'SW' ||\n radarVariable === 'N0W'\n ? 'velocity'\n : 'dbz');\n const isVelSw = decodeMode === 'velocity';\n\n let minThreshold = minimumDataValue;\n let dataInc = dataIncrement;\n if (isVelSw) {\n const pdbLooksInvalid =\n !Number.isFinite(dataInc) ||\n dataInc <= 0 ||\n dataInc > 25 ||\n !Number.isFinite(minThreshold) ||\n Math.abs(minThreshold) > 130;\n if (pdbLooksInvalid) {\n minThreshold = -63.5;\n dataInc = 0.5;\n }\n }\n /** Product 138 (DTA): MetPy `DigitalStormPrecipMapper` uses thr2 \u00C3\u2014 0.01 in, not \u00C3\u2014 0.1. */\n if (decodeMode === 'precip' && productCode === 138) {\n dataInc = depProductDescriptionShorts[2] * 0.01;\n }\n\n /** Product 135 (EET) only: DigitalEET threshold triple in PDB. Classic echo tops (41 / NET) use min+inc like reflectivity. */\n const eetRadialThresholds =\n decodeMode === 'tops_kft' && productCode === 135\n ? {\n dataMask: depProductDescriptionShorts[1],\n scale: depProductDescriptionShorts[2],\n offset: depProductDescriptionShorts[3],\n }\n : null;\n raf.readByte(); // version\n raf.readByte(); // spotBlank\n const offsetSymbology = raf.readInt();\n raf.readInt(); // offsetGraphic\n raf.readInt(); // offsetTabular\n\n let parseBytes = trimmed;\n if (compressionMethod > 0) {\n const headerBytes = trimmed.subarray(0, raf.getPos());\n const compressedTail = trimmed.subarray(raf.getPos());\n const decompressedTail = bzip.decode(compressedTail) as Uint8Array;\n parseBytes = concatUint8(headerBytes, decompressedTail);\n }\n const parseRaf = new Level3Raf(parseBytes);\n const symbologyOffsetBytes = pdbByteOffset + offsetSymbology * 2;\n\n parseRaf.seek(symbologyOffsetBytes);\n\n const blockDivider = parseRaf.readShort();\n const blockId = parseRaf.readShort();\n if (blockDivider !== -1 || blockId !== 1) {\n const oob = symbologyOffsetBytes < 0 || symbologyOffsetBytes >= parseBytes.length;\n console.warn('[aguacero][nexrad-l3][symbology-header-bad]', {\n objectKey,\n radarVariable,\n productCode,\n blockDivider,\n blockId,\n symbologyOffsetBytes,\n parseBytesLength: parseBytes.length,\n seekOob: oob,\n hint: 'Usually wrong PDB byte offset; check [sym-offset] and findLevel3PdbByteOffset.',\n });\n throw new Error(`Invalid symbology header ${blockDivider}/${blockId}`);\n }\n parseRaf.readInt(); // blockLength\n const numberLayers = parseRaf.readShort();\n\n /** Scan every layer and every packet (MetPy-style): prefer largest gate\u00C3\u2014ray footprint, then 0x10 over RLE. */\n let bestRadial: Level3RadialPick | null = null;\n let rasterParsed: Level3ParsedRaster | null = null;\n const symbologyPacketCodes: number[] = [];\n for (let layerIndex = 0; layerIndex < numberLayers; layerIndex++) {\n const layerStart = parseRaf.getPos();\n const layerDivider = parseRaf.readShort();\n /** Bytes of symbology payload following this 4-byte field (ICD; same as MetPy `layer_hdr.length`). */\n const layerPayloadLength = parseRaf.readInt();\n if (layerDivider !== -1) {\n parseRaf.seek(layerStart + 6 + layerPayloadLength);\n continue;\n }\n /** End of layer = after 6-byte layer record (divider + length) + payload (MetPy marks `layer_start` after header). */\n const layerEnd = parseRaf.getPos() + layerPayloadLength;\n while (parseRaf.getPos() < layerEnd) {\n const packetPos = parseRaf.getPos();\n const packetCode = parseRaf.readUShort();\n symbologyPacketCodes.push(packetCode);\n parseRaf.seek(packetPos);\n if (packetCode === 16) {\n const symMode: Level3SymbologyMode = isVelSw\n ? 'digital_velocity_byte'\n : decodeMode === 'precip' && !genericDigitalParams\n ? 'standard_digital'\n : 'reflectivity';\n const p = parseLevel3Packet0010(\n parseRaf,\n minThreshold,\n dataInc,\n symMode,\n productCode,\n msg134Params,\n eetRadialThresholds,\n genericDigitalParams,\n );\n const cand: Level3RadialPick = { kind: 0x10, packet: p };\n if (level3RadialPickIsBetter(cand, bestRadial)) bestRadial = cand;\n continue;\n }\n if (packetCode === 0xAF1F) {\n const symMode: Level3SymbologyMode = isVelSw\n ? 'digital_velocity_rle4'\n : decodeMode === 'precip' && !genericDigitalParams\n ? 'standard_digital'\n : 'reflectivity';\n const p = parseLevel3PacketAF1F(\n parseRaf,\n minThreshold,\n dataInc,\n symMode,\n productCode,\n msg134Params,\n eetRadialThresholds,\n genericDigitalParams,\n );\n const cand: Level3RadialPick = { kind: 0xaf1f, packet: p };\n if (level3RadialPickIsBetter(cand, bestRadial)) bestRadial = cand;\n continue;\n }\n if (packetCode === LEVEL3_PACKET_RASTER_BA07) {\n parseRaf.seek(packetPos);\n const parsed = parseLevel3PacketRasterBA07(parseRaf, layerEnd, objectKey);\n if (parsed && rasterParsed === null) rasterParsed = parsed;\n else if (!parsed) parseRaf.seek(layerEnd);\n continue;\n }\n if (trySkipLevel3OverlayPacket(parseRaf, packetCode, layerEnd)) {\n continue;\n }\n parseRaf.seek(layerEnd);\n break;\n }\n parseRaf.seek(layerEnd);\n }\n\n /**\n * EET (135): ICD uses up to **256** data levels on digital radials (packet 0x0010 full bytes).\n * Raster 0xBA07 RLE is **4-bit** (levels 0\u00E2\u20AC\u201C15 only), which caps echo-top heights near ~10 km (~33 kft)\n * even though the radial product carries the full dynamic range. Prefer radials when both exist.\n *\n * Digital precip: raster grid avoids radial fan artifacts.\n * Do **not** prefer raster for dual-pol generic-digital products (e.g. 163 N0K KDP): 0xBA07 RLE is **4-bit**\n * (levels 0\u00E2\u20AC\u201C15) while 0x0010 radials are **8-bit** \u00E2\u20AC\u201D using the raster makes KDP/ZDR-style fields one flat color.\n */\n const shouldPreferRaster =\n rasterParsed != null &&\n ((decodeMode === 'tops_kft' && productCode !== 135) || decodeMode === 'precip');\n\n if (bestRadial && !shouldPreferRaster) {\n const radialPacket = bestRadial.packet;\n const radials = radialPacket?.radials;\n const nRays = Number(radialPacket?.numberRadials);\n const nGates = Number(radialPacket?.numberBins);\n if (!Array.isArray(radials) || !Number.isFinite(nRays) || !Number.isFinite(nGates) || !Number.isFinite(stationLat) || !Number.isFinite(stationLon)) {\n console.warn('[aguacero][nexrad-l3][invalid-radial-packet]', { objectKey, radarVariable, nRays, nGates, stationLat, stationLon });\n } else {\n const gateData = new Uint8Array(nRays * nGates * 2);\n const { valueScale, valueOffset } = level3ValuePacking(decodeMode);\n for (let r = 0; r < nRays; r++) {\n const bins = radials[r]?.bins;\n for (let g = 0; g < nGates; g++) {\n const v = bins?.[g];\n const isNoData = v == null || !Number.isFinite(v);\n const rawSigned = isNoData\n ? -32768\n : Math.round((Number(v) - valueOffset) / valueScale);\n const [hi, lo] = encodeSigned16ToHiLo(rawSigned);\n const offset = (r * nGates + g) * 2;\n gateData[offset] = hi;\n gateData[offset + 1] = lo;\n }\n }\n\n const rangeMul = LEVEL3_PRODUCT_RANGE_SCALE_MUL[productCode] ?? 1;\n const rangeScaleRaw = Number(radialPacket?.rangeScaleRaw);\n const gateSpacingM =\n Number.isFinite(rangeScaleRaw) && rangeScaleRaw > 0 ? rangeScaleRaw * rangeMul : 250;\n let gateWidthKm = gateSpacingM / 1000;\n const firstBinM = Number(radialPacket?.firstBinMeters);\n let firstGateKm = Number.isFinite(firstBinM) && firstBinM >= 0 ? firstBinM / 1000 : 0;\n const decodedCoverageKm = firstGateKm + nGates * gateWidthKm;\n if (decodedCoverageKm > 0 && decodedCoverageKm < 20 && nGates >= 100) {\n gateWidthKm *= 1000;\n firstGateKm *= 1000;\n }\n // Guard against km\u00E2\u2020\u201Dm mismatch producing global wedges for precip products.\n if (decodeMode === 'precip' && decodedCoverageKm > 1500) {\n gateWidthKm /= 1000;\n firstGateKm /= 1000;\n }\n const rayBoundariesDeg = buildRayBoundariesFromLevel3Radials(radials);\n\n return {\n gateData,\n nRays,\n nGates,\n stationLat,\n stationLon,\n firstGateKm,\n gateWidthKm,\n valueScale,\n valueOffset,\n rayBoundariesDeg,\n };\n }\n }\n\n if (rasterParsed) {\n const { valueScale, valueOffset } = level3ValuePacking(decodeMode);\n const { minT, dataInc: rasterDataInc, symMode, vilLevelThresholds } = level3RasterPdbScales(\n decodeMode,\n productCode,\n minThreshold,\n dataInc,\n depProductDescriptionShorts,\n objectKey,\n genericDigitalParams,\n );\n const eetThresholds =\n decodeMode === 'tops_kft' && productCode === 135\n ? {\n dataMask: depProductDescriptionShorts[1],\n scale: depProductDescriptionShorts[2],\n offset: depProductDescriptionShorts[3],\n }\n : null;\n const rasterFrame = level3RasterToPolarFrame(\n rasterParsed,\n stationLat,\n stationLon,\n decodeMode,\n minT,\n rasterDataInc,\n symMode,\n vilLevelThresholds,\n eetThresholds,\n valueScale,\n valueOffset,\n objectKey,\n genericDigitalParams,\n productCode,\n );\n if (rasterFrame) {\n return rasterFrame;\n }\n }\n\n const hex = symbologyPacketCodes.map((c) => `0x${c.toString(16)}`);\n if (!bestRadial) {\n console.warn('[aguacero][nexrad-l3][no-radial-symbology]', {\n objectKey,\n radarVariable,\n messageCode: productCode,\n numberLayers,\n symbologyPacketCodes,\n symbologyPacketCodesHex: hex,\n hint: 'Radial: packets 0x10 / 0xAF1F. Raster: 0xBA07 is supported; if rasterParsed failed, check parseLevel3PacketRasterBA07 / inner code logs.',\n });\n }\n return null;\n } catch (err) {\n console.warn('[aguacero][nexrad-l3][decode-throw]', { objectKey, radarVariable, err });\n return null;\n }\n}\n\nconst GROUP2_VARS = ['VEL', 'SW'];\n/** g1 dual-pol + REF; order must match writer. KDP is Level-III (N0K), not in g1 bins. */\nconst GROUP1_VARS = ['REF', 'ZDR', 'RHO', 'PHI'] as const;\n/** g2 combined tilt with KDP (7 slots); order must match writer. */\nconst GROUP2_COMBINED_7_VARS = ['REF', 'ZDR', 'RHO', 'PHI', 'KDP', 'VEL', 'SW'];\nconst GROUP2_COMBINED_VARS = ['REF', 'ZDR', 'RHO', 'PHI', 'VEL', 'SW'];\n\n// Fixed sizes matching the Python writer\nconst FILE_HDR_BYTES = 64;\nconst AZ_BLOCK_BYTES = 720 * 4; // 2880\nconst SLOT_INDEX_ENTRY = 18;\nconst MAX_SLOTS = 6;\n\ninterface FileHeader {\n unixTime: number;\n nRays: number;\n nGates: number;\n elevAngle: number;\n firstGateKm: number;\n gateWidthKm: number;\n nSlots: number;\n azimuthsBuffer: ArrayBuffer; // raw big-endian float32 bytes, 720*4\n slots: Array<{ offset: number; compressedSize: number; uncompressedSize: number }>;\n}\n\nfunction int16ToFloat16(val: number): number {\n const sign = (val & 0b1000000000000000) / 0b1000000000000000;\n const exponent = (val & 0b0111110000000000) / 0b0000010000000000;\n const fraction = val & 0b0000001111111111;\n if (exponent === 0) {\n return Math.pow(-1, sign) * 2 * (0 + fraction / Math.pow(2, 10));\n }\n return Math.pow(-1, sign) * Math.pow(2, exponent - 16) * (1 + fraction / Math.pow(2, 10));\n}\n\nfunction parseFileHeader(buffer: ArrayBuffer): FileHeader {\n const view = new DataView(buffer);\n const magic = view.getUint32(0, false);\n if (magic !== 0x4E584244) throw new Error(`Bad magic: 0x${magic.toString(16)}`);\n\n const unixTime = view.getUint32(4, false);\n const nRays = view.getUint16(8, false);\n const nGates = view.getUint16(10, false);\n const elevAngle = view.getFloat32(12, false);\n const firstGateKm = view.getFloat32(16, false);\n const gateWidthKm = view.getFloat32(20, false);\n const nSlots = view.getUint16(24, false);\n\n // Azimuths: 720 big-endian float32s starting at byte 64\n const azimuthsBuffer = buffer.slice(FILE_HDR_BYTES, FILE_HDR_BYTES + AZ_BLOCK_BYTES);\n\n // Slot index starts at byte 2944\n const idxStart = FILE_HDR_BYTES + AZ_BLOCK_BYTES;\n const slots = [];\n for (let i = 0; i < nSlots; i++) {\n const base = idxStart + i * SLOT_INDEX_ENTRY;\n const offsetHigh = view.getUint32(base, false);\n const offsetLow = view.getUint32(base + 4, false);\n const offset = offsetHigh * 2 ** 32 + offsetLow;\n const compressedSize = view.getUint32(base + 8, false);\n const uncompressedSize = view.getUint32(base + 12, false);\n slots.push({ offset, compressedSize, uncompressedSize });\n }\n\n return { unixTime, nRays, nGates, elevAngle, firstGateKm, gateWidthKm,\n nSlots, azimuthsBuffer, slots };\n}\n\nfunction decodeSweepInWorker(\n objectKey: string,\n slotBuffer: ArrayBuffer,\n header: FileHeader,\n sites: NexradSite[],\n priority: 'display' | 'prefetch',\n signal?: AbortSignal,\n): Promise<DecodedRadarFrame | null> {\n if (signal?.aborted) return Promise.reject(new DOMException('Aborted', 'AbortError'));\n\n const { worker } = getDecodeWorkerForPriority(priority);\n const requestId = ++radarDecodeRequestId;\n\n // Transfer a copy of azimuthsBuffer so we don't detach the cached header\n const azCopy = header.azimuthsBuffer.slice(0);\n\n return new Promise((resolve, reject) => {\n let isSettled = false;\n const onAbort = () => {\n if (isSettled) return;\n isSettled = true;\n radarDecodePending.delete(requestId);\n radarDecodeRequestMeta.delete(requestId);\n signal?.removeEventListener('abort', onAbort);\n reject(new DOMException('Aborted', 'AbortError'));\n };\n\n radarDecodePending.set(requestId, {\n resolve: (frame) => { if (!isSettled) { isSettled = true; signal?.removeEventListener('abort', onAbort); resolve(frame); } },\n reject: (err) => { if (!isSettled) { isSettled = true; signal?.removeEventListener('abort', onAbort); reject(err); } },\n });\n\n if (signal) signal.addEventListener('abort', onAbort, { once: true });\n\n worker.postMessage({\n type: 'DECODE_SLOT',\n requestId,\n objectKey,\n slotBuffer,\n nRays: header.nRays,\n nGates: header.nGates,\n firstGateKm: header.firstGateKm,\n gateWidthKm: header.gateWidthKm,\n azimuthsBuffer: azCopy,\n sites,\n }, [slotBuffer, azCopy]);\n });\n}\n\nfunction resolveLevel3SrvMotionObjectKey(\n unixTime: number | null | undefined,\n motionMap: Record<string, string> | undefined,\n radarSource: 'level2' | 'level3',\n radarVar: string,\n useStormRelativeMotion: boolean,\n): string | null {\n if (radarVar !== 'VEL' || !useStormRelativeMotion || unixTime == null || !motionMap) {\n return null;\n }\n return pickNearestLevel3ObjectKey(unixTime, motionMap);\n}\n\nasync function applyStormMotionFromN0sObjectKey(\n frame: DecodedRadarFrame,\n motionObjectKey: string,\n logLabel: string,\n): Promise<DecodedRadarFrame> {\n const motionUrl = objectKeyToUrl(motionObjectKey, 'level3');\n try {\n const motionResp = await fetch(motionUrl);\n if (motionResp.ok) {\n const motionBuf = await motionResp.arrayBuffer();\n const motion = parseLevel3StormMotionFromBuffer(motionBuf);\n if (motion) {\n return applyLevel3StormRelativeToFrame(frame, motion.speedMs, motion.directionDeg);\n }\n }\n } catch (e) {\n console.log(`${logLabel}:srvMotionFetchError`, { motionObjectKey, err: e });\n }\n return frame;\n}\n\nexport async function fetchAndParseArchive(\n url: string,\n objectKey: string,\n radarVariable: string,\n groupId: number,\n radarSource: 'level2' | 'level3',\n options?: {\n signal?: AbortSignal;\n priority?: 'display' | 'prefetch';\n /** N0S S3 object key \u00E2\u20AC\u201D with VEL, apply SRV (L3: N0G+motion; L2: super-res velocity + nearest-time N0S motion). */\n level3MotionObjectKey?: string | null;\n },\n): Promise<DecodedRadarFrame | null> {\n const mot = options?.level3MotionObjectKey ? `|${options.level3MotionObjectKey}` : '';\n const cacheKey = `${url}:${radarVariable}:${radarSource}${mot}`;\n const priority = options?.priority ?? 'display';\n\n if (archiveCache.has(cacheKey)) {\n const cached = archiveCache.get(cacheKey)!;\n setArchiveCache(cacheKey, cached);\n return cached;\n }\n const existingInflight = inflightFetches.get(cacheKey);\n if (existingInflight) {\n const meta = inflightFetchMeta.get(cacheKey);\n if (meta) {\n meta.callers += 1;\n }\n return existingInflight;\n }\n\n if (options?.signal?.aborted) {\n return null;\n }\n\n const requestId = ++radarFetchRequestSeq;\n const startedAt = performance.now();\n inflightFetchMeta.set(cacheKey, {\n requestId,\n startedAt,\n callers: 1,\n objectKey,\n radarVariable,\n radarSource,\n priority,\n });\n\n const promise = (async (): Promise<DecodedRadarFrame | null> => {\n try {\n if (radarSource === 'level3') {\n const response = await fetch(url);\n if (!response.ok) throw new Error(`HTTP ${response.status} fetching level3 ${url}`);\n const buffer = await response.arrayBuffer();\n let decoded = decodeLevel3RasterProduct(buffer, objectKey, radarVariable);\n const motionKey = options?.level3MotionObjectKey;\n if (decoded && motionKey && radarVariable === 'VEL') {\n decoded = await applyStormMotionFromN0sObjectKey(\n decoded,\n motionKey,\n 'fetchAndParseArchive:level3',\n );\n }\n if (!decoded) {\n console.warn('[aguacero][nexrad-l3][fetch-ok-decode-null]', {\n objectKey,\n radarVariable,\n byteLength: buffer.byteLength,\n filterConsole: 'Also check [aguacero][nexrad-l3][no-radial-symbology] or decode catch logs',\n });\n } else {\n setArchiveCache(cacheKey, decoded);\n }\n return decoded;\n }\n\n// \u00E2\u201D\u20AC\u00E2\u201D\u20AC Level-2 two-request range path \u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\n // Request 1: fetch just the header + slot index to find byte offsets\n const INDEX_FETCH_BYTES = FILE_HDR_BYTES + AZ_BLOCK_BYTES + MAX_SLOTS * SLOT_INDEX_ENTRY;\n const indexResp = await fetch(url, {\n headers: {\n 'x-api-key': NEXRAD_ARCHIVE_API_KEY,\n 'Range': `bytes=0-${INDEX_FETCH_BYTES - 1}`,\n },\n });\n if (!indexResp.ok && indexResp.status !== 206) {\n throw new Error(`HTTP ${indexResp.status} fetching level2 index ${url}`);\n }\n const indexBuffer = await indexResp.arrayBuffer();\n const header = parseFileHeader(indexBuffer);\n\n // \u00E2\u201D\u20AC\u00E2\u201D\u20AC Step 2: find slot for this variable \u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\n let varList: string[];\n if (groupId === 2 && header.nSlots === 7) {\n varList = GROUP2_COMBINED_7_VARS;\n } else if (groupId === 2 && header.nSlots === 6) {\n varList = GROUP2_COMBINED_VARS;\n } else if (groupId === 2) {\n varList = GROUP2_VARS;\n } else {\n varList = [...GROUP1_VARS];\n }\n\n const slotIdx = varList.indexOf(radarVariable);\n if (slotIdx < 0 || slotIdx >= header.slots.length) {\n console.warn(`[RadarLayer] ${radarVariable} not in group ${groupId} (nSlots=${header.nSlots})`);\n setArchiveCache(cacheKey, null);\n return null;\n }\n\n const slot = header.slots[slotIdx];\n if (slot.compressedSize === 0) {\n console.warn(`[RadarLayer] ${radarVariable} slot ${slotIdx} has compressedSize=0`);\n setArchiveCache(cacheKey, null);\n return null;\n }\n\n // \u00E2\u201D\u20AC\u00E2\u201D\u20AC Step 3: fetch exactly the slot bytes \u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\n const slotRangeEnd = slot.offset + slot.compressedSize - 1;\n const slotResp = await fetch(url, {\n headers: {\n 'x-api-key': NEXRAD_ARCHIVE_API_KEY,\n 'Range': `bytes=${slot.offset}-${slotRangeEnd}`,\n },\n });\n if (!slotResp.ok && slotResp.status !== 206) {\n throw new Error(`HTTP ${slotResp.status} fetching level2 slot ${url}`);\n }\n const slotBuffer = await slotResp.arrayBuffer();\n\n // \u00E2\u201D\u20AC\u00E2\u201D\u20AC Step 4: decode in worker \u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\u00E2\u201D\u20AC\n const sites = await loadNexradSites();\n let decoded = await decodeSweepInWorker(\n objectKey, slotBuffer, header, sites,\n options?.priority ?? 'display',\n undefined,\n );\n\n if (!decoded) { setArchiveCache(cacheKey, null); return null; }\n const l2MotionKey = options?.level3MotionObjectKey;\n if (l2MotionKey && radarVariable === 'VEL') {\n decoded = await applyStormMotionFromN0sObjectKey(\n decoded,\n l2MotionKey,\n 'fetchAndParseArchive:level2',\n );\n }\n setArchiveCache(cacheKey, decoded);\n return decoded;\n } catch (err) {\n if (err instanceof DOMException && err.name === 'AbortError') {\n return null;\n }\n console.error(`[RadarLayer] fetchAndParseArchive failed for ${objectKey}:`, err);\n return null;\n } finally {\n inflightFetches.delete(cacheKey);\n inflightFetchMeta.delete(cacheKey);\n }\n })();\n\n inflightFetches.set(cacheKey, promise);\n return promise;\n}\n\n", "import {\r\n clampNexradTiltForVariable,\r\n formatTiltForApi,\r\n getDefaultRadarTilt,\r\n getRadarTilts,\r\n isTerminalRadar,\r\n} from '@aguacerowx/javascript-sdk/nexradTilts.js';\r\n\r\n/** API elevation string for Level-III listings (lowest tilt / nominal 0.5\u00B0). */\r\nexport const NEXRAD_LEVEL3_ELEV = '0.50';\r\n\r\nfunction nearestTiltInSortedList(tilts: readonly number[], target: number): number {\r\n if (!tilts.length) return target;\r\n let best = tilts[0]!;\r\n let bestD = Math.abs(best - target);\r\n for (let i = 1; i < tilts.length; i++) {\r\n const t = tilts[i]!;\r\n const d = Math.abs(t - target);\r\n if (d < bestD || (d === bestD && t < best)) {\r\n best = t;\r\n bestD = d;\r\n }\r\n }\r\n return best;\r\n}\r\n\r\nexport const NEXRAD_LEVEL3_MOTION_PRODUCT = 'N0S';\r\n\r\nexport type Level3DecodeMode =\r\n | 'velocity'\r\n | 'dbz'\r\n | 'precip'\r\n | 'categorical'\r\n | 'tops_kft'\r\n | 'vil'\r\n /** PDB/generic-digital products already in physical units (e.g. KDP \u00B0/km); fine texture packing, not dBZ scale. */\r\n | 'generic_physical';\r\n\r\nexport type NexradLevel3MenuEntry = {\r\n /** Stored as `layer.radarVariable` and used in time-anchor keys `SITE_${radarKey}_${elev}_level3`. */\r\n radarKey: string;\r\n /** S3 object-key product mnemonic (e.g. N0B, N1P). */\r\n product: string;\r\n menuLabel: string;\r\n /** DICTIONARIES.fld key for titles / metadata. */\r\n fldKey: string;\r\n /** layerProperties key (after variable_cmap resolution from fldKey). */\r\n cmapPropertyKey: string;\r\n /** Omit for velocity (VEL): use the same mph / km/h defaults as Level-2 velocity. */\r\n defaultUnit?: string;\r\n decodeMode: Level3DecodeMode;\r\n /**\r\n * When true, this entry uses storm-relative processing (N0G + N0S).\r\n * Only the `VEL` radarKey uses this; `N0G` is base velocity from the same grid without N0S.\r\n */\r\n stormRelativeVelocity?: boolean;\r\n};\r\n\r\n/**\r\n * Level-III menu: subset aligned with products we decode as radial symbology (packets 0x0010 / 0xAF1F).\r\n * See product codes vs mnemonics: https://supercell-wx.readthedocs.io/en/stable/features/nexrad-l3.html\r\n *\r\n * Intentionally omitted for now: legacy/digital precip variants (OHA/DPA/DSP/DU6/DOD/DSD/DPR) not wired in menu,\r\n * NET/N0M, and base N0G-only velocity (menu keeps storm-relative VEL = N0G + N0S only).\r\n *\r\n * Terminal (TDWR) radars: only storm-relative velocity ({@link nexradStormRelativeVelocityUsesLevel2TiltAndFetch}) is\r\n * exposed as Level-III in the UI; other Level-III products are WSR-88D-only in this app.\r\n */\r\nexport const NEXRAD_LEVEL3_MENU: NexradLevel3MenuEntry[] = [\r\n {\r\n radarKey: 'VEL',\r\n product: 'N0G',\r\n menuLabel: 'Storm Relative Velocity',\r\n fldKey: 'nexrad_vel',\r\n cmapPropertyKey: 'nexrad_vel',\r\n decodeMode: 'velocity',\r\n stormRelativeVelocity: true,\r\n },\r\n {\r\n radarKey: 'KDP',\r\n product: 'N0K',\r\n menuLabel: 'Specific Differential Phase',\r\n fldKey: 'nexrad_l3_n0k',\r\n cmapPropertyKey: 'nexrad_kdp',\r\n defaultUnit: 'deg/km',\r\n decodeMode: 'generic_physical',\r\n },\r\n {\r\n radarKey: 'N0H',\r\n product: 'N0H',\r\n menuLabel: 'Hydrometeor Classification',\r\n fldKey: 'nexrad_l3_n0h',\r\n cmapPropertyKey: 'nexrad_l3_n0h',\r\n defaultUnit: 'None',\r\n decodeMode: 'categorical',\r\n },\r\n {\r\n radarKey: 'HHC',\r\n product: 'HHC',\r\n menuLabel: 'Hybrid Hydrometeor Classification',\r\n fldKey: 'nexrad_l3_hhc',\r\n cmapPropertyKey: 'nexrad_l3_hhc',\r\n defaultUnit: 'None',\r\n decodeMode: 'categorical',\r\n },\r\n {\r\n radarKey: 'EET',\r\n product: 'EET',\r\n menuLabel: 'Enhanced Echo Tops',\r\n fldKey: 'nexrad_l3_eet',\r\n cmapPropertyKey: 'nexrad_l3_eet',\r\n defaultUnit: 'kft',\r\n decodeMode: 'tops_kft',\r\n },\r\n {\r\n radarKey: 'DVL',\r\n product: 'DVL',\r\n menuLabel: 'Vertically Integrated Liquid',\r\n fldKey: 'nexrad_l3_dvl',\r\n cmapPropertyKey: 'nexrad_l3_dvl',\r\n defaultUnit: 'kg/m\u00B2',\r\n decodeMode: 'vil',\r\n },\r\n {\r\n radarKey: 'DAA',\r\n product: 'DAA',\r\n menuLabel: '1-Hour Precipitation',\r\n fldKey: 'nexrad_l3_daa',\r\n cmapPropertyKey: 'tp_0_1',\r\n defaultUnit: 'in',\r\n decodeMode: 'precip',\r\n },\r\n {\r\n radarKey: 'DU3',\r\n product: 'DU3',\r\n menuLabel: '3-Hour Precipitation',\r\n fldKey: 'nexrad_l3_du3',\r\n cmapPropertyKey: 'tp_0_total',\r\n defaultUnit: 'in',\r\n decodeMode: 'precip',\r\n },\r\n {\r\n radarKey: 'DTA',\r\n product: 'DTA',\r\n menuLabel: 'Storm Total Precipitation',\r\n fldKey: 'nexrad_l3_dta',\r\n cmapPropertyKey: 'tp_0_total',\r\n defaultUnit: 'in',\r\n decodeMode: 'precip',\r\n },\r\n];\r\n\r\nconst byRadarKey = new Map<string, NexradLevel3MenuEntry>();\r\nfor (const e of NEXRAD_LEVEL3_MENU) {\r\n byRadarKey.set(e.radarKey, e);\r\n // Backward compatibility: older saved layers used radarVariable=NVL.\r\n if (e.radarKey === 'DVL') byRadarKey.set('NVL', e);\r\n}\r\n\r\nexport function getNexradLevel3EntryByRadarKey(radarKey: string): NexradLevel3MenuEntry | undefined {\r\n return byRadarKey.get(radarKey);\r\n}\r\n\r\n/** Digital Specific Differential Phase (163): S3 mnemonic per elevation slot (ICD order, low \u2192 high). */\r\nexport const NEXRAD_LEVEL3_KDP_PRODUCTS: readonly string[] = [\r\n 'NXK',\r\n 'NYK',\r\n 'NZK',\r\n 'N0K',\r\n 'NAK',\r\n 'N1K',\r\n 'NBK',\r\n 'N2K',\r\n 'N3K',\r\n];\r\n\r\n/** Digital Hydrometeor Classification (165): S3 mnemonic per elevation slot (ICD order, low \u2192 high). */\r\nexport const NEXRAD_LEVEL3_DHC_PRODUCTS: readonly string[] = [\r\n 'NXH',\r\n 'NYH',\r\n 'NZH',\r\n 'N0H',\r\n 'NAH',\r\n 'N1H',\r\n 'NBH',\r\n 'N2H',\r\n 'N3H',\r\n];\r\n\r\n/**\r\n * Level-III KDP/DHC products aligned with {@link getRadarTilts} indices (lowest manifest tilt first).\r\n * NXK/NYK/NZK (and NXH\u2026) are sub\u20130.5\u00B0 cuts; our tilt manifest for KDP/N0H starts at ~0.5\u00B0 like REF,\r\n * so index 0 must map to N0K/N0H \u2014 matching historical behavior before multi-tilt wiring.\r\n */\r\nconst NEXRAD_LEVEL3_KDP_PRODUCTS_FOR_MANIFEST: readonly string[] = NEXRAD_LEVEL3_KDP_PRODUCTS.slice(3);\r\nconst NEXRAD_LEVEL3_DHC_PRODUCTS_FOR_MANIFEST: readonly string[] = NEXRAD_LEVEL3_DHC_PRODUCTS.slice(3);\r\n\r\n/**\r\n * Level-III KDP / digital HC (N0H): one S3 mnemonic per manifest slot in\r\n * {@link NEXRAD_LEVEL3_KDP_PRODUCTS_FOR_MANIFEST} / {@link NEXRAD_LEVEL3_DHC_PRODUCTS_FOR_MANIFEST}.\r\n * The UI and composite keys use the first this many tilts from {@link getRadarTilts} (site order), not a fixed elevation angle.\r\n */\r\nexport const NEXRAD_LEVEL3_MANIFEST_TILT_COUNT = NEXRAD_LEVEL3_KDP_PRODUCTS_FOR_MANIFEST.length;\r\n\r\n/** Tilts available for Level-III KDP / N0H: same order as Level II, truncated after the Nth tilt ({@link NEXRAD_LEVEL3_MANIFEST_TILT_COUNT}). */\r\nexport function getNexradLevel3RadarTilts(siteId: string, radarVariable: string): number[] {\r\n return getRadarTilts(siteId, radarVariable).slice(0, NEXRAD_LEVEL3_MANIFEST_TILT_COUNT);\r\n}\r\n\r\nexport function nexradLevel3IsTiltIndexedKdpProduct(product: string): boolean {\r\n return NEXRAD_LEVEL3_KDP_PRODUCTS.includes(product);\r\n}\r\n\r\nexport function nexradLevel3IsTiltIndexedDhcProduct(product: string): boolean {\r\n return NEXRAD_LEVEL3_DHC_PRODUCTS.includes(product);\r\n}\r\n\r\n/** Layer variable is KDP or digital HC (N0H); user tilt maps to NXK..N3K / NXH..N3H. */\r\nexport function nexradLevel3UsesTiltIndexedS3Products(radarVariable: string | undefined): boolean {\r\n const v = radarVariable || '';\r\n return v === 'KDP' || v === 'N0H';\r\n}\r\n\r\n/**\r\n * Clamp stored tilt for composite keys / fetches when `radarVariable` is KDP or N0H on true Level III.\r\n */\r\nexport function clampTiltForLevel3CompositeKey(siteId: string, radarVariable: string, tilt: number): number {\r\n if (!nexradLevel3UsesTiltIndexedS3Products(radarVariable)) {\r\n return clampNexradTiltForVariable(siteId, radarVariable, tilt);\r\n }\r\n const tilts = getNexradLevel3RadarTilts(siteId, radarVariable);\r\n const c = clampNexradTiltForVariable(siteId, radarVariable, tilt);\r\n if (!tilts.length) return c;\r\n return nearestTiltInSortedList(tilts, c);\r\n}\r\n\r\n/**\r\n * Cross section fetches: one S3 product per manifest tilt in {@link getRadarTilts} order (capped by\r\n * ICD mnemonic count). Uses the full NXK\u2013N3K / NXH\u2013N3H tables; when the lowest tilt is at or above\r\n * ~0.5\u00B0, the first slot is N0K / N0H (skipping NX, NY, NZ sub-half-degree products).\r\n */\r\nexport function nexradLevel3CrossSectionTiltProductJobs(\r\n siteId: string,\r\n radarVariable: 'KDP' | 'N0H',\r\n): { tiltDeg: number; product: string }[] {\r\n const products =\r\n radarVariable === 'KDP' ? NEXRAD_LEVEL3_KDP_PRODUCTS : NEXRAD_LEVEL3_DHC_PRODUCTS;\r\n const tilts = getRadarTilts(siteId, radarVariable);\r\n if (!tilts.length) return [];\r\n const low = tilts[0]!;\r\n const startSlot = low >= 0.45 ? 3 : 0;\r\n const nSlots = Math.min(tilts.length, products.length - startSlot);\r\n const out: { tiltDeg: number; product: string }[] = [];\r\n for (let i = 0; i < nSlots; i++) {\r\n out.push({ tiltDeg: tilts[i]!, product: products[startSlot + i]! });\r\n }\r\n return out;\r\n}\r\n\r\n/**\r\n * Map site tilt to Level-III S3 product (N0K, NAK, \u2026 / N0H, \u2026) for map tiles and time keys.\r\n */\r\nexport function nexradLevel3S3ProductForSiteTilt(\r\n siteId: string,\r\n radarVariable: 'KDP' | 'N0H',\r\n tilt: number,\r\n): string {\r\n const products =\r\n radarVariable === 'KDP' ? NEXRAD_LEVEL3_KDP_PRODUCTS_FOR_MANIFEST : NEXRAD_LEVEL3_DHC_PRODUCTS_FOR_MANIFEST;\r\n const tilts = getNexradLevel3RadarTilts(siteId, radarVariable);\r\n if (!tilts.length) {\r\n return products[0]!;\r\n }\r\n const clamped = clampTiltForLevel3CompositeKey(siteId, radarVariable, tilt);\r\n let idx = tilts.indexOf(clamped);\r\n if (idx === -1) {\r\n idx = tilts.reduce(\r\n (bestI, t, i) => (Math.abs(t - clamped) < Math.abs(tilts[bestI]! - clamped) ? i : bestI),\r\n 0,\r\n );\r\n }\r\n idx = Math.min(idx, products.length - 1);\r\n return products[idx]!;\r\n}\r\n\r\n/** Elevation string for `SITE_VAR_elev_level3` keys / UI \u2014 matches manifest slot for this S3 product. */\r\nexport function nexradLevel3DisplayElevForS3Product(\r\n siteId: string,\r\n radarVariable: 'KDP' | 'N0H',\r\n s3Product: string,\r\n): string {\r\n const tilts = getNexradLevel3RadarTilts(siteId, radarVariable);\r\n if (!tilts.length) return NEXRAD_LEVEL3_ELEV;\r\n\r\n const manifestProducts =\r\n radarVariable === 'KDP' ? NEXRAD_LEVEL3_KDP_PRODUCTS_FOR_MANIFEST : NEXRAD_LEVEL3_DHC_PRODUCTS_FOR_MANIFEST;\r\n let idx = manifestProducts.indexOf(s3Product);\r\n if (idx >= 0) {\r\n const t = tilts[Math.min(idx, tilts.length - 1)]!;\r\n return formatTiltForApi(t);\r\n }\r\n\r\n /** NXK/NYK/NZK (or NXH\u2026) from listings: not in manifest-ordered slice \u2014 use lowest tilt for keying. */\r\n const full = radarVariable === 'KDP' ? NEXRAD_LEVEL3_KDP_PRODUCTS : NEXRAD_LEVEL3_DHC_PRODUCTS;\r\n const fullIdx = full.indexOf(s3Product);\r\n if (fullIdx >= 0 && fullIdx < 3) {\r\n return formatTiltForApi(tilts[0]!);\r\n }\r\n if (fullIdx >= 3) {\r\n const mIdx = fullIdx - 3;\r\n const t = tilts[Math.min(mIdx, tilts.length - 1)]!;\r\n return formatTiltForApi(t);\r\n }\r\n return NEXRAD_LEVEL3_ELEV;\r\n}\r\n\r\n/**\r\n * Level-III products that are not tied to a selectable sweep (precip accumulations, echo tops, VIL,\r\n * hybrid HC, etc.). Hide tilt controls and ignore tilt stepping for these.\r\n * Digital HC (N0H) and KDP use {@link nexradLevel3UsesTiltIndexedS3Products}.\r\n */\r\nconst LEVEL3_DECODE_MODES_WITHOUT_USER_TILT: ReadonlySet<Level3DecodeMode> = new Set([\r\n 'precip',\r\n 'tops_kft',\r\n 'vil',\r\n 'categorical',\r\n]);\r\n\r\nexport function nexradLevel3DisallowsUserTiltChange(radarVariable: string | undefined): boolean {\r\n if (nexradLevel3UsesTiltIndexedS3Products(radarVariable)) return false;\r\n const entry = getNexradLevel3EntryByRadarKey(radarVariable || '');\r\n if (!entry) return false;\r\n if (entry.stormRelativeVelocity) return false;\r\n return LEVEL3_DECODE_MODES_WITHOUT_USER_TILT.has(entry.decodeMode);\r\n}\r\n\r\n/**\r\n * Cross sections stack multiple elevation sweeps. True Level-III products that are a single grid\r\n * (precipitation totals, echo tops, VIL, hybrid HC, etc.) cannot produce a pseudo-RHI \u2014 skip fetches.\r\n */\r\nexport function nexradCrossSectionBlockedReason(layer: {\r\n radar?: string | null;\r\n radarDataSource?: string;\r\n radarVariable?: string;\r\n level3StormRelative?: boolean;\r\n}): string | null {\r\n if (!nexradLayerUsesTrueLevel3Listing(layer)) return null;\r\n if (!nexradLevel3DisallowsUserTiltChange(layer.radarVariable)) return null;\r\n const entry = getNexradLevel3EntryByRadarKey(layer.radarVariable || '');\r\n const label = entry?.menuLabel ?? layer.radarVariable ?? 'this product';\r\n return `Cross sections are not available for ${label}.`;\r\n}\r\n\r\n/** True Level-III map products (not storm-relative velocity, which uses Level II + motion). */\r\nexport function nexradLayerUsesTrueLevel3Listing(layer: {\r\n radar?: string | null;\r\n radarDataSource?: string;\r\n radarVariable?: string;\r\n level3StormRelative?: boolean;\r\n}): boolean {\r\n return (\r\n layer.radarDataSource === 'level3' && !nexradStormRelativeVelocityUsesLevel2TiltAndFetch(layer)\r\n );\r\n}\r\n\r\n/** Terminal radars do not support true Level-III map products in this app (SRV only). */\r\nexport function terminalRadarBlocksTrueLevel3(layer: {\r\n radar?: string | null;\r\n radarDataSource?: string;\r\n radarVariable?: string;\r\n level3StormRelative?: boolean;\r\n}): boolean {\r\n const site = layer.radar || '';\r\n return isTerminalRadar(site) && nexradLayerUsesTrueLevel3Listing(layer);\r\n}\r\n\r\n/** Digital (N0H) and hybrid (HHC) hydrometeor classification \u2014 discrete classes, not a continuous field. */\r\nexport function nexradLevel3IsHydrometeorClassification(radarVariable: string | undefined): boolean {\r\n const v = radarVariable || '';\r\n return v === 'N0H' || v === 'HHC';\r\n}\r\n\r\nexport type Level3ExpandTarget = { radarKey: string; attachMotionMap: boolean };\r\n\r\n/** Map raw S3 product code to one or more formatted time-anchor variables. */\r\nexport function getLevel3ExpansionTargetsForS3Product(product: string): Level3ExpandTarget[] {\r\n if (product === NEXRAD_LEVEL3_MOTION_PRODUCT) {\r\n return [];\r\n }\r\n if (product === 'DVL') {\r\n // Emit both keys so old NVL layers and new DVL layers resolve the same time map.\r\n return [\r\n { radarKey: 'DVL', attachMotionMap: false },\r\n { radarKey: 'NVL', attachMotionMap: false },\r\n ];\r\n }\r\n if (product === 'N0G') {\r\n return [\r\n { radarKey: 'N0G', attachMotionMap: false },\r\n { radarKey: 'VEL', attachMotionMap: true },\r\n ];\r\n }\r\n if (nexradLevel3IsTiltIndexedKdpProduct(product)) {\r\n return [{ radarKey: 'KDP', attachMotionMap: false }];\r\n }\r\n if (nexradLevel3IsTiltIndexedDhcProduct(product)) {\r\n return [{ radarKey: 'N0H', attachMotionMap: false }];\r\n }\r\n return [{ radarKey: product, attachMotionMap: false }];\r\n}\r\n\r\n/**\r\n * Product 135 (EET): MetPy `DigitalEETMapper` uses PDB thr1\u2013thr3 as data mask, scale, and offset:\r\n * `mapped = ((level & mask) - offset) / scale` (raw signed halfwords \u2014 no /10; unlike dBZ min/inc).\r\n *\r\n * Output is treated as **kilometers** end-to-end with the rest of `tops_kft` packing.\r\n */\r\nexport function level3EetHeightKmFromLevel(\r\n level: number,\r\n dataMaskRaw: number,\r\n scaleRaw: number,\r\n offsetRaw: number,\r\n): number | null {\r\n if (level < 2) return null;\r\n const masked = level & (dataMaskRaw & 0xffff);\r\n if (!Number.isFinite(scaleRaw) || scaleRaw === 0) {\r\n return level - 2;\r\n }\r\n const mapped = (masked - offsetRaw) / scaleRaw;\r\n if (!Number.isFinite(mapped)) return null;\r\n return mapped;\r\n}\r\n\r\nexport function level3ValuePacking(decodeMode: Level3DecodeMode): { valueScale: number; valueOffset: number } {\r\n switch (decodeMode) {\r\n case 'velocity':\r\n return { valueScale: 0.01, valueOffset: 0 };\r\n case 'dbz':\r\n return { valueScale: 0.5, valueOffset: -32 };\r\n case 'precip':\r\n return { valueScale: 0.001, valueOffset: 0 };\r\n case 'categorical':\r\n return { valueScale: 1, valueOffset: 0 };\r\n case 'tops_kft':\r\n // Shader physical = raw * valueScale (km). raw = round(km / valueScale) must stay within int16.\r\n // 0.001 implied raw = meters \u2192 tops >32.767 km clamped (seen on EET ~48 km). Use 2 m/LSb \u2192 max ~65.5 km.\r\n return { valueScale: 0.002, valueOffset: 0 };\r\n case 'vil':\r\n return { valueScale: 0.1, valueOffset: 0 };\r\n case 'generic_physical':\r\n return { valueScale: 0.01, valueOffset: 0 };\r\n default:\r\n return { valueScale: 0.5, valueOffset: -32 };\r\n }\r\n}\r\n\r\n/**\r\n * Opt-in storm-relative velocity (super-res VEL + N0S motion). Set in localStorage to trace: DEBUG_NEXRAD_VEL=1\r\n */\r\nfunction nexradVelDebug(label: string, data: Record<string, unknown>) {\r\n try {\r\n if (typeof localStorage !== 'undefined' && localStorage.getItem('DEBUG_NEXRAD_VEL') === '1') {\r\n console.log(`[NEXRAD_VEL] ${label}`, data);\r\n }\r\n } catch {\r\n /* ignore */\r\n }\r\n}\r\n\r\n/**\r\n * Storm-relative velocity is rendered from Level-2 super-res VEL at the user\u2019s tilt plus L3 N0S motion.\r\n * Layers may still have `radarDataSource: 'level3'` when chosen from the Level-III menu.\r\n *\r\n * `level3StormRelative === undefined` must NOT default to \u201Con\u201D for Level-II velocity (that broke base VEL).\r\n * For legacy layers with L3-menu VEL and no flag, infer SRV only when `radarDataSource === 'level3'`.\r\n */\r\nexport function nexradStormRelativeVelocityUsesLevel2TiltAndFetch(layer: {\r\n radar?: string | null;\r\n radarVariable?: string;\r\n level3StormRelative?: boolean;\r\n radarDataSource?: string;\r\n}): boolean {\r\n if ((layer.radarVariable || 'REF') !== 'VEL') {\r\n return false;\r\n }\r\n if (layer.level3StormRelative === true) return true;\r\n if (layer.level3StormRelative === false) return false;\r\n const inferred = (layer.radarDataSource || 'level2') === 'level3';\r\n nexradVelDebug('VEL level3StormRelative missing \u2014 infer from radarDataSource', {\r\n radar: layer.radar,\r\n radarDataSource: layer.radarDataSource,\r\n useStormRelativeVelocity: inferred,\r\n });\r\n return inferred;\r\n}\r\n\r\n/**\r\n * True when composite time keys and map wiring should use `layer.radarTilt` (like Level II), not a fixed 0.5\u00B0 token.\r\n */\r\nexport function nexradLevel3LayerUsesRadarTiltInCompositeKeys(layer: {\r\n radar?: string | null;\r\n radarVariable?: string;\r\n radarDataSource?: string;\r\n level3StormRelative?: boolean;\r\n}): boolean {\r\n if (layer.radarDataSource !== 'level3') return false;\r\n if (nexradStormRelativeVelocityUsesLevel2TiltAndFetch(layer)) return false;\r\n return nexradLevel3UsesTiltIndexedS3Products(layer.radarVariable);\r\n}\r\n\r\nexport function nexradEffectiveFetchSource(layer: {\r\n radar?: string | null;\r\n radarVariable?: string;\r\n radarDataSource?: string;\r\n level3StormRelative?: boolean;\r\n}): 'level2' | 'level3' {\r\n if (terminalRadarBlocksTrueLevel3(layer)) return 'level2';\r\n if (nexradStormRelativeVelocityUsesLevel2TiltAndFetch(layer)) return 'level2';\r\n return layer.radarDataSource === 'level3' ? 'level3' : 'level2';\r\n}\r\n\r\nexport function nexradTimesFetchOptionsFromLayer(layer: {\r\n radar?: string | null;\r\n radarVariable?: string;\r\n radarDataSource?: string;\r\n level3StormRelative?: boolean;\r\n radarTilt?: number | null;\r\n}): { level3Product?: string; level3StormRelative?: boolean } | undefined {\r\n if (terminalRadarBlocksTrueLevel3(layer)) return undefined;\r\n /** L2 fetch + N0S time alignment for storm-relative velocity (super-res VEL + motion). */\r\n if (nexradStormRelativeVelocityUsesLevel2TiltAndFetch(layer)) {\r\n return { level3StormRelative: true };\r\n }\r\n if (layer.radarDataSource !== 'level3') return undefined;\r\n const v = layer.radarVariable || 'REF';\r\n const entry = getNexradLevel3EntryByRadarKey(v);\r\n let product = entry?.product ?? (v === 'VEL' ? 'N0G' : v);\r\n const site = layer.radar || '';\r\n if (site && nexradLevel3UsesTiltIndexedS3Products(v)) {\r\n const tilt = layer.radarTilt ?? getDefaultRadarTilt(site);\r\n product = nexradLevel3S3ProductForSiteTilt(site, v as 'KDP' | 'N0H', tilt);\r\n }\r\n const stormRelative = v === 'VEL' ? nexradStormRelativeVelocityUsesLevel2TiltAndFetch(layer) : false;\r\n return { level3Product: product, level3StormRelative: stormRelative };\r\n}\r\n\r\nexport function formatLevel3TiltForApi(): string {\r\n return NEXRAD_LEVEL3_ELEV;\r\n}\r\n", "import type { DecodedRadarFrame } from './nexradArchiveCache.js';\r\n\r\n/**\r\n * Storm motion from N0S (ICD 56) product description dep8/dep9, same as AtticRadar\r\n * (loaders_nexrad.js process_storm_relative_velocity).\r\n * dep8: storm speed in tenths of knots; dep9: direction in tenths of degrees.\r\n */\r\nexport function parseLevel3StormMotionFromBuffer(buffer: ArrayBuffer): { speedMs: number; directionDeg: number } | null {\r\n const bytes = new Uint8Array(buffer);\r\n const marker = [83, 68, 85, 83];\r\n let start = 0;\r\n for (let i = 0; i <= bytes.length - 4; i++) {\r\n if (bytes[i] === marker[0] && bytes[i + 1] === marker[1] && bytes[i + 2] === marker[2] && bytes[i + 3] === marker[3]) {\r\n start = i;\r\n break;\r\n }\r\n }\r\n const dv = new DataView(buffer, start, bytes.length - start);\r\n const textLen = 30;\r\n const msgHdrLen = 18;\r\n const pdbStart = textLen + msgHdrLen;\r\n if (pdbStart + 86 > dv.byteLength) return null;\r\n if (dv.getInt16(pdbStart, false) !== -1) return null;\r\n const dep8Offset = pdbStart + 82;\r\n const dep8 = dv.getInt16(dep8Offset, false);\r\n const dep9 = dv.getInt16(dep8Offset + 2, false);\r\n const stormSpeedKt = dep8 / 10;\r\n const speedMs = stormSpeedKt * 0.514444;\r\n const directionDeg = dep9 / 10;\r\n if (!Number.isFinite(speedMs) || !Number.isFinite(directionDeg)) return null;\r\n return { speedMs, directionDeg };\r\n}\r\n\r\n/** AtticRadar calculateStormComponent \u2014 radial component of storm motion (m/s). */\r\nexport function level3StormRadialComponentMs(stormSpeedMs: number, stormDirectionDeg: number, azimuthDeg: number): number {\r\n const stormDirRad = (stormDirectionDeg * Math.PI) / 180;\r\n const azRad = (azimuthDeg * Math.PI) / 180;\r\n return stormSpeedMs * Math.cos(stormDirRad - azRad);\r\n}\r\n\r\nfunction decodeGateRawMs(hi: number, lo: number, valueScale: number, valueOffset: number): number | null {\r\n const raw = lo + hi * 256;\r\n let signed = raw;\r\n if (raw >= 32768) signed = raw - 65536;\r\n if (signed <= -32768) return null;\r\n return signed * valueScale + valueOffset;\r\n}\r\n\r\nfunction encodeGateRawMs(physicalMs: number, valueScale: number, valueOffset: number): [number, number] {\r\n const raw = Math.round((physicalMs - valueOffset) / valueScale);\r\n const signed = Math.max(-32768, Math.min(32767, raw));\r\n const u = signed < 0 ? signed + 65536 : signed;\r\n return [(u >> 8) & 0xff, u & 0xff];\r\n}\r\n\r\n/**\r\n * Apply storm-relative correction to super-res base velocity (N0G): v_srv = v + storm_radial_component.\r\n * Matches AtticRadar process_storm_relative_velocity / PR #12.\r\n */\r\nexport function applyLevel3StormRelativeToFrame(\r\n frame: DecodedRadarFrame,\r\n stormSpeedMs: number,\r\n stormDirectionDeg: number,\r\n): DecodedRadarFrame {\r\n const { nRays, nGates, gateData, rayBoundariesDeg, valueScale, valueOffset } = frame;\r\n const out = new Uint8Array(gateData.length);\r\n for (let r = 0; r < nRays; r++) {\r\n const azLow = rayBoundariesDeg[r];\r\n const azHigh = rayBoundariesDeg[r + 1];\r\n const azimuthDeg = (Number(azLow) + Number(azHigh)) * 0.5;\r\n const stormComp = level3StormRadialComponentMs(stormSpeedMs, stormDirectionDeg, azimuthDeg);\r\n for (let g = 0; g < nGates; g++) {\r\n const o = (r * nGates + g) * 2;\r\n const hi = gateData[o];\r\n const lo = gateData[o + 1];\r\n const v = decodeGateRawMs(hi, lo, valueScale, valueOffset);\r\n if (v == null) {\r\n out[o] = hi;\r\n out[o + 1] = lo;\r\n continue;\r\n }\r\n const corrected = v + stormComp;\r\n const [nh, nl] = encodeGateRawMs(corrected, valueScale, valueOffset);\r\n out[o] = nh;\r\n out[o + 1] = nl;\r\n }\r\n }\r\n return { ...frame, gateData: out };\r\n}\r\n\r\nexport function pickNearestLevel3ObjectKey(\r\n unixTime: number,\r\n timeToKeyMap: Record<string, string>,\r\n maxDeltaSec = 600,\r\n): string | null {\r\n const direct = timeToKeyMap[String(unixTime)];\r\n if (direct) return direct;\r\n const entries = Object.entries(timeToKeyMap);\r\n if (entries.length === 0) return null;\r\n let bestKey: string | null = null;\r\n let bestDelta = Infinity;\r\n for (const [tStr, key] of entries) {\r\n const t = Number(tStr);\r\n if (!Number.isFinite(t)) continue;\r\n const d = Math.abs(t - unixTime);\r\n if (d < bestDelta) {\r\n bestDelta = d;\r\n bestKey = key;\r\n }\r\n }\r\n if (bestKey == null) return null;\r\n if (bestDelta > maxDeltaSec && Number.isFinite(maxDeltaSec)) {\r\n return null;\r\n }\r\n return bestKey;\r\n}\r\n", "// Shared archive cache for decoded NEXRAD sweep frames.\r\n// Lives in a separate module so RadarLayer and GlobalStateContext can both access it\r\n// without creating a circular import dependency.\r\n//\r\n// Rolling cache across all radar sites: we do NOT clear on station or variable change,\r\n// so returning to a previously viewed site reuses cached frames. When the cache exceeds\r\n// MAX_ARCHIVE_CACHE_ENTRIES, the oldest entries (by insertion order) are evicted.\r\n\r\n// \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\nexport type DecodedRadarFrame = {\r\n gateData: Uint8Array;\r\n nRays: number;\r\n nGates: number;\r\n stationLat: number;\r\n stationLon: number;\r\n firstGateKm: number;\r\n gateWidthKm: number;\r\n valueScale: number;\r\n valueOffset: number;\r\n rayBoundariesDeg: Float32Array;\r\n};\r\n\r\n// \u2500\u2500\u2500 Cache storage \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\n// Rolling cache size. Keeps decoded frames across site/variable switches; evicts oldest when over.\r\n// ~14 tilts \u00D7 ~72 time steps \u2248 1008 frames per site; 4 sites \u2248 4k frames.\r\nconst MAX_ARCHIVE_CACHE_ENTRIES = 5000;\r\n\r\nexport const archiveCache = new Map<string, DecodedRadarFrame | null>();\r\n\r\nexport function setArchiveCache(url: string, archive: DecodedRadarFrame | null): void {\r\n archiveCache.delete(url);\r\n archiveCache.set(url, archive);\r\n while (archiveCache.size > MAX_ARCHIVE_CACHE_ENTRIES) {\r\n const oldestKey = archiveCache.keys().next().value;\r\n if (!oldestKey) break;\r\n archiveCache.delete(oldestKey);\r\n }\r\n}\r\n\r\n// \u2500\u2500\u2500 Optional explicit eviction \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\n/**\r\n * Remove all archiveCache entries that belong to a given radar station.\r\n * Not used on station change (rolling cache); available for manual/optional clearing.\r\n */\r\nexport function clearArchiveCacheForStation(stationId: string): void {\r\n const prefix = `/${stationId}_`;\r\n for (const url of Array.from(archiveCache.keys())) {\r\n if (url.includes(prefix)) archiveCache.delete(url);\r\n }\r\n}\r\n\r\n/**\r\n * Remove all archiveCache entries for a specific station + variable combination.\r\n * Not used on variable change (rolling cache); available for manual/optional clearing.\r\n */\r\nexport function clearArchiveCacheForStationVariable(stationId: string, variable: string): void {\r\n const prefix = `/${stationId}_${variable}_`;\r\n for (const url of Array.from(archiveCache.keys())) {\r\n if (url.includes(prefix)) archiveCache.delete(url);\r\n }\r\n}\r\n", "import type { NexradSite } from './PreprocessedSweepParser.js';\r\n\r\ntype NexradSitesPayload = {\r\n sites?: NexradSite[];\r\n features?: unknown[];\r\n} | NexradSite[];\r\n\r\nlet sitesUrl = 'https://d3dc62msmxkrd7.cloudfront.net/data/nexrad.json';\r\n\r\n/** Override default nexrad.json URL (e.g. host `/data/nexrad.json` locally). */\r\nexport function setNexradSitesJsonUrl(url: string) {\r\n sitesUrl = url || sitesUrl;\r\n}\r\n\r\nlet nexradSitesPayloadPromise: Promise<NexradSitesPayload> | null = null;\r\n\r\nexport function loadNexradSitesPayload(): Promise<NexradSitesPayload> {\r\n if (nexradSitesPayloadPromise) {\r\n return nexradSitesPayloadPromise;\r\n }\r\n nexradSitesPayloadPromise = fetch(sitesUrl)\r\n .then((response) => {\r\n if (!response.ok) throw new Error(`nexrad.json fetch failed: HTTP ${response.status}`);\r\n return response.json() as Promise<NexradSitesPayload>;\r\n })\r\n .catch((error) => {\r\n console.error('[mapsgl] Could not load nexrad.json:', error);\r\n nexradSitesPayloadPromise = null;\r\n throw error;\r\n });\r\n return nexradSitesPayloadPromise;\r\n}\r\n\r\nexport async function loadNexradSites(): Promise<NexradSite[]> {\r\n const payload = await loadNexradSitesPayload();\r\n if (Array.isArray(payload)) return payload as NexradSite[];\r\n const sites = (payload as { sites?: NexradSite[] }).sites;\r\n if (sites && Array.isArray(sites)) return sites;\r\n return [];\r\n}\r\n"],
|
|
5
|
+
"mappings": "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AAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QAAY;AAAA,QACpF;AAAA,QAAY;AAAA,QAAY;AAAA,Q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",
|
|
6
|
+
"names": ["offset", "decoded"]
|
|
7
|
+
}
|