@aguacerowx/javascript-sdk 0.0.8 → 0.0.10

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.
@@ -10,7 +10,6 @@ var _unitConversions = require("./unitConversions.js");
10
10
  var _dictionaries = require("./dictionaries.js");
11
11
  var _defaultColormaps = require("./default-colormaps.js");
12
12
  var _proj = _interopRequireDefault(require("proj4"));
13
- var _fzstd = require("fzstd");
14
13
  var _getBundleId = require("./getBundleId");
15
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
15
  // AguaceroCore.js - The Headless "Engine"
@@ -92,7 +91,7 @@ class AguaceroCore extends _events.EventEmitter {
92
91
  run: null,
93
92
  forecastHour: 0,
94
93
  visible: true,
95
- opacity: userLayerOptions.opacity ?? 0.85,
94
+ opacity: userLayerOptions.opacity ?? 1,
96
95
  units: options.initialUnit || 'imperial',
97
96
  shaderSmoothingEnabled: options.shaderSmoothingEnabled ?? true
98
97
  };
@@ -190,24 +189,60 @@ class AguaceroCore extends _events.EventEmitter {
190
189
  this.isPlaying ? this.pause() : this.play();
191
190
  }
192
191
  step(direction = 1) {
193
- var _this$modelStatus3;
194
- const {
195
- model,
196
- date,
197
- run,
198
- forecastHour
199
- } = this.state;
200
- const forecastHours = (_this$modelStatus3 = this.modelStatus) === null || _this$modelStatus3 === void 0 || (_this$modelStatus3 = _this$modelStatus3[model]) === null || _this$modelStatus3 === void 0 || (_this$modelStatus3 = _this$modelStatus3[date]) === null || _this$modelStatus3 === void 0 ? void 0 : _this$modelStatus3[run];
201
- if (!forecastHours || forecastHours.length === 0) return;
202
- const currentIndex = forecastHours.indexOf(forecastHour);
203
- if (currentIndex === -1) return;
204
- const maxIndex = forecastHours.length - 1;
205
- let nextIndex = currentIndex + direction;
206
- if (nextIndex > maxIndex) nextIndex = 0;
207
- if (nextIndex < 0) nextIndex = maxIndex;
208
- this.setState({
209
- forecastHour: forecastHours[nextIndex]
210
- });
192
+ // --- THIS IS THE CORRECTED MRMS LOGIC ---
193
+ if (this.state.isMRMS) {
194
+ const {
195
+ variable,
196
+ mrmsTimestamp
197
+ } = this.state;
198
+ if (!this.mrmsStatus || !this.mrmsStatus[variable]) {
199
+ console.warn('[Core.step] MRMS status or variable not available.');
200
+ return;
201
+ }
202
+
203
+ // CRITICAL FIX: The UI and state emissions use a REVERSED array (newest first).
204
+ // The step logic MUST use the same reversed array for indexes to match.
205
+ const availableTimestamps = [...(this.mrmsStatus[variable] || [])].reverse();
206
+ if (availableTimestamps.length === 0) return;
207
+ const currentIndex = availableTimestamps.indexOf(mrmsTimestamp);
208
+ if (currentIndex === -1) {
209
+ // If not found, reset to the first (newest) frame
210
+ this.setState({
211
+ mrmsTimestamp: availableTimestamps[0]
212
+ });
213
+ return;
214
+ }
215
+ const maxIndex = availableTimestamps.length - 1;
216
+ let nextIndex = currentIndex + direction;
217
+
218
+ // Loop animation
219
+ if (nextIndex > maxIndex) nextIndex = 0;
220
+ if (nextIndex < 0) nextIndex = maxIndex;
221
+ const newTimestamp = availableTimestamps[nextIndex];
222
+ this.setState({
223
+ mrmsTimestamp: newTimestamp
224
+ });
225
+ } else {
226
+ var _this$modelStatus3;
227
+ const {
228
+ model,
229
+ date,
230
+ run,
231
+ forecastHour
232
+ } = this.state;
233
+ const forecastHours = (_this$modelStatus3 = this.modelStatus) === null || _this$modelStatus3 === void 0 || (_this$modelStatus3 = _this$modelStatus3[model]) === null || _this$modelStatus3 === void 0 || (_this$modelStatus3 = _this$modelStatus3[date]) === null || _this$modelStatus3 === void 0 ? void 0 : _this$modelStatus3[run];
234
+ if (!forecastHours || forecastHours.length === 0) return;
235
+ const currentIndex = forecastHours.indexOf(forecastHour);
236
+ if (currentIndex === -1) return;
237
+ const maxIndex = forecastHours.length - 1;
238
+ let nextIndex = currentIndex + direction;
239
+ if (nextIndex > maxIndex) nextIndex = 0;
240
+ if (nextIndex < 0) nextIndex = maxIndex;
241
+ const newHour = forecastHours[nextIndex];
242
+ this.setState({
243
+ forecastHour: newHour
244
+ });
245
+ }
211
246
  }
212
247
  setPlaybackSpeed(speed) {
213
248
  if (speed > 0) {
@@ -350,6 +385,10 @@ class AguaceroCore extends _events.EventEmitter {
350
385
  return new Uint8Array(reconstructedData.buffer);
351
386
  }
352
387
  async _loadGridData(state) {
388
+ if (this.isReactNative) {
389
+ console.warn(`[AguaceroCore] _loadGridData was called in React Native. This is a bypass. Data loading is handled natively.`);
390
+ return null;
391
+ }
353
392
  const {
354
393
  model,
355
394
  date,
@@ -404,7 +443,7 @@ class AguaceroCore extends _events.EventEmitter {
404
443
  const headers = {
405
444
  'x-api-key': this.apiKey
406
445
  };
407
- if (this.bundleId) {
446
+ if (this.bundleId && this.isReactNative) {
408
447
  headers['x-app-identifier'] = this.bundleId;
409
448
  }
410
449
  const response = await fetch(urlWithApiKeyParam, {
@@ -504,20 +543,68 @@ class AguaceroCore extends _events.EventEmitter {
504
543
  const index1D = j * nx + i;
505
544
  const byteValue = gridData.data[index1D];
506
545
  const signedQuantizedValue = byteValue - 128;
546
+
547
+ // --- START OF FIX ---
548
+ // You were missing 'scale_type' in this destructuring assignment.
507
549
  const {
508
550
  scale,
509
551
  offset,
510
- missing_quantized
552
+ missing_quantized,
553
+ scale_type
511
554
  } = gridData.encoding;
555
+ // --- END OF FIX ---
556
+
512
557
  if (signedQuantizedValue === missing_quantized) return null;
513
- const nativeValue = signedQuantizedValue * scale + offset;
558
+ const intermediateValue = signedQuantizedValue * scale + offset;
559
+
560
+ // Step 2: Apply non-linear scaling if specified
561
+ let nativeValue = intermediateValue;
562
+ if (scale_type === 'sqrt') {
563
+ // Square the value while preserving its sign
564
+ nativeValue = intermediateValue < 0 ? -(intermediateValue * intermediateValue) : intermediateValue * intermediateValue;
565
+ }
514
566
  const {
567
+ colormap,
515
568
  baseUnit
516
569
  } = this._getColormapForVariable(variable);
570
+
571
+ // If the value is outside the colormap's bounds, return null.
572
+ if (colormap && colormap.length >= 2) {
573
+ const minBound = colormap[0];
574
+ const maxBound = colormap[colormap.length - 2];
575
+ if (nativeValue < minBound || nativeValue > maxBound) {
576
+ return null;
577
+ }
578
+ }
517
579
  let dataNativeUnit = baseUnit || (_dictionaries.DICTIONARIES.fld[variable] || {}).defaultUnit || 'none';
518
580
  const displayUnit = this._getTargetUnit(dataNativeUnit, units);
519
581
  const conversionFunc = (0, _unitConversions.getUnitConversionFunction)(dataNativeUnit, displayUnit);
520
- const displayValue = conversionFunc ? conversionFunc(nativeValue) : nativeValue;
582
+ let displayValue = conversionFunc ? conversionFunc(nativeValue) : nativeValue;
583
+
584
+ // --- START: ADDED CODE ---
585
+
586
+ // Create a variable to hold the precipitation type, if any.
587
+ let precipType = null;
588
+
589
+ // Check if the current variable is one of the special ptype variables.
590
+ if (variable === 'ptypeRefl' || variable === 'ptypeRate') {
591
+ const value = nativeValue; // Use the raw, unconverted value for ptype logic
592
+
593
+ if (value >= 100 && value < 200) {
594
+ displayValue -= 100;
595
+ precipType = 'Snow';
596
+ } else if (value >= 200 && value < 300) {
597
+ displayValue -= 200;
598
+ precipType = 'Frzg Rain'; // Abbreviated for tooltips
599
+ } else if (value >= 300 && value < 400) {
600
+ displayValue -= 300;
601
+ precipType = 'Ice Pellets';
602
+ } else {
603
+ precipType = 'Rain';
604
+ }
605
+ }
606
+
607
+ // Return the final payload, now including the precipType.
521
608
  return {
522
609
  lngLat: {
523
610
  lng,
@@ -528,7 +615,8 @@ class AguaceroCore extends _events.EventEmitter {
528
615
  name: this.getVariableDisplayName(variable)
529
616
  },
530
617
  value: displayValue,
531
- unit: displayUnit
618
+ unit: displayUnit,
619
+ precipType: precipType // NEW: Add this to the return object
532
620
  };
533
621
  } catch (error) {
534
622
  return null;
@@ -548,9 +636,6 @@ class AguaceroCore extends _events.EventEmitter {
548
636
  colormap: [],
549
637
  baseUnit: ''
550
638
  };
551
-
552
- // This logic for user-provided custom colormaps is correct.
553
- // If a user provides a custom map, it should always take top priority.
554
639
  if (this.customColormaps[variable] && this.customColormaps[variable].colormap) {
555
640
  return {
556
641
  colormap: this.customColormaps[variable].colormap,
@@ -566,45 +651,18 @@ class AguaceroCore extends _events.EventEmitter {
566
651
  };
567
652
  }
568
653
  const defaultColormapData = _defaultColormaps.DEFAULT_COLORMAPS[colormapKey];
569
-
570
- // --- START OF THE BUG FIX ---
571
- // This block handles the "default" case when no custom colormap is provided.
572
654
  if (defaultColormapData && defaultColormapData.units) {
573
- var _DICTIONARIES$fld$var;
574
- // 1. EDITED: Explicitly look up the CORRECT default unit from the main dictionary.
575
- // This is the information source we were previously ignoring.
576
- const preferredUnit = (_DICTIONARIES$fld$var = _dictionaries.DICTIONARIES.fld[variable]) === null || _DICTIONARIES$fld$var === void 0 ? void 0 : _DICTIONARIES$fld$var.defaultUnit; // e.g., '°C' for '2t_2'
577
-
578
- // 2. EDITED: Check if that preferred unit exists in the colormap definitions.
579
- if (preferredUnit && defaultColormapData.units[preferredUnit]) {
580
- const unitData = defaultColormapData.units[preferredUnit];
581
- if (unitData && unitData.colormap) {
582
- // 3. EDITED: If it exists, return ITS data. This is the correct path.
583
- console.log(`[AguaceroCore] Using dictionary default unit '${preferredUnit}' for variable '${variable}'.`);
584
- return {
585
- colormap: unitData.colormap,
586
- baseUnit: preferredUnit
587
- };
588
- }
589
- }
590
-
591
- // 4. EDITED: The old, buggy logic now serves as a FALLBACK ONLY.
592
- // This will only run if the specified defaultUnit is missing from the colormap data.
593
- console.warn(`[AguaceroCore] Default unit for '${variable}' not found in colormap. Using fallback.`);
594
- const availableUnits = Object.keys(defaultColormapData.units);
595
- if (availableUnits.length > 0) {
596
- const fallbackUnit = availableUnits[0]; // e.g., '°F'
597
- const unitData = defaultColormapData.units[fallbackUnit];
598
- if (unitData && unitData.colormap) {
599
- return {
600
- colormap: unitData.colormap,
601
- baseUnit: fallbackUnit
602
- };
603
- }
655
+ // ✅ Get defaultUnit from the field dictionary
656
+ const fieldInfo = _dictionaries.DICTIONARIES.fld[variable] || {};
657
+ const baseUnit = fieldInfo.defaultUnit || Object.keys(defaultColormapData.units)[0];
658
+ const unitData = defaultColormapData.units[baseUnit];
659
+ if (unitData && unitData.colormap) {
660
+ return {
661
+ colormap: unitData.colormap,
662
+ baseUnit: baseUnit
663
+ };
604
664
  }
605
665
  }
606
- // --- END OF THE BUG FIX ---
607
-
608
666
  return {
609
667
  colormap: [],
610
668
  baseUnit: ''
@@ -713,13 +771,15 @@ class AguaceroCore extends _events.EventEmitter {
713
771
  }
714
772
  _getTargetUnit(defaultUnit, system) {
715
773
  if (system === 'metric') {
716
- if (['°F', '°C'].includes(defaultUnit)) return 'celsius';
774
+ if (['°F', '°C', 'fahrenheit', 'celsius'].includes(defaultUnit)) return '°C';
717
775
  if (['kts', 'mph', 'm/s'].includes(defaultUnit)) return 'km/h';
718
776
  if (['in', 'mm', 'cm'].includes(defaultUnit)) return 'mm';
719
777
  }
720
- if (['°F', '°C'].includes(defaultUnit)) return 'fahrenheit';
721
- if (['kts', 'mph', 'm/s'].includes(defaultUnit)) return 'mph';
722
- if (['in', 'mm', 'cm'].includes(defaultUnit)) return 'in';
778
+ if (system === 'imperial') {
779
+ if (['°F', '°C', 'fahrenheit', 'celsius'].includes(defaultUnit)) return '°F';
780
+ if (['kts', 'mph', 'm/s'].includes(defaultUnit)) return 'mph';
781
+ if (['in', 'mm', 'cm'].includes(defaultUnit)) return 'in';
782
+ }
723
783
  return defaultUnit;
724
784
  }
725
785
  _getGridIndexFromLngLat(lng, lat) {
@@ -17,14 +17,10 @@ const DEFAULT_COLORMAPS = exports.DEFAULT_COLORMAPS = {
17
17
  // --- Snow Palette (Reflectivity Values Offset by +100) ---
18
18
  105, "#33ccff", 135, "#8800cc", 170, "#ffccff", 180, "#dddddd",
19
19
  // --- Freezing Rain Palette (Reflectivity Values Offset by +200) ---
20
- 205, "#ff3300", 230, "#ffaa33", 280, "#cc0066"],
21
- "breakpoints": [
22
- // Rain Breakpoints
23
- 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80,
24
- // Snow Breakpoints
25
- 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175, 180,
26
- // Freezing Rain Breakpoints
27
- 205, 210, 215, 220, 225, 230, 235, 240, 245, 250, 255, 260, 265, 270, 275, 280]
20
+ 205, "#ff3300", 230, "#ffaa33", 280, "#cc0066",
21
+ // icep
22
+ 305, "#8800cc", 370, "#ffbb00", 380, "#dddddd"],
23
+ "breakpoints": []
28
24
  }
29
25
  }
30
26
  },
@@ -811,6 +807,37 @@ const DEFAULT_COLORMAPS = exports.DEFAULT_COLORMAPS = {
811
807
  }
812
808
  }
813
809
  },
810
+ "ptypeRate": {
811
+ "type": "fill",
812
+ "gridded": false,
813
+ "interpolationType": "interpolate",
814
+ "units": {
815
+ "in/hr": {
816
+ "colormap": [
817
+ // --- Rain Palette (Standard Reflectivity Values: 5 to 80) ---
818
+ 0.005, "#00cc66", 0.1, "#ffff00", 0.3, "#ff8800", 1, "#ff0000", 1.5, '#ff00cc',
819
+ // --- Snow Palette (Reflectivity Values Offset by +100) ---
820
+ 100.05, "#33ccff", 101, "#000099", 104, "#ff00cc",
821
+ // --- Freezing Rain Palette (Reflectivity Values Offset by +200) ---
822
+ 200.005, "#ff3300", 200.1, "#ff33ff", 200.6, "#cc99cc",
823
+ // icep
824
+ 300.005, "#8800cc", 300.2, "#aa44dd", 300.6, "#cc88dd"],
825
+ "breakpoints": []
826
+ },
827
+ "mm/hr": {
828
+ "colormap": [
829
+ // --- Rain Palette (Standard Reflectivity Values: 5 to 80) ---
830
+ 0.1, "#00cc66", 3, "#ffff00", 7, "#ff8800", 24, "#ff0000", 36, '#ff00cc',
831
+ // --- Snow Palette (Reflectivity Values Offset by +100) ---
832
+ 100.1, "#33ccff", 103, "#000099", 110, "#ff00cc",
833
+ // --- Freezing Rain Palette (Reflectivity Values Offset by +200) ---
834
+ 200.1, "#ff3300", 203, "#ff33ff", 214, "#cc99cc",
835
+ // icep
836
+ 300.1, "#ff3300", 303, "#ff33ff", 314, "#cc99cc"],
837
+ "breakpoints": []
838
+ }
839
+ }
840
+ },
814
841
  "frzrRefl": {
815
842
  "type": "fill",
816
843
  "gridded": false,
@@ -902,11 +929,11 @@ const DEFAULT_COLORMAPS = exports.DEFAULT_COLORMAPS = {
902
929
  "colormap": [0.01, "#eeccff", .1, "#ff9999", .25, "#cc3366", .5, "#ff9933", .75, "#ffee00", 1, "#00cccc", 3, "#99ffff"],
903
930
  "breakpoints": [0.01, 0.1, 0.25, 0.5, 0.75, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 7, 8, 9, 10]
904
931
  },
905
- "cm": {
932
+ "cm [QPF]": {
906
933
  "colormap": [0.03, "#eeccff", .25, "#ff9999", .75, "#cc3366", 1, "#cc0066", 2, "#ffee00", 3, "#00cccc", 7, "#99ffff"],
907
934
  "breakpoints": [.03, .25, .5, .75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4, 4.5, 5, 5.5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 22, 24, 26]
908
935
  },
909
- "mm": {
936
+ "mm [QPF]": {
910
937
  "colormap": [0.3, "#eeccff", 2.5, "#ff9999", 7.5, "#cc3366", 10, "#cc0066", 20, "#ffee00", 30, "#00cccc", 70, "#99ffff"],
911
938
  "breakpoints": [0.3, 2.5, 5, 7.5, 10, 12.5, 15, 17.5, 20, 22.5, 25, 27.5, 30, 32.5, 35, 37.5, 40, 45, 50, 55, 60, 70, 80, 90, 100, 120, 140, 160, 180, 200, 220, 240, 260]
912
939
  }
@@ -921,11 +948,11 @@ const DEFAULT_COLORMAPS = exports.DEFAULT_COLORMAPS = {
921
948
  "colormap": [0.01, "#eeccff", .1, "#ff9999", .3, "#cc3366", .4, "#cc0033", .5, "#ff9933", .9, "#ffee00", 1, "#00cccc", 3, "#99ffff"],
922
949
  "breakpoints": [0.01, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.25, 1.5, 1.75, 2, 2.5, 3]
923
950
  },
924
- "cm": {
951
+ "cm [QPF]": {
925
952
  "colormap": [0.03, "#eeccff", .25, "#ff9999", .75, "#cc3366", 1, "#cc0033", 2, "#ffee00", 3, "#00cccc", 7, "#99ffff"],
926
953
  "breakpoints": [.03, .25, .5, .75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4, 4.5, 5, 5.5, 6, 7, 8, 9, 10, 12, 14, 16]
927
954
  },
928
- "mm": {
955
+ "mm [QPF]": {
929
956
  "colormap": [0.3, "#eeccff", 2.5, "#ff9999", 7.5, "#cc3366", 10, "#cc0033", 20, "#ffee00", 30, "#00cccc", 70, "#99ffff"],
930
957
  "breakpoints": [0.3, 2.5, 5, 7.5, 10, 12.5, 15, 17.5, 20, 22.5, 25, 27.5, 30, 32.5, 35, 37.5, 40, 45, 50, 55, 60, 70, 80, 90, 100, 120, 140, 160]
931
958
  }